]>
Commit | Line | Data |
---|---|---|
b7449926 | 1 | use hir::Node; |
dfeec247 | 2 | use rustc_hir as hir; |
17df50a5 | 3 | use rustc_hir::def_id::DefId; |
ba9703b0 XL |
4 | use rustc_middle::ty::query::Providers; |
5 | use rustc_middle::ty::subst::GenericArgKind; | |
fc512014 | 6 | use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, 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; |
c295e0f8 | 12 | crate mod outlives_bounds; |
abe05a73 XL |
13 | /// Code to write unit test for outlives. |
14 | pub mod test; | |
94b46f34 | 15 | mod utils; |
1a4d82fc | 16 | |
f035d41b | 17 | pub fn provide(providers: &mut Providers) { |
dfeec247 | 18 | *providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers }; |
abe05a73 | 19 | } |
223e47cc | 20 | |
dfeec247 | 21 | fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate<'_>, Span)] { |
3dfed10e | 22 | let id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local()); |
83c7162d | 23 | |
94222f64 XL |
24 | if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst) && tcx.lazy_normalization() |
25 | { | |
c295e0f8 | 26 | if tcx.hir().opt_const_param_default_param_hir_id(id).is_some() { |
94222f64 XL |
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_id = tcx.hir().get_parent_item(id); | |
39 | let item_def_id = tcx.hir().local_def_id(item_id).to_def_id(); | |
40 | // In the above code example we would be calling `inferred_outlives_of(Foo)` here | |
41 | return tcx.inferred_outlives_of(item_def_id); | |
42 | } | |
43 | } | |
44 | ||
dc9dc135 | 45 | match tcx.hir().get(id) { |
e74abb32 | 46 | Node::Item(item) => match item.kind { |
8faf50e0 | 47 | hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => { |
17df50a5 | 48 | let crate_map = tcx.inferred_outlives_crate(()); |
83c7162d | 49 | |
74b04a01 | 50 | let predicates = crate_map.predicates.get(&item_def_id).copied().unwrap_or(&[]); |
94b46f34 | 51 | |
48663c56 | 52 | if tcx.has_attr(item_def_id, sym::rustc_outlives) { |
94b46f34 XL |
53 | let mut pred: Vec<String> = predicates |
54 | .iter() | |
5869c6ff XL |
55 | .map(|(out_pred, _)| match out_pred.kind().skip_binder() { |
56 | ty::PredicateKind::RegionOutlives(p) => p.to_string(), | |
57 | ty::PredicateKind::TypeOutlives(p) => p.to_string(), | |
94b46f34 | 58 | err => bug!("unexpected predicate {:?}", err), |
dfeec247 XL |
59 | }) |
60 | .collect(); | |
94b46f34 XL |
61 | pred.sort(); |
62 | ||
63 | let span = tcx.def_span(item_def_id); | |
64 | let mut err = tcx.sess.struct_span_err(span, "rustc_outlives"); | |
65 | for p in &pred { | |
66 | err.note(p); | |
67 | } | |
68 | err.emit(); | |
69 | } | |
13cf67c4 XL |
70 | |
71 | debug!("inferred_outlives_of({:?}) = {:?}", item_def_id, predicates); | |
72 | ||
94b46f34 | 73 | predicates |
83c7162d XL |
74 | } |
75 | ||
48663c56 | 76 | _ => &[], |
83c7162d XL |
77 | }, |
78 | ||
48663c56 | 79 | _ => &[], |
83c7162d XL |
80 | } |
81 | } | |
82 | ||
17df50a5 | 83 | fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> { |
83c7162d XL |
84 | // Compute a map from each struct/enum/union S to the **explicit** |
85 | // outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote. | |
86 | // Typically there won't be many of these, except in older code where | |
87 | // they were mandatory. Nonetheless, we have to ensure that every such | |
88 | // predicate is satisfied, so they form a kind of base set of requirements | |
89 | // for the type. | |
90 | ||
91 | // Compute the inferred predicates | |
8faf50e0 XL |
92 | let mut exp_map = explicit::ExplicitPredicatesMap::new(); |
93 | ||
94 | let global_inferred_outlives = implicit_infer::infer_predicates(tcx, &mut exp_map); | |
83c7162d XL |
95 | |
96 | // Convert the inferred predicates into the "collected" form the | |
97 | // global data structure expects. | |
98 | // | |
99 | // FIXME -- consider correcting impedance mismatch in some way, | |
100 | // probably by updating the global data structure. | |
94b46f34 | 101 | let predicates = global_inferred_outlives |
83c7162d XL |
102 | .iter() |
103 | .map(|(&def_id, set)| { | |
dfeec247 | 104 | let predicates = &*tcx.arena.alloc_from_iter(set.iter().filter_map( |
f9f354fc XL |
105 | |(ty::OutlivesPredicate(kind1, region2), &span)| { |
106 | match kind1.unpack() { | |
107 | GenericArgKind::Type(ty1) => Some(( | |
c295e0f8 XL |
108 | ty::Binder::dummy(ty::PredicateKind::TypeOutlives( |
109 | ty::OutlivesPredicate(ty1, region2), | |
110 | )) | |
111 | .to_predicate(tcx), | |
f9f354fc XL |
112 | span, |
113 | )), | |
114 | GenericArgKind::Lifetime(region1) => Some(( | |
c295e0f8 XL |
115 | ty::Binder::dummy(ty::PredicateKind::RegionOutlives( |
116 | ty::OutlivesPredicate(region1, region2), | |
f9f354fc | 117 | )) |
fc512014 | 118 | .to_predicate(tcx), |
f9f354fc XL |
119 | span, |
120 | )), | |
121 | GenericArgKind::Const(_) => { | |
122 | // Generic consts don't impose any constraints. | |
123 | None | |
124 | } | |
dfeec247 XL |
125 | } |
126 | }, | |
127 | )); | |
e74abb32 | 128 | (def_id, predicates) |
dfeec247 XL |
129 | }) |
130 | .collect(); | |
83c7162d | 131 | |
f9f354fc | 132 | ty::CratePredicatesMap { predicates } |
223e47cc | 133 | } |