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