]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_hir_analysis/src/outlives/mod.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_hir_analysis / src / outlives / mod.rs
CommitLineData
b7449926 1use hir::Node;
dfeec247 2use rustc_hir as hir;
353b0b11 3use rustc_hir::def_id::LocalDefId;
49aad941 4use rustc_middle::query::Providers;
ba9703b0 5use rustc_middle::ty::subst::GenericArgKind;
487cf647 6use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
dfeec247
XL
7use rustc_span::symbol::sym;
8use rustc_span::Span;
476ff2be 9
83c7162d 10mod explicit;
83c7162d 11mod implicit_infer;
abe05a73
XL
12/// Code to write unit test for outlives.
13pub mod test;
94b46f34 14mod utils;
1a4d82fc 15
f035d41b 16pub fn provide(providers: &mut Providers) {
dfeec247 17 *providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers };
abe05a73 18}
223e47cc 19
353b0b11
FG
20fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clause<'_>, Span)] {
21 let id = tcx.hir().local_def_id_to_hir_id(item_def_id);
83c7162d 22
94222f64
XL
23 if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst) && tcx.lazy_normalization()
24 {
487cf647 25 if tcx.hir().opt_const_param_default_param_def_id(id).is_some() {
94222f64
XL
26 // In `generics_of` we set the generics' parent to be our parent's parent which means that
27 // we lose out on the predicates of our actual parent if we dont return those predicates here.
28 // (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
29 //
30 // struct Foo<'a, 'b, const N: usize = { ... }>(&'a &'b ());
31 // ^^^ ^^^^^^^ the def id we are calling
32 // ^^^ inferred_outlives_of on
33 // parent item we dont have set as the
34 // parent of generics returned by `generics_of`
35 //
36 // In the above code we want the anon const to have predicates in its param env for `'b: 'a`
5099ac24 37 let item_def_id = tcx.hir().get_parent_item(id);
94222f64
XL
38 // In the above code example we would be calling `inferred_outlives_of(Foo)` here
39 return tcx.inferred_outlives_of(item_def_id);
40 }
41 }
42
dc9dc135 43 match tcx.hir().get(id) {
e74abb32 44 Node::Item(item) => match item.kind {
8faf50e0 45 hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => {
17df50a5 46 let crate_map = tcx.inferred_outlives_crate(());
83c7162d 47
353b0b11
FG
48 let predicates =
49 crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
94b46f34 50
48663c56 51 if tcx.has_attr(item_def_id, sym::rustc_outlives) {
94b46f34
XL
52 let mut pred: Vec<String> = predicates
53 .iter()
487cf647
FG
54 .map(|(out_pred, _)| match out_pred {
55 ty::Clause::RegionOutlives(p) => p.to_string(),
56 ty::Clause::TypeOutlives(p) => p.to_string(),
57 err => bug!("unexpected clause {:?}", err),
dfeec247
XL
58 })
59 .collect();
94b46f34
XL
60 pred.sort();
61
62 let span = tcx.def_span(item_def_id);
63 let mut err = tcx.sess.struct_span_err(span, "rustc_outlives");
49aad941 64 for p in pred {
94b46f34
XL
65 err.note(p);
66 }
67 err.emit();
68 }
13cf67c4
XL
69
70 debug!("inferred_outlives_of({:?}) = {:?}", item_def_id, predicates);
71
94b46f34 72 predicates
83c7162d
XL
73 }
74
48663c56 75 _ => &[],
83c7162d
XL
76 },
77
48663c56 78 _ => &[],
83c7162d
XL
79 }
80}
81
17df50a5 82fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
83c7162d
XL
83 // Compute a map from each struct/enum/union S to the **explicit**
84 // outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote.
85 // Typically there won't be many of these, except in older code where
86 // they were mandatory. Nonetheless, we have to ensure that every such
87 // predicate is satisfied, so they form a kind of base set of requirements
88 // for the type.
89
90 // Compute the inferred predicates
064997fb 91 let global_inferred_outlives = implicit_infer::infer_predicates(tcx);
83c7162d
XL
92
93 // Convert the inferred predicates into the "collected" form the
94 // global data structure expects.
95 //
96 // FIXME -- consider correcting impedance mismatch in some way,
97 // probably by updating the global data structure.
94b46f34 98 let predicates = global_inferred_outlives
83c7162d
XL
99 .iter()
100 .map(|(&def_id, set)| {
064997fb 101 let predicates = &*tcx.arena.alloc_from_iter(set.0.iter().filter_map(
f9f354fc
XL
102 |(ty::OutlivesPredicate(kind1, region2), &span)| {
103 match kind1.unpack() {
104 GenericArgKind::Type(ty1) => Some((
487cf647 105 ty::Clause::TypeOutlives(ty::OutlivesPredicate(ty1, *region2)),
f9f354fc
XL
106 span,
107 )),
108 GenericArgKind::Lifetime(region1) => Some((
487cf647 109 ty::Clause::RegionOutlives(ty::OutlivesPredicate(region1, *region2)),
f9f354fc
XL
110 span,
111 )),
112 GenericArgKind::Const(_) => {
113 // Generic consts don't impose any constraints.
114 None
115 }
dfeec247
XL
116 }
117 },
118 ));
e74abb32 119 (def_id, predicates)
dfeec247
XL
120 })
121 .collect();
83c7162d 122
f9f354fc 123 ty::CratePredicatesMap { predicates }
223e47cc 124}