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