Skip to content

Commit

Permalink
Auto merge of #45298 - toidiu:ak-44493-infer-predicate, r=nikomatsakis
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
bors committed Apr 12, 2018
2 parents 6c53749 + 6a229cb commit c4a0328
Show file tree
Hide file tree
Showing 44 changed files with 1,415 additions and 21 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ __pycache__/
/src/libstd_unicode/UnicodeData.txt
/stage[0-9]+/
/target
target/
/test/
/tmp/
TAGS
Expand Down
1 change: 1 addition & 0 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ define_dep_nodes!( <'tcx>
[] GenericsOfItem(DefId),
[] PredicatesOfItem(DefId),
[] InferredOutlivesOf(DefId),
[] InferredOutlivesCrate(CrateNum),
[] SuperPredicatesOfItem(DefId),
[] TraitDefOfItem(DefId),
[] AdtDefOfItem(DefId),
Expand Down
14 changes: 14 additions & 0 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,20 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::CrateVariancesMap {
}
}

impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::CratePredicatesMap<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
let ty::CratePredicatesMap {
ref predicates,
// This is just an irrelevant helper value.
empty_predicate: _,
} = *self;

predicates.hash_stable(hcx, hasher);
}
}

impl_stable_hash_for!(struct ty::AssociatedItem {
def_id,
name,
Expand Down
6 changes: 6 additions & 0 deletions src/librustc/ty/maps/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::crate_variances<'tcx> {
}
}

impl<'tcx> QueryDescription<'tcx> for queries::inferred_outlives_crate<'tcx> {
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
format!("computing the inferred outlives predicates for items in this crate")
}
}

impl<'tcx> QueryDescription<'tcx> for queries::mir_shims<'tcx> {
fn describe(tcx: TyCtxt, def: ty::InstanceDef<'tcx>) -> String {
format!("generating MIR shim for `{}`",
Expand Down
7 changes: 6 additions & 1 deletion src/librustc/ty/maps/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ define_maps! { <'tcx>
/// associated generics and predicates.
[] fn generics_of: GenericsOfItem(DefId) -> &'tcx ty::Generics,
[] fn predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
[] fn explicit_predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,

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

/// Maps from def-id of a type to its (inferred) outlives.
[] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Vec<ty::Predicate<'tcx>>,
[] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Lrc<Vec<ty::Predicate<'tcx>>>,

/// Maps from def-id of a type to its (inferred) outlives.
[] fn inferred_outlives_crate: InferredOutlivesCrate(CrateNum)
-> Lrc<ty::CratePredicatesMap<'tcx>>,

/// Maps from an impl/trait def-id to a list of the def-ids of its items
[] fn associated_item_def_ids: AssociatedItemDefIds(DefId) -> Lrc<Vec<DefId>>,
Expand Down
1 change: 1 addition & 0 deletions src/librustc/ty/maps/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::GenericsOfItem => { force!(generics_of, def_id!()); }
DepKind::PredicatesOfItem => { force!(predicates_of, def_id!()); }
DepKind::InferredOutlivesOf => { force!(inferred_outlives_of, def_id!()); }
DepKind::InferredOutlivesCrate => { force!(inferred_outlives_crate, LOCAL_CRATE); }
DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); }
DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); }
DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); }
Expand Down
16 changes: 16 additions & 0 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,22 @@ pub enum Predicate<'tcx> {
ConstEvaluatable(DefId, &'tcx Substs<'tcx>),
}

/// The crate outlives map is computed during typeck and contains the
/// outlives of every item in the local crate. You should not use it
/// directly, because to do so will make your pass dependent on the
/// HIR of every item in the local crate. Instead, use
/// `tcx.inferred_outlives_of()` to get the outlives for a *particular*
/// item.
pub struct CratePredicatesMap<'tcx> {
/// For each struct with outlive bounds, maps to a vector of the
/// predicate of its outlive bounds. If an item has no outlives
/// bounds, it will have no entry.
pub predicates: FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,

/// An empty vector, useful for cloning.
pub empty_predicate: Lrc<Vec<ty::Predicate<'tcx>>>,
}

