diff options
| author | Pietro Albini <pietro@pietroalbini.org> | 2018-10-04 12:20:13 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-10-04 12:20:13 +0200 |
| commit | cbc9477bda3388062274e835523266bbd2029227 (patch) | |
| tree | 06c1d0d703a7a06a787fc053149d382be4342758 | |
| parent | 7523cdf101a17eb7d33c55b843510a2a3dcfcfd4 (diff) | |
| parent | 832797689012ca63a7c9a7acdc7a4f34322d4faf (diff) | |
| download | rust-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.rs | 36 | ||||
| -rw-r--r-- | 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 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). |
