]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/collect/type_of.rs
Add error message for using type parameter as the type of a const parameter
[rust.git] / src / librustc_typeck / collect / type_of.rs
1 use rustc_data_structures::fx::FxHashSet;
2 use rustc_errors::{struct_span_err, Applicability, ErrorReported, StashKey};
3 use rustc_hir as hir;
4 use rustc_hir::def::{DefKind, Res};
5 use rustc_hir::def_id::DefId;
6 use rustc_hir::intravisit;
7 use rustc_hir::intravisit::Visitor;
8 use rustc_hir::Node;
9 use rustc_middle::hir::map::Map;
10 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
11 use rustc_middle::ty::util::IntTypeExt;
12 use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
13 use rustc_session::parse::feature_err;
14 use rustc_span::symbol::{sym, Ident};
15 use rustc_span::{Span, DUMMY_SP};
16 use rustc_trait_selection::traits;
17
18 use super::ItemCtxt;
19 use super::{bad_placeholder_type, is_suggestable_infer_ty};
20
21 pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
22     use rustc_hir::*;
23
24     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
25
26     let icx = ItemCtxt::new(tcx, def_id);
27
28     match tcx.hir().get(hir_id) {
29         Node::TraitItem(item) => match item.kind {
30             TraitItemKind::Fn(..) => {
31                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
32                 tcx.mk_fn_def(def_id, substs)
33             }
34             TraitItemKind::Const(ref ty, body_id) => body_id
35                 .and_then(|body_id| {
36                     if is_suggestable_infer_ty(ty) {
37                         Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident))
38                     } else {
39                         None
40                     }
41                 })
42                 .unwrap_or_else(|| icx.to_ty(ty)),
43             TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
44             TraitItemKind::Type(_, None) => {
45                 span_bug!(item.span, "associated type missing default");
46             }
47         },
48
49         Node::ImplItem(item) => match item.kind {
50             ImplItemKind::Fn(..) => {
51                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
52                 tcx.mk_fn_def(def_id, substs)
53             }
54             ImplItemKind::Const(ref ty, body_id) => {
55                 if is_suggestable_infer_ty(ty) {
56                     infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
57                 } else {
58                     icx.to_ty(ty)
59                 }
60             }
61             ImplItemKind::OpaqueTy(_) => {
62                 if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id).to_def_id()).is_none() {
63                     report_assoc_ty_on_inherent_impl(tcx, item.span);
64                 }
65
66                 find_opaque_ty_constraints(tcx, def_id)
67             }
68             ImplItemKind::TyAlias(ref ty) => {
69                 if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id).to_def_id()).is_none() {
70                     report_assoc_ty_on_inherent_impl(tcx, item.span);
71                 }
72
73                 icx.to_ty(ty)
74             }
75         },
76
77         Node::Item(item) => {
78             match item.kind {
79                 ItemKind::Static(ref ty, .., body_id) | ItemKind::Const(ref ty, body_id) => {
80                     if is_suggestable_infer_ty(ty) {
81                         infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
82                     } else {
83                         icx.to_ty(ty)
84                     }
85                 }
86                 ItemKind::TyAlias(ref self_ty, _) | ItemKind::Impl { ref self_ty, .. } => {
87                     icx.to_ty(self_ty)
88                 }
89                 ItemKind::Fn(..) => {
90                     let substs = InternalSubsts::identity_for_item(tcx, def_id);
91                     tcx.mk_fn_def(def_id, substs)
92                 }
93                 ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
94                     let def = tcx.adt_def(def_id);
95                     let substs = InternalSubsts::identity_for_item(tcx, def_id);
96                     tcx.mk_adt(def, substs)
97                 }
98                 ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {
99                     find_opaque_ty_constraints(tcx, def_id)
100                 }
101                 // Opaque types desugared from `impl Trait`.
102                 ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), origin, .. }) => {
103                     let concrete_types = match origin {
104                         OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => {
105                             &tcx.mir_borrowck(owner).concrete_opaque_types
106                         }
107                         OpaqueTyOrigin::Misc => {
108                             // We shouldn't leak borrowck results through impl trait in bindings.
109                             // For example, we shouldn't be able to tell if `x` in
110                             // `let x: impl Sized + 'a = &()` has type `&'static ()` or `&'a ()`.
111                             &tcx.typeck_tables_of(owner).concrete_opaque_types
112                         }
113                         OpaqueTyOrigin::TypeAlias => {
114                             span_bug!(item.span, "Type alias impl trait shouldn't have an owner")
115                         }
116                     };
117                     let concrete_ty = concrete_types
118                         .get(&def_id)
119                         .map(|opaque| opaque.concrete_type)
120                         .unwrap_or_else(|| {
121                             tcx.sess.delay_span_bug(
122                                 DUMMY_SP,
123                                 &format!(
124                                     "owner {:?} has no opaque type for {:?} in its tables",
125                                     owner, def_id,
126                                 ),
127                             );
128                             if let Some(ErrorReported) =
129                                 tcx.typeck_tables_of(owner).tainted_by_errors
130                             {
131                                 // Some error in the
132                                 // owner fn prevented us from populating
133                                 // the `concrete_opaque_types` table.
134                                 tcx.types.err
135                             } else {
136                                 // We failed to resolve the opaque type or it
137                                 // resolves to itself. Return the non-revealed
138                                 // type, which should result in E0720.
139                                 tcx.mk_opaque(
140                                     def_id,
141                                     InternalSubsts::identity_for_item(tcx, def_id),
142                                 )
143                             }
144                         });
145                     debug!("concrete_ty = {:?}", concrete_ty);
146                     if concrete_ty.has_erased_regions() {
147                         // FIXME(impl_trait_in_bindings) Handle this case.
148                         tcx.sess.span_fatal(
149                             item.span,
150                             "lifetimes in impl Trait types in bindings are not currently supported",
151                         );
152                     }
153                     concrete_ty
154                 }
155                 ItemKind::Trait(..)
156                 | ItemKind::TraitAlias(..)
157                 | ItemKind::Mod(..)
158                 | ItemKind::ForeignMod(..)
159                 | ItemKind::GlobalAsm(..)
160                 | ItemKind::ExternCrate(..)
161                 | ItemKind::Use(..) => {
162                     span_bug!(
163                         item.span,
164                         "compute_type_of_item: unexpected item type: {:?}",
165                         item.kind
166                     );
167                 }
168             }
169         }
170
171         Node::ForeignItem(foreign_item) => match foreign_item.kind {
172             ForeignItemKind::Fn(..) => {
173                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
174                 tcx.mk_fn_def(def_id, substs)
175             }
176             ForeignItemKind::Static(ref t, _) => icx.to_ty(t),
177             ForeignItemKind::Type => tcx.mk_foreign(def_id),
178         },
179
180         Node::Ctor(&ref def) | Node::Variant(Variant { data: ref def, .. }) => match *def {
181             VariantData::Unit(..) | VariantData::Struct(..) => {
182                 tcx.type_of(tcx.hir().get_parent_did(hir_id).to_def_id())
183             }
184             VariantData::Tuple(..) => {
185                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
186                 tcx.mk_fn_def(def_id, substs)
187             }
188         },
189
190         Node::Field(field) => icx.to_ty(&field.ty),
191
192         Node::Expr(&Expr { kind: ExprKind::Closure(.., gen), .. }) => {
193             let substs = InternalSubsts::identity_for_item(tcx, def_id);
194             if let Some(movability) = gen {
195                 tcx.mk_generator(def_id, substs, movability)
196             } else {
197                 tcx.mk_closure(def_id, substs)
198             }
199         }
200
201         Node::AnonConst(_) => {
202             let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
203             match parent_node {
204                 Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
205                 | Node::Ty(&Ty { kind: TyKind::Typeof(ref constant), .. })
206                 | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
207                     if constant.hir_id == hir_id =>
208                 {
209                     tcx.types.usize
210                 }
211
212                 Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => tcx
213                     .adt_def(tcx.hir().get_parent_did(hir_id).to_def_id())
214                     .repr
215                     .discr_type()
216                     .to_ty(tcx),
217
218                 Node::Ty(&Ty { kind: TyKind::Path(_), .. })
219                 | Node::Expr(&Expr { kind: ExprKind::Struct(..), .. })
220                 | Node::Expr(&Expr { kind: ExprKind::Path(_), .. })
221                 | Node::TraitRef(..) => {
222                     let path = match parent_node {
223                         Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
224                         | Node::Expr(&Expr {
225                             kind:
226                                 ExprKind::Path(QPath::Resolved(_, path))
227                                 | ExprKind::Struct(&QPath::Resolved(_, path), ..),
228                             ..
229                         })
230                         | Node::TraitRef(&TraitRef { path, .. }) => &*path,
231                         _ => {
232                             tcx.sess.delay_span_bug(
233                                 DUMMY_SP,
234                                 &format!("unexpected const parent path {:?}", parent_node),
235                             );
236                             return tcx.types.err;
237                         }
238                     };
239
240                     // We've encountered an `AnonConst` in some path, so we need to
241                     // figure out which generic parameter it corresponds to and return
242                     // the relevant type.
243
244                     let (arg_index, segment) = path
245                         .segments
246                         .iter()
247                         .filter_map(|seg| seg.args.as_ref().map(|args| (args.args, seg)))
248                         .find_map(|(args, seg)| {
249                             args.iter()
250                                 .filter(|arg| arg.is_const())
251                                 .enumerate()
252                                 .filter(|(_, arg)| arg.id() == hir_id)
253                                 .map(|(index, _)| (index, seg))
254                                 .next()
255                         })
256                         .unwrap_or_else(|| {
257                             bug!("no arg matching AnonConst in path");
258                         });
259
260                     // Try to use the segment resolution if it is valid, otherwise we
261                     // default to the path resolution.
262                     let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
263                     let generics = match res {
264                         Res::Def(DefKind::Ctor(..), def_id) => {
265                             tcx.generics_of(tcx.parent(def_id).unwrap())
266                         }
267                         Res::Def(_, def_id) => tcx.generics_of(def_id),
268                         res => {
269                             tcx.sess.delay_span_bug(
270                                 DUMMY_SP,
271                                 &format!(
272                                     "unexpected anon const res {:?} in path: {:?}",
273                                     res, path,
274                                 ),
275                             );
276                             return tcx.types.err;
277                         }
278                     };
279
280                     let ty = generics
281                         .params
282                         .iter()
283                         .filter(|param| {
284                             if let ty::GenericParamDefKind::Const = param.kind {
285                                 true
286                             } else {
287                                 false
288                             }
289                         })
290                         .nth(arg_index)
291                         .map(|param| tcx.type_of(param.def_id));
292
293                     if let Some(ty) = ty {
294                         ty
295                     } else {
296                         // This is no generic parameter associated with the arg. This is
297                         // probably from an extra arg where one is not needed.
298                         tcx.sess.delay_span_bug(
299                             DUMMY_SP,
300                             &format!(
301                                 "missing generic parameter for `AnonConst`, parent: {:?}, res: {:?}",
302                                 parent_node, res
303                             ),
304                         );
305                         tcx.types.err
306                     }
307                 }
308
309                 x => {
310                     tcx.sess.delay_span_bug(
311                         DUMMY_SP,
312                         &format!("unexpected const parent in type_of_def_id(): {:?}", x),
313                     );
314                     tcx.types.err
315                 }
316             }
317         }
318
319         Node::GenericParam(param) => match &param.kind {
320             GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty),
321             GenericParamKind::Const { ty: ref hir_ty, .. } => {
322                 let ty = icx.to_ty(hir_ty);
323                 if !tcx.features().const_compare_raw_pointers {
324                     let err = match ty.peel_refs().kind {
325                         ty::FnPtr(_) => Some("function pointers"),
326                         ty::RawPtr(_) => Some("raw pointers"),
327                         _ => None,
328                     };
329                     if let Some(unsupported_type) = err {
330                         feature_err(
331                             &tcx.sess.parse_sess,
332                             sym::const_compare_raw_pointers,
333                             hir_ty.span,
334                             &format!(
335                                 "using {} as const generic parameters is unstable",
336                                 unsupported_type
337                             ),
338                         )
339                         .emit();
340                     };
341                 }
342                 if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty)
343                     .is_some()
344                 {
345                     // We use the same error code in both branches, because this is really the same
346                     // issue: we just special-case the message for type parameters to make it
347                     // clearer.
348                     if let ty::Param(_) = ty.peel_refs().kind {
349                         // Const parameters may not have type parameters as their types,
350                         // because we cannot be sure that the type parameter derives `PartialEq`
351                         // and `Eq` (just implementing them is not enough for `structural_match`).
352                         struct_span_err!(
353                             tcx.sess,
354                             hir_ty.span,
355                             E0741,
356                             "`{}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \
357                              used as the type of a const parameter",
358                             ty,
359                         )
360                         .span_label(
361                             hir_ty.span,
362                             format!("`{}` may not derive both `PartialEq` and `Eq`", ty),
363                         )
364                         .note(
365                             "it is not currently possible to use a type parameter as the type of a \
366                              const parameter",
367                         )
368                         .emit();
369                     } else {
370                         struct_span_err!(
371                             tcx.sess,
372                             hir_ty.span,
373                             E0741,
374                             "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
375                              the type of a const parameter",
376                             ty,
377                         )
378                         .span_label(
379                             hir_ty.span,
380                             format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty),
381                         )
382                         .emit();
383                     }
384                 }
385                 ty
386             }
387             x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
388         },
389
390         x => {
391             bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
392         }
393     }
394 }
395
396 fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
397     use rustc_hir::{Expr, ImplItem, Item, TraitItem};
398
399     debug!("find_opaque_ty_constraints({:?})", def_id);
400
401     struct ConstraintLocator<'tcx> {
402         tcx: TyCtxt<'tcx>,
403         def_id: DefId,
404         // (first found type span, actual type)
405         found: Option<(Span, Ty<'tcx>)>,
406     }
407
408     impl ConstraintLocator<'_> {
409         fn check(&mut self, def_id: DefId) {
410             // Don't try to check items that cannot possibly constrain the type.
411             if !self.tcx.has_typeck_tables(def_id) {
412                 debug!(
413                     "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`: no tables",
414                     self.def_id, def_id,
415                 );
416                 return;
417             }
418             // Calling `mir_borrowck` can lead to cycle errors through
419             // const-checking, avoid calling it if we don't have to.
420             if !self.tcx.typeck_tables_of(def_id).concrete_opaque_types.contains_key(&self.def_id) {
421                 debug!(
422                     "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`",
423                     self.def_id, def_id,
424                 );
425                 return;
426             }
427             // Use borrowck to get the type with unerased regions.
428             let ty = self.tcx.mir_borrowck(def_id).concrete_opaque_types.get(&self.def_id);
429             if let Some(ty::ResolvedOpaqueTy { concrete_type, substs }) = ty {
430                 debug!(
431                     "find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}",
432                     self.def_id, def_id, ty,
433                 );
434
435                 // FIXME(oli-obk): trace the actual span from inference to improve errors.
436                 let span = self.tcx.def_span(def_id);
437
438                 // HACK(eddyb) this check shouldn't be needed, as `wfcheck`
439                 // performs the same checks, in theory, but I've kept it here
440                 // using `delay_span_bug`, just in case `wfcheck` slips up.
441                 let opaque_generics = self.tcx.generics_of(self.def_id);
442                 let mut used_params: FxHashSet<_> = FxHashSet::default();
443                 for (i, arg) in substs.iter().enumerate() {
444                     let arg_is_param = match arg.unpack() {
445                         GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
446                         GenericArgKind::Lifetime(lt) => {
447                             matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_))
448                         }
449                         GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
450                     };
451
452                     if arg_is_param {
453                         if !used_params.insert(arg) {
454                             // There was already an entry for `arg`, meaning a generic parameter
455                             // was used twice.
456                             self.tcx.sess.delay_span_bug(
457                                 span,
458                                 &format!(
459                                     "defining opaque type use restricts opaque \
460                                      type by using the generic parameter `{}` twice",
461                                     arg,
462                                 ),
463                             );
464                         }
465                     } else {
466                         let param = opaque_generics.param_at(i, self.tcx);
467                         self.tcx.sess.delay_span_bug(
468                             span,
469                             &format!(
470                                 "defining opaque type use does not fully define opaque type: \
471                                  generic parameter `{}` is specified as concrete {} `{}`",
472                                 param.name,
473                                 param.kind.descr(),
474                                 arg,
475                             ),
476                         );
477                     }
478                 }
479
480                 if let Some((prev_span, prev_ty)) = self.found {
481                     if *concrete_type != prev_ty {
482                         debug!("find_opaque_ty_constraints: span={:?}", span);
483                         // Found different concrete types for the opaque type.
484                         let mut err = self.tcx.sess.struct_span_err(
485                             span,
486                             "concrete type differs from previous defining opaque type use",
487                         );
488                         err.span_label(
489                             span,
490                             format!("expected `{}`, got `{}`", prev_ty, concrete_type),
491                         );
492                         err.span_note(prev_span, "previous use here");
493                         err.emit();
494                     }
495                 } else {
496                     self.found = Some((span, concrete_type));
497                 }
498             } else {
499                 debug!(
500                     "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`",
501                     self.def_id, def_id,
502                 );
503             }
504         }
505     }
506
507     impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
508         type Map = Map<'tcx>;
509
510         fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
511             intravisit::NestedVisitorMap::All(self.tcx.hir())
512         }
513         fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
514             if let hir::ExprKind::Closure(..) = ex.kind {
515                 let def_id = self.tcx.hir().local_def_id(ex.hir_id);
516                 self.check(def_id);
517             }
518             intravisit::walk_expr(self, ex);
519         }
520         fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
521             debug!("find_existential_constraints: visiting {:?}", it);
522             let def_id = self.tcx.hir().local_def_id(it.hir_id);
523             // The opaque type itself or its children are not within its reveal scope.
524             if def_id != self.def_id {
525                 self.check(def_id);
526                 intravisit::walk_item(self, it);
527             }
528         }
529         fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
530             debug!("find_existential_constraints: visiting {:?}", it);
531             let def_id = self.tcx.hir().local_def_id(it.hir_id);
532             // The opaque type itself or its children are not within its reveal scope.
533             if def_id != self.def_id {
534                 self.check(def_id);
535                 intravisit::walk_impl_item(self, it);
536             }
537         }
538         fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
539             debug!("find_existential_constraints: visiting {:?}", it);
540             let def_id = self.tcx.hir().local_def_id(it.hir_id);
541             self.check(def_id);
542             intravisit::walk_trait_item(self, it);
543         }
544     }
545
546     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
547     let scope = tcx.hir().get_defining_scope(hir_id);
548     let mut locator = ConstraintLocator { def_id, tcx, found: None };
549
550     debug!("find_opaque_ty_constraints: scope={:?}", scope);
551
552     if scope == hir::CRATE_HIR_ID {
553         intravisit::walk_crate(&mut locator, tcx.hir().krate());
554     } else {
555         debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope));
556         match tcx.hir().get(scope) {
557             // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
558             // This allows our visitor to process the defining item itself, causing
559             // it to pick up any 'sibling' defining uses.
560             //
561             // For example, this code:
562             // ```
563             // fn foo() {
564             //     type Blah = impl Debug;
565             //     let my_closure = || -> Blah { true };
566             // }
567             // ```
568             //
569             // requires us to explicitly process `foo()` in order
570             // to notice the defining usage of `Blah`.
571             Node::Item(ref it) => locator.visit_item(it),
572             Node::ImplItem(ref it) => locator.visit_impl_item(it),
573             Node::TraitItem(ref it) => locator.visit_trait_item(it),
574             other => bug!("{:?} is not a valid scope for an opaque type item", other),
575         }
576     }
577
578     match locator.found {
579         Some((_, ty)) => ty,
580         None => {
581             let span = tcx.def_span(def_id);
582             tcx.sess.span_err(span, "could not find defining uses");
583             tcx.types.err
584         }
585     }
586 }
587
588 fn infer_placeholder_type(
589     tcx: TyCtxt<'_>,
590     def_id: DefId,
591     body_id: hir::BodyId,
592     span: Span,
593     item_ident: Ident,
594 ) -> Ty<'_> {
595     let ty = tcx.diagnostic_only_typeck_tables_of(def_id).node_type(body_id.hir_id);
596
597     // If this came from a free `const` or `static mut?` item,
598     // then the user may have written e.g. `const A = 42;`.
599     // In this case, the parser has stashed a diagnostic for
600     // us to improve in typeck so we do that now.
601     match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) {
602         Some(mut err) => {
603             // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
604             // We are typeck and have the real type, so remove that and suggest the actual type.
605             err.suggestions.clear();
606             err.span_suggestion(
607                 span,
608                 "provide a type for the item",
609                 format!("{}: {}", item_ident, ty),
610                 Applicability::MachineApplicable,
611             )
612             .emit();
613         }
614         None => {
615             let mut diag = bad_placeholder_type(tcx, vec![span]);
616             if ty != tcx.types.err {
617                 diag.span_suggestion(
618                     span,
619                     "replace `_` with the correct type",
620                     ty.to_string(),
621                     Applicability::MaybeIncorrect,
622                 );
623             }
624             diag.emit();
625         }
626     }
627
628     // Typeck doesn't expect erased regions to be returned from `type_of`.
629     tcx.fold_regions(&ty, &mut false, |r, _| match r {
630         ty::ReErased => tcx.lifetimes.re_static,
631         _ => r,
632     })
633 }
634
635 fn report_assoc_ty_on_inherent_impl(tcx: TyCtxt<'_>, span: Span) {
636     struct_span_err!(
637         tcx.sess,
638         span,
639         E0202,
640         "associated types are not yet supported in inherent impls (see #8995)"
641     )
642     .emit();
643 }