]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/outlives/mod.rs
Rollup merge of #74109 - nbdd0121:issue-74082, r=petrochenkov
[rust.git] / src / librustc_typeck / outlives / mod.rs
1 use hir::Node;
2 use rustc_hir as hir;
3 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
4 use rustc_middle::ty::query::Providers;
5 use rustc_middle::ty::subst::GenericArgKind;
6 use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt};
7 use rustc_span::symbol::sym;
8 use rustc_span::Span;
9
10 mod explicit;
11 mod implicit_infer;
12 /// Code to write unit test for outlives.
13 pub mod test;
14 mod utils;
15
16 pub fn provide(providers: &mut Providers) {
17     *providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers };
18 }
19
20 fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate<'_>, Span)] {
21     let id = tcx.hir().as_local_hir_id(item_def_id.expect_local());
22
23     match tcx.hir().get(id) {
24         Node::Item(item) => match item.kind {
25             hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => {
26                 let crate_map = tcx.inferred_outlives_crate(LOCAL_CRATE);
27
28                 let predicates = crate_map.predicates.get(&item_def_id).copied().unwrap_or(&[]);
29
30                 if tcx.has_attr(item_def_id, sym::rustc_outlives) {
31                     let mut pred: Vec<String> = predicates
32                         .iter()
33                         .map(|(out_pred, _)| match out_pred.kind() {
34                             ty::PredicateKind::RegionOutlives(p) => p.to_string(),
35                             ty::PredicateKind::TypeOutlives(p) => p.to_string(),
36                             err => bug!("unexpected predicate {:?}", err),
37                         })
38                         .collect();
39                     pred.sort();
40
41                     let span = tcx.def_span(item_def_id);
42                     let mut err = tcx.sess.struct_span_err(span, "rustc_outlives");
43                     for p in &pred {
44                         err.note(p);
45                     }
46                     err.emit();
47                 }
48
49                 debug!("inferred_outlives_of({:?}) = {:?}", item_def_id, predicates);
50
51                 predicates
52             }
53
54             _ => &[],
55         },
56
57         _ => &[],
58     }
59 }
60
61 fn inferred_outlives_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CratePredicatesMap<'_> {
62     assert_eq!(crate_num, LOCAL_CRATE);
63
64     // Compute a map from each struct/enum/union S to the **explicit**
65     // outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote.
66     // Typically there won't be many of these, except in older code where
67     // they were mandatory. Nonetheless, we have to ensure that every such
68     // predicate is satisfied, so they form a kind of base set of requirements
69     // for the type.
70
71     // Compute the inferred predicates
72     let mut exp_map = explicit::ExplicitPredicatesMap::new();
73
74     let global_inferred_outlives = implicit_infer::infer_predicates(tcx, &mut exp_map);
75
76     // Convert the inferred predicates into the "collected" form the
77     // global data structure expects.
78     //
79     // FIXME -- consider correcting impedance mismatch in some way,
80     // probably by updating the global data structure.
81     let predicates = global_inferred_outlives
82         .iter()
83         .map(|(&def_id, set)| {
84             let predicates = &*tcx.arena.alloc_from_iter(set.iter().filter_map(
85                 |(ty::OutlivesPredicate(kind1, region2), &span)| {
86                     match kind1.unpack() {
87                         GenericArgKind::Type(ty1) => Some((
88                             ty::PredicateKind::TypeOutlives(ty::Binder::bind(
89                                 ty::OutlivesPredicate(ty1, region2),
90                             ))
91                             .to_predicate(tcx),
92                             span,
93                         )),
94                         GenericArgKind::Lifetime(region1) => Some((
95                             ty::PredicateKind::RegionOutlives(ty::Binder::bind(
96                                 ty::OutlivesPredicate(region1, region2),
97                             ))
98                             .to_predicate(tcx),
99                             span,
100                         )),
101                         GenericArgKind::Const(_) => {
102                             // Generic consts don't impose any constraints.
103                             None
104                         }
105                     }
106                 },
107             ));
108             (def_id, predicates)
109         })
110         .collect();
111
112     ty::CratePredicatesMap { predicates }
113 }