1
Fork 0

Auto merge of #45473 - SimonSapin:variance-red-green, r=nikomatsakis

Remove dependency tracking for variance computation

This custom tracking is now replaced by the red/green algorithm.

Fix https://github.com/rust-lang/rust/issues/45471
This commit is contained in:
bors 2017-10-25 05:02:32 +00:00
commit b2478052f8
6 changed files with 11 additions and 50 deletions

View file

@ -755,13 +755,11 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::CrateVariancesMap {
hcx: &mut StableHashingContext<'gcx>, hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) { hasher: &mut StableHasher<W>) {
let ty::CrateVariancesMap { let ty::CrateVariancesMap {
ref dependencies,
ref variances, ref variances,
// This is just an irrelevant helper value. // This is just an irrelevant helper value.
empty_variance: _, empty_variance: _,
} = *self; } = *self;
dependencies.hash_stable(hcx, hasher);
variances.hash_stable(hcx, hasher); variances.hash_stable(hcx, hasher);
} }
} }

View file

@ -55,7 +55,6 @@ use rustc_const_math::ConstInt;
use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter; use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
HashStable}; HashStable};
use rustc_data_structures::transitive_relation::TransitiveRelation;
use hir; use hir;
@ -313,11 +312,6 @@ pub enum Variance {
/// `tcx.variances_of()` to get the variance for a *particular* /// `tcx.variances_of()` to get the variance for a *particular*
/// item. /// item.
pub struct CrateVariancesMap { pub struct CrateVariancesMap {
/// This relation tracks the dependencies between the variance of
/// various items. In particular, if `a < b`, then the variance of
/// `a` depends on the sources of `b`.
pub dependencies: TransitiveRelation<DefId>,
/// For each item with generics, maps to a vector of the variance /// For each item with generics, maps to a vector of the variance
/// of its generics. If an item has no generics, it will have no /// of its generics. If an item has no generics, it will have no
/// entry. /// entry.

View file

@ -104,22 +104,16 @@ into two queries:
- `crate_variances` computes the variance for all items in the current crate. - `crate_variances` computes the variance for all items in the current crate.
- `variances_of` accesses the variance for an individual reading; it - `variances_of` accesses the variance for an individual reading; it
works by requesting `crate_variances` and extracting the relevant data. works by requesting `crate_variances` and extracting the relevant data.
If you limit yourself to reading `variances_of`, your code will only If you limit yourself to reading `variances_of`, your code will only
depend then on the inference inferred for that particular item. depend then on the inference inferred for that particular item.
Eventually, the goal is to rely on the red-green dependency management Ultimately, this setup relies on the red-green algorithm.
algorithm. At the moment, however, we rely instead on a hack, where In particular, every variance query ultimately depends on -- effectively --
`variances_of` ignores the dependencies of accessing all type definitions in the entire crate (through `crate_variances`),
`crate_variances` and instead computes the *correct* dependencies but since most changes will not result in a change
itself. To this end, when we build up the constraints in the system, to the actual results from variance inference,
we also built up a transitive `dependencies` relation as part of the the `variances_of` query will wind up being considered green after it is re-evaluated.
crate map. A `(X, Y)` pair is added to the map each time we have a
constraint that the variance of some inferred for the item `X` depends
on the variance of some element of `Y`. This is to some extent a
mirroring of the inference graph in the dependency graph. This means
we can just completely ignore the fixed-point iteration, since it is
just shuffling values along this graph.
### Addendum: Variance on traits ### Addendum: Variance on traits

View file

@ -22,7 +22,6 @@ use syntax::ast;
use rustc::hir; use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc_data_structures::transitive_relation::TransitiveRelation;
use rustc_data_structures::stable_hasher::StableHashingContextProvider; use rustc_data_structures::stable_hasher::StableHashingContextProvider;
use super::terms::*; use super::terms::*;
@ -38,11 +37,6 @@ pub struct ConstraintContext<'a, 'tcx: 'a> {
bivariant: VarianceTermPtr<'a>, bivariant: VarianceTermPtr<'a>,
pub constraints: Vec<Constraint<'a>>, pub constraints: Vec<Constraint<'a>>,
/// This relation tracks the dependencies between the variance of
/// various items. In particular, if `a < b`, then the variance of
/// `a` depends on the sources of `b`.
pub dependencies: TransitiveRelation<DefId>,
} }
/// Declares that the variable `decl_id` appears in a location with /// Declares that the variable `decl_id` appears in a location with
@ -63,7 +57,6 @@ pub struct Constraint<'a> {
/// then while we are visiting `Bar<T>`, the `CurrentItem` would have /// then while we are visiting `Bar<T>`, the `CurrentItem` would have
/// the def-id and the start of `Foo`'s inferreds. /// the def-id and the start of `Foo`'s inferreds.
pub struct CurrentItem { pub struct CurrentItem {
def_id: DefId,
inferred_start: InferredIndex, inferred_start: InferredIndex,
} }
@ -81,7 +74,6 @@ pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>)
invariant, invariant,
bivariant, bivariant,
constraints: Vec::new(), constraints: Vec::new(),
dependencies: TransitiveRelation::new(),
}; };
tcx.hir.krate().visit_all_item_likes(&mut constraint_cx); tcx.hir.krate().visit_all_item_likes(&mut constraint_cx);
@ -201,7 +193,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
let id = tcx.hir.as_local_node_id(def_id).unwrap(); let id = tcx.hir.as_local_node_id(def_id).unwrap();
let inferred_start = self.terms_cx.inferred_starts[&id]; let inferred_start = self.terms_cx.inferred_starts[&id];
let current_item = &CurrentItem { def_id, inferred_start }; let current_item = &CurrentItem { inferred_start };
match tcx.type_of(def_id).sty { match tcx.type_of(def_id).sty {
ty::TyAdt(def, _) => { ty::TyAdt(def, _) => {
// Not entirely obvious: constraints on structs/enums do not // Not entirely obvious: constraints on structs/enums do not
@ -410,12 +402,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
return; return;
} }
// Add a corresponding relation into the dependencies to
// indicate that the variance for `current` relies on `def_id`.
if self.tcx().dep_graph.is_fully_enabled() {
self.dependencies.add(current.def_id, def_id);
}
let (local, remote) = if let Some(id) = self.tcx().hir.as_local_node_id(def_id) { let (local, remote) = if let Some(id) = self.tcx().hir.as_local_node_id(def_id) {
(Some(self.terms_cx.inferred_starts[&id]), None) (Some(self.terms_cx.inferred_starts[&id]), None)
} else { } else {

View file

@ -94,20 +94,9 @@ fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId)
// Everything else must be inferred. // Everything else must be inferred.
// Lacking red/green, we read the variances for all items here let crate_map = tcx.crate_variances(LOCAL_CRATE);
// but ignore the dependencies, then re-synthesize the ones we need.
let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE));
let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
tcx.dep_graph.read(dep_node); tcx.dep_graph.read(dep_node);
for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) {
if dep_def_id.is_local() {
let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
tcx.dep_graph.read(dep_node);
} else {
let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances);
tcx.dep_graph.read(dep_node);
}
}
crate_map.variances.get(&item_def_id) crate_map.variances.get(&item_def_id)
.unwrap_or(&crate_map.empty_variance) .unwrap_or(&crate_map.empty_variance)

View file

@ -34,7 +34,7 @@ struct SolveContext<'a, 'tcx: 'a> {
} }
pub fn solve_constraints(constraints_cx: ConstraintContext) -> ty::CrateVariancesMap { pub fn solve_constraints(constraints_cx: ConstraintContext) -> ty::CrateVariancesMap {
let ConstraintContext { terms_cx, dependencies, constraints, .. } = constraints_cx; let ConstraintContext { terms_cx, constraints, .. } = constraints_cx;
let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()]; let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()];
for &(id, ref variances) in &terms_cx.lang_items { for &(id, ref variances) in &terms_cx.lang_items {
@ -53,7 +53,7 @@ pub fn solve_constraints(constraints_cx: ConstraintContext) -> ty::CrateVariance
let variances = solutions_cx.create_map(); let variances = solutions_cx.create_map();
let empty_variance = Rc::new(Vec::new()); let empty_variance = Rc::new(Vec::new());
ty::CrateVariancesMap { dependencies, variances, empty_variance } ty::CrateVariancesMap { variances, empty_variance }
} }
impl<'a, 'tcx> SolveContext<'a, 'tcx> { impl<'a, 'tcx> SolveContext<'a, 'tcx> {