Rollup merge of #54780 - scalexm:dup-predicates, r=nikomatsakis

Remove duplicate predicates in `explicit_predicates_of`

I took a more brutal approach than described in #52187. I could have used the `linked_hash_map` crate but this seems overkill, especially as we need a vec storage in the end.

r? @nikomatsakis
This commit is contained in:
Pietro Albini 2018-10-04 12:20:13 +02:00 committed by GitHub
commit cbc9477bda
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 6 deletions

View file

@ -1637,9 +1637,39 @@ fn explicit_predicates_of<'a, 'tcx>(
def_id: DefId,
) -> ty::GenericPredicates<'tcx> {
use rustc::hir::*;
use rustc_data_structures::fx::FxHashSet;
debug!("explicit_predicates_of(def_id={:?})", def_id);
/// A data structure with unique elements, which preserves order of insertion.
/// Preserving the order of insertion is important here so as not to break
/// compile-fail UI tests.
struct UniquePredicates<'tcx> {
predicates: Vec<(ty::Predicate<'tcx>, Span)>,
uniques: FxHashSet<(ty::Predicate<'tcx>, Span)>,
}
impl<'tcx> UniquePredicates<'tcx> {
fn new() -> Self {
UniquePredicates {
predicates: vec![],
uniques: FxHashSet::default(),
}
}
fn push(&mut self, value: (ty::Predicate<'tcx>, Span)) {
if self.uniques.insert(value) {
self.predicates.push(value);
}
}
fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter: I) {
for value in iter {
self.push(value);
}
}
}
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
let node = tcx.hir.get(node_id);
@ -1649,7 +1679,7 @@ fn explicit_predicates_of<'a, 'tcx>(
let icx = ItemCtxt::new(tcx, def_id);
let no_generics = hir::Generics::empty();
let mut predicates = vec![];
let mut predicates = UniquePredicates::new();
let ast_generics = match node {
Node::TraitItem(item) => &item.generics,
@ -1744,7 +1774,7 @@ fn explicit_predicates_of<'a, 'tcx>(
// on a trait we need to add in the supertrait bounds and bounds found on
// associated types.
if let Some((_trait_ref, _)) = is_trait {
predicates = tcx.super_predicates_of(def_id).predicates;
predicates.extend(tcx.super_predicates_of(def_id).predicates);
}
// In default impls, we can assume that the self type implements
@ -1895,6 +1925,8 @@ fn explicit_predicates_of<'a, 'tcx>(
}))
}
let mut predicates = predicates.predicates;
// Subtle: before we store the predicates into the tcx, we
// sort them so that predicates like `T: Foo<Item=U>` come
// before uses of `U`. This avoids false ambiguity errors

View file

@ -5,9 +5,8 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
= note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
= note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo), WellFormed(Self: Foo).
= note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo).
error: program clause dump
--> $DIR/lower_env1.rs:19:1
@ -16,11 +15,10 @@ LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
= note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
= note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
= note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
= note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo), WellFormed(Self: Foo).
= note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo).
= note: WellFormed(Self: Foo) :- Implemented(Self: Foo).
= note: WellFormed(Self: std::marker::Sized) :- Implemented(Self: std::marker::Sized).