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