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