2 use crate::traits::error_reporting::InferCtxtExt as _;
3 use crate::traits::TraitEngineExt as _;
4 use rustc_data_structures::fx::FxHashMap;
5 use rustc_hir::def_id::DefId;
6 use rustc_hir::OpaqueTyOrigin;
7 use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
8 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt as _};
9 use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine};
10 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
11 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
12 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt};
15 pub trait InferCtxtExt<'tcx> {
16 fn infer_opaque_definition_from_instantiation(
18 opaque_type_key: OpaqueTypeKey<'tcx>,
19 instantiated_ty: OpaqueHiddenType<'tcx>,
20 origin: OpaqueTyOrigin,
24 impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
25 /// Given the fully resolved, instantiated type for an opaque
26 /// type, i.e., the value of an inference variable like C1 or C2
27 /// (*), computes the "definition type" for an opaque type
28 /// definition -- that is, the inferred value of `Foo1<'x>` or
29 /// `Foo2<'x>` that we would conceptually use in its definition:
30 /// ```ignore (illustrative)
31 /// type Foo1<'x> = impl Bar<'x> = AAA; // <-- this type AAA
32 /// type Foo2<'x> = impl Bar<'x> = BBB; // <-- or this type BBB
33 /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
35 /// Note that these values are defined in terms of a distinct set of
36 /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main
37 /// purpose of this function is to do that translation.
39 /// (*) C1 and C2 were introduced in the comments on
40 /// `register_member_constraints`. Read that comment for more context.
44 /// - `def_id`, the `impl Trait` type
45 /// - `substs`, the substs used to instantiate this opaque type
46 /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
47 /// `opaque_defn.concrete_ty`
48 #[instrument(level = "debug", skip(self))]
49 fn infer_opaque_definition_from_instantiation(
51 opaque_type_key: OpaqueTypeKey<'tcx>,
52 instantiated_ty: OpaqueHiddenType<'tcx>,
53 origin: OpaqueTyOrigin,
55 if self.is_tainted_by_errors() {
56 return self.tcx.ty_error();
59 let OpaqueTypeKey { def_id, substs } = opaque_type_key;
61 // Use substs to build up a reverse map from regions to their
62 // identity mappings. This is necessary because of `impl
63 // Trait` lifetimes are computed by replacing existing
64 // lifetimes with 'static and remapping only those used in the
65 // `impl Trait` return type, resulting in the parameters
67 let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
69 let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
70 substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect();
71 debug!("map = {:#?}", map);
73 // Convert the type from the function into a type valid outside
74 // the function, by replacing invalid regions with 'static,
75 // after producing an error for each of them.
76 let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new(
83 debug!(?definition_ty);
85 if !check_opaque_type_parameter_valid(
91 return self.tcx.ty_error();
94 // Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs`
95 // on stable and we'd break that.
96 if let OpaqueTyOrigin::TyAlias = origin {
97 // This logic duplicates most of `check_opaque_meets_bounds`.
98 // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
99 let param_env = self.tcx.param_env(def_id);
100 let body_id = self.tcx.local_def_id_to_hir_id(def_id.as_local().unwrap());
101 self.tcx.infer_ctxt().enter(move |infcx| {
102 // Require the hidden type to be well-formed with only the generics of the opaque type.
103 // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
104 // hidden type is well formed even without those bounds.
106 ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()))
107 .to_predicate(infcx.tcx);
108 let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
110 // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
111 // the bounds that the function supplies.
112 match infcx.register_hidden_type(
113 OpaqueTypeKey { def_id, substs: id_substs },
114 ObligationCause::misc(instantiated_ty.span, body_id),
120 for obligation in infer_ok.obligations {
121 fulfillment_cx.register_predicate_obligation(&infcx, obligation);
126 .report_mismatched_types(
127 &ObligationCause::misc(instantiated_ty.span, body_id),
128 self.tcx.mk_opaque(def_id, id_substs),
136 fulfillment_cx.register_predicate_obligation(
138 Obligation::misc(instantiated_ty.span, body_id, param_env, predicate),
141 // Check that all obligations are satisfied by the implementation's
143 let errors = fulfillment_cx.select_all_or_error(&infcx);
145 let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
147 if errors.is_empty() {
150 infcx.report_fulfillment_errors(&errors, None, false);
160 fn check_opaque_type_parameter_valid(
162 opaque_type_key: OpaqueTypeKey<'_>,
163 origin: OpaqueTyOrigin,
167 // No need to check return position impl trait (RPIT)
168 // because for type and const parameters they are correct
169 // by construction: we convert
171 // fn foo<P0..Pn>() -> impl Trait
176 // fn foo<P0..Pn>() -> Foo<P0...Pn>.
178 // For lifetime parameters we convert
180 // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
184 // type foo::<'p0..'pn>::Foo<'q0..'qm>
185 // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
187 // which would error here on all of the `'static` args.
188 OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true,
190 OpaqueTyOrigin::TyAlias => {}
192 let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
193 let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
194 for (i, arg) in opaque_type_key.substs.iter().enumerate() {
195 let arg_is_param = match arg.unpack() {
196 GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
197 GenericArgKind::Lifetime(lt) if lt.is_static() => {
199 .struct_span_err(span, "non-defining opaque type use in defining scope")
201 tcx.def_span(opaque_generics.param_at(i, tcx).def_id),
202 "cannot use static lifetime; use a bound lifetime \
203 instead or remove the lifetime parameter from the \
209 GenericArgKind::Lifetime(lt) => {
210 matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_))
212 GenericArgKind::Const(ct) => matches!(ct.val(), ty::ConstKind::Param(_)),
216 seen_params.entry(arg).or_default().push(i);
218 // Prevent `fn foo() -> Foo<u32>` from being defining.
219 let opaque_param = opaque_generics.param_at(i, tcx);
221 .struct_span_err(span, "non-defining opaque type use in defining scope")
223 tcx.def_span(opaque_param.def_id),
225 "used non-generic {} `{}` for generic parameter",
226 opaque_param.kind.descr(),
235 for (_, indices) in seen_params {
236 if indices.len() > 1 {
237 let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
238 let spans: Vec<_> = indices
240 .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
243 .struct_span_err(span, "non-defining opaque type use in defining scope")
244 .span_note(spans, &format!("{} used multiple times", descr))
252 struct ReverseMapper<'tcx> {
255 opaque_type_def_id: DefId,
256 map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
257 map_missing_regions_to_empty: bool,
259 /// initially `Some`, set to `None` once error has been reported
260 hidden_ty: Option<Ty<'tcx>>,
262 /// Span of function being checked.
266 impl<'tcx> ReverseMapper<'tcx> {
269 opaque_type_def_id: DefId,
270 map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
278 map_missing_regions_to_empty: false,
279 hidden_ty: Some(hidden_ty),
284 fn fold_kind_mapping_missing_regions_to_empty(
286 kind: GenericArg<'tcx>,
287 ) -> GenericArg<'tcx> {
288 assert!(!self.map_missing_regions_to_empty);
289 self.map_missing_regions_to_empty = true;
290 let kind = kind.fold_with(self);
291 self.map_missing_regions_to_empty = false;
295 fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
296 assert!(!self.map_missing_regions_to_empty);
301 impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
302 fn tcx(&self) -> TyCtxt<'tcx> {
306 #[instrument(skip(self), level = "debug")]
307 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
309 // Ignore bound regions and `'static` regions that appear in the
310 // type, we only need to remap regions that reference lifetimes
311 // from the function declaration.
312 // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
313 ty::ReLateBound(..) | ty::ReStatic => return r,
315 // If regions have been erased (by writeback), don't try to unerase
317 ty::ReErased => return r,
319 // The regions that we expect from borrow checking.
320 ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
322 ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) => {
323 // All of the regions in the type should either have been
324 // erased by writeback, or mapped back to named regions by
326 bug!("unexpected region kind in opaque type: {:?}", r);
330 let generics = self.tcx().generics_of(self.opaque_type_def_id);
331 match self.map.get(&r.into()).map(|k| k.unpack()) {
332 Some(GenericArgKind::Lifetime(r1)) => r1,
333 Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
334 None if self.map_missing_regions_to_empty => self.tcx.lifetimes.re_root_empty,
335 None if generics.parent.is_some() => {
336 if let Some(hidden_ty) = self.hidden_ty.take() {
337 unexpected_hidden_region_diagnostic(
339 self.tcx.def_span(self.opaque_type_def_id),
345 self.tcx.lifetimes.re_root_empty
350 .struct_span_err(self.span, "non-defining opaque type use in defining scope")
354 "lifetime `{}` is part of concrete type but not used in \
355 parameter list of the `impl Trait` type alias",
361 self.tcx().lifetimes.re_static
366 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
368 ty::Closure(def_id, substs) => {
369 // I am a horrible monster and I pray for death. When
370 // we encounter a closure here, it is always a closure
371 // from within the function that we are currently
372 // type-checking -- one that is now being encapsulated
373 // in an opaque type. Ideally, we would
374 // go through the types/lifetimes that it references
375 // and treat them just like we would any other type,
376 // which means we would error out if we find any
377 // reference to a type/region that is not in the
380 // **However,** in the case of closures, there is a
381 // somewhat subtle (read: hacky) consideration. The
382 // problem is that our closure types currently include
383 // all the lifetime parameters declared on the
384 // enclosing function, even if they are unused by the
385 // closure itself. We can't readily filter them out,
386 // so here we replace those values with `'empty`. This
387 // can't really make a difference to the rest of the
388 // compiler; those regions are ignored for the
389 // outlives relation, and hence don't affect trait
390 // selection or auto traits, and they are erased
393 let generics = self.tcx.generics_of(def_id);
394 let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
395 if index < generics.parent_count {
396 // Accommodate missing regions in the parent kinds...
397 self.fold_kind_mapping_missing_regions_to_empty(kind)
399 // ...but not elsewhere.
400 self.fold_kind_normally(kind)
404 self.tcx.mk_closure(def_id, substs)
407 ty::Generator(def_id, substs, movability) => {
408 let generics = self.tcx.generics_of(def_id);
409 let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
410 if index < generics.parent_count {
411 // Accommodate missing regions in the parent kinds...
412 self.fold_kind_mapping_missing_regions_to_empty(kind)
414 // ...but not elsewhere.
415 self.fold_kind_normally(kind)
419 self.tcx.mk_generator(def_id, substs, movability)
422 ty::Param(param) => {
423 // Look it up in the substitution list.
424 match self.map.get(&ty.into()).map(|k| k.unpack()) {
425 // Found it in the substitution list; replace with the parameter from the
427 Some(GenericArgKind::Type(t1)) => t1,
428 Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
430 debug!(?param, ?self.map);
436 "type parameter `{}` is part of concrete type but not \
437 used in parameter list for the `impl Trait` type alias",
443 self.tcx().ty_error()
448 _ => ty.super_fold_with(self),
452 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
453 trace!("checking const {:?}", ct);
454 // Find a const parameter
456 ty::ConstKind::Param(..) => {
457 // Look it up in the substitution list.
458 match self.map.get(&ct.into()).map(|k| k.unpack()) {
459 // Found it in the substitution list, replace with the parameter from the
461 Some(GenericArgKind::Const(c1)) => c1,
462 Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
469 "const parameter `{}` is part of concrete type but not \
470 used in parameter list for the `impl Trait` type alias",
476 self.tcx().const_error(ct.ty())
486 /// Given a set of predicates that apply to an object type, returns
487 /// the region bounds that the (erased) `Self` type must
488 /// outlive. Precisely *because* the `Self` type is erased, the
489 /// parameter `erased_self_ty` must be supplied to indicate what type
490 /// has been used to represent `Self` in the predicates
491 /// themselves. This should really be a unique type; `FreshTy(0)` is a
494 /// N.B., in some cases, particularly around higher-ranked bounds,
495 /// this function returns a kind of conservative approximation.
496 /// That is, all regions returned by this function are definitely
497 /// required, but there may be other region bounds that are not
498 /// returned, as well as requirements like `for<'a> T: 'a`.
500 /// Requires that trait definitions have been processed so that we can
501 /// elaborate predicates and walk supertraits.
502 #[instrument(skip(tcx, predicates), level = "debug")]
503 pub(crate) fn required_region_bounds<'tcx>(
505 erased_self_ty: Ty<'tcx>,
506 predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
507 ) -> Vec<ty::Region<'tcx>> {
508 assert!(!erased_self_ty.has_escaping_bound_vars());
510 traits::elaborate_predicates(tcx, predicates)
511 .filter_map(|obligation| {
513 match obligation.predicate.kind().skip_binder() {
514 ty::PredicateKind::Projection(..)
515 | ty::PredicateKind::Trait(..)
516 | ty::PredicateKind::Subtype(..)
517 | ty::PredicateKind::Coerce(..)
518 | ty::PredicateKind::WellFormed(..)
519 | ty::PredicateKind::ObjectSafe(..)
520 | ty::PredicateKind::ClosureKind(..)
521 | ty::PredicateKind::RegionOutlives(..)
522 | ty::PredicateKind::ConstEvaluatable(..)
523 | ty::PredicateKind::ConstEquate(..)
524 | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
525 ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
526 // Search for a bound of the form `erased_self_ty
527 // : 'a`, but be wary of something like `for<'a>
528 // erased_self_ty : 'a` (we interpret a
529 // higher-ranked bound like that as 'static,
530 // though at present the code in `fulfill.rs`
531 // considers such bounds to be unsatisfiable, so
532 // it's kind of a moot point since you could never
533 // construct such an object, but this seems
534 // correct even if that code changes).
535 if t == &erased_self_ty && !r.has_escaping_bound_vars() {