rustc_hir_analysis/outlives/mod.rs
1use rustc_hir::def::DefKind;
2use rustc_hir::def_id::LocalDefId;
3use rustc_middle::query::Providers;
4use rustc_middle::ty::{self, CratePredicatesMap, GenericArgKind, TyCtxt, Upcast};
5use rustc_span::Span;
6
7pub(crate) mod dump;
8mod explicit;
9mod implicit_infer;
10mod utils;
11
12pub(crate) fn provide(providers: &mut Providers) {
13 *providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers };
14}
15
16fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clause<'_>, Span)] {
17 match tcx.def_kind(item_def_id) {
18 DefKind::Struct | DefKind::Enum | DefKind::Union => {
19 let crate_map = tcx.inferred_outlives_crate(());
20 crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[])
21 }
22 DefKind::TyAlias if tcx.type_alias_is_lazy(item_def_id) => {
23 let crate_map = tcx.inferred_outlives_crate(());
24 crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[])
25 }
26 DefKind::AnonConst if tcx.features().generic_const_exprs() => {
27 let id = tcx.local_def_id_to_hir_id(item_def_id);
28 if tcx.hir().opt_const_param_default_param_def_id(id).is_some() {
29 // In `generics_of` we set the generics' parent to be our parent's parent which means that
30 // we lose out on the predicates of our actual parent if we dont return those predicates here.
31 // (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
32 //
33 // struct Foo<'a, 'b, const N: usize = { ... }>(&'a &'b ());
34 // ^^^ ^^^^^^^ the def id we are calling
35 // ^^^ inferred_outlives_of on
36 // parent item we dont have set as the
37 // parent of generics returned by `generics_of`
38 //
39 // In the above code we want the anon const to have predicates in its param env for `'b: 'a`
40 let item_def_id = tcx.hir().get_parent_item(id);
41 // In the above code example we would be calling `inferred_outlives_of(Foo)` here
42 tcx.inferred_outlives_of(item_def_id)
43 } else {
44 &[]
45 }
46 }
47 _ => &[],
48 }
49}
50
51fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
52 // Compute a map from each ADT (struct/enum/union) and lazy type alias to
53 // the **explicit** outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote.
54 // Typically there won't be many of these, except in older code where
55 // they were mandatory. Nonetheless, we have to ensure that every such
56 // predicate is satisfied, so they form a kind of base set of requirements
57 // for the type.
58
59 // Compute the inferred predicates
60 let global_inferred_outlives = implicit_infer::infer_predicates(tcx);
61
62 // Convert the inferred predicates into the "collected" form the
63 // global data structure expects.
64 //
65 // FIXME -- consider correcting impedance mismatch in some way,
66 // probably by updating the global data structure.
67 let predicates = global_inferred_outlives
68 .iter()
69 .map(|(&def_id, set)| {
70 let predicates =
71 &*tcx.arena.alloc_from_iter(set.as_ref().skip_binder().iter().filter_map(
72 |(ty::OutlivesPredicate(kind1, region2), &span)| {
73 match kind1.unpack() {
74 GenericArgKind::Type(ty1) => Some((
75 ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty1, *region2))
76 .upcast(tcx),
77 span,
78 )),
79 GenericArgKind::Lifetime(region1) => Some((
80 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
81 region1, *region2,
82 ))
83 .upcast(tcx),
84 span,
85 )),
86 GenericArgKind::Const(_) => {
87 // Generic consts don't impose any constraints.
88 None
89 }
90 }
91 },
92 ));
93 (def_id, predicates)
94 })
95 .collect();
96
97 ty::CratePredicatesMap { predicates }
98}