]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_typeck/src/outlives/mod.rs
New upstream version 1.57.0+dfsg1
[rustc.git] / compiler / rustc_typeck / src / outlives / mod.rs
CommitLineData
b7449926 1use hir::Node;
dfeec247 2use rustc_hir as hir;
17df50a5 3use rustc_hir::def_id::DefId;
ba9703b0
XL
4use rustc_middle::ty::query::Providers;
5use rustc_middle::ty::subst::GenericArgKind;
fc512014 6use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt};
dfeec247
XL
7use rustc_span::symbol::sym;
8use rustc_span::Span;
476ff2be 9
83c7162d 10mod explicit;
83c7162d 11mod implicit_infer;
c295e0f8 12crate mod outlives_bounds;
abe05a73
XL
13/// Code to write unit test for outlives.
14pub mod test;
94b46f34 15mod utils;
1a4d82fc 16
f035d41b 17pub fn provide(providers: &mut Providers) {
dfeec247 18 *providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers };
abe05a73 19}
223e47cc 20
dfeec247 21fn 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 83fn 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}