]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/collect/type_of.rs
Stabilize File::options()
[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                     tcx.typeck(def_id).node_type(anon_const.hir_id)
498                 }
499
500                 Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
501                 | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
502                     if asm.operands.iter().any(|(op, _op_sp)| match op {
503                         hir::InlineAsmOperand::Const { anon_const } => anon_const.hir_id == hir_id,
504                         _ => false,
505                     }) =>
506                 {
507                     tcx.typeck(def_id).node_type(hir_id)
508                 }
509
510                 Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => tcx
511                     .adt_def(tcx.hir().get_parent_did(hir_id).to_def_id())
512                     .repr
513                     .discr_type()
514                     .to_ty(tcx),
515
516                 Node::GenericParam(&GenericParam {
517                     hir_id: param_hir_id,
518                     kind: GenericParamKind::Const { default: Some(ct), .. },
519                     ..
520                 }) if ct.hir_id == hir_id => tcx.type_of(tcx.hir().local_def_id(param_hir_id)),
521
522                 x => tcx.ty_error_with_message(
523                     DUMMY_SP,
524                     &format!("unexpected const parent in type_of(): {:?}", x),
525                 ),
526             }
527         }
528
529         Node::GenericParam(param) => match &param.kind {
530             GenericParamKind::Type { default: Some(ty), .. }
531             | GenericParamKind::Const { ty, .. } => icx.to_ty(ty),
532             x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
533         },
534
535         x => {
536             bug!("unexpected sort of node in type_of(): {:?}", x);
537         }
538     }
539 }
540
541 #[instrument(skip(tcx), level = "debug")]
542 /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
543 /// laid for "higher-order pattern unification".
544 /// This ensures that inference is tractable.
545 /// In particular, definitions of opaque types can only use other generics as arguments,
546 /// and they cannot repeat an argument. Example:
547 ///
548 /// ```rust
549 /// type Foo<A, B> = impl Bar<A, B>;
550 ///
551 /// // Okay -- `Foo` is applied to two distinct, generic types.
552 /// fn a<T, U>() -> Foo<T, U> { .. }
553 ///
554 /// // Not okay -- `Foo` is applied to `T` twice.
555 /// fn b<T>() -> Foo<T, T> { .. }
556 ///
557 /// // Not okay -- `Foo` is applied to a non-generic type.
558 /// fn b<T>() -> Foo<T, u32> { .. }
559 /// ```
560 ///
561 fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
562     use rustc_hir::{Expr, ImplItem, Item, TraitItem};
563
564     struct ConstraintLocator<'tcx> {
565         tcx: TyCtxt<'tcx>,
566
567         /// def_id of the opaque type whose defining uses are being checked
568         def_id: DefId,
569
570         /// as we walk the defining uses, we are checking that all of them
571         /// define the same hidden type. This variable is set to `Some`
572         /// with the first type that we find, and then later types are
573         /// checked against it (we also carry the span of that first
574         /// type).
575         found: Option<(Span, Ty<'tcx>)>,
576     }
577
578     impl ConstraintLocator<'_> {
579         #[instrument(skip(self), level = "debug")]
580         fn check(&mut self, def_id: LocalDefId) {
581             // Don't try to check items that cannot possibly constrain the type.
582             if !self.tcx.has_typeck_results(def_id) {
583                 debug!("no constraint: no typeck results");
584                 return;
585             }
586             // Calling `mir_borrowck` can lead to cycle errors through
587             // const-checking, avoid calling it if we don't have to.
588             if !self.tcx.typeck(def_id).concrete_opaque_types.contains(&self.def_id) {
589                 debug!("no constraints in typeck results");
590                 return;
591             }
592             // Use borrowck to get the type with unerased regions.
593             let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
594             debug!(?concrete_opaque_types);
595             for (opaque_type_key, concrete_type) in concrete_opaque_types {
596                 if opaque_type_key.def_id != self.def_id {
597                     // Ignore constraints for other opaque types.
598                     continue;
599                 }
600
601                 debug!(?concrete_type, ?opaque_type_key.substs, "found constraint");
602
603                 // FIXME(oli-obk): trace the actual span from inference to improve errors.
604                 let span = self.tcx.def_span(def_id);
605
606                 if let Some((prev_span, prev_ty)) = self.found {
607                     if *concrete_type != prev_ty && !(*concrete_type, prev_ty).references_error() {
608                         debug!(?span);
609                         // Found different concrete types for the opaque type.
610                         let mut err = self.tcx.sess.struct_span_err(
611                             span,
612                             "concrete type differs from previous defining opaque type use",
613                         );
614                         err.span_label(
615                             span,
616                             format!("expected `{}`, got `{}`", prev_ty, concrete_type),
617                         );
618                         err.span_note(prev_span, "previous use here");
619                         err.emit();
620                     }
621                 } else {
622                     self.found = Some((span, concrete_type));
623                 }
624             }
625         }
626     }
627
628     impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
629         type Map = Map<'tcx>;
630
631         fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
632             intravisit::NestedVisitorMap::All(self.tcx.hir())
633         }
634         fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
635             if let hir::ExprKind::Closure(..) = ex.kind {
636                 let def_id = self.tcx.hir().local_def_id(ex.hir_id);
637                 self.check(def_id);
638             }
639             intravisit::walk_expr(self, ex);
640         }
641         fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
642             debug!("find_existential_constraints: visiting {:?}", it);
643             // The opaque type itself or its children are not within its reveal scope.
644             if it.def_id.to_def_id() != self.def_id {
645                 self.check(it.def_id);
646                 intravisit::walk_item(self, it);
647             }
648         }
649         fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
650             debug!("find_existential_constraints: visiting {:?}", it);
651             // The opaque type itself or its children are not within its reveal scope.
652             if it.def_id.to_def_id() != self.def_id {
653                 self.check(it.def_id);
654                 intravisit::walk_impl_item(self, it);
655             }
656         }
657         fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
658             debug!("find_existential_constraints: visiting {:?}", it);
659             self.check(it.def_id);
660             intravisit::walk_trait_item(self, it);
661         }
662     }
663
664     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
665     let scope = tcx.hir().get_defining_scope(hir_id);
666     let mut locator = ConstraintLocator { def_id: def_id.to_def_id(), tcx, found: None };
667
668     debug!("find_opaque_ty_constraints: scope={:?}", scope);
669
670     if scope == hir::CRATE_HIR_ID {
671         tcx.hir().walk_toplevel_module(&mut locator);
672     } else {
673         debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope));
674         match tcx.hir().get(scope) {
675             // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
676             // This allows our visitor to process the defining item itself, causing
677             // it to pick up any 'sibling' defining uses.
678             //
679             // For example, this code:
680             // ```
681             // fn foo() {
682             //     type Blah = impl Debug;
683             //     let my_closure = || -> Blah { true };
684             // }
685             // ```
686             //
687             // requires us to explicitly process `foo()` in order
688             // to notice the defining usage of `Blah`.
689             Node::Item(it) => locator.visit_item(it),
690             Node::ImplItem(it) => locator.visit_impl_item(it),
691             Node::TraitItem(it) => locator.visit_trait_item(it),
692             other => bug!("{:?} is not a valid scope for an opaque type item", other),
693         }
694     }
695
696     match locator.found {
697         Some((_, ty)) => ty,
698         None => {
699             let span = tcx.def_span(def_id);
700             tcx.sess.span_err(span, "could not find defining uses");
701             tcx.ty_error()
702         }
703     }
704 }
705
706 fn infer_placeholder_type<'a>(
707     tcx: TyCtxt<'a>,
708     def_id: LocalDefId,
709     body_id: hir::BodyId,
710     span: Span,
711     item_ident: Ident,
712     kind: &'static str,
713 ) -> Ty<'a> {
714     // Attempts to make the type nameable by turning FnDefs into FnPtrs.
715     struct MakeNameable<'tcx> {
716         success: bool,
717         tcx: TyCtxt<'tcx>,
718     }
719
720     impl<'tcx> MakeNameable<'tcx> {
721         fn new(tcx: TyCtxt<'tcx>) -> Self {
722             MakeNameable { success: true, tcx }
723         }
724     }
725
726     impl TypeFolder<'tcx> for MakeNameable<'tcx> {
727         fn tcx(&self) -> TyCtxt<'tcx> {
728             self.tcx
729         }
730
731         fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
732             if !self.success {
733                 return ty;
734             }
735
736             match ty.kind() {
737                 ty::FnDef(def_id, _) => self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id)),
738                 // FIXME: non-capturing closures should also suggest a function pointer
739                 ty::Closure(..) | ty::Generator(..) => {
740                     self.success = false;
741                     ty
742                 }
743                 _ => ty.super_fold_with(self),
744             }
745         }
746     }
747
748     let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id);
749
750     // If this came from a free `const` or `static mut?` item,
751     // then the user may have written e.g. `const A = 42;`.
752     // In this case, the parser has stashed a diagnostic for
753     // us to improve in typeck so we do that now.
754     match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) {
755         Some(mut err) => {
756             if !ty.references_error() {
757                 // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
758                 // We are typeck and have the real type, so remove that and suggest the actual type.
759                 err.suggestions.clear();
760
761                 // Suggesting unnameable types won't help.
762                 let mut mk_nameable = MakeNameable::new(tcx);
763                 let ty = mk_nameable.fold_ty(ty);
764                 let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
765                 if let Some(sugg_ty) = sugg_ty {
766                     err.span_suggestion(
767                         span,
768                         &format!("provide a type for the {item}", item = kind),
769                         format!("{}: {}", item_ident, sugg_ty),
770                         Applicability::MachineApplicable,
771                     );
772                 } else {
773                     err.span_note(
774                         tcx.hir().body(body_id).value.span,
775                         &format!("however, the inferred type `{}` cannot be named", ty),
776                     );
777                 }
778             }
779
780             err.emit();
781         }
782         None => {
783             let mut diag = bad_placeholder_type(tcx, vec![span], kind);
784
785             if !ty.references_error() {
786                 let mut mk_nameable = MakeNameable::new(tcx);
787                 let ty = mk_nameable.fold_ty(ty);
788                 let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
789                 if let Some(sugg_ty) = sugg_ty {
790                     diag.span_suggestion(
791                         span,
792                         "replace with the correct type",
793                         sugg_ty.to_string(),
794                         Applicability::MaybeIncorrect,
795                     );
796                 } else {
797                     diag.span_note(
798                         tcx.hir().body(body_id).value.span,
799                         &format!("however, the inferred type `{}` cannot be named", ty),
800                     );
801                 }
802             }
803
804             diag.emit();
805         }
806     }
807
808     // Typeck doesn't expect erased regions to be returned from `type_of`.
809     tcx.fold_regions(ty, &mut false, |r, _| match r {
810         ty::ReErased => tcx.lifetimes.re_static,
811         _ => r,
812     })
813 }
814
815 fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {
816     if !tcx.features().inherent_associated_types {
817         use rustc_session::parse::feature_err;
818         use rustc_span::symbol::sym;
819         feature_err(
820             &tcx.sess.parse_sess,
821             sym::inherent_associated_types,
822             span,
823             "inherent associated types are unstable",
824         )
825         .emit();
826     }
827 }