1 //! The code in this module gathers up all of the inherent impls in
2 //! the current crate and organizes them in a map. It winds up
3 //! touching the whole crate and thus must be recomputed completely
4 //! for any change, but it is very cheap to compute. In practice, most
5 //! code in the compiler never *directly* requests this map. Instead,
6 //! it requests the inherent impls specific to some type (via
7 //! `tcx.inherent_impls(def_id)`). That value, however,
8 //! is computed by selecting an idea from this table.
10 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
12 use rustc::hir::itemlikevisit::ItemLikeVisitor;
13 use rustc::ty::{self, CrateInherentImpls, TyCtxt};
18 use rustc_error_codes::*;
20 /// On-demand query: yields a map containing all types mapped to their inherent impls.
21 pub fn crate_inherent_impls(
24 ) -> &CrateInherentImpls {
25 assert_eq!(crate_num, LOCAL_CRATE);
27 let krate = tcx.hir().krate();
28 let mut collect = InherentCollect {
30 impls_map: Default::default(),
32 krate.visit_all_item_likes(&mut collect);
33 tcx.arena.alloc(collect.impls_map)
36 /// On-demand query: yields a vector of the inherent impls for a specific type.
37 pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: DefId) -> &[DefId] {
38 assert!(ty_def_id.is_local());
40 let crate_map = tcx.crate_inherent_impls(ty_def_id.krate);
41 match crate_map.inherent_impls.get(&ty_def_id) {
47 struct InherentCollect<'tcx> {
49 impls_map: CrateInherentImpls,
52 impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
53 fn visit_item(&mut self, item: &hir::Item<'_>) {
54 let ty = match item.kind {
55 hir::ItemKind::Impl(.., None, ref ty, _) => ty,
59 let def_id = self.tcx.hir().local_def_id(item.hir_id);
60 let self_ty = self.tcx.type_of(def_id);
61 let lang_items = self.tcx.lang_items();
64 self.check_def_id(item, def.did);
67 self.check_def_id(item, did);
69 ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => {
70 self.check_def_id(item, data.principal_def_id().unwrap());
73 self.check_primitive_impl(def_id,
74 lang_items.bool_impl(),
81 self.check_primitive_impl(def_id,
82 lang_items.char_impl(),
89 self.check_primitive_impl(def_id,
90 lang_items.str_impl(),
91 lang_items.str_alloc_impl(),
96 ty::Slice(slice_item) if slice_item == self.tcx.types.u8 => {
97 self.check_primitive_impl(def_id,
98 lang_items.slice_u8_impl(),
99 lang_items.slice_u8_alloc_impl(),
105 self.check_primitive_impl(def_id,
106 lang_items.slice_impl(),
107 lang_items.slice_alloc_impl(),
112 ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
113 self.check_primitive_impl(def_id,
114 lang_items.const_ptr_impl(),
120 ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => {
121 self.check_primitive_impl(def_id,
122 lang_items.mut_ptr_impl(),
128 ty::Int(ast::IntTy::I8) => {
129 self.check_primitive_impl(def_id,
130 lang_items.i8_impl(),
136 ty::Int(ast::IntTy::I16) => {
137 self.check_primitive_impl(def_id,
138 lang_items.i16_impl(),
144 ty::Int(ast::IntTy::I32) => {
145 self.check_primitive_impl(def_id,
146 lang_items.i32_impl(),
152 ty::Int(ast::IntTy::I64) => {
153 self.check_primitive_impl(def_id,
154 lang_items.i64_impl(),
160 ty::Int(ast::IntTy::I128) => {
161 self.check_primitive_impl(def_id,
162 lang_items.i128_impl(),
168 ty::Int(ast::IntTy::Isize) => {
169 self.check_primitive_impl(def_id,
170 lang_items.isize_impl(),
176 ty::Uint(ast::UintTy::U8) => {
177 self.check_primitive_impl(def_id,
178 lang_items.u8_impl(),
184 ty::Uint(ast::UintTy::U16) => {
185 self.check_primitive_impl(def_id,
186 lang_items.u16_impl(),
192 ty::Uint(ast::UintTy::U32) => {
193 self.check_primitive_impl(def_id,
194 lang_items.u32_impl(),
200 ty::Uint(ast::UintTy::U64) => {
201 self.check_primitive_impl(def_id,
202 lang_items.u64_impl(),
208 ty::Uint(ast::UintTy::U128) => {
209 self.check_primitive_impl(def_id,
210 lang_items.u128_impl(),
216 ty::Uint(ast::UintTy::Usize) => {
217 self.check_primitive_impl(def_id,
218 lang_items.usize_impl(),
224 ty::Float(ast::FloatTy::F32) => {
225 self.check_primitive_impl(def_id,
226 lang_items.f32_impl(),
227 lang_items.f32_runtime_impl(),
232 ty::Float(ast::FloatTy::F64) => {
233 self.check_primitive_impl(def_id,
234 lang_items.f64_impl(),
235 lang_items.f64_runtime_impl(),
244 struct_span_err!(self.tcx.sess,
247 "no base type found for inherent implementation")
248 .span_label(ty.span, "impl requires a base type")
249 .note(&format!("either implement a trait on it or create a newtype \
250 to wrap it instead"))
257 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {
260 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
264 impl InherentCollect<'tcx> {
265 fn check_def_id(&mut self, item: &hir::Item<'_>, def_id: DefId) {
266 if def_id.is_local() {
267 // Add the implementation to the mapping from implementation to base
268 // type def ID, if there is a base type for this implementation and
269 // the implementation does not have any associated traits.
270 let impl_def_id = self.tcx.hir().local_def_id(item.hir_id);
271 let vec = self.impls_map.inherent_impls.entry(def_id).or_default();
272 vec.push(impl_def_id);
274 struct_span_err!(self.tcx.sess,
277 "cannot define inherent `impl` for a type outside of the crate \
278 where the type is defined")
279 .span_label(item.span, "impl for type defined outside of crate.")
280 .note("define and implement a trait or new type instead")
285 fn check_primitive_impl(&self,
287 lang_def_id: Option<DefId>,
288 lang_def_id2: Option<DefId>,
292 match (lang_def_id, lang_def_id2) {
293 (Some(lang_def_id), _) if lang_def_id == impl_def_id => {
296 (_, Some(lang_def_id)) if lang_def_id == impl_def_id => {
300 struct_span_err!(self.tcx.sess,
303 "only a single inherent implementation marked with `#[lang = \
304 \"{}\"]` is allowed for the `{}` primitive",
307 .span_help(span, "consider using a trait to implement these methods")