Skip to content

Commit 49a97ef

Browse files
committed
Auto merge of #50070 - toidiu:ak-2093-outlives, r=nikomatsakis
2093 infer outlives requirements Tracking issue: #44493 RFC: rust-lang/rfcs#2093 - [x] add `rustc_attrs` flag - [x] use `RequirePredicates` type - [x] handle explicit predicates on `dyn` Trait - [x] handle explicit predicates on projections - [x] more tests - [x] remove `unused`, `dead_code` and etc.. - [x] documentation
2 parents 07c415c + 3da7123 commit 49a97ef

Some content is hidden

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

45 files changed

+676
-725
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# `infer_outlives_requirements`
2+
3+
The tracking issue for this feature is: [#44493]
4+
5+
[#44493]: https://github.com/rust-lang/rust/issues/44493
6+
7+
------------------------
8+
The `infer_outlives_requirements` feature indicates that certain
9+
outlives requirements can be infered by the compiler rather than
10+
stating them explicitly.
11+
12+
For example, currently generic struct definitions that contain
13+
references, require where-clauses of the form T: 'a. By using
14+
this feature the outlives predicates will be infered, although
15+
they may still be written explicitly.
16+
17+
```rust,ignore (pseudo-Rust)
18+
struct Foo<'a, T>
19+
where T: 'a // <-- currently required
20+
{
21+
bar: &'a T,
22+
}
23+
```
24+
25+
26+
## Examples:
27+
28+
29+
```rust,ignore (pseudo-Rust)
30+
#![feature(infer_outlives_requirements)]
31+
32+
// Implicitly infer T: 'a
33+
struct Foo<'a, T> {
34+
bar: &'a T,
35+
}
36+
```
37+
38+
```rust,ignore (pseudo-Rust)
39+
#![feature(infer_outlives_requirements)]
40+
41+
// Implicitly infer `U: 'b`
42+
struct Foo<'b, U> {
43+
bar: Bar<'b, U>
44+
}
45+
46+
struct Bar<'a, T> where T: 'a {
47+
x: &'a (),
48+
y: T,
49+
}
50+
```
51+
52+
```rust,ignore (pseudo-Rust)
53+
#![feature(infer_outlives_requirements)]
54+
55+
// Implicitly infer `b': 'a`
56+
struct Foo<'a, 'b, T> {
57+
x: &'a &'b T
58+
}
59+
```
60+
61+
```rust,ignore (pseudo-Rust)
62+
#![feature(infer_outlives_requirements)]
63+
64+
// Implicitly infer `<T as std::iter::Iterator>::Item : 'a`
65+
struct Foo<'a, T: Iterator> {
66+
bar: &'a T::Item
67+
```

src/librustc_typeck/outlives/explicit.rs

+29-27
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,19 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use hir::map as hir_map;
1211
use rustc::hir;
13-
use rustc::hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
12+
use rustc::hir::def_id::{CrateNum, DefId};
1413
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;
14+
use rustc::ty::{self, TyCtxt};
1815
use util::nodemap::FxHashMap;
1916

17+
use super::utils::*;
18+
2019
pub fn explicit_predicates<'tcx>(
2120
tcx: TyCtxt<'_, 'tcx, 'tcx>,
2221
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();
22+
) -> FxHashMap<DefId, RequiredPredicates<'tcx>> {
23+
let mut predicates = FxHashMap::default();
2624

2725
// iterate over the entire crate
2826
tcx.hir.krate().visit_all_item_likes(&mut ExplicitVisitor {
@@ -36,7 +34,7 @@ pub fn explicit_predicates<'tcx>(
3634

3735
pub struct ExplicitVisitor<'cx, 'tcx: 'cx> {
3836
tcx: TyCtxt<'cx, 'tcx, 'tcx>,
39-
explicit_predicates: &'cx mut FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
37+
explicit_predicates: &'cx mut FxHashMap<DefId, RequiredPredicates<'tcx>>,
4038
crate_num: CrateNum,
4139
}
4240

@@ -47,36 +45,40 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for ExplicitVisitor<'cx, 'tcx> {
4745
index: item.hir_id.owner,
4846
};
4947

50-
let local_explicit_predicate = self.tcx.explicit_predicates_of(def_id);
48+
let mut required_predicates = RequiredPredicates::default();
49+
let local_explicit_predicate = self.tcx.explicit_predicates_of(def_id).predicates;
50+
51+
for pred in local_explicit_predicate.into_iter() {
52+
match pred {
53+
ty::Predicate::TypeOutlives(predicate) => {
54+
let ty::OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder();
55+
insert_outlives_predicate(self.tcx, (*ty).into(), reg, &mut required_predicates)
56+
}
5157

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,
58+
ty::Predicate::RegionOutlives(predicate) => {
59+
let ty::OutlivesPredicate(ref reg1, ref reg2) = predicate.skip_binder();
60+
insert_outlives_predicate(
61+
self.tcx,
62+
(*reg1).into(),
63+
reg2,
64+
&mut required_predicates,
65+
)
66+
}
5767

5868
ty::Predicate::Trait(..)
5969
| ty::Predicate::Projection(..)
6070
| ty::Predicate::WellFormed(..)
6171
| ty::Predicate::ObjectSafe(..)
6272
| ty::Predicate::ClosureKind(..)
6373
| 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);
74+
| ty::Predicate::ConstEvaluatable(..) => (),
7175
}
72-
_ => {}
7376
}
7477

75-
self.explicit_predicates
76-
.insert(def_id, Lrc::new(filtered_predicates));
78+
self.explicit_predicates.insert(def_id, required_predicates);
7779
}
7880

79-
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {}
81+
fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem) {}
8082

81-
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {}
83+
fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) {}
8284
}

src/librustc_typeck/outlives/implicit_empty.rs

-52
This file was deleted.

0 commit comments

Comments
 (0)