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