]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/outlives/mod.rs
pin docs: add some forward references
[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, 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::Atom(ty::PredicateAtom::RegionOutlives(p)) => {
35                                 p.to_string()
36                             }
37                             ty::PredicateKind::Atom(ty::PredicateAtom::TypeOutlives(p)) => {
38                                 p.to_string()
39                             }
40                             err => bug!("unexpected predicate {:?}", err),
41                         })
42                         .collect();
43                     pred.sort();
44
45                     let span = tcx.def_span(item_def_id);
46                     let mut err = tcx.sess.struct_span_err(span, "rustc_outlives");
47                     for p in &pred {
48                         err.note(p);
49                     }
50                     err.emit();
51                 }
52
53                 debug!("inferred_outlives_of({:?}) = {:?}", item_def_id, predicates);
54
55                 predicates
56             }
57
58             _ => &[],
59         },
60
61         _ => &[],
62     }
63 }
64
65 fn inferred_outlives_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CratePredicatesMap<'_> {
66     assert_eq!(crate_num, LOCAL_CRATE);
67
68     // Compute a map from each struct/enum/union S to the **explicit**
69     // outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote.
70     // Typically there won't be many of these, except in older code where
71     // they were mandatory. Nonetheless, we have to ensure that every such
72     // predicate is satisfied, so they form a kind of base set of requirements
73     // for the type.
74
75     // Compute the inferred predicates
76     let mut exp_map = explicit::ExplicitPredicatesMap::new();
77
78     let global_inferred_outlives = implicit_infer::infer_predicates(tcx, &mut exp_map);
79
80     // Convert the inferred predicates into the "collected" form the
81     // global data structure expects.
82     //
83     // FIXME -- consider correcting impedance mismatch in some way,
84     // probably by updating the global data structure.
85     let predicates = global_inferred_outlives
86         .iter()
87         .map(|(&def_id, set)| {
88             let predicates = &*tcx.arena.alloc_from_iter(set.iter().filter_map(
89                 |(ty::OutlivesPredicate(kind1, region2), &span)| {
90                     match kind1.unpack() {
91                         GenericArgKind::Type(ty1) => Some((
92                             ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty1, region2))
93                                 .potentially_quantified(tcx, ty::PredicateKind::ForAll),
94                             span,
95                         )),
96                         GenericArgKind::Lifetime(region1) => Some((
97                             ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(
98                                 region1, region2,
99                             ))
100                             .potentially_quantified(tcx, ty::PredicateKind::ForAll),
101                             span,
102                         )),
103                         GenericArgKind::Const(_) => {
104                             // Generic consts don't impose any constraints.
105                             None
106                         }
107                     }
108                 },
109             ));
110             (def_id, predicates)
111         })
112         .collect();
113
114     ty::CratePredicatesMap { predicates }
115 }