diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index f933f1c3c94a7..52ca23c4b303e 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -13,7 +13,7 @@ use crate::traits::{ self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext, }; -//use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; @@ -44,7 +44,7 @@ pub enum Conflict { pub struct OverlapResult<'tcx> { pub impl_header: ty::ImplHeader<'tcx>, - pub intercrate_ambiguity_causes: Vec, + pub intercrate_ambiguity_causes: FxIndexSet, /// `true` if the overlap might've been permitted before the shift /// to universes. diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 21e14eae0ee27..96d83deeeb7ab 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -110,7 +110,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } }; debug!(?cause, "evaluate_stack: pushing cause"); - self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause); } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index b205ca8fa1169..2bb53a466caa4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -24,7 +24,7 @@ use crate::traits::error_reporting::InferCtxtExt; use crate::traits::project::ProjectAndUnifyResult; use crate::traits::project::ProjectionCacheKeyExt; use crate::traits::ProjectionCacheKey; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Diagnostic, ErrorGuaranteed}; use rustc_hir as hir; @@ -52,7 +52,7 @@ pub use rustc_middle::traits::select::*; mod candidate_assembly; mod confirmation; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq, Hash)] pub enum IntercrateAmbiguityCause { DownstreamCrate { trait_desc: String, self_desc: Option }, UpstreamCrateUpdate { trait_desc: String, self_desc: Option }, @@ -128,7 +128,7 @@ pub struct SelectionContext<'cx, 'tcx> { /// We don't do his until we detect a coherence error because it can /// lead to false overflow results (#47139) and because always /// computing it may negatively impact performance. - intercrate_ambiguity_causes: Option>, + intercrate_ambiguity_causes: Option>, /// The mode that trait queries run in, which informs our error handling /// policy. In essence, canonicalized queries need their errors propagated @@ -254,14 +254,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) { assert!(self.intercrate); assert!(self.intercrate_ambiguity_causes.is_none()); - self.intercrate_ambiguity_causes = Some(vec![]); + self.intercrate_ambiguity_causes = Some(FxIndexSet::default()); debug!("selcx: enable_tracking_intercrate_ambiguity_causes"); } /// Gets the intercrate ambiguity causes collected since tracking /// was enabled and disables tracking at the same time. If /// tracking is not enabled, just returns an empty vector. - pub fn take_intercrate_ambiguity_causes(&mut self) -> Vec { + pub fn take_intercrate_ambiguity_causes(&mut self) -> FxIndexSet { assert!(self.intercrate); self.intercrate_ambiguity_causes.take().unwrap_or_default() } @@ -960,7 +960,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); debug!(?cause, "evaluate_stack: pushing cause"); - self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause); } } } @@ -1252,7 +1252,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { reservation impl ambiguity on {:?}", def_id ); - intercrate_ambiguity_clauses.push( + intercrate_ambiguity_clauses.insert( IntercrateAmbiguityCause::ReservationImpl { message: value.to_string(), }, diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 13848d378909d..2c4a453aefc34 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -15,7 +15,7 @@ use specialization_graph::GraphExt; use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::{struct_span_err, EmissionGuarantee, LintDiagnosticBuilder}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; @@ -33,7 +33,7 @@ pub struct OverlapError { pub with_impl: DefId, pub trait_desc: String, pub self_desc: Option, - pub intercrate_ambiguity_causes: Vec, + pub intercrate_ambiguity_causes: FxIndexSet, pub involves_placeholder: bool, } diff --git a/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr b/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr index 8e7d4589e6140..b1ee0795b2eb3 100644 --- a/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr +++ b/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr @@ -8,7 +8,6 @@ LL | impl Foo for A { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` | = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions - = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.rs b/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.rs new file mode 100644 index 0000000000000..5b11c78ab2605 --- /dev/null +++ b/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.rs @@ -0,0 +1,19 @@ +struct S; + +impl From<()> for S { + fn from(x: ()) -> Self { + S + } +} + +impl From for S +//~^ ERROR conflicting implementations of trait +where + I: Iterator, +{ + fn from(x: I) -> Self { + S + } +} + +fn main() {} diff --git a/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.stderr b/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.stderr new file mode 100644 index 0000000000000..038a0199a8f27 --- /dev/null +++ b/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `std::convert::From<()>` for type `S` + --> $DIR/inter-crate-ambiguity-causes-notes.rs:9:1 + | +LL | impl From<()> for S { + | ------------------- first implementation here +... +LL | impl From for S + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S` + | + = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`.