2 use rustc_data_structures::fx::FxHashMap;
3 use rustc_hir::def_id::DefId;
4 use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
5 use rustc_infer::infer::InferCtxt;
6 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
7 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
8 use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt};
11 pub trait InferCtxtExt<'tcx> {
12 fn infer_opaque_definition_from_instantiation(
14 opaque_type_key: OpaqueTypeKey<'tcx>,
15 instantiated_ty: Ty<'tcx>,
20 impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
21 /// Given the fully resolved, instantiated type for an opaque
22 /// type, i.e., the value of an inference variable like C1 or C2
23 /// (*), computes the "definition type" for an opaque type
24 /// definition -- that is, the inferred value of `Foo1<'x>` or
25 /// `Foo2<'x>` that we would conceptually use in its definition:
27 /// type Foo1<'x> = impl Bar<'x> = AAA; <-- this type AAA
28 /// type Foo2<'x> = impl Bar<'x> = BBB; <-- or this type BBB
29 /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
31 /// Note that these values are defined in terms of a distinct set of
32 /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main
33 /// purpose of this function is to do that translation.
35 /// (*) C1 and C2 were introduced in the comments on
36 /// `register_member_constraints`. Read that comment for more context.
40 /// - `def_id`, the `impl Trait` type
41 /// - `substs`, the substs used to instantiate this opaque type
42 /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
43 /// `opaque_defn.concrete_ty`
44 #[instrument(level = "debug", skip(self))]
45 fn infer_opaque_definition_from_instantiation(
47 opaque_type_key: OpaqueTypeKey<'tcx>,
48 instantiated_ty: Ty<'tcx>,
51 if self.is_tainted_by_errors() {
52 return self.tcx.ty_error();
55 let OpaqueTypeKey { def_id, substs } = opaque_type_key;
57 // Use substs to build up a reverse map from regions to their
58 // identity mappings. This is necessary because of `impl
59 // Trait` lifetimes are computed by replacing existing
60 // lifetimes with 'static and remapping only those used in the
61 // `impl Trait` return type, resulting in the parameters
63 let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
65 let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
66 substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect();
67 debug!("map = {:#?}", map);
69 // Convert the type from the function into a type valid outside
70 // the function, by replacing invalid regions with 'static,
71 // after producing an error for each of them.
72 let definition_ty = instantiated_ty.fold_with(&mut ReverseMapper::new(
79 debug!(?definition_ty);
85 struct ReverseMapper<'tcx> {
88 opaque_type_def_id: DefId,
89 map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
90 map_missing_regions_to_empty: bool,
92 /// initially `Some`, set to `None` once error has been reported
93 hidden_ty: Option<Ty<'tcx>>,
95 /// Span of function being checked.
99 impl<'tcx> ReverseMapper<'tcx> {
102 opaque_type_def_id: DefId,
103 map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
111 map_missing_regions_to_empty: false,
112 hidden_ty: Some(hidden_ty),
117 fn fold_kind_mapping_missing_regions_to_empty(
119 kind: GenericArg<'tcx>,
120 ) -> GenericArg<'tcx> {
121 assert!(!self.map_missing_regions_to_empty);
122 self.map_missing_regions_to_empty = true;
123 let kind = kind.fold_with(self);
124 self.map_missing_regions_to_empty = false;
128 fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
129 assert!(!self.map_missing_regions_to_empty);
134 impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
135 fn tcx(&self) -> TyCtxt<'tcx> {
139 #[instrument(skip(self), level = "debug")]
140 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
142 // Ignore bound regions and `'static` regions that appear in the
143 // type, we only need to remap regions that reference lifetimes
144 // from the function declaraion.
145 // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
146 ty::ReLateBound(..) | ty::ReStatic => return r,
148 // If regions have been erased (by writeback), don't try to unerase
150 ty::ReErased => return r,
152 // The regions that we expect from borrow checking.
153 ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
155 ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) => {
156 // All of the regions in the type should either have been
157 // erased by writeback, or mapped back to named regions by
159 bug!("unexpected region kind in opaque type: {:?}", r);
163 let generics = self.tcx().generics_of(self.opaque_type_def_id);
164 match self.map.get(&r.into()).map(|k| k.unpack()) {
165 Some(GenericArgKind::Lifetime(r1)) => r1,
166 Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
167 None if self.map_missing_regions_to_empty => self.tcx.lifetimes.re_root_empty,
168 None if generics.parent.is_some() => {
169 if let Some(hidden_ty) = self.hidden_ty.take() {
170 unexpected_hidden_region_diagnostic(
172 self.tcx.def_span(self.opaque_type_def_id),
178 self.tcx.lifetimes.re_root_empty
183 .struct_span_err(self.span, "non-defining opaque type use in defining scope")
187 "lifetime `{}` is part of concrete type but not used in \
188 parameter list of the `impl Trait` type alias",
194 self.tcx().lifetimes.re_static
199 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
201 ty::Closure(def_id, substs) => {
202 // I am a horrible monster and I pray for death. When
203 // we encounter a closure here, it is always a closure
204 // from within the function that we are currently
205 // type-checking -- one that is now being encapsulated
206 // in an opaque type. Ideally, we would
207 // go through the types/lifetimes that it references
208 // and treat them just like we would any other type,
209 // which means we would error out if we find any
210 // reference to a type/region that is not in the
213 // **However,** in the case of closures, there is a
214 // somewhat subtle (read: hacky) consideration. The
215 // problem is that our closure types currently include
216 // all the lifetime parameters declared on the
217 // enclosing function, even if they are unused by the
218 // closure itself. We can't readily filter them out,
219 // so here we replace those values with `'empty`. This
220 // can't really make a difference to the rest of the
221 // compiler; those regions are ignored for the
222 // outlives relation, and hence don't affect trait
223 // selection or auto traits, and they are erased
226 let generics = self.tcx.generics_of(def_id);
227 let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
228 if index < generics.parent_count {
229 // Accommodate missing regions in the parent kinds...
230 self.fold_kind_mapping_missing_regions_to_empty(kind)
232 // ...but not elsewhere.
233 self.fold_kind_normally(kind)
237 self.tcx.mk_closure(def_id, substs)
240 ty::Generator(def_id, substs, movability) => {
241 let generics = self.tcx.generics_of(def_id);
242 let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
243 if index < generics.parent_count {
244 // Accommodate missing regions in the parent kinds...
245 self.fold_kind_mapping_missing_regions_to_empty(kind)
247 // ...but not elsewhere.
248 self.fold_kind_normally(kind)
252 self.tcx.mk_generator(def_id, substs, movability)
255 ty::Param(param) => {
256 // Look it up in the substitution list.
257 match self.map.get(&ty.into()).map(|k| k.unpack()) {
258 // Found it in the substitution list; replace with the parameter from the
260 Some(GenericArgKind::Type(t1)) => t1,
261 Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
263 debug!(?param, ?self.map);
269 "type parameter `{}` is part of concrete type but not \
270 used in parameter list for the `impl Trait` type alias",
276 self.tcx().ty_error()
281 _ => ty.super_fold_with(self),
285 fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
286 trace!("checking const {:?}", ct);
287 // Find a const parameter
289 ty::ConstKind::Param(..) => {
290 // Look it up in the substitution list.
291 match self.map.get(&ct.into()).map(|k| k.unpack()) {
292 // Found it in the substitution list, replace with the parameter from the
294 Some(GenericArgKind::Const(c1)) => c1,
295 Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
302 "const parameter `{}` is part of concrete type but not \
303 used in parameter list for the `impl Trait` type alias",
309 self.tcx().const_error(ct.ty)
319 /// Given a set of predicates that apply to an object type, returns
320 /// the region bounds that the (erased) `Self` type must
321 /// outlive. Precisely *because* the `Self` type is erased, the
322 /// parameter `erased_self_ty` must be supplied to indicate what type
323 /// has been used to represent `Self` in the predicates
324 /// themselves. This should really be a unique type; `FreshTy(0)` is a
327 /// N.B., in some cases, particularly around higher-ranked bounds,
328 /// this function returns a kind of conservative approximation.
329 /// That is, all regions returned by this function are definitely
330 /// required, but there may be other region bounds that are not
331 /// returned, as well as requirements like `for<'a> T: 'a`.
333 /// Requires that trait definitions have been processed so that we can
334 /// elaborate predicates and walk supertraits.
335 #[instrument(skip(tcx, predicates), level = "debug")]
336 crate fn required_region_bounds<'tcx>(
338 erased_self_ty: Ty<'tcx>,
339 predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
340 ) -> Vec<ty::Region<'tcx>> {
341 assert!(!erased_self_ty.has_escaping_bound_vars());
343 traits::elaborate_predicates(tcx, predicates)
344 .filter_map(|obligation| {
346 match obligation.predicate.kind().skip_binder() {
347 ty::PredicateKind::Projection(..)
348 | ty::PredicateKind::Trait(..)
349 | ty::PredicateKind::Subtype(..)
350 | ty::PredicateKind::Coerce(..)
351 | ty::PredicateKind::WellFormed(..)
352 | ty::PredicateKind::ObjectSafe(..)
353 | ty::PredicateKind::ClosureKind(..)
354 | ty::PredicateKind::RegionOutlives(..)
355 | ty::PredicateKind::ConstEvaluatable(..)
356 | ty::PredicateKind::ConstEquate(..)
357 | ty::PredicateKind::OpaqueType(..)
358 | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
359 ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
360 // Search for a bound of the form `erased_self_ty
361 // : 'a`, but be wary of something like `for<'a>
362 // erased_self_ty : 'a` (we interpret a
363 // higher-ranked bound like that as 'static,
364 // though at present the code in `fulfill.rs`
365 // considers such bounds to be unsatisfiable, so
366 // it's kind of a moot point since you could never
367 // construct such an object, but this seems
368 // correct even if that code changes).
369 if t == &erased_self_ty && !r.has_escaping_bound_vars() {