]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_borrowck/src/region_infer/opaque_types.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / compiler / rustc_borrowck / src / region_infer / opaque_types.rs
CommitLineData
064997fb 1use rustc_data_structures::fx::FxHashMap;
17df50a5 2use rustc_data_structures::vec_map::VecMap;
064997fb 3use rustc_hir::def_id::LocalDefId;
c295e0f8 4use rustc_hir::OpaqueTyOrigin;
064997fb
FG
5use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
6use rustc_infer::infer::TyCtxtInferExt as _;
7use rustc_infer::infer::{DefiningAnchor, InferCtxt};
8use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine};
9use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
10use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
11use rustc_middle::ty::visit::TypeVisitable;
12use rustc_middle::ty::{
13 self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt, TypeFoldable,
14};
15use rustc_span::Span;
16use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
17use rustc_trait_selection::traits::TraitEngineExt as _;
74b04a01
XL
18
19use super::RegionInferenceContext;
20
21impl<'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
186pub 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
195impl<'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
337fn 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
429struct 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
443impl<'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
478impl<'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}