diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index a4208cdc3c62c..603c58f3a6632 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -12,11 +12,8 @@ use crate::solve::{deeply_normalize_for_diagnostics, inspect, FulfillmentCtxt}; use crate::traits::engine::TraitEngineExt as _; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::structural_normalize::StructurallyNormalizeExt; -use crate::traits::NormalizeExt; -use crate::traits::SkipLeakCheck; -use crate::traits::{ - Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext, -}; +use crate::traits::{NormalizeExt, SelectionContext, SkipLeakCheck}; +use crate::traits::{Obligation, ObligationCause, PredicateObligation, PredicateObligations}; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir::def::DefKind; @@ -346,9 +343,15 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( ) -> IntersectionHasImpossibleObligations<'tcx> { let infcx = selcx.infcx; + // Elaborate obligations in case the current obligation is unknowable, + // but its super trait bound is not. See #124532 for more details. + // + // FIXME(-Znext-solver=coinductive): Once we always prove super trait + // bounds when using impls this `elaborate` call can be ignored. + let obligations = util::elaborate(infcx.tcx, obligations.iter().cloned()); if infcx.next_trait_solver() { let mut fulfill_cx = FulfillmentCtxt::new(infcx); - fulfill_cx.register_predicate_obligations(infcx, obligations.iter().cloned()); + fulfill_cx.register_predicate_obligations(infcx, obligations); // We only care about the obligations that are *definitely* true errors. // Ambiguities do not prove the disjointness of two impls. @@ -371,7 +374,7 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( for obligation in obligations { // We use `evaluate_root_obligation` to correctly track intercrate // ambiguity clauses. - let evaluation_result = selcx.evaluate_root_obligation(obligation); + let evaluation_result = selcx.evaluate_root_obligation(&obligation); match evaluation_result { Ok(result) => { diff --git a/tests/ui/coherence/normalize-for-errors.current.stderr b/tests/ui/coherence/normalize-for-errors.current.stderr index dcbb73bd1ff10..e273a4db1da77 100644 --- a/tests/ui/coherence/normalize-for-errors.current.stderr +++ b/tests/ui/coherence/normalize-for-errors.current.stderr @@ -8,6 +8,7 @@ LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Ite | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, _)` | = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions + = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions error: aborting due to 1 previous error diff --git a/tests/ui/coherence/normalize-for-errors.rs b/tests/ui/coherence/normalize-for-errors.rs index 2288118676ab3..d212d85427ab8 100644 --- a/tests/ui/coherence/normalize-for-errors.rs +++ b/tests/ui/coherence/normalize-for-errors.rs @@ -18,5 +18,6 @@ impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} //~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, //~| NOTE conflicting implementation for `(Box<(MyType,)>, //~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions +//[current]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs new file mode 100644 index 0000000000000..0e56084d6548f --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs @@ -0,0 +1,18 @@ +// Added in #124532. While `(): Super` is knowable, `(): Sub` is not. +// +// We therefore elaborate super trait bounds in the implicit negative +// overlap check. + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +trait Super {} +trait Sub: Super {} + +trait Overlap {} +impl> Overlap for U {} +impl Overlap for () {} + +fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs new file mode 100644 index 0000000000000..02341d1663a51 --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs @@ -0,0 +1,33 @@ +// A regression test for pyella-0.1.5 which broke when +// enabling the new solver in coherence. +// +// `Tensor: TensorValue` is knowable while `Tensor: TensorOp` +// may be implemented downstream. We previously didn't check the +// super trait bound in coherence, causing these impls to overlap. +// +// However, we did fail to normalize ` {} +pub trait TensorOp: TensorValue {} + +pub struct Tensor; +impl TensorCompare for Tensor {} +impl TensorCompare for T1 +where + T1: TensorOp, + T1::Unmasked: Sized, +{} + + +fn main() {} diff --git a/tests/ui/issues/issue-48728.rs b/tests/ui/issues/issue-48728.rs index cbdc10bd2e1ea..48e688cbd36fd 100644 --- a/tests/ui/issues/issue-48728.rs +++ b/tests/ui/issues/issue-48728.rs @@ -1,7 +1,12 @@ // Regression test for #48728, an ICE that occurred computing // coherence "help" information. -#[derive(Clone)] //~ ERROR conflicting implementations of trait `Clone` +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +#[derive(Clone)] struct Node(Box); impl Clone for Node<[T]> {