]>
Commit | Line | Data |
---|---|---|
b7449926 | 1 | use hir::Node; |
dfeec247 | 2 | use rustc_hir as hir; |
353b0b11 | 3 | use rustc_hir::def_id::LocalDefId; |
49aad941 | 4 | use rustc_middle::query::Providers; |
ba9703b0 | 5 | use rustc_middle::ty::subst::GenericArgKind; |
487cf647 | 6 | use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt}; |
dfeec247 XL |
7 | use rustc_span::symbol::sym; |
8 | use rustc_span::Span; | |
476ff2be | 9 | |
83c7162d | 10 | mod explicit; |
83c7162d | 11 | mod implicit_infer; |
abe05a73 XL |
12 | /// Code to write unit test for outlives. |
13 | pub mod test; | |
94b46f34 | 14 | mod utils; |
1a4d82fc | 15 | |
f035d41b | 16 | pub fn provide(providers: &mut Providers) { |
dfeec247 | 17 | *providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers }; |
abe05a73 | 18 | } |
223e47cc | 19 | |
353b0b11 FG |
20 | fn 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 | 82 | fn 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 | } |