]>
Commit | Line | Data |
---|---|---|
353b0b11 FG |
1 | use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; |
2 | use super::{DefineOpaqueTypes, InferResult}; | |
f2b60f7d | 3 | use crate::errors::OpaqueHiddenTypeDiag; |
49aad941 FG |
4 | use crate::infer::{InferCtxt, InferOk}; |
5 | use crate::traits::{self, PredicateObligation}; | |
5e7ed085 | 6 | use hir::def_id::{DefId, LocalDefId}; |
9ffffee4 | 7 | use hir::OpaqueTyOrigin; |
353b0b11 | 8 | use rustc_data_structures::fx::FxIndexMap; |
3c0e092e | 9 | use rustc_data_structures::sync::Lrc; |
94222f64 | 10 | use rustc_hir as hir; |
49aad941 | 11 | use rustc_middle::traits::{DefiningAnchor, ObligationCause}; |
2b03887a | 12 | use rustc_middle::ty::error::{ExpectedFound, TypeError}; |
3c0e092e | 13 | use rustc_middle::ty::fold::BottomUpFolder; |
2b03887a | 14 | use rustc_middle::ty::GenericArgKind; |
5e7ed085 | 15 | use rustc_middle::ty::{ |
064997fb | 16 | self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, |
9ffffee4 | 17 | TypeVisitable, TypeVisitableExt, TypeVisitor, |
5e7ed085 | 18 | }; |
94222f64 | 19 | use rustc_span::Span; |
3c0e092e XL |
20 | use std::ops::ControlFlow; |
21 | ||
5e7ed085 FG |
22 | mod table; |
23 | ||
353b0b11 | 24 | pub type OpaqueTypeMap<'tcx> = FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>; |
5e7ed085 FG |
25 | pub use table::{OpaqueTypeStorage, OpaqueTypeTable}; |
26 | ||
94222f64 XL |
27 | /// Information about the opaque types whose values we |
28 | /// are inferring in this function (these are the `impl Trait` that | |
29 | /// appear in the return type). | |
5e7ed085 | 30 | #[derive(Clone, Debug)] |
94222f64 | 31 | pub struct OpaqueTypeDecl<'tcx> { |
5e7ed085 FG |
32 | /// The hidden types that have been inferred for this opaque type. |
33 | /// There can be multiple, but they are all `lub`ed together at the end | |
34 | /// to obtain the canonical hidden type. | |
35 | pub hidden_type: OpaqueHiddenType<'tcx>, | |
94222f64 XL |
36 | |
37 | /// The origin of the opaque type. | |
38 | pub origin: hir::OpaqueTyOrigin, | |
39 | } | |
3c0e092e | 40 | |
2b03887a | 41 | impl<'tcx> InferCtxt<'tcx> { |
5e7ed085 FG |
42 | /// This is a backwards compatibility hack to prevent breaking changes from |
43 | /// lazy TAIT around RPIT handling. | |
9ffffee4 | 44 | pub fn replace_opaque_types_with_inference_vars<T: TypeFoldable<TyCtxt<'tcx>>>( |
3c0e092e | 45 | &self, |
3c0e092e | 46 | value: T, |
9ffffee4 | 47 | body_id: LocalDefId, |
5e7ed085 FG |
48 | span: Span, |
49 | param_env: ty::ParamEnv<'tcx>, | |
3c0e092e | 50 | ) -> InferOk<'tcx, T> { |
49aad941 FG |
51 | // We handle opaque types differently in the new solver. |
52 | if self.tcx.trait_solver_next() { | |
53 | return InferOk { value, obligations: vec![] }; | |
54 | } | |
55 | ||
5e7ed085 FG |
56 | if !value.has_opaque_types() { |
57 | return InferOk { value, obligations: vec![] }; | |
58 | } | |
49aad941 | 59 | |
5e7ed085 | 60 | let mut obligations = vec![]; |
064997fb | 61 | let replace_opaque_type = |def_id: DefId| { |
49aad941 | 62 | def_id.as_local().is_some_and(|def_id| self.opaque_type_origin(def_id).is_some()) |
064997fb | 63 | }; |
9c376795 | 64 | let value = value.fold_with(&mut BottomUpFolder { |
5e7ed085 FG |
65 | tcx: self.tcx, |
66 | lt_op: |lt| lt, | |
67 | ct_op: |ct| ct, | |
68 | ty_op: |ty| match *ty.kind() { | |
9c376795 FG |
69 | ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) |
70 | if replace_opaque_type(def_id) => | |
71 | { | |
064997fb FG |
72 | let def_span = self.tcx.def_span(def_id); |
73 | let span = if span.contains(def_span) { def_span } else { span }; | |
74 | let code = traits::ObligationCauseCode::OpaqueReturnType(None); | |
75 | let cause = ObligationCause::new(span, body_id, code); | |
923072b8 FG |
76 | // FIXME(compiler-errors): We probably should add a new TypeVariableOriginKind |
77 | // for opaque types, and then use that kind to fix the spans for type errors | |
78 | // that we see later on. | |
5e7ed085 | 79 | let ty_var = self.next_ty_var(TypeVariableOrigin { |
f2b60f7d | 80 | kind: TypeVariableOriginKind::OpaqueTypeInference(def_id), |
923072b8 | 81 | span, |
5e7ed085 FG |
82 | }); |
83 | obligations.extend( | |
84 | self.handle_opaque_type(ty, ty_var, true, &cause, param_env) | |
85 | .unwrap() | |
86 | .obligations, | |
87 | ); | |
88 | ty_var | |
89 | } | |
90 | _ => ty, | |
91 | }, | |
92 | }); | |
93 | InferOk { value, obligations } | |
94 | } | |
95 | ||
96 | pub fn handle_opaque_type( | |
97 | &self, | |
98 | a: Ty<'tcx>, | |
99 | b: Ty<'tcx>, | |
100 | a_is_expected: bool, | |
101 | cause: &ObligationCause<'tcx>, | |
102 | param_env: ty::ParamEnv<'tcx>, | |
103 | ) -> InferResult<'tcx, ()> { | |
104 | if a.references_error() || b.references_error() { | |
105 | return Ok(InferOk { value: (), obligations: vec![] }); | |
106 | } | |
107 | let (a, b) = if a_is_expected { (a, b) } else { (b, a) }; | |
2b03887a | 108 | let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() { |
9c376795 | 109 | ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) if def_id.is_local() => { |
064997fb FG |
110 | let def_id = def_id.expect_local(); |
111 | let origin = match self.defining_use_anchor { | |
112 | DefiningAnchor::Bind(_) => { | |
113 | // Check that this is `impl Trait` type is | |
114 | // declared by `parent_def_id` -- i.e., one whose | |
9c376795 | 115 | // value we are inferring. At present, this is |
064997fb FG |
116 | // always true during the first phase of |
117 | // type-check, but not always true later on during | |
118 | // NLL. Once we support named opaque types more fully, | |
119 | // this same scenario will be able to arise during all phases. | |
120 | // | |
121 | // Here is an example using type alias `impl Trait` | |
122 | // that indicates the distinction we are checking for: | |
123 | // | |
124 | // ```rust | |
125 | // mod a { | |
126 | // pub type Foo = impl Iterator; | |
127 | // pub fn make_foo() -> Foo { .. } | |
128 | // } | |
129 | // | |
130 | // mod b { | |
131 | // fn foo() -> a::Foo { a::make_foo() } | |
132 | // } | |
133 | // ``` | |
134 | // | |
135 | // Here, the return type of `foo` references an | |
136 | // `Opaque` indeed, but not one whose value is | |
137 | // presently being inferred. You can get into a | |
138 | // similar situation with closure return types | |
139 | // today: | |
140 | // | |
141 | // ```rust | |
142 | // fn foo() -> impl Iterator { .. } | |
143 | // fn bar() { | |
144 | // let x = || foo(); // returns the Opaque assoc with `foo` | |
145 | // } | |
146 | // ``` | |
9ffffee4 | 147 | self.opaque_type_origin(def_id)? |
064997fb | 148 | } |
9ffffee4 | 149 | DefiningAnchor::Bubble => self.opaque_type_origin_unchecked(def_id), |
064997fb | 150 | DefiningAnchor::Error => return None, |
5e7ed085 | 151 | }; |
9c376795 | 152 | if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() { |
5e7ed085 FG |
153 | // We could accept this, but there are various ways to handle this situation, and we don't |
154 | // want to make a decision on it right now. Likely this case is so super rare anyway, that | |
155 | // no one encounters it in practice. | |
156 | // It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`, | |
157 | // where it is of no concern, so we only check for TAITs. | |
49aad941 | 158 | if let Some(OpaqueTyOrigin::TyAlias { .. }) = |
9ffffee4 | 159 | b_def_id.as_local().and_then(|b_def_id| self.opaque_type_origin(b_def_id)) |
5e7ed085 | 160 | { |
f2b60f7d FG |
161 | self.tcx.sess.emit_err(OpaqueHiddenTypeDiag { |
162 | span: cause.span, | |
9c376795 | 163 | hidden_type: self.tcx.def_span(b_def_id), |
f2b60f7d FG |
164 | opaque_type: self.tcx.def_span(def_id), |
165 | }); | |
5e7ed085 FG |
166 | } |
167 | } | |
168 | Some(self.register_hidden_type( | |
169 | OpaqueTypeKey { def_id, substs }, | |
170 | cause.clone(), | |
171 | param_env, | |
172 | b, | |
173 | origin, | |
2b03887a | 174 | a_is_expected, |
5e7ed085 FG |
175 | )) |
176 | } | |
177 | _ => None, | |
178 | }; | |
2b03887a | 179 | if let Some(res) = process(a, b, true) { |
5e7ed085 | 180 | res |
2b03887a | 181 | } else if let Some(res) = process(b, a, false) { |
5e7ed085 FG |
182 | res |
183 | } else { | |
2b03887a FG |
184 | let (a, b) = self.resolve_vars_if_possible((a, b)); |
185 | Err(TypeError::Sorts(ExpectedFound::new(true, a, b))) | |
5e7ed085 | 186 | } |
3c0e092e XL |
187 | } |
188 | ||
189 | /// Given the map `opaque_types` containing the opaque | |
190 | /// `impl Trait` types whose underlying, hidden types are being | |
191 | /// inferred, this method adds constraints to the regions | |
192 | /// appearing in those underlying hidden types to ensure that they | |
193 | /// at least do not refer to random scopes within the current | |
194 | /// function. These constraints are not (quite) sufficient to | |
195 | /// guarantee that the regions are actually legal values; that | |
196 | /// final condition is imposed after region inference is done. | |
197 | /// | |
198 | /// # The Problem | |
199 | /// | |
200 | /// Let's work through an example to explain how it works. Assume | |
201 | /// the current function is as follows: | |
202 | /// | |
203 | /// ```text | |
204 | /// fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>) | |
205 | /// ``` | |
206 | /// | |
207 | /// Here, we have two `impl Trait` types whose values are being | |
208 | /// inferred (the `impl Bar<'a>` and the `impl | |
209 | /// Bar<'b>`). Conceptually, this is sugar for a setup where we | |
210 | /// define underlying opaque types (`Foo1`, `Foo2`) and then, in | |
211 | /// the return type of `foo`, we *reference* those definitions: | |
212 | /// | |
213 | /// ```text | |
214 | /// type Foo1<'x> = impl Bar<'x>; | |
215 | /// type Foo2<'x> = impl Bar<'x>; | |
216 | /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. } | |
217 | /// // ^^^^ ^^ | |
218 | /// // | | | |
219 | /// // | substs | |
220 | /// // def_id | |
221 | /// ``` | |
222 | /// | |
223 | /// As indicating in the comments above, each of those references | |
224 | /// is (in the compiler) basically a substitution (`substs`) | |
225 | /// applied to the type of a suitable `def_id` (which identifies | |
226 | /// `Foo1` or `Foo2`). | |
227 | /// | |
228 | /// Now, at this point in compilation, what we have done is to | |
229 | /// replace each of the references (`Foo1<'a>`, `Foo2<'b>`) with | |
230 | /// fresh inference variables C1 and C2. We wish to use the values | |
231 | /// of these variables to infer the underlying types of `Foo1` and | |
232 | /// `Foo2`. That is, this gives rise to higher-order (pattern) unification | |
233 | /// constraints like: | |
234 | /// | |
235 | /// ```text | |
236 | /// for<'a> (Foo1<'a> = C1) | |
237 | /// for<'b> (Foo1<'b> = C2) | |
238 | /// ``` | |
239 | /// | |
240 | /// For these equation to be satisfiable, the types `C1` and `C2` | |
241 | /// can only refer to a limited set of regions. For example, `C1` | |
242 | /// can only refer to `'static` and `'a`, and `C2` can only refer | |
243 | /// to `'static` and `'b`. The job of this function is to impose that | |
244 | /// constraint. | |
245 | /// | |
246 | /// Up to this point, C1 and C2 are basically just random type | |
247 | /// inference variables, and hence they may contain arbitrary | |
248 | /// regions. In fact, it is fairly likely that they do! Consider | |
249 | /// this possible definition of `foo`: | |
250 | /// | |
251 | /// ```text | |
252 | /// fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) { | |
253 | /// (&*x, &*y) | |
254 | /// } | |
255 | /// ``` | |
256 | /// | |
257 | /// Here, the values for the concrete types of the two impl | |
258 | /// traits will include inference variables: | |
259 | /// | |
260 | /// ```text | |
261 | /// &'0 i32 | |
262 | /// &'1 i32 | |
263 | /// ``` | |
264 | /// | |
265 | /// Ordinarily, the subtyping rules would ensure that these are | |
266 | /// sufficiently large. But since `impl Bar<'a>` isn't a specific | |
267 | /// type per se, we don't get such constraints by default. This | |
268 | /// is where this function comes into play. It adds extra | |
269 | /// constraints to ensure that all the regions which appear in the | |
270 | /// inferred type are regions that could validly appear. | |
271 | /// | |
272 | /// This is actually a bit of a tricky constraint in general. We | |
273 | /// want to say that each variable (e.g., `'0`) can only take on | |
274 | /// values that were supplied as arguments to the opaque type | |
275 | /// (e.g., `'a` for `Foo1<'a>`) or `'static`, which is always in | |
276 | /// scope. We don't have a constraint quite of this kind in the current | |
277 | /// region checker. | |
278 | /// | |
279 | /// # The Solution | |
280 | /// | |
281 | /// We generally prefer to make `<=` constraints, since they | |
282 | /// integrate best into the region solver. To do that, we find the | |
283 | /// "minimum" of all the arguments that appear in the substs: that | |
284 | /// is, some region which is less than all the others. In the case | |
285 | /// of `Foo1<'a>`, that would be `'a` (it's the only choice, after | |
286 | /// all). Then we apply that as a least bound to the variables | |
287 | /// (e.g., `'a <= '0`). | |
288 | /// | |
289 | /// In some cases, there is no minimum. Consider this example: | |
290 | /// | |
291 | /// ```text | |
292 | /// fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... } | |
293 | /// ``` | |
294 | /// | |
295 | /// Here we would report a more complex "in constraint", like `'r | |
296 | /// in ['a, 'b, 'static]` (where `'r` is some region appearing in | |
297 | /// the hidden type). | |
298 | /// | |
299 | /// # Constrain regions, not the hidden concrete type | |
300 | /// | |
301 | /// Note that generating constraints on each region `Rc` is *not* | |
5e7ed085 | 302 | /// the same as generating an outlives constraint on `Tc` itself. |
3c0e092e XL |
303 | /// For example, if we had a function like this: |
304 | /// | |
04454e1e FG |
305 | /// ``` |
306 | /// # #![feature(type_alias_impl_trait)] | |
307 | /// # fn main() {} | |
308 | /// # trait Foo<'a> {} | |
309 | /// # impl<'a, T> Foo<'a> for (&'a u32, T) {} | |
3c0e092e XL |
310 | /// fn foo<'a, T>(x: &'a u32, y: T) -> impl Foo<'a> { |
311 | /// (x, y) | |
312 | /// } | |
313 | /// | |
314 | /// // Equivalent to: | |
04454e1e | 315 | /// # mod dummy { use super::*; |
3c0e092e | 316 | /// type FooReturn<'a, T> = impl Foo<'a>; |
04454e1e FG |
317 | /// fn foo<'a, T>(x: &'a u32, y: T) -> FooReturn<'a, T> { |
318 | /// (x, y) | |
319 | /// } | |
320 | /// # } | |
3c0e092e XL |
321 | /// ``` |
322 | /// | |
323 | /// then the hidden type `Tc` would be `(&'0 u32, T)` (where `'0` | |
324 | /// is an inference variable). If we generated a constraint that | |
325 | /// `Tc: 'a`, then this would incorrectly require that `T: 'a` -- | |
326 | /// but this is not necessary, because the opaque type we | |
327 | /// create will be allowed to reference `T`. So we only generate a | |
328 | /// constraint that `'0: 'a`. | |
3c0e092e | 329 | #[instrument(level = "debug", skip(self))] |
5e7ed085 | 330 | pub fn register_member_constraints( |
3c0e092e | 331 | &self, |
5e7ed085 | 332 | param_env: ty::ParamEnv<'tcx>, |
3c0e092e | 333 | opaque_type_key: OpaqueTypeKey<'tcx>, |
5e7ed085 FG |
334 | concrete_ty: Ty<'tcx>, |
335 | span: Span, | |
3c0e092e | 336 | ) { |
5e7ed085 | 337 | let concrete_ty = self.resolve_vars_if_possible(concrete_ty); |
3c0e092e XL |
338 | debug!(?concrete_ty); |
339 | ||
487cf647 FG |
340 | let variances = self.tcx.variances_of(opaque_type_key.def_id); |
341 | debug!(?variances); | |
3c0e092e XL |
342 | |
343 | // For a case like `impl Foo<'a, 'b>`, we would generate a constraint | |
344 | // `'r in ['a, 'b, 'static]` for each region `'r` that appears in the | |
345 | // hidden type (i.e., it must be equal to `'a`, `'b`, or `'static`). | |
346 | // | |
347 | // `conflict1` and `conflict2` are the two region bounds that we | |
348 | // detected which were unrelated. They are used for diagnostics. | |
349 | ||
350 | // Create the set of choice regions: each region in the hidden | |
351 | // type can be equal to any of the region parameters of the | |
352 | // opaque type definition. | |
353 | let choice_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new( | |
487cf647 FG |
354 | opaque_type_key |
355 | .substs | |
3c0e092e | 356 | .iter() |
487cf647 FG |
357 | .enumerate() |
358 | .filter(|(i, _)| variances[*i] == ty::Variance::Invariant) | |
359 | .filter_map(|(_, arg)| match arg.unpack() { | |
3c0e092e XL |
360 | GenericArgKind::Lifetime(r) => Some(r), |
361 | GenericArgKind::Type(_) | GenericArgKind::Const(_) => None, | |
362 | }) | |
363 | .chain(std::iter::once(self.tcx.lifetimes.re_static)) | |
364 | .collect(), | |
365 | ); | |
366 | ||
367 | concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { | |
487cf647 | 368 | tcx: self.tcx, |
064997fb | 369 | op: |r| self.member_constraint(opaque_type_key, span, concrete_ty, r, &choice_regions), |
3c0e092e XL |
370 | }); |
371 | } | |
5099ac24 | 372 | |
9ffffee4 FG |
373 | /// Returns the origin of the opaque type `def_id` if we're currently |
374 | /// in its defining scope. | |
f2b60f7d | 375 | #[instrument(skip(self), level = "trace", ret)] |
9ffffee4 | 376 | pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> { |
5e7ed085 | 377 | let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); |
064997fb FG |
378 | let parent_def_id = match self.defining_use_anchor { |
379 | DefiningAnchor::Bubble | DefiningAnchor::Error => return None, | |
380 | DefiningAnchor::Bind(bind) => bind, | |
381 | }; | |
9ffffee4 FG |
382 | |
383 | let origin = self.opaque_type_origin_unchecked(def_id); | |
384 | let in_definition_scope = match origin { | |
5099ac24 FG |
385 | // Async `impl Trait` |
386 | hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id, | |
387 | // Anonymous `impl Trait` | |
388 | hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, | |
389 | // Named `type Foo = impl Bar;` | |
49aad941 FG |
390 | hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => { |
391 | if in_assoc_ty { | |
392 | self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id) | |
393 | } else { | |
394 | may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id) | |
395 | } | |
5099ac24 FG |
396 | } |
397 | }; | |
9ffffee4 | 398 | in_definition_scope.then_some(origin) |
5099ac24 | 399 | } |
5e7ed085 | 400 | |
9ffffee4 FG |
401 | /// Returns the origin of the opaque type `def_id` even if we are not in its |
402 | /// defining scope. | |
f2b60f7d | 403 | #[instrument(skip(self), level = "trace", ret)] |
9ffffee4 | 404 | fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin { |
49aad941 | 405 | self.tcx.hir().expect_item(def_id).expect_opaque_ty().origin |
5e7ed085 | 406 | } |
3c0e092e XL |
407 | } |
408 | ||
487cf647 FG |
409 | /// Visitor that requires that (almost) all regions in the type visited outlive |
410 | /// `least_region`. We cannot use `push_outlives_components` because regions in | |
411 | /// closure signatures are not included in their outlives components. We need to | |
412 | /// ensure all regions outlive the given bound so that we don't end up with, | |
413 | /// say, `ReVar` appearing in a return type and causing ICEs when other | |
414 | /// functions end up with region constraints involving regions from other | |
415 | /// functions. | |
416 | /// | |
417 | /// We also cannot use `for_each_free_region` because for closures it includes | |
418 | /// the regions parameters from the enclosing item. | |
419 | /// | |
420 | /// We ignore any type parameters because impl trait values are assumed to | |
421 | /// capture all the in-scope type parameters. | |
422 | pub struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP: FnMut(ty::Region<'tcx>)> { | |
423 | pub tcx: TyCtxt<'tcx>, | |
424 | pub op: OP, | |
3c0e092e XL |
425 | } |
426 | ||
9ffffee4 | 427 | impl<'tcx, OP> TypeVisitor<TyCtxt<'tcx>> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP> |
3c0e092e XL |
428 | where |
429 | OP: FnMut(ty::Region<'tcx>), | |
430 | { | |
9ffffee4 | 431 | fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( |
3c0e092e XL |
432 | &mut self, |
433 | t: &ty::Binder<'tcx, T>, | |
434 | ) -> ControlFlow<Self::BreakTy> { | |
923072b8 | 435 | t.super_visit_with(self); |
9c376795 | 436 | ControlFlow::Continue(()) |
3c0e092e XL |
437 | } |
438 | ||
439 | fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { | |
440 | match *r { | |
441 | // ignore bound regions, keep visiting | |
9c376795 | 442 | ty::ReLateBound(_, _) => ControlFlow::Continue(()), |
3c0e092e XL |
443 | _ => { |
444 | (self.op)(r); | |
9c376795 | 445 | ControlFlow::Continue(()) |
3c0e092e XL |
446 | } |
447 | } | |
448 | } | |
449 | ||
450 | fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { | |
451 | // We're only interested in types involving regions | |
5099ac24 | 452 | if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) { |
9c376795 | 453 | return ControlFlow::Continue(()); |
3c0e092e XL |
454 | } |
455 | ||
456 | match ty.kind() { | |
457 | ty::Closure(_, ref substs) => { | |
458 | // Skip lifetime parameters of the enclosing item(s) | |
459 | ||
460 | substs.as_closure().tupled_upvars_ty().visit_with(self); | |
461 | substs.as_closure().sig_as_fn_ptr_ty().visit_with(self); | |
462 | } | |
463 | ||
464 | ty::Generator(_, ref substs, _) => { | |
465 | // Skip lifetime parameters of the enclosing item(s) | |
466 | // Also skip the witness type, because that has no free regions. | |
467 | ||
468 | substs.as_generator().tupled_upvars_ty().visit_with(self); | |
469 | substs.as_generator().return_ty().visit_with(self); | |
470 | substs.as_generator().yield_ty().visit_with(self); | |
471 | substs.as_generator().resume_ty().visit_with(self); | |
472 | } | |
487cf647 | 473 | |
9c376795 FG |
474 | ty::Alias(ty::Opaque, ty::AliasTy { def_id, ref substs, .. }) => { |
475 | // Skip lifetime parameters that are not captures. | |
487cf647 FG |
476 | let variances = self.tcx.variances_of(*def_id); |
477 | ||
478 | for (v, s) in std::iter::zip(variances, substs.iter()) { | |
479 | if *v != ty::Variance::Bivariant { | |
480 | s.visit_with(self); | |
481 | } | |
482 | } | |
483 | } | |
484 | ||
353b0b11 | 485 | ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => { |
9c376795 FG |
486 | // Skip lifetime parameters that are not captures. |
487 | let variances = self.tcx.variances_of(proj.def_id); | |
487cf647 FG |
488 | |
489 | for (v, s) in std::iter::zip(variances, proj.substs.iter()) { | |
490 | if *v != ty::Variance::Bivariant { | |
491 | s.visit_with(self); | |
492 | } | |
493 | } | |
494 | } | |
495 | ||
3c0e092e XL |
496 | _ => { |
497 | ty.super_visit_with(self); | |
498 | } | |
499 | } | |
500 | ||
9c376795 | 501 | ControlFlow::Continue(()) |
3c0e092e XL |
502 | } |
503 | } | |
504 | ||
5e7ed085 FG |
505 | pub enum UseKind { |
506 | DefiningUse, | |
507 | OpaqueUse, | |
3c0e092e XL |
508 | } |
509 | ||
5e7ed085 FG |
510 | impl UseKind { |
511 | pub fn is_defining(self) -> bool { | |
512 | match self { | |
513 | UseKind::DefiningUse => true, | |
514 | UseKind::OpaqueUse => false, | |
515 | } | |
3c0e092e | 516 | } |
5e7ed085 | 517 | } |
3c0e092e | 518 | |
2b03887a | 519 | impl<'tcx> InferCtxt<'tcx> { |
3c0e092e | 520 | #[instrument(skip(self), level = "debug")] |
2b03887a | 521 | fn register_hidden_type( |
5e7ed085 | 522 | &self, |
3c0e092e | 523 | opaque_type_key: OpaqueTypeKey<'tcx>, |
5e7ed085 FG |
524 | cause: ObligationCause<'tcx>, |
525 | param_env: ty::ParamEnv<'tcx>, | |
526 | hidden_ty: Ty<'tcx>, | |
3c0e092e | 527 | origin: hir::OpaqueTyOrigin, |
2b03887a | 528 | a_is_expected: bool, |
5e7ed085 | 529 | ) -> InferResult<'tcx, ()> { |
3c0e092e XL |
530 | // Ideally, we'd get the span where *this specific `ty` came |
531 | // from*, but right now we just use the span from the overall | |
532 | // value being folded. In simple cases like `-> impl Foo`, | |
533 | // these are the same span, but not in cases like `-> (impl | |
534 | // Foo, impl Bar)`. | |
5e7ed085 | 535 | let span = cause.span; |
5e7ed085 | 536 | let prev = self.inner.borrow_mut().opaque_types().register( |
49aad941 | 537 | opaque_type_key, |
5e7ed085 FG |
538 | OpaqueHiddenType { ty: hidden_ty, span }, |
539 | origin, | |
540 | ); | |
49aad941 FG |
541 | let mut obligations = if let Some(prev) = prev { |
542 | self.at(&cause, param_env) | |
353b0b11 | 543 | .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)? |
49aad941 FG |
544 | .obligations |
545 | } else { | |
546 | Vec::new() | |
547 | }; | |
548 | ||
549 | self.add_item_bounds_for_hidden_type( | |
550 | opaque_type_key, | |
551 | cause, | |
552 | param_env, | |
553 | hidden_ty, | |
554 | &mut obligations, | |
555 | ); | |
556 | ||
557 | Ok(InferOk { value: (), obligations }) | |
558 | } | |
3c0e092e | 559 | |
49aad941 FG |
560 | /// Registers an opaque's hidden type -- only should be used when the opaque |
561 | /// can be defined. For something more fallible -- checks the anchors, tries | |
562 | /// to unify opaques in both dirs, etc. -- use `InferCtxt::handle_opaque_type`. | |
563 | pub fn register_hidden_type_in_new_solver( | |
564 | &self, | |
565 | opaque_type_key: OpaqueTypeKey<'tcx>, | |
566 | param_env: ty::ParamEnv<'tcx>, | |
567 | hidden_ty: Ty<'tcx>, | |
568 | ) -> InferResult<'tcx, ()> { | |
569 | assert!(self.tcx.trait_solver_next()); | |
570 | let origin = self | |
571 | .opaque_type_origin(opaque_type_key.def_id) | |
572 | .expect("should be called for defining usages only"); | |
573 | self.register_hidden_type( | |
574 | opaque_type_key, | |
575 | ObligationCause::dummy(), | |
576 | param_env, | |
577 | hidden_ty, | |
578 | origin, | |
579 | true, | |
580 | ) | |
581 | } | |
582 | ||
583 | pub fn add_item_bounds_for_hidden_type( | |
584 | &self, | |
585 | OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>, | |
586 | cause: ObligationCause<'tcx>, | |
587 | param_env: ty::ParamEnv<'tcx>, | |
588 | hidden_ty: Ty<'tcx>, | |
589 | obligations: &mut Vec<PredicateObligation<'tcx>>, | |
590 | ) { | |
591 | let tcx = self.tcx; | |
592 | let item_bounds = tcx.explicit_item_bounds(def_id); | |
3c0e092e | 593 | |
2b03887a | 594 | for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) { |
5099ac24 FG |
595 | let predicate = predicate.fold_with(&mut BottomUpFolder { |
596 | tcx, | |
597 | ty_op: |ty| match *ty.kind() { | |
5e7ed085 FG |
598 | // We can't normalize associated types from `rustc_infer`, |
599 | // but we can eagerly register inference variables for them. | |
2b03887a | 600 | // FIXME(RPITIT): Don't replace RPITITs with inference vars. |
49aad941 | 601 | // FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too. |
9c376795 | 602 | ty::Alias(ty::Projection, projection_ty) |
2b03887a | 603 | if !projection_ty.has_escaping_bound_vars() |
49aad941 FG |
604 | && !tcx.is_impl_trait_in_trait(projection_ty.def_id) |
605 | && !tcx.trait_solver_next() => | |
2b03887a | 606 | { |
5e7ed085 FG |
607 | self.infer_projection( |
608 | param_env, | |
609 | projection_ty, | |
610 | cause.clone(), | |
5099ac24 | 611 | 0, |
49aad941 | 612 | obligations, |
5099ac24 FG |
613 | ) |
614 | } | |
5e7ed085 FG |
615 | // Replace all other mentions of the same opaque type with the hidden type, |
616 | // as the bounds must hold on the hidden type after all. | |
9c376795 | 617 | ty::Alias(ty::Opaque, ty::AliasTy { def_id: def_id2, substs: substs2, .. }) |
064997fb FG |
618 | if def_id.to_def_id() == def_id2 && substs == substs2 => |
619 | { | |
5e7ed085 FG |
620 | hidden_ty |
621 | } | |
2b03887a | 622 | // FIXME(RPITIT): This can go away when we move to associated types |
49aad941 | 623 | // FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too. |
9c376795 FG |
624 | ty::Alias( |
625 | ty::Projection, | |
626 | ty::AliasTy { def_id: def_id2, substs: substs2, .. }, | |
627 | ) if def_id.to_def_id() == def_id2 && substs == substs2 => hidden_ty, | |
3c0e092e XL |
628 | _ => ty, |
629 | }, | |
630 | lt_op: |lt| lt, | |
631 | ct_op: |ct| ct, | |
632 | }); | |
3c0e092e | 633 | |
487cf647 FG |
634 | if let ty::PredicateKind::Clause(ty::Clause::Projection(projection)) = |
635 | predicate.kind().skip_binder() | |
636 | { | |
5099ac24 | 637 | if projection.term.references_error() { |
49aad941 FG |
638 | // No point on adding any obligations since there's a type error involved. |
639 | obligations.clear(); | |
640 | return; | |
3c0e092e XL |
641 | } |
642 | } | |
3c0e092e XL |
643 | // Require that the predicate holds for the concrete type. |
644 | debug!(?predicate); | |
487cf647 FG |
645 | obligations.push(traits::Obligation::new( |
646 | self.tcx, | |
647 | cause.clone(), | |
648 | param_env, | |
649 | predicate, | |
650 | )); | |
3c0e092e | 651 | } |
3c0e092e XL |
652 | } |
653 | } | |
654 | ||
655 | /// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `def_id`. | |
656 | /// | |
657 | /// Example: | |
04454e1e FG |
658 | /// ```ignore UNSOLVED (is this a bug?) |
659 | /// # #![feature(type_alias_impl_trait)] | |
3c0e092e XL |
660 | /// pub mod foo { |
661 | /// pub mod bar { | |
04454e1e | 662 | /// pub trait Bar { /* ... */ } |
3c0e092e XL |
663 | /// pub type Baz = impl Bar; |
664 | /// | |
04454e1e FG |
665 | /// # impl Bar for () {} |
666 | /// fn f1() -> Baz { /* ... */ } | |
3c0e092e | 667 | /// } |
04454e1e | 668 | /// fn f2() -> bar::Baz { /* ... */ } |
3c0e092e XL |
669 | /// } |
670 | /// ``` | |
671 | /// | |
672 | /// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`), | |
673 | /// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`. | |
674 | /// For the above example, this function returns `true` for `f1` and `false` for `f2`. | |
675 | fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool { | |
676 | let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id); | |
677 | ||
678 | // Named opaque types can be defined by any siblings or children of siblings. | |
679 | let scope = tcx.hir().get_defining_scope(opaque_hir_id); | |
680 | // We walk up the node tree until we hit the root or the scope of the opaque type. | |
681 | while hir_id != scope && hir_id != hir::CRATE_HIR_ID { | |
2b03887a | 682 | hir_id = tcx.hir().get_parent_item(hir_id).into(); |
3c0e092e XL |
683 | } |
684 | // Syntactically, we are allowed to define the concrete type if: | |
685 | let res = hir_id == scope; | |
686 | trace!( | |
687 | "may_define_opaque_type(def={:?}, opaque_node={:?}) = {}", | |
688 | tcx.hir().find(hir_id), | |
689 | tcx.hir().get(opaque_hir_id), | |
690 | res | |
691 | ); | |
692 | res | |
693 | } |