]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/collect/type_of.rs
Auto merge of #75137 - Aaron1011:fix/hygiene-skip-expndata, r=petrochenkov
[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_ty_str;
330                 let err = if tcx.features().min_const_generics {
331                     match ty.kind {
332                         ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => None,
333                         ty::FnPtr(_) => Some("function pointers"),
334                         ty::RawPtr(_) => Some("raw pointers"),
335                         _ => {
336                             err_ty_str = format!("`{}`", ty);
337                             Some(err_ty_str.as_str())
338                         }
339                     }
340                 } else {
341                     match ty.peel_refs().kind {
342                         ty::FnPtr(_) => Some("function pointers"),
343                         ty::RawPtr(_) => Some("raw pointers"),
344                         _ => None,
345                     }
346                 };
347                 if let Some(unsupported_type) = err {
348                     let mut err = tcx.sess.struct_span_err(
349                         hir_ty.span,
350                         &format!(
351                             "using {} as const generic parameters is forbidden",
352                             unsupported_type
353                         ),
354                     );
355
356                     if tcx.features().min_const_generics {
357                         err.note("the only supported types are integers, `bool` and `char`")
358                         .note("more complex types are supported with `#[feature(const_generics)]`").emit()
359                     } else {
360                         err.emit();
361                     }
362                 };
363                 if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty)
364                     .is_some()
365                 {
366                     // We use the same error code in both branches, because this is really the same
367                     // issue: we just special-case the message for type parameters to make it
368                     // clearer.
369                     if let ty::Param(_) = ty.peel_refs().kind {
370                         // Const parameters may not have type parameters as their types,
371                         // because we cannot be sure that the type parameter derives `PartialEq`
372                         // and `Eq` (just implementing them is not enough for `structural_match`).
373                         struct_span_err!(
374                             tcx.sess,
375                             hir_ty.span,
376                             E0741,
377                             "`{}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \
378                              used as the type of a const parameter",
379                             ty,
380                         )
381                         .span_label(
382                             hir_ty.span,
383                             format!("`{}` may not derive both `PartialEq` and `Eq`", ty),
384                         )
385                         .note(
386                             "it is not currently possible to use a type parameter as the type of a \
387                              const parameter",
388                         )
389                         .emit();
390                     } else {
391                         struct_span_err!(
392                             tcx.sess,
393                             hir_ty.span,
394                             E0741,
395                             "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
396                              the type of a const parameter",
397                             ty,
398                         )
399                         .span_label(
400                             hir_ty.span,
401                             format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty),
402                         )
403                         .emit();
404                     }
405                 }
406                 ty
407             }
408             x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
409         },
410
411         x => {
412             bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
413         }
414     }
415 }
416
417 fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
418     use rustc_hir::{Expr, ImplItem, Item, TraitItem};
419
420     debug!("find_opaque_ty_constraints({:?})", def_id);
421
422     struct ConstraintLocator<'tcx> {
423         tcx: TyCtxt<'tcx>,
424         def_id: DefId,
425         // (first found type span, actual type)
426         found: Option<(Span, Ty<'tcx>)>,
427     }
428
429     impl ConstraintLocator<'_> {
430         fn check(&mut self, def_id: LocalDefId) {
431             // Don't try to check items that cannot possibly constrain the type.
432             if !self.tcx.has_typeck_results(def_id) {
433                 debug!(
434                     "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`: no typeck results",
435                     self.def_id, def_id,
436                 );
437                 return;
438             }
439             // Calling `mir_borrowck` can lead to cycle errors through
440             // const-checking, avoid calling it if we don't have to.
441             if !self.tcx.typeck(def_id).concrete_opaque_types.contains_key(&self.def_id) {
442                 debug!(
443                     "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`",
444                     self.def_id, def_id,
445                 );
446                 return;
447             }
448             // Use borrowck to get the type with unerased regions.
449             let ty = self.tcx.mir_borrowck(def_id).concrete_opaque_types.get(&self.def_id);
450             if let Some(ty::ResolvedOpaqueTy { concrete_type, substs }) = ty {
451                 debug!(
452                     "find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}",
453                     self.def_id, def_id, ty,
454                 );
455
456                 // FIXME(oli-obk): trace the actual span from inference to improve errors.
457                 let span = self.tcx.def_span(def_id);
458
459                 // HACK(eddyb) this check shouldn't be needed, as `wfcheck`
460                 // performs the same checks, in theory, but I've kept it here
461                 // using `delay_span_bug`, just in case `wfcheck` slips up.
462                 let opaque_generics = self.tcx.generics_of(self.def_id);
463                 let mut used_params: FxHashSet<_> = FxHashSet::default();
464                 for (i, arg) in substs.iter().enumerate() {
465                     let arg_is_param = match arg.unpack() {
466                         GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
467                         GenericArgKind::Lifetime(lt) => {
468                             matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_))
469                         }
470                         GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
471                     };
472
473                     if arg_is_param {
474                         if !used_params.insert(arg) {
475                             // There was already an entry for `arg`, meaning a generic parameter
476                             // was used twice.
477                             self.tcx.sess.delay_span_bug(
478                                 span,
479                                 &format!(
480                                     "defining opaque type use restricts opaque \
481                                      type by using the generic parameter `{}` twice",
482                                     arg,
483                                 ),
484                             );
485                         }
486                     } else {
487                         let param = opaque_generics.param_at(i, self.tcx);
488                         self.tcx.sess.delay_span_bug(
489                             span,
490                             &format!(
491                                 "defining opaque type use does not fully define opaque type: \
492                                  generic parameter `{}` is specified as concrete {} `{}`",
493                                 param.name,
494                                 param.kind.descr(),
495                                 arg,
496                             ),
497                         );
498                     }
499                 }
500
501                 if let Some((prev_span, prev_ty)) = self.found {
502                     if *concrete_type != prev_ty {
503                         debug!("find_opaque_ty_constraints: span={:?}", span);
504                         // Found different concrete types for the opaque type.
505                         let mut err = self.tcx.sess.struct_span_err(
506                             span,
507                             "concrete type differs from previous defining opaque type use",
508                         );
509                         err.span_label(
510                             span,
511                             format!("expected `{}`, got `{}`", prev_ty, concrete_type),
512                         );
513                         err.span_note(prev_span, "previous use here");
514                         err.emit();
515                     }
516                 } else {
517                     self.found = Some((span, concrete_type));
518                 }
519             } else {
520                 debug!(
521                     "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`",
522                     self.def_id, def_id,
523                 );
524             }
525         }
526     }
527
528     impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
529         type Map = Map<'tcx>;
530
531         fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
532             intravisit::NestedVisitorMap::All(self.tcx.hir())
533         }
534         fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
535             if let hir::ExprKind::Closure(..) = ex.kind {
536                 let def_id = self.tcx.hir().local_def_id(ex.hir_id);
537                 self.check(def_id);
538             }
539             intravisit::walk_expr(self, ex);
540         }
541         fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
542             debug!("find_existential_constraints: visiting {:?}", it);
543             let def_id = self.tcx.hir().local_def_id(it.hir_id);
544             // The opaque type itself or its children are not within its reveal scope.
545             if def_id.to_def_id() != self.def_id {
546                 self.check(def_id);
547                 intravisit::walk_item(self, it);
548             }
549         }
550         fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
551             debug!("find_existential_constraints: visiting {:?}", it);
552             let def_id = self.tcx.hir().local_def_id(it.hir_id);
553             // The opaque type itself or its children are not within its reveal scope.
554             if def_id.to_def_id() != self.def_id {
555                 self.check(def_id);
556                 intravisit::walk_impl_item(self, it);
557             }
558         }
559         fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
560             debug!("find_existential_constraints: visiting {:?}", it);
561             let def_id = self.tcx.hir().local_def_id(it.hir_id);
562             self.check(def_id);
563             intravisit::walk_trait_item(self, it);
564         }
565     }
566
567     let hir_id = tcx.hir().as_local_hir_id(def_id);
568     let scope = tcx.hir().get_defining_scope(hir_id);
569     let mut locator = ConstraintLocator { def_id: def_id.to_def_id(), tcx, found: None };
570
571     debug!("find_opaque_ty_constraints: scope={:?}", scope);
572
573     if scope == hir::CRATE_HIR_ID {
574         intravisit::walk_crate(&mut locator, tcx.hir().krate());
575     } else {
576         debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope));
577         match tcx.hir().get(scope) {
578             // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
579             // This allows our visitor to process the defining item itself, causing
580             // it to pick up any 'sibling' defining uses.
581             //
582             // For example, this code:
583             // ```
584             // fn foo() {
585             //     type Blah = impl Debug;
586             //     let my_closure = || -> Blah { true };
587             // }
588             // ```
589             //
590             // requires us to explicitly process `foo()` in order
591             // to notice the defining usage of `Blah`.
592             Node::Item(ref it) => locator.visit_item(it),
593             Node::ImplItem(ref it) => locator.visit_impl_item(it),
594             Node::TraitItem(ref it) => locator.visit_trait_item(it),
595             other => bug!("{:?} is not a valid scope for an opaque type item", other),
596         }
597     }
598
599     match locator.found {
600         Some((_, ty)) => ty,
601         None => {
602             let span = tcx.def_span(def_id);
603             tcx.sess.span_err(span, "could not find defining uses");
604             tcx.ty_error()
605         }
606     }
607 }
608
609 /// Retrieve the inferred concrete type for let position impl trait.
610 ///
611 /// This is different to other kinds of impl trait because:
612 ///
613 /// 1. We know which function contains the defining use (the function that
614 ///    contains the let statement)
615 /// 2. We do not currently allow (free) lifetimes in the return type. `let`
616 ///    statements in some statically unreachable code are removed from the MIR
617 ///    by the time we borrow check, and it's not clear how we should handle
618 ///    those.
619 fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty<'_> {
620     let scope = tcx.hir().get_defining_scope(tcx.hir().as_local_hir_id(opaque_ty_id));
621     let scope_def_id = tcx.hir().local_def_id(scope);
622
623     let opaque_ty_def_id = opaque_ty_id.to_def_id();
624
625     let owner_typeck_results = tcx.typeck(scope_def_id);
626     let concrete_ty = owner_typeck_results
627         .concrete_opaque_types
628         .get(&opaque_ty_def_id)
629         .map(|opaque| opaque.concrete_type)
630         .unwrap_or_else(|| {
631             tcx.sess.delay_span_bug(
632                 DUMMY_SP,
633                 &format!(
634                     "owner {:?} has no opaque type for {:?} in its typeck results",
635                     scope_def_id, opaque_ty_id
636                 ),
637             );
638             if let Some(ErrorReported) = owner_typeck_results.tainted_by_errors {
639                 // Some error in the owner fn prevented us from populating the
640                 // `concrete_opaque_types` table.
641                 tcx.ty_error()
642             } else {
643                 // We failed to resolve the opaque type or it resolves to
644                 // itself. Return the non-revealed type, which should result in
645                 // E0720.
646                 tcx.mk_opaque(
647                     opaque_ty_def_id,
648                     InternalSubsts::identity_for_item(tcx, opaque_ty_def_id),
649                 )
650             }
651         });
652     debug!("concrete_ty = {:?}", concrete_ty);
653     if concrete_ty.has_erased_regions() {
654         // FIXME(impl_trait_in_bindings) Handle this case.
655         tcx.sess.span_fatal(
656             tcx.hir().span(tcx.hir().as_local_hir_id(opaque_ty_id)),
657             "lifetimes in impl Trait types in bindings are not currently supported",
658         );
659     }
660     concrete_ty
661 }
662
663 fn infer_placeholder_type(
664     tcx: TyCtxt<'_>,
665     def_id: LocalDefId,
666     body_id: hir::BodyId,
667     span: Span,
668     item_ident: Ident,
669 ) -> Ty<'_> {
670     let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id);
671
672     // If this came from a free `const` or `static mut?` item,
673     // then the user may have written e.g. `const A = 42;`.
674     // In this case, the parser has stashed a diagnostic for
675     // us to improve in typeck so we do that now.
676     match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) {
677         Some(mut err) => {
678             // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
679             // We are typeck and have the real type, so remove that and suggest the actual type.
680             err.suggestions.clear();
681             err.span_suggestion(
682                 span,
683                 "provide a type for the item",
684                 format!("{}: {}", item_ident, ty),
685                 Applicability::MachineApplicable,
686             )
687             .emit();
688         }
689         None => {
690             let mut diag = bad_placeholder_type(tcx, vec![span]);
691             if !matches!(ty.kind, ty::Error(_)) {
692                 diag.span_suggestion(
693                     span,
694                     "replace `_` with the correct type",
695                     ty.to_string(),
696                     Applicability::MaybeIncorrect,
697                 );
698             }
699             diag.emit();
700         }
701     }
702
703     // Typeck doesn't expect erased regions to be returned from `type_of`.
704     tcx.fold_regions(&ty, &mut false, |r, _| match r {
705         ty::ReErased => tcx.lifetimes.re_static,
706         _ => r,
707     })
708 }
709
710 fn report_assoc_ty_on_inherent_impl(tcx: TyCtxt<'_>, span: Span) {
711     struct_span_err!(
712         tcx.sess,
713         span,
714         E0202,
715         "associated types are not yet supported in inherent impls (see #8995)"
716     )
717     .emit();
718 }