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