]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_trait_selection/src/opaque_types.rs
Rollup merge of #95495 - GuillaumeGomez:rm-unneeded-to-string, r=notriddle
[rust.git] / compiler / rustc_trait_selection / src / opaque_types.rs
1 use crate::traits;
2 use rustc_data_structures::fx::FxHashMap;
3 use rustc_hir::def_id::DefId;
4 use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
5 use rustc_infer::infer::InferCtxt;
6 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
7 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
8 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt};
9 use rustc_span::Span;
10
11 pub trait InferCtxtExt<'tcx> {
12     fn infer_opaque_definition_from_instantiation(
13         &self,
14         opaque_type_key: OpaqueTypeKey<'tcx>,
15         instantiated_ty: OpaqueHiddenType<'tcx>,
16     ) -> Ty<'tcx>;
17 }
18
19 impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
20     /// Given the fully resolved, instantiated type for an opaque
21     /// type, i.e., the value of an inference variable like C1 or C2
22     /// (*), computes the "definition type" for an opaque type
23     /// definition -- that is, the inferred value of `Foo1<'x>` or
24     /// `Foo2<'x>` that we would conceptually use in its definition:
25     ///
26     ///     type Foo1<'x> = impl Bar<'x> = AAA; <-- this type AAA
27     ///     type Foo2<'x> = impl Bar<'x> = BBB; <-- or this type BBB
28     ///     fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
29     ///
30     /// Note that these values are defined in terms of a distinct set of
31     /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main
32     /// purpose of this function is to do that translation.
33     ///
34     /// (*) C1 and C2 were introduced in the comments on
35     /// `register_member_constraints`. Read that comment for more context.
36     ///
37     /// # Parameters
38     ///
39     /// - `def_id`, the `impl Trait` type
40     /// - `substs`, the substs  used to instantiate this opaque type
41     /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
42     ///   `opaque_defn.concrete_ty`
43     #[instrument(level = "debug", skip(self))]
44     fn infer_opaque_definition_from_instantiation(
45         &self,
46         opaque_type_key: OpaqueTypeKey<'tcx>,
47         instantiated_ty: OpaqueHiddenType<'tcx>,
48     ) -> Ty<'tcx> {
49         if self.is_tainted_by_errors() {
50             return self.tcx.ty_error();
51         }
52
53         let OpaqueTypeKey { def_id, substs } = opaque_type_key;
54
55         // Use substs to build up a reverse map from regions to their
56         // identity mappings. This is necessary because of `impl
57         // Trait` lifetimes are computed by replacing existing
58         // lifetimes with 'static and remapping only those used in the
59         // `impl Trait` return type, resulting in the parameters
60         // shifting.
61         let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
62         debug!(?id_substs);
63         let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
64             substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect();
65         debug!("map = {:#?}", map);
66
67         // Convert the type from the function into a type valid outside
68         // the function, by replacing invalid regions with 'static,
69         // after producing an error for each of them.
70         let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new(
71             self.tcx,
72             def_id,
73             map,
74             instantiated_ty.ty,
75             instantiated_ty.span,
76         ));
77         debug!(?definition_ty);
78
79         definition_ty
80     }
81 }
82
83 struct ReverseMapper<'tcx> {
84     tcx: TyCtxt<'tcx>,
85
86     opaque_type_def_id: DefId,
87     map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
88     map_missing_regions_to_empty: bool,
89
90     /// initially `Some`, set to `None` once error has been reported
91     hidden_ty: Option<Ty<'tcx>>,
92
93     /// Span of function being checked.
94     span: Span,
95 }
96
97 impl<'tcx> ReverseMapper<'tcx> {
98     fn new(
99         tcx: TyCtxt<'tcx>,
100         opaque_type_def_id: DefId,
101         map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
102         hidden_ty: Ty<'tcx>,
103         span: Span,
104     ) -> Self {
105         Self {
106             tcx,
107             opaque_type_def_id,
108             map,
109             map_missing_regions_to_empty: false,
110             hidden_ty: Some(hidden_ty),
111             span,
112         }
113     }
114
115     fn fold_kind_mapping_missing_regions_to_empty(
116         &mut self,
117         kind: GenericArg<'tcx>,
118     ) -> GenericArg<'tcx> {
119         assert!(!self.map_missing_regions_to_empty);
120         self.map_missing_regions_to_empty = true;
121         let kind = kind.fold_with(self);
122         self.map_missing_regions_to_empty = false;
123         kind
124     }
125
126     fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
127         assert!(!self.map_missing_regions_to_empty);
128         kind.fold_with(self)
129     }
130 }
131
132 impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
133     fn tcx(&self) -> TyCtxt<'tcx> {
134         self.tcx
135     }
136
137     #[instrument(skip(self), level = "debug")]
138     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
139         match *r {
140             // Ignore bound regions and `'static` regions that appear in the
141             // type, we only need to remap regions that reference lifetimes
142             // from the function declaration.
143             // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
144             ty::ReLateBound(..) | ty::ReStatic => return r,
145
146             // If regions have been erased (by writeback), don't try to unerase
147             // them.
148             ty::ReErased => return r,
149
150             // The regions that we expect from borrow checking.
151             ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
152
153             ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) => {
154                 // All of the regions in the type should either have been
155                 // erased by writeback, or mapped back to named regions by
156                 // borrow checking.
157                 bug!("unexpected region kind in opaque type: {:?}", r);
158             }
159         }
160
161         let generics = self.tcx().generics_of(self.opaque_type_def_id);
162         match self.map.get(&r.into()).map(|k| k.unpack()) {
163             Some(GenericArgKind::Lifetime(r1)) => r1,
164             Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
165             None if self.map_missing_regions_to_empty => self.tcx.lifetimes.re_root_empty,
166             None if generics.parent.is_some() => {
167                 if let Some(hidden_ty) = self.hidden_ty.take() {
168                     unexpected_hidden_region_diagnostic(
169                         self.tcx,
170                         self.tcx.def_span(self.opaque_type_def_id),
171                         hidden_ty,
172                         r,
173                     )
174                     .emit();
175                 }
176                 self.tcx.lifetimes.re_root_empty
177             }
178             None => {
179                 self.tcx
180                     .sess
181                     .struct_span_err(self.span, "non-defining opaque type use in defining scope")
182                     .span_label(
183                         self.span,
184                         format!(
185                             "lifetime `{}` is part of concrete type but not used in \
186                                  parameter list of the `impl Trait` type alias",
187                             r
188                         ),
189                     )
190                     .emit();
191
192                 self.tcx().lifetimes.re_static
193             }
194         }
195     }
196
197     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
198         match *ty.kind() {
199             ty::Closure(def_id, substs) => {
200                 // I am a horrible monster and I pray for death. When
201                 // we encounter a closure here, it is always a closure
202                 // from within the function that we are currently
203                 // type-checking -- one that is now being encapsulated
204                 // in an opaque type. Ideally, we would
205                 // go through the types/lifetimes that it references
206                 // and treat them just like we would any other type,
207                 // which means we would error out if we find any
208                 // reference to a type/region that is not in the
209                 // "reverse map".
210                 //
211                 // **However,** in the case of closures, there is a
212                 // somewhat subtle (read: hacky) consideration. The
213                 // problem is that our closure types currently include
214                 // all the lifetime parameters declared on the
215                 // enclosing function, even if they are unused by the
216                 // closure itself. We can't readily filter them out,
217                 // so here we replace those values with `'empty`. This
218                 // can't really make a difference to the rest of the
219                 // compiler; those regions are ignored for the
220                 // outlives relation, and hence don't affect trait
221                 // selection or auto traits, and they are erased
222                 // during codegen.
223
224                 let generics = self.tcx.generics_of(def_id);
225                 let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
226                     if index < generics.parent_count {
227                         // Accommodate missing regions in the parent kinds...
228                         self.fold_kind_mapping_missing_regions_to_empty(kind)
229                     } else {
230                         // ...but not elsewhere.
231                         self.fold_kind_normally(kind)
232                     }
233                 }));
234
235                 self.tcx.mk_closure(def_id, substs)
236             }
237
238             ty::Generator(def_id, substs, movability) => {
239                 let generics = self.tcx.generics_of(def_id);
240                 let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
241                     if index < generics.parent_count {
242                         // Accommodate missing regions in the parent kinds...
243                         self.fold_kind_mapping_missing_regions_to_empty(kind)
244                     } else {
245                         // ...but not elsewhere.
246                         self.fold_kind_normally(kind)
247                     }
248                 }));
249
250                 self.tcx.mk_generator(def_id, substs, movability)
251             }
252
253             ty::Param(param) => {
254                 // Look it up in the substitution list.
255                 match self.map.get(&ty.into()).map(|k| k.unpack()) {
256                     // Found it in the substitution list; replace with the parameter from the
257                     // opaque type.
258                     Some(GenericArgKind::Type(t1)) => t1,
259                     Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
260                     None => {
261                         debug!(?param, ?self.map);
262                         self.tcx
263                             .sess
264                             .struct_span_err(
265                                 self.span,
266                                 &format!(
267                                     "type parameter `{}` is part of concrete type but not \
268                                           used in parameter list for the `impl Trait` type alias",
269                                     ty
270                                 ),
271                             )
272                             .emit();
273
274                         self.tcx().ty_error()
275                     }
276                 }
277             }
278
279             _ => ty.super_fold_with(self),
280         }
281     }
282
283     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
284         trace!("checking const {:?}", ct);
285         // Find a const parameter
286         match ct.val() {
287             ty::ConstKind::Param(..) => {
288                 // Look it up in the substitution list.
289                 match self.map.get(&ct.into()).map(|k| k.unpack()) {
290                     // Found it in the substitution list, replace with the parameter from the
291                     // opaque type.
292                     Some(GenericArgKind::Const(c1)) => c1,
293                     Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
294                     None => {
295                         self.tcx
296                             .sess
297                             .struct_span_err(
298                                 self.span,
299                                 &format!(
300                                     "const parameter `{}` is part of concrete type but not \
301                                           used in parameter list for the `impl Trait` type alias",
302                                     ct
303                                 ),
304                             )
305                             .emit();
306
307                         self.tcx().const_error(ct.ty())
308                     }
309                 }
310             }
311
312             _ => ct,
313         }
314     }
315 }
316
317 /// Given a set of predicates that apply to an object type, returns
318 /// the region bounds that the (erased) `Self` type must
319 /// outlive. Precisely *because* the `Self` type is erased, the
320 /// parameter `erased_self_ty` must be supplied to indicate what type
321 /// has been used to represent `Self` in the predicates
322 /// themselves. This should really be a unique type; `FreshTy(0)` is a
323 /// popular choice.
324 ///
325 /// N.B., in some cases, particularly around higher-ranked bounds,
326 /// this function returns a kind of conservative approximation.
327 /// That is, all regions returned by this function are definitely
328 /// required, but there may be other region bounds that are not
329 /// returned, as well as requirements like `for<'a> T: 'a`.
330 ///
331 /// Requires that trait definitions have been processed so that we can
332 /// elaborate predicates and walk supertraits.
333 #[instrument(skip(tcx, predicates), level = "debug")]
334 crate fn required_region_bounds<'tcx>(
335     tcx: TyCtxt<'tcx>,
336     erased_self_ty: Ty<'tcx>,
337     predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
338 ) -> Vec<ty::Region<'tcx>> {
339     assert!(!erased_self_ty.has_escaping_bound_vars());
340
341     traits::elaborate_predicates(tcx, predicates)
342         .filter_map(|obligation| {
343             debug!(?obligation);
344             match obligation.predicate.kind().skip_binder() {
345                 ty::PredicateKind::Projection(..)
346                 | ty::PredicateKind::Trait(..)
347                 | ty::PredicateKind::Subtype(..)
348                 | ty::PredicateKind::Coerce(..)
349                 | ty::PredicateKind::WellFormed(..)
350                 | ty::PredicateKind::ObjectSafe(..)
351                 | ty::PredicateKind::ClosureKind(..)
352                 | ty::PredicateKind::RegionOutlives(..)
353                 | ty::PredicateKind::ConstEvaluatable(..)
354                 | ty::PredicateKind::ConstEquate(..)
355                 | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
356                 ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
357                     // Search for a bound of the form `erased_self_ty
358                     // : 'a`, but be wary of something like `for<'a>
359                     // erased_self_ty : 'a` (we interpret a
360                     // higher-ranked bound like that as 'static,
361                     // though at present the code in `fulfill.rs`
362                     // considers such bounds to be unsatisfiable, so
363                     // it's kind of a moot point since you could never
364                     // construct such an object, but this seems
365                     // correct even if that code changes).
366                     if t == &erased_self_ty && !r.has_escaping_bound_vars() {
367                         Some(*r)
368                     } else {
369                         None
370                     }
371                 }
372             }
373         })
374         .collect()
375 }