]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/coherence/inherent_impls.rs
Rollup merge of #75485 - RalfJung:pin, r=nagisa
[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_errors::struct_span_err;
11 use rustc_hir as hir;
12 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
13 use rustc_hir::itemlikevisit::ItemLikeVisitor;
14 use rustc_middle::ty::{self, CrateInherentImpls, TyCtxt};
15
16 use rustc_ast::ast;
17 use rustc_span::Span;
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     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::Array(_, _) => {
116                 self.check_primitive_impl(
117                     def_id,
118                     lang_items.array_impl(),
119                     None,
120                     "array",
121                     "[T; N]",
122                     item.span,
123                 );
124             }
125             ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not })
126                 if matches!(inner.kind, ty::Slice(_)) =>
127             {
128                 self.check_primitive_impl(
129                     def_id,
130                     lang_items.const_slice_ptr_impl(),
131                     None,
132                     "const_slice_ptr",
133                     "*const [T]",
134                     item.span,
135                 );
136             }
137             ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Mut })
138                 if matches!(inner.kind, ty::Slice(_)) =>
139             {
140                 self.check_primitive_impl(
141                     def_id,
142                     lang_items.mut_slice_ptr_impl(),
143                     None,
144                     "mut_slice_ptr",
145                     "*mut [T]",
146                     item.span,
147                 );
148             }
149             ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
150                 self.check_primitive_impl(
151                     def_id,
152                     lang_items.const_ptr_impl(),
153                     None,
154                     "const_ptr",
155                     "*const T",
156                     item.span,
157                 );
158             }
159             ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => {
160                 self.check_primitive_impl(
161                     def_id,
162                     lang_items.mut_ptr_impl(),
163                     None,
164                     "mut_ptr",
165                     "*mut T",
166                     item.span,
167                 );
168             }
169             ty::Int(ast::IntTy::I8) => {
170                 self.check_primitive_impl(
171                     def_id,
172                     lang_items.i8_impl(),
173                     None,
174                     "i8",
175                     "i8",
176                     item.span,
177                 );
178             }
179             ty::Int(ast::IntTy::I16) => {
180                 self.check_primitive_impl(
181                     def_id,
182                     lang_items.i16_impl(),
183                     None,
184                     "i16",
185                     "i16",
186                     item.span,
187                 );
188             }
189             ty::Int(ast::IntTy::I32) => {
190                 self.check_primitive_impl(
191                     def_id,
192                     lang_items.i32_impl(),
193                     None,
194                     "i32",
195                     "i32",
196                     item.span,
197                 );
198             }
199             ty::Int(ast::IntTy::I64) => {
200                 self.check_primitive_impl(
201                     def_id,
202                     lang_items.i64_impl(),
203                     None,
204                     "i64",
205                     "i64",
206                     item.span,
207                 );
208             }
209             ty::Int(ast::IntTy::I128) => {
210                 self.check_primitive_impl(
211                     def_id,
212                     lang_items.i128_impl(),
213                     None,
214                     "i128",
215                     "i128",
216                     item.span,
217                 );
218             }
219             ty::Int(ast::IntTy::Isize) => {
220                 self.check_primitive_impl(
221                     def_id,
222                     lang_items.isize_impl(),
223                     None,
224                     "isize",
225                     "isize",
226                     item.span,
227                 );
228             }
229             ty::Uint(ast::UintTy::U8) => {
230                 self.check_primitive_impl(
231                     def_id,
232                     lang_items.u8_impl(),
233                     None,
234                     "u8",
235                     "u8",
236                     item.span,
237                 );
238             }
239             ty::Uint(ast::UintTy::U16) => {
240                 self.check_primitive_impl(
241                     def_id,
242                     lang_items.u16_impl(),
243                     None,
244                     "u16",
245                     "u16",
246                     item.span,
247                 );
248             }
249             ty::Uint(ast::UintTy::U32) => {
250                 self.check_primitive_impl(
251                     def_id,
252                     lang_items.u32_impl(),
253                     None,
254                     "u32",
255                     "u32",
256                     item.span,
257                 );
258             }
259             ty::Uint(ast::UintTy::U64) => {
260                 self.check_primitive_impl(
261                     def_id,
262                     lang_items.u64_impl(),
263                     None,
264                     "u64",
265                     "u64",
266                     item.span,
267                 );
268             }
269             ty::Uint(ast::UintTy::U128) => {
270                 self.check_primitive_impl(
271                     def_id,
272                     lang_items.u128_impl(),
273                     None,
274                     "u128",
275                     "u128",
276                     item.span,
277                 );
278             }
279             ty::Uint(ast::UintTy::Usize) => {
280                 self.check_primitive_impl(
281                     def_id,
282                     lang_items.usize_impl(),
283                     None,
284                     "usize",
285                     "usize",
286                     item.span,
287                 );
288             }
289             ty::Float(ast::FloatTy::F32) => {
290                 self.check_primitive_impl(
291                     def_id,
292                     lang_items.f32_impl(),
293                     lang_items.f32_runtime_impl(),
294                     "f32",
295                     "f32",
296                     item.span,
297                 );
298             }
299             ty::Float(ast::FloatTy::F64) => {
300                 self.check_primitive_impl(
301                     def_id,
302                     lang_items.f64_impl(),
303                     lang_items.f64_runtime_impl(),
304                     "f64",
305                     "f64",
306                     item.span,
307                 );
308             }
309             ty::Error(_) => {}
310             _ => {
311                 struct_span_err!(
312                     self.tcx.sess,
313                     ty.span,
314                     E0118,
315                     "no base type found for inherent implementation"
316                 )
317                 .span_label(ty.span, "impl requires a base type")
318                 .note(
319                     "either implement a trait on it or create a newtype \
320                        to wrap it instead",
321                 )
322                 .emit();
323             }
324         }
325     }
326
327     fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
328
329     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
330 }
331
332 impl InherentCollect<'tcx> {
333     fn check_def_id(&mut self, item: &hir::Item<'_>, def_id: DefId) {
334         if def_id.is_local() {
335             // Add the implementation to the mapping from implementation to base
336             // type def ID, if there is a base type for this implementation and
337             // the implementation does not have any associated traits.
338             let impl_def_id = self.tcx.hir().local_def_id(item.hir_id);
339             let vec = self.impls_map.inherent_impls.entry(def_id).or_default();
340             vec.push(impl_def_id.to_def_id());
341         } else {
342             struct_span_err!(
343                 self.tcx.sess,
344                 item.span,
345                 E0116,
346                 "cannot define inherent `impl` for a type outside of the crate \
347                               where the type is defined"
348             )
349             .span_label(item.span, "impl for type defined outside of crate.")
350             .note("define and implement a trait or new type instead")
351             .emit();
352         }
353     }
354
355     fn check_primitive_impl(
356         &self,
357         impl_def_id: LocalDefId,
358         lang_def_id: Option<DefId>,
359         lang_def_id2: Option<DefId>,
360         lang: &str,
361         ty: &str,
362         span: Span,
363     ) {
364         match (lang_def_id, lang_def_id2) {
365             (Some(lang_def_id), _) if lang_def_id == impl_def_id.to_def_id() => {
366                 // OK
367             }
368             (_, Some(lang_def_id)) if lang_def_id == impl_def_id.to_def_id() => {
369                 // OK
370             }
371             _ => {
372                 struct_span_err!(
373                     self.tcx.sess,
374                     span,
375                     E0390,
376                     "only a single inherent implementation marked with `#[lang = \
377                                   \"{}\"]` is allowed for the `{}` primitive",
378                     lang,
379                     ty
380                 )
381                 .span_help(span, "consider using a trait to implement these methods")
382                 .emit();
383             }
384         }
385     }
386 }