Skip to content

Commit c4a0328

Browse files
committed
Auto merge of #45298 - toidiu:ak-44493-infer-predicate, r=nikomatsakis
Ak 44493 infer predicate **WIP** Implements #44493 Things to do: - [x] add feature gate and appropriate tests (see [forge](https://forge.rust-lang.org/feature-guide.html) for some details) - [x] add a unit testing system similar to `#[rustc_variance]` - [x] to see how, maybe `rg rustc_variance` and take some notes - [ ] add more tests: - [x] we need to decide how to handle `struct Foo<'a, T> { x: &'a T::Item }` - [x] handle explicit predicates on types - [ ] handle explicit predicates on `dyn Trait` (this could be put off to a follow-up PR) - [ ] handle explicit predicates on projections (this could be put off to a follow-up PR)
2 parents 6c53749 + 6a229cb commit c4a0328

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1415
-21
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ __pycache__/
8383
/src/libstd_unicode/UnicodeData.txt
8484
/stage[0-9]+/
8585
/target
86+
target/
8687
/test/
8788
/tmp/
8889
TAGS

src/librustc/dep_graph/dep_node.rs

+1
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ define_dep_nodes!( <'tcx>
500500
[] GenericsOfItem(DefId),
501501
[] PredicatesOfItem(DefId),
502502
[] InferredOutlivesOf(DefId),
503+
[] InferredOutlivesCrate(CrateNum),
503504
[] SuperPredicatesOfItem(DefId),
504505
[] TraitDefOfItem(DefId),
505506
[] AdtDefOfItem(DefId),

src/librustc/ich/impls_ty.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,20 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::CrateVariancesMap {
11001100
}
11011101
}
11021102

1103+
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::CratePredicatesMap<'gcx> {
1104+
fn hash_stable<W: StableHasherResult>(&self,
1105+
hcx: &mut StableHashingContext<'a>,
1106+
hasher: &mut StableHasher<W>) {
1107+
let ty::CratePredicatesMap {
1108+
ref predicates,
1109+
// This is just an irrelevant helper value.
1110+
empty_predicate: _,
1111+
} = *self;
1112+
1113+
predicates.hash_stable(hcx, hasher);
1114+
}
1115+
}
1116+
11031117
impl_stable_hash_for!(struct ty::AssociatedItem {
11041118
def_id,
11051119
name,

src/librustc/ty/maps/config.rs

+6
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::crate_variances<'tcx> {
155155
}
156156
}
157157

158+
impl<'tcx> QueryDescription<'tcx> for queries::inferred_outlives_crate<'tcx> {
159+
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
160+
format!("computing the inferred outlives predicates for items in this crate")
161+
}
162+
}
163+
158164
impl<'tcx> QueryDescription<'tcx> for queries::mir_shims<'tcx> {
159165
fn describe(tcx: TyCtxt, def: ty::InstanceDef<'tcx>) -> String {
160166
format!("generating MIR shim for `{}`",

src/librustc/ty/maps/mod.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ define_maps! { <'tcx>
102102
/// associated generics and predicates.
103103
[] fn generics_of: GenericsOfItem(DefId) -> &'tcx ty::Generics,
104104
[] fn predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
105+
[] fn explicit_predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
105106

106107
/// Maps from the def-id of a trait to the list of
107108
/// super-predicates. This is a subset of the full list of
@@ -139,7 +140,11 @@ define_maps! { <'tcx>
139140
[] fn variances_of: ItemVariances(DefId) -> Lrc<Vec<ty::Variance>>,
140141

141142
/// Maps from def-id of a type to its (inferred) outlives.
142-
[] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Vec<ty::Predicate<'tcx>>,
143+
[] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Lrc<Vec<ty::Predicate<'tcx>>>,
144+
145+
/// Maps from def-id of a type to its (inferred) outlives.
146+
[] fn inferred_outlives_crate: InferredOutlivesCrate(CrateNum)
147+
-> Lrc<ty::CratePredicatesMap<'tcx>>,
143148

144149
/// Maps from an impl/trait def-id to a list of the def-ids of its items
145150
[] fn associated_item_def_ids: AssociatedItemDefIds(DefId) -> Lrc<Vec<DefId>>,

src/librustc/ty/maps/plumbing.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
10071007
DepKind::GenericsOfItem => { force!(generics_of, def_id!()); }
10081008
DepKind::PredicatesOfItem => { force!(predicates_of, def_id!()); }
10091009
DepKind::InferredOutlivesOf => { force!(inferred_outlives_of, def_id!()); }
1010+
DepKind::InferredOutlivesCrate => { force!(inferred_outlives_crate, LOCAL_CRATE); }
10101011
DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); }
10111012
DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); }
10121013
DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); }

