Skip to content

Commit ef57fea

Browse files
committed
elaborate obligations in coherence
1 parent cf77474 commit ef57fea

9 files changed

+112
-3
lines changed

compiler/rustc_trait_selection/src/traits/coherence.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,9 +358,12 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
358358
) -> IntersectionHasImpossibleObligations<'tcx> {
359359
let infcx = selcx.infcx;
360360

361+
// Elaborate obligations in case the current obligation is unknowable,
362+
// but its super trait bound is not. See #124532 for more details.
363+
let obligations = util::elaborate(infcx.tcx, obligations.iter().cloned());
361364
if infcx.next_trait_solver() {
362365
let ocx = ObligationCtxt::new(infcx);
363-
ocx.register_obligations(obligations.iter().cloned());
366+
ocx.register_obligations(obligations);
364367
let errors_and_ambiguities = ocx.select_all_or_error();
365368
// We only care about the obligations that are *definitely* true errors.
366369
// Ambiguities do not prove the disjointness of two impls.
@@ -387,7 +390,7 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
387390
for obligation in obligations {
388391
// We use `evaluate_root_obligation` to correctly track intercrate
389392
// ambiguity clauses.
390-
let evaluation_result = selcx.evaluate_root_obligation(obligation);
393+
let evaluation_result = selcx.evaluate_root_obligation(&obligation);
391394

392395
match evaluation_result {
393396
Ok(result) => {

tests/ui/coherence/normalize-for-errors.current.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ LL | impl<S: Iterator> MyTrait<S> for (Box<<(MyType,) as Mirror>::Assoc>, S::Ite
88
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, _)`
99
|
1010
= note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
11+
= note: upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions
1112

1213
error: aborting due to 1 previous error
1314

tests/ui/coherence/normalize-for-errors.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ impl<S: Iterator> MyTrait<S> for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {}
1818
//~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>,
1919
//~| NOTE conflicting implementation for `(Box<(MyType,)>,
2020
//~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
21+
//[current]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions
2122

2223
fn main() {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Added in #124532. While `(): Super` is knowable, `(): Sub<?t>` is not.
2+
//
3+
// We therefore elaborate super trait bounds in the implicit negative
4+
// overlap check.
5+
6+
//@ revisions: current next
7+
//@ ignore-compare-mode-next-solver (explicit revisions)
8+
//@[next] compile-flags: -Znext-solver
9+
//@ check-pass
10+
11+
trait Super {}
12+
trait Sub<T>: Super {}
13+
14+
trait Overlap<T> {}
15+
impl<T, U: Sub<T>> Overlap<T> for U {}
16+
impl<T> Overlap<T> for () {}
17+
18+
fn main() {}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// A regression test for pyella-0.1.5 which broke when
2+
// enabling the new solver in coherence.
3+
//
4+
// `Tensor: TensorValue` is knowable while `Tensor: TensorOp<?t2>`
5+
// may be implemented downstream. We previously didn't check the
6+
// super trait bound in coherence, causing these impls to overlap.
7+
//
8+
// However, we did fail to normalize `<Tensor as TensorValue::Unmasked`
9+
// which caused the old solver to emit a `Tensor: TensorValue` goal in
10+
// `fn normalize_to_error` which then failed, causing this test to pass.
11+
12+
//@ revisions: current next
13+
//@ ignore-compare-mode-next-solver (explicit revisions)
14+
//@[next] compile-flags: -Znext-solver
15+
//@ check-pass
16+
17+
pub trait TensorValue {
18+
type Unmasked;
19+
}
20+
21+
trait TensorCompare<T> {}
22+
pub trait TensorOp<T>: TensorValue {}
23+
24+
pub struct Tensor;
25+
impl<T2> TensorCompare<T2> for Tensor {}
26+
impl<T1, T2> TensorCompare<T2> for T1
27+
where
28+
T1: TensorOp<T2>,
29+
T1::Unmasked: Sized,
30+
{}
31+
32+
33+
fn main() {}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()`
2+
--> $DIR/super-trait-knowable-nested.rs:19:1
3+
|
4+
LL | impl<T, U: Bound<T>> Overlap<T> for U {}
5+
| ------------------------------------- first implementation here
6+
LL | impl<T> Overlap<T> for () {}
7+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
8+
|
9+
= note: downstream crates may implement trait `Bound<_>` for type `()`
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0119`.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()`
2+
--> $DIR/super-trait-knowable-nested.rs:19:1
3+
|
4+
LL | impl<T, U: Bound<T>> Overlap<T> for U {}
5+
| ------------------------------------- first implementation here
6+
LL | impl<T> Overlap<T> for () {}
7+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
8+
|
9+
= note: downstream crates may implement trait `Bound<_>` for type `()`
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0119`.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Unlike in `super-trait-knowable-1.rs`, the knowable
2+
// super trait bound is in a nested goal and we currently
3+
// only elaborate in the root. This can, and should, be#
4+
// changed in the future.
5+
6+
//@ revisions: current next
7+
//@ ignore-compare-mode-next-solver (explicit revisions)
8+
//@[next] compile-flags: -Znext-solver
9+
10+
trait Super {}
11+
trait Sub<T>: Super {}
12+
13+
trait Bound<T> {}
14+
15+
impl<T: Sub<T>, U> Bound<U> for T {}
16+
17+
trait Overlap<T> {}
18+
impl<T, U: Bound<T>> Overlap<T> for U {}
19+
impl<T> Overlap<T> for () {}
20+
//~^ ERROR conflicting implementations of trait `Overlap<_>` for type `()`
21+
22+
fn main() {}

tests/ui/issues/issue-48728.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
// Regression test for #48728, an ICE that occurred computing
22
// coherence "help" information.
33

4-
#[derive(Clone)] //~ ERROR conflicting implementations of trait `Clone`
4+
//@ revisions: current next
5+
//@ ignore-compare-mode-next-solver (explicit revisions)
6+
//@[next] compile-flags: -Znext-solver
7+
//@ check-pass
8+
9+
#[derive(Clone)]
510
struct Node<T: ?Sized>(Box<T>);
611

712
impl<T: Clone + ?Sized> Clone for Node<[T]> {

0 commit comments

Comments
 (0)