impl<'tcx> AsRef<Predicate<'tcx>> for Predicate<'tcx> {
fn as_ref(&self) -> &Predicate<'tcx> {
self
Expand Down
9 changes: 7 additions & 2 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub fn provide(providers: &mut Providers) {
type_of,
generics_of,
predicates_of,
explicit_predicates_of,
super_predicates_of,
type_param_predicates,
trait_def,
Expand Down Expand Up @@ -1296,13 +1297,17 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> ty::GenericPredicates<'tcx> {
let explicit = explicit_predicates_of(tcx, def_id);
let predicates = if tcx.sess.features_untracked().infer_outlives_requirements {
[&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat()
} else { explicit.predicates };

ty::GenericPredicates {
parent: explicit.parent,
predicates: [&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat()
predicates: predicates,
}
}

fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> ty::GenericPredicates<'tcx> {
use rustc::hir::map::*;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4840,11 +4840,11 @@ register_diagnostics! {
E0588, // packed type cannot transitively contain a `[repr(align)]` type
E0592, // duplicate definitions with name `{}`
// E0613, // Removed (merged with E0609)
E0640, // infer outlives
E0627, // yield statement outside of generator literal
E0632, // cannot provide explicit type parameters when `impl Trait` is used in
// argument position.
E0634, // type has conflicting packed representaton hints
E0640, // infer outlives requirements
E0641, // cannot cast to/from a pointer with an unknown kind
E0645, // trait aliases not finished
E0907, // type inside generator must be known in this context
Expand Down
1 change: 1 addition & 0 deletions src/librustc_typeck/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ This API is completely unstable and subject to change.
#![feature(slice_patterns)]
#![feature(slice_sort_by_cached_key)]
#![feature(dyn_trait)]
#![feature(underscore_lifetimes)]

#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
Expand Down
82 changes: 82 additions & 0 deletions src/librustc_typeck/outlives/explicit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// 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::itemlikevisit::ItemLikeVisitor;
use rustc::ty::maps::Providers;
use rustc::ty::{self, CratePredicatesMap, TyCtxt};
use rustc_data_structures::sync::Lrc;
use util::nodemap::FxHashMap;

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();

// iterate over the entire crate
tcx.hir.krate().visit_all_item_likes(&mut ExplicitVisitor {
tcx: tcx,
explicit_predicates: &mut predicates,
crate_num: crate_num,
});

predicates
}

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

impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for ExplicitVisitor<'cx, 'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
let def_id = DefId {
krate: self.crate_num,
index: item.hir_id.owner,
};

let local_explicit_predicate = self.tcx.explicit_predicates_of(def_id);

let filtered_predicates = local_explicit_predicate
.predicates
.into_iter()
.filter(|pred| match pred {
ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => true,

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);
}
_ => {}
}

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

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

fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {}
}
52 changes: 52 additions & 0 deletions src/librustc_typeck/outlives/implicit_empty.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// 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::{self, CrateNum, DefId, LOCAL_CRATE};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::ty::maps::Providers;
use rustc::ty::{self, CratePredicatesMap, TyCtxt};
use rustc_data_structures::sync::Lrc;
use util::nodemap::FxHashMap;

// Create the sets of inferred predicates for each type. These sets
// are initially empty but will grow during the inference step.
pub fn empty_predicate_map<'tcx>(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
) -> FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>> {
let mut predicates = FxHashMap();

// iterate over the entire crate
tcx.hir
.krate()
.visit_all_item_likes(&mut EmptyImplicitVisitor {
tcx,
predicates: &mut predicates,
});

predicates
}

pub struct EmptyImplicitVisitor<'cx, 'tcx: 'cx> {
tcx: TyCtxt<'cx, 'tcx, 'tcx>,
predicates: &'cx mut FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
}

impl<'a, 'p, 'v> ItemLikeVisitor<'v> for EmptyImplicitVisitor<'a, 'p> {
fn visit_item(&mut self, item: &hir::Item) {
self.predicates
.insert(self.tcx.hir.local_def_id(item.id), Lrc::new(Vec::new()));
}

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

fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {}
}
Loading

0 comments on commit c4a0328

Please sign in to comment.