]>
Commit | Line | Data |
---|---|---|
064997fb | 1 | use rustc_data_structures::fx::FxHashMap; |
17df50a5 | 2 | use rustc_data_structures::vec_map::VecMap; |
064997fb | 3 | use rustc_hir::def_id::LocalDefId; |
c295e0f8 | 4 | use rustc_hir::OpaqueTyOrigin; |
064997fb FG |
5 | use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; |
6 | use rustc_infer::infer::TyCtxtInferExt as _; | |
7 | use rustc_infer::infer::{DefiningAnchor, InferCtxt}; | |
8 | use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine}; | |
9 | use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; | |
10 | use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts}; | |
11 | use rustc_middle::ty::visit::TypeVisitable; | |
12 | use rustc_middle::ty::{ | |
13 | self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt, TypeFoldable, | |
14 | }; | |
15 | use rustc_span::Span; | |
16 | use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; | |
17 | use rustc_trait_selection::traits::TraitEngineExt as _; | |
74b04a01 XL |
18 | |
19 | use super::RegionInferenceContext; | |
20 | ||
21 | impl<'tcx> RegionInferenceContext<'tcx> { | |
22 | /// Resolve any opaque types that were encountered while borrow checking | |
23 | /// this item. This is then used to get the type in the `type_of` query. | |
24 | /// | |
25 | /// For example consider `fn f<'a>(x: &'a i32) -> impl Sized + 'a { x }`. | |
26 | /// This is lowered to give HIR something like | |
27 | /// | |
28 | /// type f<'a>::_Return<'_a> = impl Sized + '_a; | |
29 | /// fn f<'a>(x: &'a i32) -> f<'static>::_Return<'a> { x } | |
30 | /// | |
31 | /// When checking the return type record the type from the return and the | |
32 | /// type used in the return value. In this case they might be `_Return<'1>` | |
33 | /// and `&'2 i32` respectively. | |
34 | /// | |
35 | /// Once we to this method, we have completed region inference and want to | |
36 | /// call `infer_opaque_definition_from_instantiation` to get the inferred | |
37 | /// type of `_Return<'_a>`. `infer_opaque_definition_from_instantiation` | |
38 | /// compares lifetimes directly, so we need to map the inference variables | |
39 | /// back to concrete lifetimes: `'static`, `ReEarlyBound` or `ReFree`. | |
40 | /// | |
41 | /// First we map all the lifetimes in the concrete type to an equal | |
42 | /// universal region that occurs in the concrete type's substs, in this case | |
43 | /// this would result in `&'1 i32`. We only consider regions in the substs | |
44 | /// in case there is an equal region that does not. For example, this should | |
45 | /// be allowed: | |
46 | /// `fn f<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a { x }` | |
47 | /// | |
48 | /// Then we map the regions in both the type and the subst to their | |
49 | /// `external_name` giving `concrete_type = &'a i32`, | |
50 | /// `substs = ['static, 'a]`. This will then allow | |
51 | /// `infer_opaque_definition_from_instantiation` to determine that | |
52 | /// `_Return<'_a> = &'_a i32`. | |
53 | /// | |
54 | /// There's a slight complication around closures. Given | |
55 | /// `fn f<'a: 'a>() { || {} }` the closure's type is something like | |
56 | /// `f::<'a>::{{closure}}`. The region parameter from f is essentially | |
57 | /// ignored by type checking so ends up being inferred to an empty region. | |
58 | /// Calling `universal_upper_bound` for such a region gives `fr_fn_body`, | |
59 | /// which has no `external_name` in which case we use `'empty` as the | |
60 | /// region to pass to `infer_opaque_definition_from_instantiation`. | |
c295e0f8 XL |
61 | #[instrument(level = "debug", skip(self, infcx))] |
62 | pub(crate) fn infer_opaque_types( | |
74b04a01 XL |
63 | &self, |
64 | infcx: &InferCtxt<'_, 'tcx>, | |
5e7ed085 | 65 | opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>, |
064997fb FG |
66 | ) -> VecMap<LocalDefId, OpaqueHiddenType<'tcx>> { |
67 | let mut result: VecMap<LocalDefId, OpaqueHiddenType<'tcx>> = VecMap::new(); | |
5e7ed085 FG |
68 | for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls { |
69 | let substs = opaque_type_key.substs; | |
70 | debug!(?concrete_type, ?substs); | |
74b04a01 | 71 | |
5e7ed085 | 72 | let mut subst_regions = vec![self.universal_regions.fr_static]; |
064997fb | 73 | let universal_substs = infcx.tcx.fold_regions(substs, |region, _| { |
5e7ed085 FG |
74 | if let ty::RePlaceholder(..) = region.kind() { |
75 | // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs. | |
76 | return region; | |
77 | } | |
78 | let vid = self.to_region_vid(region); | |
79 | trace!(?vid); | |
80 | let scc = self.constraint_sccs.scc(vid); | |
81 | trace!(?scc); | |
82 | match self.scc_values.universal_regions_outlived_by(scc).find_map(|lb| { | |
83 | self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?) | |
84 | }) { | |
85 | Some(region) => { | |
86 | let vid = self.universal_regions.to_region_vid(region); | |
87 | subst_regions.push(vid); | |
88 | region | |
89 | } | |
90 | None => { | |
91 | subst_regions.push(vid); | |
92 | infcx.tcx.sess.delay_span_bug( | |
93 | concrete_type.span, | |
94 | "opaque type with non-universal region substs", | |
95 | ); | |
136023e0 | 96 | infcx.tcx.lifetimes.re_static |
5e7ed085 FG |
97 | } |
98 | } | |
99 | }); | |
74b04a01 | 100 | |
5e7ed085 FG |
101 | subst_regions.sort(); |
102 | subst_regions.dedup(); | |
74b04a01 | 103 | |
5e7ed085 | 104 | let universal_concrete_type = |
064997fb | 105 | infcx.tcx.fold_regions(concrete_type, |region, _| match *region { |
5e7ed085 FG |
106 | ty::ReVar(vid) => subst_regions |
107 | .iter() | |
108 | .find(|ur_vid| self.eval_equal(vid, **ur_vid)) | |
109 | .and_then(|ur_vid| self.definitions[*ur_vid].external_name) | |
110 | .unwrap_or(infcx.tcx.lifetimes.re_root_empty), | |
111 | _ => region, | |
112 | }); | |
74b04a01 | 113 | |
5e7ed085 | 114 | debug!(?universal_concrete_type, ?universal_substs); |
c295e0f8 | 115 | |
5e7ed085 FG |
116 | let opaque_type_key = |
117 | OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs }; | |
04454e1e | 118 | let ty = infcx.infer_opaque_definition_from_instantiation( |
5e7ed085 FG |
119 | opaque_type_key, |
120 | universal_concrete_type, | |
5e7ed085 | 121 | origin, |
04454e1e | 122 | ); |
5e7ed085 FG |
123 | // Sometimes two opaque types are the same only after we remap the generic parameters |
124 | // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)` | |
125 | // and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that | |
126 | // once we convert the generic parameters to those of the opaque type. | |
04454e1e | 127 | if let Some(prev) = result.get_mut(&opaque_type_key.def_id) { |
5e7ed085 | 128 | if prev.ty != ty { |
04454e1e FG |
129 | if !ty.references_error() { |
130 | prev.report_mismatch( | |
131 | &OpaqueHiddenType { ty, span: concrete_type.span }, | |
132 | infcx.tcx, | |
133 | ); | |
134 | } | |
5e7ed085 FG |
135 | prev.ty = infcx.tcx.ty_error(); |
136 | } | |
137 | // Pick a better span if there is one. | |
138 | // FIXME(oli-obk): collect multiple spans for better diagnostics down the road. | |
139 | prev.span = prev.span.substitute_dummy(concrete_type.span); | |
140 | } else { | |
04454e1e FG |
141 | result.insert( |
142 | opaque_type_key.def_id, | |
143 | OpaqueHiddenType { ty, span: concrete_type.span }, | |
144 | ); | |
5e7ed085 FG |
145 | } |
146 | } | |
147 | result | |
74b04a01 XL |
148 | } |
149 | ||
150 | /// Map the regions in the type to named regions. This is similar to what | |
151 | /// `infer_opaque_types` does, but can infer any universal region, not only | |
152 | /// ones from the substs for the opaque type. It also doesn't double check | |
153 | /// that the regions produced are in fact equal to the named region they are | |
154 | /// replaced with. This is fine because this function is only to improve the | |
155 | /// region names in error messages. | |
c295e0f8 | 156 | pub(crate) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T |
74b04a01 XL |
157 | where |
158 | T: TypeFoldable<'tcx>, | |
159 | { | |
064997fb | 160 | tcx.fold_regions(ty, |region, _| match *region { |
74b04a01 | 161 | ty::ReVar(vid) => { |
f035d41b XL |
162 | // Find something that we can name |
163 | let upper_bound = self.approx_universal_upper_bound(vid); | |
c295e0f8 XL |
164 | let upper_bound = &self.definitions[upper_bound]; |
165 | match upper_bound.external_name { | |
166 | Some(reg) => reg, | |
167 | None => { | |
168 | // Nothing exact found, so we pick the first one that we find. | |
169 | let scc = self.constraint_sccs.scc(vid); | |
170 | for vid in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) { | |
171 | match self.definitions[vid].external_name { | |
172 | None => {} | |
5099ac24 | 173 | Some(region) if region.is_static() => {} |
c295e0f8 XL |
174 | Some(region) => return region, |
175 | } | |
176 | } | |
177 | region | |
178 | } | |
179 | } | |
74b04a01 XL |
180 | } |
181 | _ => region, | |
182 | }) | |
183 | } | |
184 | } | |
064997fb FG |
185 | |
186 | pub trait InferCtxtExt<'tcx> { | |
187 | fn infer_opaque_definition_from_instantiation( | |
188 | &self, | |
189 | opaque_type_key: OpaqueTypeKey<'tcx>, | |
190 | instantiated_ty: OpaqueHiddenType<'tcx>, | |
191 | origin: OpaqueTyOrigin, | |
192 | ) -> Ty<'tcx>; | |
193 | } | |
194 | ||
195 | impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | |
196 | /// Given the fully resolved, instantiated type for an opaque | |
197 | /// type, i.e., the value of an inference variable like C1 or C2 | |
198 | /// (*), computes the "definition type" for an opaque type | |
199 | /// definition -- that is, the inferred value of `Foo1<'x>` or | |
200 | /// `Foo2<'x>` that we would conceptually use in its definition: | |
201 | /// ```ignore (illustrative) | |
202 | /// type Foo1<'x> = impl Bar<'x> = AAA; // <-- this type AAA | |
203 | /// type Foo2<'x> = impl Bar<'x> = BBB; // <-- or this type BBB | |
204 | /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. } | |
205 | /// ``` | |
206 | /// Note that these values are defined in terms of a distinct set of | |
207 | /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main | |
208 | /// purpose of this function is to do that translation. | |
209 | /// | |
210 | /// (*) C1 and C2 were introduced in the comments on | |
211 | /// `register_member_constraints`. Read that comment for more context. | |
212 | /// | |
213 | /// # Parameters | |
214 | /// | |
215 | /// - `def_id`, the `impl Trait` type | |
216 | /// - `substs`, the substs used to instantiate this opaque type | |
217 | /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of | |
218 | /// `opaque_defn.concrete_ty` | |
219 | #[instrument(level = "debug", skip(self))] | |
220 | fn infer_opaque_definition_from_instantiation( | |
221 | &self, | |
222 | opaque_type_key: OpaqueTypeKey<'tcx>, | |
223 | instantiated_ty: OpaqueHiddenType<'tcx>, | |
224 | origin: OpaqueTyOrigin, | |
225 | ) -> Ty<'tcx> { | |
226 | if self.is_tainted_by_errors() { | |
227 | return self.tcx.ty_error(); | |
228 | } | |
229 | ||
230 | let OpaqueTypeKey { def_id, substs } = opaque_type_key; | |
231 | ||
232 | // Use substs to build up a reverse map from regions to their | |
233 | // identity mappings. This is necessary because of `impl | |
234 | // Trait` lifetimes are computed by replacing existing | |
235 | // lifetimes with 'static and remapping only those used in the | |
236 | // `impl Trait` return type, resulting in the parameters | |
237 | // shifting. | |
238 | let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id.to_def_id()); | |
239 | debug!(?id_substs); | |
240 | let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> = | |
241 | substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect(); | |
242 | debug!("map = {:#?}", map); | |
243 | ||
244 | // Convert the type from the function into a type valid outside | |
245 | // the function, by replacing invalid regions with 'static, | |
246 | // after producing an error for each of them. | |
247 | let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new( | |
248 | self.tcx, | |
249 | opaque_type_key, | |
250 | map, | |
251 | instantiated_ty.ty, | |
252 | instantiated_ty.span, | |
253 | )); | |
254 | debug!(?definition_ty); | |
255 | ||
256 | if !check_opaque_type_parameter_valid( | |
257 | self.tcx, | |
258 | opaque_type_key, | |
259 | origin, | |
260 | instantiated_ty.span, | |
261 | ) { | |
262 | return self.tcx.ty_error(); | |
263 | } | |
264 | ||
265 | // Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs` | |
266 | // on stable and we'd break that. | |
267 | if let OpaqueTyOrigin::TyAlias = origin { | |
268 | // This logic duplicates most of `check_opaque_meets_bounds`. | |
269 | // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely. | |
270 | let param_env = self.tcx.param_env(def_id); | |
271 | let body_id = self.tcx.local_def_id_to_hir_id(def_id); | |
272 | // HACK This bubble is required for this tests to pass: | |
273 | // type-alias-impl-trait/issue-67844-nested-opaque.rs | |
274 | self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter( | |
275 | move |infcx| { | |
276 | // Require the hidden type to be well-formed with only the generics of the opaque type. | |
277 | // Defining use functions may have more bounds than the opaque type, which is ok, as long as the | |
278 | // hidden type is well formed even without those bounds. | |
279 | let predicate = | |
280 | ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into())) | |
281 | .to_predicate(infcx.tcx); | |
282 | let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx); | |
283 | ||
284 | // Require that the hidden type actually fulfills all the bounds of the opaque type, even without | |
285 | // the bounds that the function supplies. | |
286 | match infcx.register_hidden_type( | |
287 | OpaqueTypeKey { def_id, substs: id_substs }, | |
288 | ObligationCause::misc(instantiated_ty.span, body_id), | |
289 | param_env, | |
290 | definition_ty, | |
291 | origin, | |
292 | ) { | |
293 | Ok(infer_ok) => { | |
294 | for obligation in infer_ok.obligations { | |
295 | fulfillment_cx.register_predicate_obligation(&infcx, obligation); | |
296 | } | |
297 | } | |
298 | Err(err) => { | |
299 | infcx | |
300 | .report_mismatched_types( | |
301 | &ObligationCause::misc(instantiated_ty.span, body_id), | |
302 | self.tcx.mk_opaque(def_id.to_def_id(), id_substs), | |
303 | definition_ty, | |
304 | err, | |
305 | ) | |
306 | .emit(); | |
307 | } | |
308 | } | |
309 | ||
310 | fulfillment_cx.register_predicate_obligation( | |
311 | &infcx, | |
312 | Obligation::misc(instantiated_ty.span, body_id, param_env, predicate), | |
313 | ); | |
314 | ||
315 | // Check that all obligations are satisfied by the implementation's | |
316 | // version. | |
317 | let errors = fulfillment_cx.select_all_or_error(&infcx); | |
318 | ||
319 | // This is still required for many(half of the tests in ui/type-alias-impl-trait) | |
320 | // tests to pass | |
321 | let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); | |
322 | ||
323 | if errors.is_empty() { | |
324 | definition_ty | |
325 | } else { | |
326 | infcx.report_fulfillment_errors(&errors, None, false); | |
327 | self.tcx.ty_error() | |
328 | } | |
329 | }, | |
330 | ) | |
331 | } else { | |
332 | definition_ty | |
333 | } | |
334 | } | |
335 | } | |
336 | ||
337 | fn check_opaque_type_parameter_valid( | |
338 | tcx: TyCtxt<'_>, | |
339 | opaque_type_key: OpaqueTypeKey<'_>, | |
340 | origin: OpaqueTyOrigin, | |
341 | span: Span, | |
342 | ) -> bool { | |
343 | match origin { | |
344 | // No need to check return position impl trait (RPIT) | |
345 | // because for type and const parameters they are correct | |
346 | // by construction: we convert | |
347 | // | |
348 | // fn foo<P0..Pn>() -> impl Trait | |
349 | // | |
350 | // into | |
351 | // | |
352 | // type Foo<P0...Pn> | |
353 | // fn foo<P0..Pn>() -> Foo<P0...Pn>. | |
354 | // | |
355 | // For lifetime parameters we convert | |
356 | // | |
357 | // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> | |
358 | // | |
359 | // into | |
360 | // | |
361 | // type foo::<'p0..'pn>::Foo<'q0..'qm> | |
362 | // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>. | |
363 | // | |
364 | // which would error here on all of the `'static` args. | |
365 | OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true, | |
366 | // Check these | |
367 | OpaqueTyOrigin::TyAlias => {} | |
368 | } | |
369 | let opaque_generics = tcx.generics_of(opaque_type_key.def_id); | |
370 | let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default(); | |
371 | for (i, arg) in opaque_type_key.substs.iter().enumerate() { | |
372 | let arg_is_param = match arg.unpack() { | |
373 | GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), | |
374 | GenericArgKind::Lifetime(lt) if lt.is_static() => { | |
375 | tcx.sess | |
376 | .struct_span_err(span, "non-defining opaque type use in defining scope") | |
377 | .span_label( | |
378 | tcx.def_span(opaque_generics.param_at(i, tcx).def_id), | |
379 | "cannot use static lifetime; use a bound lifetime \ | |
380 | instead or remove the lifetime parameter from the \ | |
381 | opaque type", | |
382 | ) | |
383 | .emit(); | |
384 | return false; | |
385 | } | |
386 | GenericArgKind::Lifetime(lt) => { | |
387 | matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_)) | |
388 | } | |
389 | GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)), | |
390 | }; | |
391 | ||
392 | if arg_is_param { | |
393 | seen_params.entry(arg).or_default().push(i); | |
394 | } else { | |
395 | // Prevent `fn foo() -> Foo<u32>` from being defining. | |
396 | let opaque_param = opaque_generics.param_at(i, tcx); | |
397 | tcx.sess | |
398 | .struct_span_err(span, "non-defining opaque type use in defining scope") | |
399 | .span_note( | |
400 | tcx.def_span(opaque_param.def_id), | |
401 | &format!( | |
402 | "used non-generic {} `{}` for generic parameter", | |
403 | opaque_param.kind.descr(), | |
404 | arg, | |
405 | ), | |
406 | ) | |
407 | .emit(); | |
408 | return false; | |
409 | } | |
410 | } | |
411 | ||
412 | for (_, indices) in seen_params { | |
413 | if indices.len() > 1 { | |
414 | let descr = opaque_generics.param_at(indices[0], tcx).kind.descr(); | |
415 | let spans: Vec<_> = indices | |
416 | .into_iter() | |
417 | .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) | |
418 | .collect(); | |
419 | tcx.sess | |
420 | .struct_span_err(span, "non-defining opaque type use in defining scope") | |
421 | .span_note(spans, &format!("{} used multiple times", descr)) | |
422 | .emit(); | |
423 | return false; | |
424 | } | |
425 | } | |
426 | true | |
427 | } | |
428 | ||
429 | struct ReverseMapper<'tcx> { | |
430 | tcx: TyCtxt<'tcx>, | |
431 | ||
432 | key: ty::OpaqueTypeKey<'tcx>, | |
433 | map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>, | |
434 | map_missing_regions_to_empty: bool, | |
435 | ||
436 | /// initially `Some`, set to `None` once error has been reported | |
437 | hidden_ty: Option<Ty<'tcx>>, | |
438 | ||
439 | /// Span of function being checked. | |
440 | span: Span, | |
441 | } | |
442 | ||
443 | impl<'tcx> ReverseMapper<'tcx> { | |
444 | fn new( | |
445 | tcx: TyCtxt<'tcx>, | |
446 | key: ty::OpaqueTypeKey<'tcx>, | |
447 | map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>, | |
448 | hidden_ty: Ty<'tcx>, | |
449 | span: Span, | |
450 | ) -> Self { | |
451 | Self { | |
452 | tcx, | |
453 | key, | |
454 | map, | |
455 | map_missing_regions_to_empty: false, | |
456 | hidden_ty: Some(hidden_ty), | |
457 | span, | |
458 | } | |
459 | } | |
460 | ||
461 | fn fold_kind_mapping_missing_regions_to_empty( | |
462 | &mut self, | |
463 | kind: GenericArg<'tcx>, | |
464 | ) -> GenericArg<'tcx> { | |
465 | assert!(!self.map_missing_regions_to_empty); | |
466 | self.map_missing_regions_to_empty = true; | |
467 | let kind = kind.fold_with(self); | |
468 | self.map_missing_regions_to_empty = false; | |
469 | kind | |
470 | } | |
471 | ||
472 | fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> { | |
473 | assert!(!self.map_missing_regions_to_empty); | |
474 | kind.fold_with(self) | |
475 | } | |
476 | } | |
477 | ||
478 | impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> { | |
479 | fn tcx(&self) -> TyCtxt<'tcx> { | |
480 | self.tcx | |
481 | } | |
482 | ||
483 | #[instrument(skip(self), level = "debug")] | |
484 | fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { | |
485 | match *r { | |
486 | // Ignore bound regions and `'static` regions that appear in the | |
487 | // type, we only need to remap regions that reference lifetimes | |
488 | // from the function declaration. | |
489 | // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`. | |
490 | ty::ReLateBound(..) | ty::ReStatic => return r, | |
491 | ||
492 | // If regions have been erased (by writeback), don't try to unerase | |
493 | // them. | |
494 | ty::ReErased => return r, | |
495 | ||
496 | // The regions that we expect from borrow checking. | |
497 | ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {} | |
498 | ||
499 | ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) => { | |
500 | // All of the regions in the type should either have been | |
501 | // erased by writeback, or mapped back to named regions by | |
502 | // borrow checking. | |
503 | bug!("unexpected region kind in opaque type: {:?}", r); | |
504 | } | |
505 | } | |
506 | ||
507 | let generics = self.tcx().generics_of(self.key.def_id); | |
508 | match self.map.get(&r.into()).map(|k| k.unpack()) { | |
509 | Some(GenericArgKind::Lifetime(r1)) => r1, | |
510 | Some(u) => panic!("region mapped to unexpected kind: {:?}", u), | |
511 | None if self.map_missing_regions_to_empty => self.tcx.lifetimes.re_root_empty, | |
512 | None if generics.parent.is_some() => { | |
513 | if let Some(hidden_ty) = self.hidden_ty.take() { | |
514 | unexpected_hidden_region_diagnostic( | |
515 | self.tcx, | |
516 | self.tcx.def_span(self.key.def_id), | |
517 | hidden_ty, | |
518 | r, | |
519 | self.key, | |
520 | ) | |
521 | .emit(); | |
522 | } | |
523 | self.tcx.lifetimes.re_root_empty | |
524 | } | |
525 | None => { | |
526 | self.tcx | |
527 | .sess | |
528 | .struct_span_err(self.span, "non-defining opaque type use in defining scope") | |
529 | .span_label( | |
530 | self.span, | |
531 | format!( | |
532 | "lifetime `{}` is part of concrete type but not used in \ | |
533 | parameter list of the `impl Trait` type alias", | |
534 | r | |
535 | ), | |
536 | ) | |
537 | .emit(); | |
538 | ||
539 | self.tcx().lifetimes.re_static | |
540 | } | |
541 | } | |
542 | } | |
543 | ||
544 | fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { | |
545 | match *ty.kind() { | |
546 | ty::Closure(def_id, substs) => { | |
547 | // I am a horrible monster and I pray for death. When | |
548 | // we encounter a closure here, it is always a closure | |
549 | // from within the function that we are currently | |
550 | // type-checking -- one that is now being encapsulated | |
551 | // in an opaque type. Ideally, we would | |
552 | // go through the types/lifetimes that it references | |
553 | // and treat them just like we would any other type, | |
554 | // which means we would error out if we find any | |
555 | // reference to a type/region that is not in the | |
556 | // "reverse map". | |
557 | // | |
558 | // **However,** in the case of closures, there is a | |
559 | // somewhat subtle (read: hacky) consideration. The | |
560 | // problem is that our closure types currently include | |
561 | // all the lifetime parameters declared on the | |
562 | // enclosing function, even if they are unused by the | |
563 | // closure itself. We can't readily filter them out, | |
564 | // so here we replace those values with `'empty`. This | |
565 | // can't really make a difference to the rest of the | |
566 | // compiler; those regions are ignored for the | |
567 | // outlives relation, and hence don't affect trait | |
568 | // selection or auto traits, and they are erased | |
569 | // during codegen. | |
570 | ||
571 | let generics = self.tcx.generics_of(def_id); | |
572 | let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| { | |
573 | if index < generics.parent_count { | |
574 | // Accommodate missing regions in the parent kinds... | |
575 | self.fold_kind_mapping_missing_regions_to_empty(kind) | |
576 | } else { | |
577 | // ...but not elsewhere. | |
578 | self.fold_kind_normally(kind) | |
579 | } | |
580 | })); | |
581 | ||
582 | self.tcx.mk_closure(def_id, substs) | |
583 | } | |
584 | ||
585 | ty::Generator(def_id, substs, movability) => { | |
586 | let generics = self.tcx.generics_of(def_id); | |
587 | let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| { | |
588 | if index < generics.parent_count { | |
589 | // Accommodate missing regions in the parent kinds... | |
590 | self.fold_kind_mapping_missing_regions_to_empty(kind) | |
591 | } else { | |
592 | // ...but not elsewhere. | |
593 | self.fold_kind_normally(kind) | |
594 | } | |
595 | })); | |
596 | ||
597 | self.tcx.mk_generator(def_id, substs, movability) | |
598 | } | |
599 | ||
600 | ty::Param(param) => { | |
601 | // Look it up in the substitution list. | |
602 | match self.map.get(&ty.into()).map(|k| k.unpack()) { | |
603 | // Found it in the substitution list; replace with the parameter from the | |
604 | // opaque type. | |
605 | Some(GenericArgKind::Type(t1)) => t1, | |
606 | Some(u) => panic!("type mapped to unexpected kind: {:?}", u), | |
607 | None => { | |
608 | debug!(?param, ?self.map); | |
609 | self.tcx | |
610 | .sess | |
611 | .struct_span_err( | |
612 | self.span, | |
613 | &format!( | |
614 | "type parameter `{}` is part of concrete type but not \ | |
615 | used in parameter list for the `impl Trait` type alias", | |
616 | ty | |
617 | ), | |
618 | ) | |
619 | .emit(); | |
620 | ||
621 | self.tcx().ty_error() | |
622 | } | |
623 | } | |
624 | } | |
625 | ||
626 | _ => ty.super_fold_with(self), | |
627 | } | |
628 | } | |
629 | ||
630 | fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { | |
631 | trace!("checking const {:?}", ct); | |
632 | // Find a const parameter | |
633 | match ct.kind() { | |
634 | ty::ConstKind::Param(..) => { | |
635 | // Look it up in the substitution list. | |
636 | match self.map.get(&ct.into()).map(|k| k.unpack()) { | |
637 | // Found it in the substitution list, replace with the parameter from the | |
638 | // opaque type. | |
639 | Some(GenericArgKind::Const(c1)) => c1, | |
640 | Some(u) => panic!("const mapped to unexpected kind: {:?}", u), | |
641 | None => { | |
642 | self.tcx | |
643 | .sess | |
644 | .struct_span_err( | |
645 | self.span, | |
646 | &format!( | |
647 | "const parameter `{}` is part of concrete type but not \ | |
648 | used in parameter list for the `impl Trait` type alias", | |
649 | ct | |
650 | ), | |
651 | ) | |
652 | .emit(); | |
653 | ||
654 | self.tcx().const_error(ct.ty()) | |
655 | } | |
656 | } | |
657 | } | |
658 | ||
659 | _ => ct, | |
660 | } | |
661 | } | |
662 | } |