src/librustc/ty/mod.rs

+16
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,22 @@ pub enum Predicate<'tcx> {
956956
ConstEvaluatable(DefId, &'tcx Substs<'tcx>),
957957
}
958958

959+
/// The crate outlives map is computed during typeck and contains the
960+
/// outlives of every item in the local crate. You should not use it
961+
/// directly, because to do so will make your pass dependent on the
962+
/// HIR of every item in the local crate. Instead, use
963+
/// `tcx.inferred_outlives_of()` to get the outlives for a *particular*
964+
/// item.
965+
pub struct CratePredicatesMap<'tcx> {
966+
/// For each struct with outlive bounds, maps to a vector of the
967+
/// predicate of its outlive bounds. If an item has no outlives
968+
/// bounds, it will have no entry.
969+
pub predicates: FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
970+
971+
/// An empty vector, useful for cloning.
972+
pub empty_predicate: Lrc<Vec<ty::Predicate<'tcx>>>,
973+
}
974+
959975
impl<'tcx> AsRef<Predicate<'tcx>> for Predicate<'tcx> {
960976
fn as_ref(&self) -> &Predicate<'tcx> {
961977
self

src/librustc_typeck/collect.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ pub fn provide(providers: &mut Providers) {
6464
type_of,
6565
generics_of,
6666
predicates_of,
67+
explicit_predicates_of,
6768
super_predicates_of,
6869
type_param_predicates,
6970
trait_def,
@@ -1296,13 +1297,17 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
12961297
def_id: DefId)
12971298
-> ty::GenericPredicates<'tcx> {
12981299
let explicit = explicit_predicates_of(tcx, def_id);
1300+
let predicates = if tcx.sess.features_untracked().infer_outlives_requirements {
1301+
[&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat()
1302+
} else { explicit.predicates };
1303+
12991304
ty::GenericPredicates {
13001305
parent: explicit.parent,
1301-
predicates: [&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat()
1306+
predicates: predicates,
13021307
}
13031308
}
13041309

1305-
fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1310+
pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
13061311
def_id: DefId)
13071312
-> ty::GenericPredicates<'tcx> {
13081313
use rustc::hir::map::*;

