Skip to content

Commit

Permalink
Auto merge of #50070 - toidiu:ak-2093-outlives, r=nikomatsakis
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed May 26, 2018
2 parents 07c415c + 3da7123 commit 49a97ef
Show file tree
Hide file tree
Showing 45 changed files with 676 additions and 725 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# `infer_outlives_requirements`

The tracking issue for this feature is: [#44493]

[#44493]: https://github.com/rust-lang/rust/issues/44493

------------------------
The `infer_outlives_requirements` feature indicates that certain
outlives requirements can be infered by the compiler rather than
stating them explicitly.

For example, currently generic struct definitions that contain
references, require where-clauses of the form T: 'a. By using
this feature the outlives predicates will be infered, although
they may still be written explicitly.

```rust,ignore (pseudo-Rust)
struct Foo<'a, T>
where T: 'a // <-- currently required
{
bar: &'a T,
}
```


## Examples:


```rust,ignore (pseudo-Rust)
#![feature(infer_outlives_requirements)]
// Implicitly infer T: 'a
struct Foo<'a, T> {
bar: &'a T,
}
```

```rust,ignore (pseudo-Rust)
#![feature(infer_outlives_requirements)]
// Implicitly infer `U: 'b`
struct Foo<'b, U> {
bar: Bar<'b, U>
}
struct Bar<'a, T> where T: 'a {
x: &'a (),
y: T,
}
```

```rust,ignore (pseudo-Rust)
#![feature(infer_outlives_requirements)]
// Implicitly infer `b': 'a`
struct Foo<'a, 'b, T> {
x: &'a &'b T
}
```

```rust,ignore (pseudo-Rust)
#![feature(infer_outlives_requirements)]
// Implicitly infer `<T as std::iter::Iterator>::Item : 'a`
struct Foo<'a, T: Iterator> {
bar: &'a T::Item
```
56 changes: 29 additions & 27 deletions src/librustc_typeck/outlives/explicit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,19 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use hir::map as hir_map;
use rustc::hir;
use rustc::hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc::hir::def_id::{CrateNum, DefId};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::ty::maps::Providers;
use rustc::ty::{self, CratePredicatesMap, TyCtxt};
use rustc_data_structures::sync::Lrc;
use rustc::ty::{self, TyCtxt};
use util::nodemap::FxHashMap;

use super::utils::*;

pub fn explicit_predicates<'tcx>(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
crate_num: CrateNum,
) -> FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>> {
assert_eq!(crate_num, LOCAL_CRATE);
let mut predicates: FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>> = FxHashMap();
) -> FxHashMap<DefId, RequiredPredicates<'tcx>> {
let mut predicates = FxHashMap::default();

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

pub struct ExplicitVisitor<'cx, 'tcx: 'cx> {
tcx: TyCtxt<'cx, 'tcx, 'tcx>,
explicit_predicates: &'cx mut FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
explicit_predicates: &'cx mut FxHashMap<DefId, RequiredPredicates<'tcx>>,
crate_num: CrateNum,
}

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

let local_explicit_predicate = self.tcx.explicit_predicates_of(def_id);
let mut required_predicates = RequiredPredicates::default();
let local_explicit_predicate = self.tcx.explicit_predicates_of(def_id).predicates;

for pred in local_explicit_predicate.into_iter() {
match pred {
ty::Predicate::TypeOutlives(predicate) => {
let ty::OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder();
insert_outlives_predicate(self.tcx, (*ty).into(), reg, &mut required_predicates)
}

let filtered_predicates = local_explicit_predicate
.predicates
.into_iter()
.filter(|pred| match pred {
ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => true,
ty::Predicate::RegionOutlives(predicate) => {
let ty::OutlivesPredicate(ref reg1, ref reg2) = predicate.skip_binder();
insert_outlives_predicate(
self.tcx,
(*reg1).into(),
reg2,
&mut required_predicates,
)
}

ty::Predicate::Trait(..)
| ty::Predicate::Projection(..)
| ty::Predicate::WellFormed(..)
| ty::Predicate::ObjectSafe(..)
| ty::Predicate::ClosureKind(..)
| ty::Predicate::Subtype(..)
| ty::Predicate::ConstEvaluatable(..) => false,
})
.collect();

match item.node {
hir::ItemStruct(..) | hir::ItemEnum(..) => {
self.tcx.adt_def(def_id);
| ty::Predicate::ConstEvaluatable(..) => (),
}
_ => {}
}

self.explicit_predicates
.insert(def_id, Lrc::new(filtered_predicates));
self.explicit_predicates.insert(def_id, required_predicates);
}

fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {}
fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem) {}

fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {}
fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) {}
}
52 changes: 0 additions & 52 deletions src/librustc_typeck/outlives/implicit_empty.rs

This file was deleted.

Loading

0 comments on commit 49a97ef

Please sign in to comment.