about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPietro Albini <pietro@pietroalbini.org>2018-10-04 12:20:13 +0200
committerGitHub <noreply@github.com>2018-10-04 12:20:13 +0200
commitcbc9477bda3388062274e835523266bbd2029227 (patch)
tree06c1d0d703a7a06a787fc053149d382be4342758
parent7523cdf101a17eb7d33c55b843510a2a3dcfcfd4 (diff)
parent832797689012ca63a7c9a7acdc7a4f34322d4faf (diff)
downloadrust-cbc9477bda3388062274e835523266bbd2029227.tar.gz
rust-cbc9477bda3388062274e835523266bbd2029227.zip
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
-rw-r--r--src/librustc_typeck/collect.rs36
-rw-r--r--src/test/ui/chalkify/lower_env1.stderr6
2 files changed, 36 insertions, 6 deletions
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 17e0b0431da..f96c85ae7ae 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<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
diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr
index d6673f6a8a6..4a3e14ac034 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).