]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_trait_selection/src/opaque_types.rs
Auto merge of #97191 - wesleywiser:main_thread_name, r=ChrisDenton
[rust.git] / compiler / rustc_trait_selection / src / opaque_types.rs
1 use crate::traits;
2 use crate::traits::error_reporting::InferCtxtExt as _;
3 use crate::traits::TraitEngineExt as _;
4 use rustc_data_structures::fx::FxHashMap;
5 use rustc_hir::def_id::DefId;
6 use rustc_hir::OpaqueTyOrigin;
7 use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
8 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt as _};
9 use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine};
10 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
11 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
12 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt};
13 use rustc_span::Span;
14
15 pub trait InferCtxtExt<'tcx> {
16     fn infer_opaque_definition_from_instantiation(
17         &self,
18         opaque_type_key: OpaqueTypeKey<'tcx>,
19         instantiated_ty: OpaqueHiddenType<'tcx>,
20         origin: OpaqueTyOrigin,
21     ) -> Ty<'tcx>;
22 }
23
24 impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
25     /// Given the fully resolved, instantiated type for an opaque
26     /// type, i.e., the value of an inference variable like C1 or C2
27     /// (*), computes the "definition type" for an opaque type
28     /// definition -- that is, the inferred value of `Foo1<'x>` or
29     /// `Foo2<'x>` that we would conceptually use in its definition:
30     /// ```ignore (illustrative)
31     /// type Foo1<'x> = impl Bar<'x> = AAA;  // <-- this type AAA
32     /// type Foo2<'x> = impl Bar<'x> = BBB;  // <-- or this type BBB
33     /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
34     /// ```
35     /// Note that these values are defined in terms of a distinct set of
36     /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main
37     /// purpose of this function is to do that translation.
38     ///
39     /// (*) C1 and C2 were introduced in the comments on
40     /// `register_member_constraints`. Read that comment for more context.
41     ///
42     /// # Parameters
43     ///
44     /// - `def_id`, the `impl Trait` type
45     /// - `substs`, the substs  used to instantiate this opaque type
46     /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
47     ///   `opaque_defn.concrete_ty`
48     #[instrument(level = "debug", skip(self))]
49     fn infer_opaque_definition_from_instantiation(
50         &self,
51         opaque_type_key: OpaqueTypeKey<'tcx>,
52         instantiated_ty: OpaqueHiddenType<'tcx>,
53         origin: OpaqueTyOrigin,
54     ) -> Ty<'tcx> {
55         if self.is_tainted_by_errors() {
56             return self.tcx.ty_error();
57         }
58
59         let OpaqueTypeKey { def_id, substs } = opaque_type_key;
60
61         // Use substs to build up a reverse map from regions to their
62         // identity mappings. This is necessary because of `impl
63         // Trait` lifetimes are computed by replacing existing
64         // lifetimes with 'static and remapping only those used in the
65         // `impl Trait` return type, resulting in the parameters
66         // shifting.
67         let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
68         debug!(?id_substs);
69         let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
70             substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect();
71         debug!("map = {:#?}", map);
72
73         // Convert the type from the function into a type valid outside
74         // the function, by replacing invalid regions with 'static,
75         // after producing an error for each of them.
76         let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new(
77             self.tcx,
78             def_id,
79             map,
80             instantiated_ty.ty,
81             instantiated_ty.span,
82         ));
83         debug!(?definition_ty);
84
85         if !check_opaque_type_parameter_valid(
86             self.tcx,
87             opaque_type_key,
88             origin,
89             instantiated_ty.span,
90         ) {
91             return self.tcx.ty_error();
92         }
93
94         // Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs`
95         // on stable and we'd break that.
96         if let OpaqueTyOrigin::TyAlias = origin {
97             // This logic duplicates most of `check_opaque_meets_bounds`.
98             // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
99             let param_env = self.tcx.param_env(def_id);
100             let body_id = self.tcx.local_def_id_to_hir_id(def_id.as_local().unwrap());
101             self.tcx.infer_ctxt().enter(move |infcx| {
102                 // Require the hidden type to be well-formed with only the generics of the opaque type.
103                 // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
104                 // hidden type is well formed even without those bounds.
105                 let predicate =
106                     ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()))
107                         .to_predicate(infcx.tcx);
108                 let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
109
110                 // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
111                 // the bounds that the function supplies.
112                 match infcx.register_hidden_type(
113                     OpaqueTypeKey { def_id, substs: id_substs },
114                     ObligationCause::misc(instantiated_ty.span, body_id),
115                     param_env,
116                     definition_ty,
117                     origin,
118                 ) {
119                     Ok(infer_ok) => {
120                         for obligation in infer_ok.obligations {
121                             fulfillment_cx.register_predicate_obligation(&infcx, obligation);
122                         }
123                     }
124                     Err(err) => {
125                         infcx
126                             .report_mismatched_types(
127                                 &ObligationCause::misc(instantiated_ty.span, body_id),
128                                 self.tcx.mk_opaque(def_id, id_substs),
129                                 definition_ty,
130                                 err,
131                             )
132                             .emit();
133                     }
134                 }
135
136                 fulfillment_cx.register_predicate_obligation(
137                     &infcx,
138                     Obligation::misc(instantiated_ty.span, body_id, param_env, predicate),
139                 );
140
141                 // Check that all obligations are satisfied by the implementation's
142                 // version.
143                 let errors = fulfillment_cx.select_all_or_error(&infcx);
144
145                 let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
146
147                 if errors.is_empty() {
148                     definition_ty
149                 } else {
150                     infcx.report_fulfillment_errors(&errors, None, false);
151                     self.tcx.ty_error()
152                 }
153             })
154         } else {
155             definition_ty
156         }
157     }
158 }
159
160 fn check_opaque_type_parameter_valid(
161     tcx: TyCtxt<'_>,
162     opaque_type_key: OpaqueTypeKey<'_>,
163     origin: OpaqueTyOrigin,
164     span: Span,
165 ) -> bool {
166     match origin {
167         // No need to check return position impl trait (RPIT)
168         // because for type and const parameters they are correct
169         // by construction: we convert
170         //
171         // fn foo<P0..Pn>() -> impl Trait
172         //
173         // into
174         //
175         // type Foo<P0...Pn>
176         // fn foo<P0..Pn>() -> Foo<P0...Pn>.
177         //
178         // For lifetime parameters we convert
179         //
180         // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
181         //
182         // into
183         //
184         // type foo::<'p0..'pn>::Foo<'q0..'qm>
185         // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
186         //
187         // which would error here on all of the `'static` args.
188         OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true,
189         // Check these
190         OpaqueTyOrigin::TyAlias => {}
191     }
192     let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
193     let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
194     for (i, arg) in opaque_type_key.substs.iter().enumerate() {
195         let arg_is_param = match arg.unpack() {
196             GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
197             GenericArgKind::Lifetime(lt) if lt.is_static() => {
198                 tcx.sess
199                     .struct_span_err(span, "non-defining opaque type use in defining scope")
200                     .span_label(
201                         tcx.def_span(opaque_generics.param_at(i, tcx).def_id),
202                         "cannot use static lifetime; use a bound lifetime \
203                                     instead or remove the lifetime parameter from the \
204                                     opaque type",
205                     )
206                     .emit();
207                 return false;
208             }
209             GenericArgKind::Lifetime(lt) => {
210                 matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_))
211             }
212             GenericArgKind::Const(ct) => matches!(ct.val(), ty::ConstKind::Param(_)),
213         };
214
215         if arg_is_param {
216             seen_params.entry(arg).or_default().push(i);
217         } else {
218             // Prevent `fn foo() -> Foo<u32>` from being defining.
219             let opaque_param = opaque_generics.param_at(i, tcx);
220             tcx.sess
221                 .struct_span_err(span, "non-defining opaque type use in defining scope")
222                 .span_note(
223                     tcx.def_span(opaque_param.def_id),
224                     &format!(
225                         "used non-generic {} `{}` for generic parameter",
226                         opaque_param.kind.descr(),
227                         arg,
228                     ),
229                 )
230                 .emit();
231             return false;
232         }
233     }
234
235     for (_, indices) in seen_params {
236         if indices.len() > 1 {
237             let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
238             let spans: Vec<_> = indices
239                 .into_iter()
240                 .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
241                 .collect();
242             tcx.sess
243                 .struct_span_err(span, "non-defining opaque type use in defining scope")
244                 .span_note(spans, &format!("{} used multiple times", descr))
245                 .emit();
246             return false;
247         }
248     }
249     true
250 }
251
252 struct ReverseMapper<'tcx> {
253     tcx: TyCtxt<'tcx>,
254
255     opaque_type_def_id: DefId,
256     map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
257     map_missing_regions_to_empty: bool,
258
259     /// initially `Some`, set to `None` once error has been reported
260     hidden_ty: Option<Ty<'tcx>>,
261
262     /// Span of function being checked.
263     span: Span,
264 }
265
266 impl<'tcx> ReverseMapper<'tcx> {
267     fn new(
268         tcx: TyCtxt<'tcx>,
269         opaque_type_def_id: DefId,
270         map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
271         hidden_ty: Ty<'tcx>,
272         span: Span,
273     ) -> Self {
274         Self {
275             tcx,
276             opaque_type_def_id,
277             map,
278             map_missing_regions_to_empty: false,
279             hidden_ty: Some(hidden_ty),
280             span,
281         }
282     }
283
284     fn fold_kind_mapping_missing_regions_to_empty(
285         &mut self,
286         kind: GenericArg<'tcx>,
287     ) -> GenericArg<'tcx> {
288         assert!(!self.map_missing_regions_to_empty);
289         self.map_missing_regions_to_empty = true;
290         let kind = kind.fold_with(self);
291         self.map_missing_regions_to_empty = false;
292         kind
293     }
294
295     fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
296         assert!(!self.map_missing_regions_to_empty);
297         kind.fold_with(self)
298     }
299 }
300
301 impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
302     fn tcx(&self) -> TyCtxt<'tcx> {
303         self.tcx
304     }
305
306     #[instrument(skip(self), level = "debug")]
307     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
308         match *r {
309             // Ignore bound regions and `'static` regions that appear in the
310             // type, we only need to remap regions that reference lifetimes
311             // from the function declaration.
312             // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
313             ty::ReLateBound(..) | ty::ReStatic => return r,
314
315             // If regions have been erased (by writeback), don't try to unerase
316             // them.
317             ty::ReErased => return r,
318
319             // The regions that we expect from borrow checking.
320             ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
321
322             ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) => {
323                 // All of the regions in the type should either have been
324                 // erased by writeback, or mapped back to named regions by
325                 // borrow checking.
326                 bug!("unexpected region kind in opaque type: {:?}", r);
327             }
328         }
329
330         let generics = self.tcx().generics_of(self.opaque_type_def_id);
331         match self.map.get(&r.into()).map(|k| k.unpack()) {
332             Some(GenericArgKind::Lifetime(r1)) => r1,
333             Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
334             None if self.map_missing_regions_to_empty => self.tcx.lifetimes.re_root_empty,
335             None if generics.parent.is_some() => {
336                 if let Some(hidden_ty) = self.hidden_ty.take() {
337                     unexpected_hidden_region_diagnostic(
338                         self.tcx,
339                         self.tcx.def_span(self.opaque_type_def_id),
340                         hidden_ty,
341                         r,
342                     )
343                     .emit();
344                 }
345                 self.tcx.lifetimes.re_root_empty
346             }
347             None => {
348                 self.tcx
349                     .sess
350                     .struct_span_err(self.span, "non-defining opaque type use in defining scope")
351                     .span_label(
352                         self.span,
353                         format!(
354                             "lifetime `{}` is part of concrete type but not used in \
355                                  parameter list of the `impl Trait` type alias",
356                             r
357                         ),
358                     )
359                     .emit();
360
361                 self.tcx().lifetimes.re_static
362             }
363         }
364     }
365
366     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
367         match *ty.kind() {
368             ty::Closure(def_id, substs) => {
369                 // I am a horrible monster and I pray for death. When
370                 // we encounter a closure here, it is always a closure
371                 // from within the function that we are currently
372                 // type-checking -- one that is now being encapsulated
373                 // in an opaque type. Ideally, we would
374                 // go through the types/lifetimes that it references
375                 // and treat them just like we would any other type,
376                 // which means we would error out if we find any
377                 // reference to a type/region that is not in the
378                 // "reverse map".
379                 //
380                 // **However,** in the case of closures, there is a
381                 // somewhat subtle (read: hacky) consideration. The
382                 // problem is that our closure types currently include
383                 // all the lifetime parameters declared on the
384                 // enclosing function, even if they are unused by the
385                 // closure itself. We can't readily filter them out,
386                 // so here we replace those values with `'empty`. This
387                 // can't really make a difference to the rest of the
388                 // compiler; those regions are ignored for the
389                 // outlives relation, and hence don't affect trait
390                 // selection or auto traits, and they are erased
391                 // during codegen.
392
393                 let generics = self.tcx.generics_of(def_id);
394                 let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
395                     if index < generics.parent_count {
396                         // Accommodate missing regions in the parent kinds...
397                         self.fold_kind_mapping_missing_regions_to_empty(kind)
398                     } else {
399                         // ...but not elsewhere.
400                         self.fold_kind_normally(kind)
401                     }
402                 }));
403
404                 self.tcx.mk_closure(def_id, substs)
405             }
406
407             ty::Generator(def_id, substs, movability) => {
408                 let generics = self.tcx.generics_of(def_id);
409                 let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
410                     if index < generics.parent_count {
411                         // Accommodate missing regions in the parent kinds...
412                         self.fold_kind_mapping_missing_regions_to_empty(kind)
413                     } else {
414                         // ...but not elsewhere.
415                         self.fold_kind_normally(kind)
416                     }
417                 }));
418
419                 self.tcx.mk_generator(def_id, substs, movability)
420             }
421
422             ty::Param(param) => {
423                 // Look it up in the substitution list.
424                 match self.map.get(&ty.into()).map(|k| k.unpack()) {
425                     // Found it in the substitution list; replace with the parameter from the
426                     // opaque type.
427                     Some(GenericArgKind::Type(t1)) => t1,
428                     Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
429                     None => {
430                         debug!(?param, ?self.map);
431                         self.tcx
432                             .sess
433                             .struct_span_err(
434                                 self.span,
435                                 &format!(
436                                     "type parameter `{}` is part of concrete type but not \
437                                           used in parameter list for the `impl Trait` type alias",
438                                     ty
439                                 ),
440                             )
441                             .emit();
442
443                         self.tcx().ty_error()
444                     }
445                 }
446             }
447
448             _ => ty.super_fold_with(self),
449         }
450     }
451
452     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
453         trace!("checking const {:?}", ct);
454         // Find a const parameter
455         match ct.val() {
456             ty::ConstKind::Param(..) => {
457                 // Look it up in the substitution list.
458                 match self.map.get(&ct.into()).map(|k| k.unpack()) {
459                     // Found it in the substitution list, replace with the parameter from the
460                     // opaque type.
461                     Some(GenericArgKind::Const(c1)) => c1,
462                     Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
463                     None => {
464                         self.tcx
465                             .sess
466                             .struct_span_err(
467                                 self.span,
468                                 &format!(
469                                     "const parameter `{}` is part of concrete type but not \
470                                           used in parameter list for the `impl Trait` type alias",
471                                     ct
472                                 ),
473                             )
474                             .emit();
475
476                         self.tcx().const_error(ct.ty())
477                     }
478                 }
479             }
480
481             _ => ct,
482         }
483     }
484 }
485
486 /// Given a set of predicates that apply to an object type, returns
487 /// the region bounds that the (erased) `Self` type must
488 /// outlive. Precisely *because* the `Self` type is erased, the
489 /// parameter `erased_self_ty` must be supplied to indicate what type
490 /// has been used to represent `Self` in the predicates
491 /// themselves. This should really be a unique type; `FreshTy(0)` is a
492 /// popular choice.
493 ///
494 /// N.B., in some cases, particularly around higher-ranked bounds,
495 /// this function returns a kind of conservative approximation.
496 /// That is, all regions returned by this function are definitely
497 /// required, but there may be other region bounds that are not
498 /// returned, as well as requirements like `for<'a> T: 'a`.
499 ///
500 /// Requires that trait definitions have been processed so that we can
501 /// elaborate predicates and walk supertraits.
502 #[instrument(skip(tcx, predicates), level = "debug")]
503 pub(crate) fn required_region_bounds<'tcx>(
504     tcx: TyCtxt<'tcx>,
505     erased_self_ty: Ty<'tcx>,
506     predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
507 ) -> Vec<ty::Region<'tcx>> {
508     assert!(!erased_self_ty.has_escaping_bound_vars());
509
510     traits::elaborate_predicates(tcx, predicates)
511         .filter_map(|obligation| {
512             debug!(?obligation);
513             match obligation.predicate.kind().skip_binder() {
514                 ty::PredicateKind::Projection(..)
515                 | ty::PredicateKind::Trait(..)
516                 | ty::PredicateKind::Subtype(..)
517                 | ty::PredicateKind::Coerce(..)
518                 | ty::PredicateKind::WellFormed(..)
519                 | ty::PredicateKind::ObjectSafe(..)
520                 | ty::PredicateKind::ClosureKind(..)
521                 | ty::PredicateKind::RegionOutlives(..)
522                 | ty::PredicateKind::ConstEvaluatable(..)
523                 | ty::PredicateKind::ConstEquate(..)
524                 | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
525                 ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
526                     // Search for a bound of the form `erased_self_ty
527                     // : 'a`, but be wary of something like `for<'a>
528                     // erased_self_ty : 'a` (we interpret a
529                     // higher-ranked bound like that as 'static,
530                     // though at present the code in `fulfill.rs`
531                     // considers such bounds to be unsatisfiable, so
532                     // it's kind of a moot point since you could never
533                     // construct such an object, but this seems
534                     // correct even if that code changes).
535                     if t == &erased_self_ty && !r.has_escaping_bound_vars() {
536                         Some(*r)
537                     } else {
538                         None
539                     }
540                 }
541             }
542         })
543         .collect()
544 }