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