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