From 832797689012ca63a7c9a7acdc7a4f34322d4faf Mon Sep 17 00:00:00 2001 From: scalexm Date: Wed, 3 Oct 2018 11:47:09 +0200 Subject: [PATCH] Remove duplicate predicates in `explicit_predicates_of` Fixes #52187. --- src/librustc_typeck/collect.rs | 36 ++++++++++++++++++++++++-- src/test/ui/chalkify/lower_env1.stderr | 6 ++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 17e0b0431da6e..f96c85ae7ae3f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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, 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` come // before uses of `U`. This avoids false ambiguity errors diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr index d6673f6a8a6fb..4a3e14ac03472 100644 --- a/src/test/ui/chalkify/lower_env1.stderr +++ b/src/test/ui/chalkify/lower_env1.stderr @@ -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).