src/librustc_typeck/diagnostics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4840,11 +4840,11 @@ register_diagnostics! {
48404840
E0588, // packed type cannot transitively contain a `[repr(align)]` type
48414841
E0592, // duplicate definitions with name `{}`
48424842
// E0613, // Removed (merged with E0609)
4843-
E0640, // infer outlives
48444843
E0627, // yield statement outside of generator literal
48454844
E0632, // cannot provide explicit type parameters when `impl Trait` is used in
48464845
// argument position.
48474846
E0634, // type has conflicting packed representaton hints
4847+
E0640, // infer outlives requirements
48484848
E0641, // cannot cast to/from a pointer with an unknown kind
48494849
E0645, // trait aliases not finished
48504850
E0907, // type inside generator must be known in this context

src/librustc_typeck/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ This API is completely unstable and subject to change.
8282
#![feature(slice_patterns)]
8383
#![feature(slice_sort_by_cached_key)]
8484
#![feature(dyn_trait)]
85+
#![feature(underscore_lifetimes)]
8586

8687
#[macro_use] extern crate log;
8788
#[macro_use] extern crate syntax;
+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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::map as hir_map;
12+
use rustc::hir;
13+
use rustc::hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
14+
use rustc::hir::itemlikevisit::ItemLikeVisitor;
15+
use rustc::ty::maps::Providers;
16+
use rustc::ty::{self, CratePredicatesMap, TyCtxt};
17+
use rustc_data_structures::sync::Lrc;
18+
use util::nodemap::FxHashMap;
19+
20+
pub fn explicit_predicates<'tcx>(
21+
tcx: TyCtxt<'_, 'tcx, 'tcx>,
22+
crate_num: CrateNum,
23+
) -> FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>> {
24+
assert_eq!(crate_num, LOCAL_CRATE);
25+
let mut predicates: FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>> = FxHashMap();
26+
27+
// iterate over the entire crate
28+
tcx.hir.krate().visit_all_item_likes(&mut ExplicitVisitor {
29+
tcx: tcx,
30+
explicit_predicates: &mut predicates,
31+
crate_num: crate_num,
32+
});
33+
34+
predicates
35+
}
36+
37+
pub struct ExplicitVisitor<'cx, 'tcx: 'cx> {
38+
tcx: TyCtxt<'cx, 'tcx, 'tcx>,
39+
explicit_predicates: &'cx mut FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
40+
crate_num: CrateNum,
41+
}
42+
43+
impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for ExplicitVisitor<'cx, 'tcx> {
44+
fn visit_item(&mut self, item: &'tcx hir::Item) {
45+
let def_id = DefId {
46+
krate: self.crate_num,
47+
index: item.hir_id.owner,
48+
};
49+
50+
let local_explicit_predicate = self.tcx.explicit_predicates_of(def_id);
51+
52+
let filtered_predicates = local_explicit_predicate
53+
.predicates
54+
.into_iter()
55+
.filter(|pred| match pred {
56+
ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => true,
57+
58+
ty::Predicate::Trait(..)
59+
| ty::Predicate::Projection(..)
60+
| ty::Predicate::WellFormed(..)
61+
| ty::Predicate::ObjectSafe(..)
62+
| ty::Predicate::ClosureKind(..)
63+
| ty::Predicate::Subtype(..)
64+
| ty::Predicate::ConstEvaluatable(..) => false,
65+
})
66+
.collect();
67+
68+
match item.node {
69+
hir::ItemStruct(..) | hir::ItemEnum(..) => {
70+
self.tcx.adt_def(def_id);
71+
}
72+
_ => {}
73+
}
74+
75+
self.explicit_predicates
76+
.insert(def_id, Lrc::new(filtered_predicates));
77+
}
78+
79+
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {}
80+
81+
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {}
82+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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::map as hir_map;
12+
use rustc::hir;
13+
use rustc::hir::def_id::{self, CrateNum, DefId, LOCAL_CRATE};
14+
use rustc::hir::itemlikevisit::ItemLikeVisitor;
15+
use rustc::ty::maps::Providers;
16+
use rustc::ty::{self, CratePredicatesMap, TyCtxt};
17+
use rustc_data_structures::sync::Lrc;
18+
use util::nodemap::FxHashMap;
19+
20+
// Create the sets of inferred predicates for each type. These sets
21+
// are initially empty but will grow during the inference step.
22+
pub fn empty_predicate_map<'tcx>(
23+
tcx: TyCtxt<'_, 'tcx, 'tcx>,
24+
) -> FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>> {
25+
let mut predicates = FxHashMap();
26+
27+
// iterate over the entire crate
28+
tcx.hir
29+
.krate()
30+
.visit_all_item_likes(&mut EmptyImplicitVisitor {
31+
tcx,
32+
predicates: &mut predicates,
33+
});
34+
35+
predicates
36+
}
37+
38+
pub struct EmptyImplicitVisitor<'cx, 'tcx: 'cx> {
39+
tcx: TyCtxt<'cx, 'tcx, 'tcx>,
40+
predicates: &'cx mut FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
41+
}
42+
43+
impl<'a, 'p, 'v> ItemLikeVisitor<'v> for EmptyImplicitVisitor<'a, 'p> {
44+
fn visit_item(&mut self, item: &hir::Item) {
45+
self.predicates
46+
.insert(self.tcx.hir.local_def_id(item.id), Lrc::new(Vec::new()));
47+
}
48+
49+
fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {}
50+
51+
fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {}
52+
}

0 commit comments

Comments
 (0)