1 use crate::infer::InferCtxt;
2 use rustc_data_structures::sync::Lrc;
3 use rustc_data_structures::vec_map::VecMap;
5 use rustc_middle::ty::subst::GenericArgKind;
6 use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor};
9 use std::ops::ControlFlow;
11 pub type OpaqueTypeMap<'tcx> = VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>;
13 /// Information about the opaque types whose values we
14 /// are inferring in this function (these are the `impl Trait` that
15 /// appear in the return type).
16 #[derive(Copy, Clone, Debug)]
17 pub struct OpaqueTypeDecl<'tcx> {
18 /// The opaque type (`ty::Opaque`) for this declaration.
19 pub opaque_type: Ty<'tcx>,
21 /// The span of this particular definition of the opaque type. So
24 /// ```ignore (incomplete snippet)
25 /// type Foo = impl Baz;
27 /// // ^^^ This is the span we are looking for!
31 /// In cases where the fn returns `(impl Trait, impl Trait)` or
32 /// other such combinations, the result is currently
33 /// over-approximated, but better than nothing.
34 pub definition_span: Span,
36 /// The type variable that represents the value of the opaque type
37 /// that we require. In other words, after we compile this function,
38 /// we will be created a constraint like:
42 /// where `?C` is the value of this type variable. =) It may
43 /// naturally refer to the type and lifetime parameters in scope
44 /// in this function, though ultimately it should only reference
45 /// those that are arguments to `Foo` in the constraint above. (In
46 /// other words, `?C` should not include `'b`, even though it's a
47 /// lifetime parameter on `foo`.)
48 pub concrete_ty: Ty<'tcx>,
50 /// The origin of the opaque type.
51 pub origin: hir::OpaqueTyOrigin,
54 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
55 /// Given the map `opaque_types` containing the opaque
56 /// `impl Trait` types whose underlying, hidden types are being
57 /// inferred, this method adds constraints to the regions
58 /// appearing in those underlying hidden types to ensure that they
59 /// at least do not refer to random scopes within the current
60 /// function. These constraints are not (quite) sufficient to
61 /// guarantee that the regions are actually legal values; that
62 /// final condition is imposed after region inference is done.
66 /// Let's work through an example to explain how it works. Assume
67 /// the current function is as follows:
70 /// fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>)
73 /// Here, we have two `impl Trait` types whose values are being
74 /// inferred (the `impl Bar<'a>` and the `impl
75 /// Bar<'b>`). Conceptually, this is sugar for a setup where we
76 /// define underlying opaque types (`Foo1`, `Foo2`) and then, in
77 /// the return type of `foo`, we *reference* those definitions:
80 /// type Foo1<'x> = impl Bar<'x>;
81 /// type Foo2<'x> = impl Bar<'x>;
82 /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
89 /// As indicating in the comments above, each of those references
90 /// is (in the compiler) basically a substitution (`substs`)
91 /// applied to the type of a suitable `def_id` (which identifies
92 /// `Foo1` or `Foo2`).
94 /// Now, at this point in compilation, what we have done is to
95 /// replace each of the references (`Foo1<'a>`, `Foo2<'b>`) with
96 /// fresh inference variables C1 and C2. We wish to use the values
97 /// of these variables to infer the underlying types of `Foo1` and
98 /// `Foo2`. That is, this gives rise to higher-order (pattern) unification
102 /// for<'a> (Foo1<'a> = C1)
103 /// for<'b> (Foo1<'b> = C2)
106 /// For these equation to be satisfiable, the types `C1` and `C2`
107 /// can only refer to a limited set of regions. For example, `C1`
108 /// can only refer to `'static` and `'a`, and `C2` can only refer
109 /// to `'static` and `'b`. The job of this function is to impose that
112 /// Up to this point, C1 and C2 are basically just random type
113 /// inference variables, and hence they may contain arbitrary
114 /// regions. In fact, it is fairly likely that they do! Consider
115 /// this possible definition of `foo`:
118 /// fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) {
123 /// Here, the values for the concrete types of the two impl
124 /// traits will include inference variables:
131 /// Ordinarily, the subtyping rules would ensure that these are
132 /// sufficiently large. But since `impl Bar<'a>` isn't a specific
133 /// type per se, we don't get such constraints by default. This
134 /// is where this function comes into play. It adds extra
135 /// constraints to ensure that all the regions which appear in the
136 /// inferred type are regions that could validly appear.
138 /// This is actually a bit of a tricky constraint in general. We
139 /// want to say that each variable (e.g., `'0`) can only take on
140 /// values that were supplied as arguments to the opaque type
141 /// (e.g., `'a` for `Foo1<'a>`) or `'static`, which is always in
142 /// scope. We don't have a constraint quite of this kind in the current
147 /// We generally prefer to make `<=` constraints, since they
148 /// integrate best into the region solver. To do that, we find the
149 /// "minimum" of all the arguments that appear in the substs: that
150 /// is, some region which is less than all the others. In the case
151 /// of `Foo1<'a>`, that would be `'a` (it's the only choice, after
152 /// all). Then we apply that as a least bound to the variables
153 /// (e.g., `'a <= '0`).
155 /// In some cases, there is no minimum. Consider this example:
158 /// fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... }
161 /// Here we would report a more complex "in constraint", like `'r
162 /// in ['a, 'b, 'static]` (where `'r` is some region appearing in
163 /// the hidden type).
165 /// # Constrain regions, not the hidden concrete type
167 /// Note that generating constraints on each region `Rc` is *not*
168 /// the same as generating an outlives constraint on `Tc` iself.
169 /// For example, if we had a function like this:
172 /// fn foo<'a, T>(x: &'a u32, y: T) -> impl Foo<'a> {
176 /// // Equivalent to:
177 /// type FooReturn<'a, T> = impl Foo<'a>;
178 /// fn foo<'a, T>(..) -> FooReturn<'a, T> { .. }
181 /// then the hidden type `Tc` would be `(&'0 u32, T)` (where `'0`
182 /// is an inference variable). If we generated a constraint that
183 /// `Tc: 'a`, then this would incorrectly require that `T: 'a` --
184 /// but this is not necessary, because the opaque type we
185 /// create will be allowed to reference `T`. So we only generate a
186 /// constraint that `'0: 'a`.
188 /// # The `free_region_relations` parameter
190 /// The `free_region_relations` argument is used to find the
191 /// "minimum" of the regions supplied to a given opaque type.
192 /// It must be a relation that can answer whether `'a <= 'b`,
193 /// where `'a` and `'b` are regions that appear in the "substs"
194 /// for the opaque type references (the `<'a>` in `Foo1<'a>`).
196 /// Note that we do not impose the constraints based on the
197 /// generic regions from the `Foo1` definition (e.g., `'x`). This
198 /// is because the constraints we are imposing here is basically
199 /// the concern of the one generating the constraining type C1,
200 /// which is the current function. It also means that we can
201 /// take "implied bounds" into account in some cases:
204 /// trait SomeTrait<'a, 'b> { }
205 /// fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. }
208 /// Here, the fact that `'b: 'a` is known only because of the
209 /// implied bounds from the `&'a &'b u32` parameter, and is not
210 /// "inherent" to the opaque type definition.
214 /// - `opaque_types` -- the map produced by `instantiate_opaque_types`
215 /// - `free_region_relations` -- something that can be used to relate
216 /// the free regions (`'a`) that appear in the impl trait.
217 #[instrument(level = "debug", skip(self))]
218 pub fn constrain_opaque_type(
220 opaque_type_key: OpaqueTypeKey<'tcx>,
221 opaque_defn: &OpaqueTypeDecl<'tcx>,
223 let def_id = opaque_type_key.def_id;
227 let concrete_ty = self.resolve_vars_if_possible(opaque_defn.concrete_ty);
229 debug!(?concrete_ty);
231 let first_own_region = match opaque_defn.origin {
232 hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => {
235 // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
239 // type foo::<'p0..'pn>::Foo<'q0..'qm>
240 // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
242 // For these types we only iterate over `'l0..lm` below.
243 tcx.generics_of(def_id).parent_count
245 // These opaque type inherit all lifetime parameters from their
246 // parent, so we have to check them all.
247 hir::OpaqueTyOrigin::TyAlias => 0,
250 // For a case like `impl Foo<'a, 'b>`, we would generate a constraint
251 // `'r in ['a, 'b, 'static]` for each region `'r` that appears in the
252 // hidden type (i.e., it must be equal to `'a`, `'b`, or `'static`).
254 // `conflict1` and `conflict2` are the two region bounds that we
255 // detected which were unrelated. They are used for diagnostics.
257 // Create the set of choice regions: each region in the hidden
258 // type can be equal to any of the region parameters of the
259 // opaque type definition.
260 let choice_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new(
261 opaque_type_key.substs[first_own_region..]
263 .filter_map(|arg| match arg.unpack() {
264 GenericArgKind::Lifetime(r) => Some(r),
265 GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
267 .chain(std::iter::once(self.tcx.lifetimes.re_static))
271 concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
274 self.member_constraint(
275 opaque_type_key.def_id,
276 opaque_defn.definition_span,
286 // Visitor that requires that (almost) all regions in the type visited outlive
287 // `least_region`. We cannot use `push_outlives_components` because regions in
288 // closure signatures are not included in their outlives components. We need to
289 // ensure all regions outlive the given bound so that we don't end up with,
290 // say, `ReVar` appearing in a return type and causing ICEs when other
291 // functions end up with region constraints involving regions from other
294 // We also cannot use `for_each_free_region` because for closures it includes
295 // the regions parameters from the enclosing item.
297 // We ignore any type parameters because impl trait values are assumed to
298 // capture all the in-scope type parameters.
299 struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP> {
304 impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
306 OP: FnMut(ty::Region<'tcx>),
308 fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
312 fn visit_binder<T: TypeFoldable<'tcx>>(
314 t: &ty::Binder<'tcx, T>,
315 ) -> ControlFlow<Self::BreakTy> {
316 t.as_ref().skip_binder().visit_with(self);
317 ControlFlow::CONTINUE
320 fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
322 // ignore bound regions, keep visiting
323 ty::ReLateBound(_, _) => ControlFlow::CONTINUE,
326 ControlFlow::CONTINUE
331 fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
332 // We're only interested in types involving regions
333 if !ty.flags().intersects(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
334 return ControlFlow::CONTINUE;
338 ty::Closure(_, ref substs) => {
339 // Skip lifetime parameters of the enclosing item(s)
341 substs.as_closure().tupled_upvars_ty().visit_with(self);
342 substs.as_closure().sig_as_fn_ptr_ty().visit_with(self);
345 ty::Generator(_, ref substs, _) => {
346 // Skip lifetime parameters of the enclosing item(s)
347 // Also skip the witness type, because that has no free regions.
349 substs.as_generator().tupled_upvars_ty().visit_with(self);
350 substs.as_generator().return_ty().visit_with(self);
351 substs.as_generator().yield_ty().visit_with(self);
352 substs.as_generator().resume_ty().visit_with(self);
355 ty.super_visit_with(self);
359 ControlFlow::CONTINUE