]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/outlives/mod.rs
improve debug output related to bound calculation
[rust.git] / src / librustc_typeck / outlives / mod.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use hir::Node;
12 use rustc::hir;
13 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
14 use rustc::ty::query::Providers;
15 use rustc::ty::subst::UnpackedKind;
16 use rustc::ty::{self, CratePredicatesMap, TyCtxt};
17 use rustc_data_structures::sync::Lrc;
18
19 mod explicit;
20 mod implicit_infer;
21 /// Code to write unit test for outlives.
22 pub mod test;
23 mod utils;
24
25 pub fn provide(providers: &mut Providers) {
26     *providers = Providers {
27         inferred_outlives_of,
28         inferred_outlives_crate,
29         ..*providers
30     };
31 }
32
33 fn inferred_outlives_of<'a, 'tcx>(
34     tcx: TyCtxt<'a, 'tcx, 'tcx>,
35     item_def_id: DefId,
36 ) -> Lrc<Vec<ty::Predicate<'tcx>>> {
37     let id = tcx
38         .hir
39         .as_local_node_id(item_def_id)
40         .expect("expected local def-id");
41
42     match tcx.hir.get(id) {
43         Node::Item(item) => match item.node {
44             hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => {
45                 let crate_map = tcx.inferred_outlives_crate(LOCAL_CRATE);
46
47                 let predicates = crate_map
48                     .predicates
49                     .get(&item_def_id)
50                     .unwrap_or(&crate_map.empty_predicate)
51                     .clone();
52
53                 if tcx.has_attr(item_def_id, "rustc_outlives") {
54                     let mut pred: Vec<String> = predicates
55                         .iter()
56                         .map(|out_pred| match out_pred {
57                             ty::Predicate::RegionOutlives(p) => p.to_string(),
58                             ty::Predicate::TypeOutlives(p) => p.to_string(),
59                             err => bug!("unexpected predicate {:?}", err),
60                         }).collect();
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                 }
70
71                 debug!("inferred_outlives_of({:?}) = {:?}", item_def_id, predicates);
72
73                 predicates
74             }
75
76             _ => Lrc::new(Vec::new()),
77         },
78
79         _ => Lrc::new(Vec::new()),
80     }
81 }
82
83 fn inferred_outlives_crate<'tcx>(
84     tcx: TyCtxt<'_, 'tcx, 'tcx>,
85     crate_num: CrateNum,
86 ) -> Lrc<CratePredicatesMap<'tcx>> {
87     assert_eq!(crate_num, LOCAL_CRATE);
88
89     // Compute a map from each struct/enum/union S to the **explicit**
90     // outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote.
91     // Typically there won't be many of these, except in older code where
92     // they were mandatory. Nonetheless, we have to ensure that every such
93     // predicate is satisfied, so they form a kind of base set of requirements
94     // for the type.
95
96     // Compute the inferred predicates
97     let mut exp_map = explicit::ExplicitPredicatesMap::new();
98
99     let global_inferred_outlives = implicit_infer::infer_predicates(tcx, &mut exp_map);
100
101     // Convert the inferred predicates into the "collected" form the
102     // global data structure expects.
103     //
104     // FIXME -- consider correcting impedance mismatch in some way,
105     // probably by updating the global data structure.
106     let predicates = global_inferred_outlives
107         .iter()
108         .map(|(&def_id, set)| {
109             let vec: Vec<ty::Predicate<'tcx>> = set
110                 .iter()
111                 .map(
112                     |ty::OutlivesPredicate(kind1, region2)| match kind1.unpack() {
113                         UnpackedKind::Type(ty1) => ty::Predicate::TypeOutlives(ty::Binder::bind(
114                             ty::OutlivesPredicate(ty1, region2),
115                         )),
116                         UnpackedKind::Lifetime(region1) => ty::Predicate::RegionOutlives(
117                             ty::Binder::bind(ty::OutlivesPredicate(region1, region2)),
118                         ),
119                     },
120                 ).collect();
121             (def_id, Lrc::new(vec))
122         }).collect();
123
124     let empty_predicate = Lrc::new(Vec::new());
125
126     Lrc::new(ty::CratePredicatesMap {
127         predicates,
128         empty_predicate,
129     })
130 }