]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/coherence/inherent_impls.rs
Rename `Item.node` to `Item.kind`
[rust.git] / src / librustc_typeck / coherence / inherent_impls.rs
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.
9
10 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
11 use rustc::hir;
12 use rustc::hir::itemlikevisit::ItemLikeVisitor;
13 use rustc::ty::{self, CrateInherentImpls, TyCtxt};
14
15 use syntax::ast;
16 use syntax_pos::Span;
17
18 /// On-demand query: yields a map containing all types mapped to their inherent impls.
19 pub fn crate_inherent_impls(
20     tcx: TyCtxt<'_>,
21     crate_num: CrateNum,
22 ) -> &CrateInherentImpls {
23     assert_eq!(crate_num, LOCAL_CRATE);
24
25     let krate = tcx.hir().krate();
26     let mut collect = InherentCollect {
27         tcx,
28         impls_map: Default::default(),
29     };
30     krate.visit_all_item_likes(&mut collect);
31     tcx.arena.alloc(collect.impls_map)
32 }
33
34 /// On-demand query: yields a vector of the inherent impls for a specific type.
35 pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: DefId) -> &[DefId] {
36     assert!(ty_def_id.is_local());
37
38     let crate_map = tcx.crate_inherent_impls(ty_def_id.krate);
39     match crate_map.inherent_impls.get(&ty_def_id) {
40         Some(v) => &v[..],
41         None => &[],
42     }
43 }
44
45 struct InherentCollect<'tcx> {
46     tcx: TyCtxt<'tcx>,
47     impls_map: CrateInherentImpls,
48 }
49
50 impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
51     fn visit_item(&mut self, item: &hir::Item) {
52         let ty = match item.kind {
53             hir::ItemKind::Impl(.., None, ref ty, _) => ty,
54             _ => return
55         };
56
57         let def_id = self.tcx.hir().local_def_id(item.hir_id);
58         let self_ty = self.tcx.type_of(def_id);
59         let lang_items = self.tcx.lang_items();
60         match self_ty.kind {
61             ty::Adt(def, _) => {
62                 self.check_def_id(item, def.did);
63             }
64             ty::Foreign(did) => {
65                 self.check_def_id(item, did);
66             }
67             ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => {
68                 self.check_def_id(item, data.principal_def_id().unwrap());
69             }
70             ty::Bool => {
71                 self.check_primitive_impl(def_id,
72                                           lang_items.bool_impl(),
73                                           None,
74                                           "bool",
75                                           "bool",
76                                           item.span);
77             }
78             ty::Char => {
79                 self.check_primitive_impl(def_id,
80                                           lang_items.char_impl(),
81                                           None,
82                                           "char",
83                                           "char",
84                                           item.span);
85             }
86             ty::Str => {
87                 self.check_primitive_impl(def_id,
88                                           lang_items.str_impl(),
89                                           lang_items.str_alloc_impl(),
90                                           "str",
91                                           "str",
92                                           item.span);
93             }
94             ty::Slice(slice_item) if slice_item == self.tcx.types.u8 => {
95                 self.check_primitive_impl(def_id,
96                                           lang_items.slice_u8_impl(),
97                                           lang_items.slice_u8_alloc_impl(),
98                                           "slice_u8",
99                                           "[u8]",
100                                           item.span);
101             }
102             ty::Slice(_) => {
103                 self.check_primitive_impl(def_id,
104                                           lang_items.slice_impl(),
105                                           lang_items.slice_alloc_impl(),
106                                           "slice",
107                                           "[T]",
108                                           item.span);
109             }
110             ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
111                 self.check_primitive_impl(def_id,
112                                           lang_items.const_ptr_impl(),
113                                           None,
114                                           "const_ptr",
115                                           "*const T",
116                                           item.span);
117             }
118             ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
119                 self.check_primitive_impl(def_id,
120                                           lang_items.mut_ptr_impl(),
121                                           None,
122                                           "mut_ptr",
123                                           "*mut T",
124                                           item.span);
125             }
126             ty::Int(ast::IntTy::I8) => {
127                 self.check_primitive_impl(def_id,
128                                           lang_items.i8_impl(),
129                                           None,
130                                           "i8",
131                                           "i8",
132                                           item.span);
133             }
134             ty::Int(ast::IntTy::I16) => {
135                 self.check_primitive_impl(def_id,
136                                           lang_items.i16_impl(),
137                                           None,
138                                           "i16",
139                                           "i16",
140                                           item.span);
141             }
142             ty::Int(ast::IntTy::I32) => {
143                 self.check_primitive_impl(def_id,
144                                           lang_items.i32_impl(),
145                                           None,
146                                           "i32",
147                                           "i32",
148                                           item.span);
149             }
150             ty::Int(ast::IntTy::I64) => {
151                 self.check_primitive_impl(def_id,
152                                           lang_items.i64_impl(),
153                                           None,
154                                           "i64",
155                                           "i64",
156                                           item.span);
157             }
158             ty::Int(ast::IntTy::I128) => {
159                 self.check_primitive_impl(def_id,
160                                           lang_items.i128_impl(),
161                                           None,
162                                           "i128",
163                                           "i128",
164                                           item.span);
165             }
166             ty::Int(ast::IntTy::Isize) => {
167                 self.check_primitive_impl(def_id,
168                                           lang_items.isize_impl(),
169                                           None,
170                                           "isize",
171                                           "isize",
172                                           item.span);
173             }
174             ty::Uint(ast::UintTy::U8) => {
175                 self.check_primitive_impl(def_id,
176                                           lang_items.u8_impl(),
177                                           None,
178                                           "u8",
179                                           "u8",
180                                           item.span);
181             }
182             ty::Uint(ast::UintTy::U16) => {
183                 self.check_primitive_impl(def_id,
184                                           lang_items.u16_impl(),
185                                           None,
186                                           "u16",
187                                           "u16",
188                                           item.span);
189             }
190             ty::Uint(ast::UintTy::U32) => {
191                 self.check_primitive_impl(def_id,
192                                           lang_items.u32_impl(),
193                                           None,
194                                           "u32",
195                                           "u32",
196                                           item.span);
197             }
198             ty::Uint(ast::UintTy::U64) => {
199                 self.check_primitive_impl(def_id,
200                                           lang_items.u64_impl(),
201                                           None,
202                                           "u64",
203                                           "u64",
204                                           item.span);
205             }
206             ty::Uint(ast::UintTy::U128) => {
207                 self.check_primitive_impl(def_id,
208                                           lang_items.u128_impl(),
209                                           None,
210                                           "u128",
211                                           "u128",
212                                           item.span);
213             }
214             ty::Uint(ast::UintTy::Usize) => {
215                 self.check_primitive_impl(def_id,
216                                           lang_items.usize_impl(),
217                                           None,
218                                           "usize",
219                                           "usize",
220                                           item.span);
221             }
222             ty::Float(ast::FloatTy::F32) => {
223                 self.check_primitive_impl(def_id,
224                                           lang_items.f32_impl(),
225                                           lang_items.f32_runtime_impl(),
226                                           "f32",
227                                           "f32",
228                                           item.span);
229             }
230             ty::Float(ast::FloatTy::F64) => {
231                 self.check_primitive_impl(def_id,
232                                           lang_items.f64_impl(),
233                                           lang_items.f64_runtime_impl(),
234                                           "f64",
235                                           "f64",
236                                           item.span);
237             }
238             ty::Error => {
239                 return;
240             }
241             _ => {
242                 struct_span_err!(self.tcx.sess,
243                                  ty.span,
244                                  E0118,
245                                  "no base type found for inherent implementation")
246                     .span_label(ty.span, "impl requires a base type")
247                     .note(&format!("either implement a trait on it or create a newtype \
248                                     to wrap it instead"))
249                     .emit();
250                 return;
251             }
252         }
253     }
254
255     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
256     }
257
258     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
259     }
260 }
261
262 impl InherentCollect<'tcx> {
263     fn check_def_id(&mut self, item: &hir::Item, def_id: DefId) {
264         if def_id.is_local() {
265             // Add the implementation to the mapping from implementation to base
266             // type def ID, if there is a base type for this implementation and
267             // the implementation does not have any associated traits.
268             let impl_def_id = self.tcx.hir().local_def_id(item.hir_id);
269             let vec = self.impls_map.inherent_impls.entry(def_id).or_default();
270             vec.push(impl_def_id);
271         } else {
272             struct_span_err!(self.tcx.sess,
273                              item.span,
274                              E0116,
275                              "cannot define inherent `impl` for a type outside of the crate \
276                               where the type is defined")
277                 .span_label(item.span, "impl for type defined outside of crate.")
278                 .note("define and implement a trait or new type instead")
279                 .emit();
280         }
281     }
282
283     fn check_primitive_impl(&self,
284                             impl_def_id: DefId,
285                             lang_def_id: Option<DefId>,
286                             lang_def_id2: Option<DefId>,
287                             lang: &str,
288                             ty: &str,
289                             span: Span) {
290         match (lang_def_id, lang_def_id2) {
291             (Some(lang_def_id), _) if lang_def_id == impl_def_id => {
292                 // OK
293             }
294             (_, Some(lang_def_id)) if lang_def_id == impl_def_id => {
295                 // OK
296             }
297             _ => {
298                 struct_span_err!(self.tcx.sess,
299                                  span,
300                                  E0390,
301                                  "only a single inherent implementation marked with `#[lang = \
302                                   \"{}\"]` is allowed for the `{}` primitive",
303                                  lang,
304                                  ty)
305                     .span_help(span, "consider using a trait to implement these methods")
306                     .emit();
307             }
308         }
309     }
310 }