]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/collect/type_of.rs
remove unnecessary fixme
[rust.git] / compiler / rustc_typeck / src / collect / type_of.rs
1 use rustc_errors::{Applicability, ErrorReported, StashKey};
2 use rustc_hir as hir;
3 use rustc_hir::def::{DefKind, Res};
4 use rustc_hir::def_id::{DefId, LocalDefId};
5 use rustc_hir::intravisit;
6 use rustc_hir::intravisit::Visitor;
7 use rustc_hir::{HirId, Node};
8 use rustc_middle::hir::nested_filter;
9 use rustc_middle::ty::subst::InternalSubsts;
10 use rustc_middle::ty::util::IntTypeExt;
11 use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder};
12 use rustc_span::symbol::Ident;
13 use rustc_span::{Span, DUMMY_SP};
14
15 use super::ItemCtxt;
16 use super::{bad_placeholder, is_suggestable_infer_ty};
17
18 /// Computes the relevant generic parameter for a potential generic const argument.
19 ///
20 /// This should be called using the query `tcx.opt_const_param_of`.
21 #[instrument(level = "debug", skip(tcx))]
22 pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
23     use hir::*;
24     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
25
26     match tcx.hir().get(hir_id) {
27         Node::AnonConst(_) => (),
28         _ => return None,
29     };
30
31     let parent_node_id = tcx.hir().get_parent_node(hir_id);
32     let parent_node = tcx.hir().get(parent_node_id);
33
34     let (generics, arg_idx) = match parent_node {
35         // This match arm is for when the def_id appears in a GAT whose
36         // path can't be resolved without typechecking e.g.
37         //
38         // trait Foo {
39         //   type Assoc<const N: usize>;
40         //   fn foo() -> Self::Assoc<3>;
41         // }
42         //
43         // In the above code we would call this query with the def_id of 3 and
44         // the parent_node we match on would be the hir node for Self::Assoc<3>
45         //
46         // `Self::Assoc<3>` cant be resolved without typchecking here as we
47         // didnt write <Self as Foo>::Assoc<3>. If we did then another match
48         // arm would handle this.
49         //
50         // I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU
51         Node::Ty(hir_ty @ Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => {
52             // Find the Item containing the associated type so we can create an ItemCtxt.
53             // Using the ItemCtxt convert the HIR for the unresolved assoc type into a
54             // ty which is a fully resolved projection.
55             // For the code example above, this would mean converting Self::Assoc<3>
56             // into a ty::Projection(<Self as Foo>::Assoc<3>)
57             let item_hir_id = tcx
58                 .hir()
59                 .parent_iter(hir_id)
60                 .filter(|(_, node)| matches!(node, Node::Item(_)))
61                 .map(|(id, _)| id)
62                 .next()
63                 .unwrap();
64             let item_did = tcx.hir().local_def_id(item_hir_id).to_def_id();
65             let item_ctxt = &ItemCtxt::new(tcx, item_did) as &dyn crate::astconv::AstConv<'_>;
66             let ty = item_ctxt.ast_ty_to_ty(hir_ty);
67
68             // Iterate through the generics of the projection to find the one that corresponds to
69             // the def_id that this query was called with. We filter to only const args here as a
70             // precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
71             // but it can't hurt to be safe ^^
72             if let ty::Projection(projection) = ty.kind() {
73                 let generics = tcx.generics_of(projection.item_def_id);
74
75                 let arg_index = segment
76                     .args
77                     .and_then(|args| {
78                         args.args
79                             .iter()
80                             .filter(|arg| arg.is_ty_or_const())
81                             .position(|arg| arg.id() == hir_id)
82                     })
83                     .unwrap_or_else(|| {
84                         bug!("no arg matching AnonConst in segment");
85                     });
86
87                 (generics, arg_index)
88             } else {
89                 // I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
90                 tcx.sess.delay_span_bug(
91                     tcx.def_span(def_id),
92                     "unexpected non-GAT usage of an anon const",
93                 );
94                 return None;
95             }
96         }
97         Node::Expr(&Expr {
98             kind:
99                 ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
100             ..
101         }) => {
102             let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id));
103             let tables = tcx.typeck(body_owner);
104             // This may fail in case the method/path does not actually exist.
105             // As there is no relevant param for `def_id`, we simply return
106             // `None` here.
107             let type_dependent_def = tables.type_dependent_def_id(parent_node_id)?;
108             let idx = segment
109                 .args
110                 .and_then(|args| {
111                     args.args
112                         .iter()
113                         .filter(|arg| arg.is_ty_or_const())
114                         .position(|arg| arg.id() == hir_id)
115                 })
116                 .unwrap_or_else(|| {
117                     bug!("no arg matching AnonConst in segment");
118                 });
119
120             (tcx.generics_of(type_dependent_def), idx)
121         }
122
123         Node::Ty(&Ty { kind: TyKind::Path(_), .. })
124         | Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. })
125         | Node::TraitRef(..)
126         | Node::Pat(_) => {
127             let path = match parent_node {
128                 Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
129                 | Node::TraitRef(&TraitRef { path, .. }) => &*path,
130                 Node::Expr(&Expr {
131                     kind:
132                         ExprKind::Path(QPath::Resolved(_, path))
133                         | ExprKind::Struct(&QPath::Resolved(_, path), ..),
134                     ..
135                 }) => {
136                     let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id));
137                     let _tables = tcx.typeck(body_owner);
138                     &*path
139                 }
140                 Node::Pat(pat) => {
141                     if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
142                         path
143                     } else {
144                         tcx.sess.delay_span_bug(
145                             tcx.def_span(def_id),
146                             &format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
147                         );
148                         return None;
149                     }
150                 }
151                 _ => {
152                     tcx.sess.delay_span_bug(
153                         tcx.def_span(def_id),
154                         &format!("unexpected const parent path {:?}", parent_node),
155                     );
156                     return None;
157                 }
158             };
159
160             // We've encountered an `AnonConst` in some path, so we need to
161             // figure out which generic parameter it corresponds to and return
162             // the relevant type.
163             let filtered = path
164                 .segments
165                 .iter()
166                 .filter_map(|seg| seg.args.map(|args| (args.args, seg)))
167                 .find_map(|(args, seg)| {
168                     args.iter()
169                         .filter(|arg| arg.is_ty_or_const())
170                         .position(|arg| arg.id() == hir_id)
171                         .map(|index| (index, seg))
172                 });
173             let (arg_index, segment) = match filtered {
174                 None => {
175                     tcx.sess
176                         .delay_span_bug(tcx.def_span(def_id), "no arg matching AnonConst in path");
177                     return None;
178                 }
179                 Some(inner) => inner,
180             };
181
182             // Try to use the segment resolution if it is valid, otherwise we
183             // default to the path resolution.
184             let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
185             use def::CtorOf;
186             let generics = match res {
187                 Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => tcx
188                     .generics_of(tcx.parent(def_id).and_then(|def_id| tcx.parent(def_id)).unwrap()),
189                 Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => {
190                     tcx.generics_of(tcx.parent(def_id).unwrap())
191                 }
192                 // Other `DefKind`s don't have generics and would ICE when calling
193                 // `generics_of`.
194                 Res::Def(
195                     DefKind::Struct
196                     | DefKind::Union
197                     | DefKind::Enum
198                     | DefKind::Trait
199                     | DefKind::OpaqueTy
200                     | DefKind::TyAlias
201                     | DefKind::ForeignTy
202                     | DefKind::TraitAlias
203                     | DefKind::AssocTy
204                     | DefKind::Fn
205                     | DefKind::AssocFn
206                     | DefKind::AssocConst
207                     | DefKind::Impl,
208                     def_id,
209                 ) => tcx.generics_of(def_id),
210                 Res::Err => {
211                     tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err");
212                     return None;
213                 }
214                 _ => {
215                     // If the user tries to specify generics on a type that does not take them,
216                     // e.g. `usize<T>`, we may hit this branch, in which case we treat it as if
217                     // no arguments have been passed. An error should already have been emitted.
218                     tcx.sess.delay_span_bug(
219                         tcx.def_span(def_id),
220                         &format!("unexpected anon const res {:?} in path: {:?}", res, path),
221                     );
222                     return None;
223                 }
224             };
225
226             (generics, arg_index)
227         }
228         _ => return None,
229     };
230
231     debug!(?parent_node);
232     debug!(?generics, ?arg_idx);
233     generics
234         .params
235         .iter()
236         .filter(|param| param.kind.is_ty_or_const())
237         .nth(match generics.has_self && generics.parent.is_none() {
238             true => arg_idx + 1,
239             false => arg_idx,
240         })
241         .and_then(|param| match param.kind {
242             ty::GenericParamDefKind::Const { .. } => {
243                 debug!(?param);
244                 Some(param.def_id)
245             }
246             _ => None,
247         })
248 }
249
250 fn get_path_containing_arg_in_pat<'hir>(
251     pat: &'hir hir::Pat<'hir>,
252     arg_id: HirId,
253 ) -> Option<&'hir hir::Path<'hir>> {
254     use hir::*;
255
256     let is_arg_in_path = |p: &hir::Path<'_>| {
257         p.segments
258             .iter()
259             .filter_map(|seg| seg.args)
260             .flat_map(|args| args.args)
261             .any(|arg| arg.id() == arg_id)
262     };
263     let mut arg_path = None;
264     pat.walk(|pat| match pat.kind {
265         PatKind::Struct(QPath::Resolved(_, path), _, _)
266         | PatKind::TupleStruct(QPath::Resolved(_, path), _, _)
267         | PatKind::Path(QPath::Resolved(_, path))
268             if is_arg_in_path(path) =>
269         {
270             arg_path = Some(path);
271             false
272         }
273         _ => true,
274     });
275     arg_path
276 }
277
278 pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
279     let def_id = def_id.expect_local();
280     use rustc_hir::*;
281
282     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
283
284     let icx = ItemCtxt::new(tcx, def_id.to_def_id());
285
286     match tcx.hir().get(hir_id) {
287         Node::TraitItem(item) => match item.kind {
288             TraitItemKind::Fn(..) => {
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             TraitItemKind::Const(ty, body_id) => body_id
293                 .and_then(|body_id| {
294                     if is_suggestable_infer_ty(ty) {
295                         Some(infer_placeholder_type(
296                             tcx, def_id, body_id, ty.span, item.ident, "constant",
297                         ))
298                     } else {
299                         None
300                     }
301                 })
302                 .unwrap_or_else(|| icx.to_ty(ty)),
303             TraitItemKind::Type(_, Some(ty)) => icx.to_ty(ty),
304             TraitItemKind::Type(_, None) => {
305                 span_bug!(item.span, "associated type missing default");
306             }
307         },
308
309         Node::ImplItem(item) => match item.kind {
310             ImplItemKind::Fn(..) => {
311                 let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
312                 tcx.mk_fn_def(def_id.to_def_id(), substs)
313             }
314             ImplItemKind::Const(ty, body_id) => {
315                 if is_suggestable_infer_ty(ty) {
316                     infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant")
317                 } else {
318                     icx.to_ty(ty)
319                 }
320             }
321             ImplItemKind::TyAlias(ty) => {
322                 if tcx.impl_trait_ref(tcx.hir().get_parent_item(hir_id)).is_none() {
323                     check_feature_inherent_assoc_ty(tcx, item.span);
324                 }
325
326                 icx.to_ty(ty)
327             }
328         },
329
330         Node::Item(item) => {
331             match item.kind {
332                 ItemKind::Static(ty, .., body_id) => {
333                     if is_suggestable_infer_ty(ty) {
334                         infer_placeholder_type(
335                             tcx,
336                             def_id,
337                             body_id,
338                             ty.span,
339                             item.ident,
340                             "static variable",
341                         )
342                     } else {
343                         icx.to_ty(ty)
344                     }
345                 }
346                 ItemKind::Const(ty, body_id) => {
347                     if is_suggestable_infer_ty(ty) {
348                         infer_placeholder_type(
349                             tcx, def_id, body_id, ty.span, item.ident, "constant",
350                         )
351                     } else {
352                         icx.to_ty(ty)
353                     }
354                 }
355                 ItemKind::TyAlias(self_ty, _)
356                 | ItemKind::Impl(hir::Impl { self_ty, .. }) => icx.to_ty(self_ty),
357                 ItemKind::Fn(..) => {
358                     let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
359                     tcx.mk_fn_def(def_id.to_def_id(), substs)
360                 }
361                 ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
362                     let def = tcx.adt_def(def_id);
363                     let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
364                     tcx.mk_adt(def, substs)
365                 }
366                 ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
367                     find_opaque_ty_constraints(tcx, def_id)
368                 }
369                 // Opaque types desugared from `impl Trait`.
370                 ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), .. }) => {
371                     let concrete_ty = tcx
372                         .mir_borrowck(owner)
373                         .concrete_opaque_types
374                         .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id())
375                         .copied()
376                         .unwrap_or_else(|| {
377                             tcx.sess.delay_span_bug(
378                                 DUMMY_SP,
379                                 &format!(
380                                     "owner {:?} has no opaque type for {:?} in its typeck results",
381                                     owner, def_id,
382                                 ),
383                             );
384                             if let Some(ErrorReported) =
385                                 tcx.typeck(owner).tainted_by_errors
386                             {
387                                 // Some error in the
388                                 // owner fn prevented us from populating
389                                 // the `concrete_opaque_types` table.
390                                 tcx.ty_error()
391                             } else {
392                                 // We failed to resolve the opaque type or it
393                                 // resolves to itself. Return the non-revealed
394                                 // type, which should result in E0720.
395                                 tcx.mk_opaque(
396                                     def_id.to_def_id(),
397                                     InternalSubsts::identity_for_item(tcx, def_id.to_def_id()),
398                                 )
399                             }
400                         });
401                     debug!("concrete_ty = {:?}", concrete_ty);
402                     concrete_ty
403                 }
404                 ItemKind::Trait(..)
405                 | ItemKind::TraitAlias(..)
406                 | ItemKind::Macro(..)
407                 | ItemKind::Mod(..)
408                 | ItemKind::ForeignMod { .. }
409                 | ItemKind::GlobalAsm(..)
410                 | ItemKind::ExternCrate(..)
411                 | ItemKind::Use(..) => {
412                     span_bug!(
413                         item.span,
414                         "compute_type_of_item: unexpected item type: {:?}",
415                         item.kind
416                     );
417                 }
418             }
419         }
420
421         Node::ForeignItem(foreign_item) => match foreign_item.kind {
422             ForeignItemKind::Fn(..) => {
423                 let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
424                 tcx.mk_fn_def(def_id.to_def_id(), substs)
425             }
426             ForeignItemKind::Static(t, _) => icx.to_ty(t),
427             ForeignItemKind::Type => tcx.mk_foreign(def_id.to_def_id()),
428         },
429
430         Node::Ctor(&ref def) | Node::Variant(Variant { data: ref def, .. }) => match *def {
431             VariantData::Unit(..) | VariantData::Struct(..) => {
432                 tcx.type_of(tcx.hir().get_parent_item(hir_id))
433             }
434             VariantData::Tuple(..) => {
435                 let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
436                 tcx.mk_fn_def(def_id.to_def_id(), substs)
437             }
438         },
439
440         Node::Field(field) => icx.to_ty(field.ty),
441
442         Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => tcx.typeck(def_id).node_type(hir_id),
443
444         Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => {
445             // We defer to `type_of` of the corresponding parameter
446             // for generic arguments.
447             tcx.type_of(param)
448         }
449
450         Node::AnonConst(_) => {
451             let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
452             match parent_node {
453                 Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
454                 | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
455                     if constant.hir_id() == hir_id =>
456                 {
457                     tcx.types.usize
458                 }
459                 Node::Ty(&Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => {
460                     tcx.typeck(def_id).node_type(e.hir_id)
461                 }
462
463                 Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. })
464                     if anon_const.hir_id == hir_id =>
465                 {
466                     let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
467                     substs.as_inline_const().ty()
468                 }
469
470                 Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
471                 | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
472                     if asm.operands.iter().any(|(op, _op_sp)| match op {
473                         hir::InlineAsmOperand::Const { anon_const } => anon_const.hir_id == hir_id,
474                         _ => false,
475                     }) =>
476                 {
477                     tcx.typeck(def_id).node_type(hir_id)
478                 }
479
480                 Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => tcx
481                     .adt_def(tcx.hir().get_parent_item(hir_id))
482                     .repr
483                     .discr_type()
484                     .to_ty(tcx),
485
486                 Node::GenericParam(&GenericParam {
487                     hir_id: param_hir_id,
488                     kind: GenericParamKind::Const { default: Some(ct), .. },
489                     ..
490                 }) if ct.hir_id == hir_id => tcx.type_of(tcx.hir().local_def_id(param_hir_id)),
491
492                 x => tcx.ty_error_with_message(
493                     DUMMY_SP,
494                     &format!("unexpected const parent in type_of(): {:?}", x),
495                 ),
496             }
497         }
498
499         Node::GenericParam(param) => match &param.kind {
500             GenericParamKind::Type { default: Some(ty), .. }
501             | GenericParamKind::Const { ty, .. } => icx.to_ty(ty),
502             x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
503         },
504
505         x => {
506             bug!("unexpected sort of node in type_of(): {:?}", x);
507         }
508     }
509 }
510
511 #[instrument(skip(tcx), level = "debug")]
512 /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
513 /// laid for "higher-order pattern unification".
514 /// This ensures that inference is tractable.
515 /// In particular, definitions of opaque types can only use other generics as arguments,
516 /// and they cannot repeat an argument. Example:
517 ///
518 /// ```rust
519 /// type Foo<A, B> = impl Bar<A, B>;
520 ///
521 /// // Okay -- `Foo` is applied to two distinct, generic types.
522 /// fn a<T, U>() -> Foo<T, U> { .. }
523 ///
524 /// // Not okay -- `Foo` is applied to `T` twice.
525 /// fn b<T>() -> Foo<T, T> { .. }
526 ///
527 /// // Not okay -- `Foo` is applied to a non-generic type.
528 /// fn b<T>() -> Foo<T, u32> { .. }
529 /// ```
530 ///
531 fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
532     use rustc_hir::{Expr, ImplItem, Item, TraitItem};
533
534     struct ConstraintLocator<'tcx> {
535         tcx: TyCtxt<'tcx>,
536
537         /// def_id of the opaque type whose defining uses are being checked
538         def_id: DefId,
539
540         /// as we walk the defining uses, we are checking that all of them
541         /// define the same hidden type. This variable is set to `Some`
542         /// with the first type that we find, and then later types are
543         /// checked against it (we also carry the span of that first
544         /// type).
545         found: Option<(Span, Ty<'tcx>)>,
546     }
547
548     impl ConstraintLocator<'_> {
549         #[instrument(skip(self), level = "debug")]
550         fn check(&mut self, def_id: LocalDefId) {
551             // Don't try to check items that cannot possibly constrain the type.
552             if !self.tcx.has_typeck_results(def_id) {
553                 debug!("no constraint: no typeck results");
554                 return;
555             }
556             // Calling `mir_borrowck` can lead to cycle errors through
557             // const-checking, avoid calling it if we don't have to.
558             if !self.tcx.typeck(def_id).concrete_opaque_types.contains(&self.def_id) {
559                 debug!("no constraints in typeck results");
560                 return;
561             }
562             // Use borrowck to get the type with unerased regions.
563             let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
564             debug!(?concrete_opaque_types);
565             for (opaque_type_key, concrete_type) in concrete_opaque_types {
566                 if opaque_type_key.def_id != self.def_id {
567                     // Ignore constraints for other opaque types.
568                     continue;
569                 }
570
571                 debug!(?concrete_type, ?opaque_type_key.substs, "found constraint");
572
573                 // FIXME(oli-obk): trace the actual span from inference to improve errors.
574                 let span = self.tcx.def_span(def_id);
575
576                 if let Some((prev_span, prev_ty)) = self.found {
577                     if *concrete_type != prev_ty && !(*concrete_type, prev_ty).references_error() {
578                         debug!(?span);
579                         // Found different concrete types for the opaque type.
580                         let mut err = self.tcx.sess.struct_span_err(
581                             span,
582                             "concrete type differs from previous defining opaque type use",
583                         );
584                         err.span_label(
585                             span,
586                             format!("expected `{}`, got `{}`", prev_ty, concrete_type),
587                         );
588                         err.span_note(prev_span, "previous use here");
589                         err.emit();
590                     }
591                 } else {
592                     self.found = Some((span, concrete_type));
593                 }
594             }
595         }
596     }
597
598     impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
599         type NestedFilter = nested_filter::All;
600
601         fn nested_visit_map(&mut self) -> Self::Map {
602             self.tcx.hir()
603         }
604         fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
605             if let hir::ExprKind::Closure(..) = ex.kind {
606                 let def_id = self.tcx.hir().local_def_id(ex.hir_id);
607                 self.check(def_id);
608             }
609             intravisit::walk_expr(self, ex);
610         }
611         fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
612             debug!("find_existential_constraints: visiting {:?}", it);
613             // The opaque type itself or its children are not within its reveal scope.
614             if it.def_id.to_def_id() != self.def_id {
615                 self.check(it.def_id);
616                 intravisit::walk_item(self, it);
617             }
618         }
619         fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
620             debug!("find_existential_constraints: visiting {:?}", it);
621             // The opaque type itself or its children are not within its reveal scope.
622             if it.def_id.to_def_id() != self.def_id {
623                 self.check(it.def_id);
624                 intravisit::walk_impl_item(self, it);
625             }
626         }
627         fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
628             debug!("find_existential_constraints: visiting {:?}", it);
629             self.check(it.def_id);
630             intravisit::walk_trait_item(self, it);
631         }
632     }
633
634     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
635     let scope = tcx.hir().get_defining_scope(hir_id);
636     let mut locator = ConstraintLocator { def_id: def_id.to_def_id(), tcx, found: None };
637
638     debug!("find_opaque_ty_constraints: scope={:?}", scope);
639
640     if scope == hir::CRATE_HIR_ID {
641         tcx.hir().walk_toplevel_module(&mut locator);
642     } else {
643         debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope));
644         match tcx.hir().get(scope) {
645             // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
646             // This allows our visitor to process the defining item itself, causing
647             // it to pick up any 'sibling' defining uses.
648             //
649             // For example, this code:
650             // ```
651             // fn foo() {
652             //     type Blah = impl Debug;
653             //     let my_closure = || -> Blah { true };
654             // }
655             // ```
656             //
657             // requires us to explicitly process `foo()` in order
658             // to notice the defining usage of `Blah`.
659             Node::Item(it) => locator.visit_item(it),
660             Node::ImplItem(it) => locator.visit_impl_item(it),
661             Node::TraitItem(it) => locator.visit_trait_item(it),
662             other => bug!("{:?} is not a valid scope for an opaque type item", other),
663         }
664     }
665
666     match locator.found {
667         Some((_, ty)) => ty,
668         None => {
669             let span = tcx.def_span(def_id);
670             tcx.sess.span_err(span, "could not find defining uses");
671             tcx.ty_error()
672         }
673     }
674 }
675
676 fn infer_placeholder_type<'a>(
677     tcx: TyCtxt<'a>,
678     def_id: LocalDefId,
679     body_id: hir::BodyId,
680     span: Span,
681     item_ident: Ident,
682     kind: &'static str,
683 ) -> Ty<'a> {
684     // Attempts to make the type nameable by turning FnDefs into FnPtrs.
685     struct MakeNameable<'tcx> {
686         success: bool,
687         tcx: TyCtxt<'tcx>,
688     }
689
690     impl<'tcx> MakeNameable<'tcx> {
691         fn new(tcx: TyCtxt<'tcx>) -> Self {
692             MakeNameable { success: true, tcx }
693         }
694     }
695
696     impl<'tcx> TypeFolder<'tcx> for MakeNameable<'tcx> {
697         fn tcx(&self) -> TyCtxt<'tcx> {
698             self.tcx
699         }
700
701         fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
702             if !self.success {
703                 return ty;
704             }
705
706             match ty.kind() {
707                 ty::FnDef(def_id, _) => self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id)),
708                 // FIXME: non-capturing closures should also suggest a function pointer
709                 ty::Closure(..) | ty::Generator(..) => {
710                     self.success = false;
711                     ty
712                 }
713                 _ => ty.super_fold_with(self),
714             }
715         }
716     }
717
718     let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id);
719
720     // If this came from a free `const` or `static mut?` item,
721     // then the user may have written e.g. `const A = 42;`.
722     // In this case, the parser has stashed a diagnostic for
723     // us to improve in typeck so we do that now.
724     match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) {
725         Some(mut err) => {
726             if !ty.references_error() {
727                 // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
728                 // We are typeck and have the real type, so remove that and suggest the actual type.
729                 err.suggestions.clear();
730
731                 // Suggesting unnameable types won't help.
732                 let mut mk_nameable = MakeNameable::new(tcx);
733                 let ty = mk_nameable.fold_ty(ty);
734                 let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
735                 if let Some(sugg_ty) = sugg_ty {
736                     err.span_suggestion(
737                         span,
738                         &format!("provide a type for the {item}", item = kind),
739                         format!("{}: {}", item_ident, sugg_ty),
740                         Applicability::MachineApplicable,
741                     );
742                 } else {
743                     err.span_note(
744                         tcx.hir().body(body_id).value.span,
745                         &format!("however, the inferred type `{}` cannot be named", ty),
746                     );
747                 }
748             }
749
750             err.emit();
751         }
752         None => {
753             let mut diag = bad_placeholder(tcx, "type", vec![span], kind);
754
755             if !ty.references_error() {
756                 let mut mk_nameable = MakeNameable::new(tcx);
757                 let ty = mk_nameable.fold_ty(ty);
758                 let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
759                 if let Some(sugg_ty) = sugg_ty {
760                     diag.span_suggestion(
761                         span,
762                         "replace with the correct type",
763                         sugg_ty.to_string(),
764                         Applicability::MaybeIncorrect,
765                     );
766                 } else {
767                     diag.span_note(
768                         tcx.hir().body(body_id).value.span,
769                         &format!("however, the inferred type `{}` cannot be named", ty),
770                     );
771                 }
772             }
773
774             diag.emit();
775         }
776     }
777
778     // Typeck doesn't expect erased regions to be returned from `type_of`.
779     tcx.fold_regions(ty, &mut false, |r, _| match r {
780         ty::ReErased => tcx.lifetimes.re_static,
781         _ => r,
782     })
783 }
784
785 fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {
786     if !tcx.features().inherent_associated_types {
787         use rustc_session::parse::feature_err;
788         use rustc_span::symbol::sym;
789         feature_err(
790             &tcx.sess.parse_sess,
791             sym::inherent_associated_types,
792             span,
793             "inherent associated types are unstable",
794         )
795         .emit();
796     }
797 }