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