Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
elaborate obligations in coherence
  • Loading branch information
lcnr committed May 10, 2024
commit 4fde2415b5e74f5d0e5dd0b2c9dbb18d1c5520bc
7 changes: 5 additions & 2 deletions compiler/rustc_trait_selection/src/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,9 +358,12 @@ 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.
let obligations = util::elaborate(infcx.tcx, obligations.iter().cloned());
if infcx.next_trait_solver() {
let ocx = ObligationCtxt::new(infcx);
ocx.register_obligations(obligations.iter().cloned());
ocx.register_obligations(obligations);
let errors_and_ambiguities = ocx.select_all_or_error();
// We only care about the obligations that are *definitely* true errors.
// Ambiguities do not prove the disjointness of two impls.
Expand All @@ -387,7 +390,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) => {
Expand Down
1 change: 0 additions & 1 deletion src/tools/tidy/src/issues.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4061,7 +4061,6 @@ ui/traits/issue-6128.rs
ui/traits/issue-6334.rs
ui/traits/issue-65284-suggest-generic-trait-bound.rs
ui/traits/issue-65673.rs
ui/traits/issue-66768.rs
ui/traits/issue-68295.rs
ui/traits/issue-7013.rs
ui/traits/issue-70944.rs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ LL | | for<'a> <T as WithAssoc<'a>>::Assoc: WhereBound,
LL | impl<T> Trait for Box<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
|
= note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>`
= note: downstream crates may implement trait `WhereBound` for type `<std::boxed::Box<_> as WithAssoc<'a>>::Assoc`
= note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>`

error: aborting due to 1 previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ LL | | for<'a> Box<<T as WithAssoc<'a>>::Assoc>: WhereBound,
LL | impl<T> Trait for Box<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
|
= note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>`
= note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<<std::boxed::Box<_> as WithAssoc<'a>>::Assoc>`
= note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>`

error: aborting due to 1 previous error

Expand Down
1 change: 1 addition & 0 deletions tests/ui/coherence/normalize-for-errors.current.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ LL | impl<S: Iterator> MyTrait<S> 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

Expand Down
1 change: 1 addition & 0 deletions tests/ui/coherence/normalize-for-errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ impl<S: Iterator> MyTrait<S> 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() {}
18 changes: 18 additions & 0 deletions tests/ui/coherence/super-traits/super-trait-knowable-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Added in #124532. While `(): Super` is knowable, `(): Sub<?t>` 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<T>: Super {}

trait Overlap<T> {}
impl<T, U: Sub<T>> Overlap<T> for U {}
impl<T> Overlap<T> for () {}

fn main() {}
33 changes: 33 additions & 0 deletions tests/ui/coherence/super-traits/super-trait-knowable-2.rs
Original file line number Diff line number Diff line change
@@ -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<?t2>`
// 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 `<Tensor as TensorValue::Unmasked`
// which caused the old solver to emit a `Tensor: TensorValue` goal in
// `fn normalize_to_error` which then failed, causing this test to pass.

//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@ check-pass

pub trait TensorValue {
type Unmasked;
}

trait TensorCompare<T> {}
pub trait TensorOp<T>: TensorValue {}

pub struct Tensor;
impl<T2> TensorCompare<T2> for Tensor {}
impl<T1, T2> TensorCompare<T2> for T1
where
T1: TensorOp<T2>,
T1::Unmasked: Sized,
{}


fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()`
--> $DIR/super-trait-knowable-nested.rs:19:1
|
LL | impl<T, U: Bound<T>> Overlap<T> for U {}
| ------------------------------------- first implementation here
LL | impl<T> Overlap<T> for () {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
|
= note: downstream crates may implement trait `Bound<_>` for type `()`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0119`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()`
--> $DIR/super-trait-knowable-nested.rs:19:1
|
LL | impl<T, U: Bound<T>> Overlap<T> for U {}
| ------------------------------------- first implementation here
LL | impl<T> Overlap<T> for () {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
|
= note: downstream crates may implement trait `Bound<_>` for type `()`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0119`.
22 changes: 22 additions & 0 deletions tests/ui/coherence/super-traits/super-trait-knowable-nested.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Unlike in `super-trait-knowable-1.rs`, the knowable
// super trait bound is in a nested goal and we currently
// only elaborate in the root. This can, and should, be#
// changed in the future.

//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver

trait Super {}
trait Sub<T>: Super {}

trait Bound<T> {}

impl<T: Sub<T>, U> Bound<U> for T {}

trait Overlap<T> {}
impl<T, U: Bound<T>> Overlap<T> for U {}
impl<T> Overlap<T> for () {}
//~^ ERROR conflicting implementations of trait `Overlap<_>` for type `()`

fn main() {}
7 changes: 6 additions & 1 deletion tests/ui/issues/issue-48728.rs
Original file line number Diff line number Diff line change
@@ -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<T: ?Sized>(Box<T>);

impl<T: Clone + ?Sized> Clone for Node<[T]> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
error[E0119]: conflicting implementations of trait `Trait` for type `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>`
error[E0119]: conflicting implementations of trait `Trait` for type `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>>`
--> $DIR/coherence-fulfill-overflow.rs:12:1
|
LL | impl<T: ?Sized + TwoW> Trait for W<T> {}
| ------------------------------------- first implementation here
LL | impl<T: ?Sized + TwoW> Trait for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>>`
|
= note: overflow evaluating the requirement `W<W<W<W<W<_>>>>>: TwoW`
= note: overflow evaluating the requirement `W<W<W<W<_>>>>: TwoW`
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`coherence_fulfill_overflow`)

Expand Down