Skip to content

Commit fe0bd76

Browse files
committed
elaborate unknowable goals
if a trait is unknowable, but its super trait is definitely not implemented, then the trait itself is definitely also not implemented.
1 parent 0fdfb61 commit fe0bd76

11 files changed

+122
-2
lines changed

compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,18 @@ where
699699
if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? {
700700
Err(NoSolution)
701701
} else {
702+
// While the trait bound itself may be unknowable, we may be able to
703+
// prove that a super trait is not implemented. For this, we recursively
704+
// prove the super trait bounds of the current goal.
705+
//
706+
// We skip the goal itself as that one would cycle.
707+
let predicate: I::Predicate = trait_ref.upcast(cx);
708+
ecx.add_goals(
709+
GoalSource::Misc,
710+
elaborate::elaborate(cx, [predicate])
711+
.skip(1)
712+
.map(|predicate| goal.with(cx, predicate)),
713+
);
702714
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
703715
}
704716
},

compiler/rustc_type_ir/src/inherent.rs

+1
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ pub trait Predicate<I: Interner<Predicate = Self>>:
433433
+ UpcastFrom<I, ty::OutlivesPredicate<I, I::Ty>>
434434
+ UpcastFrom<I, ty::OutlivesPredicate<I, I::Region>>
435435
+ IntoKind<Kind = ty::Binder<I, ty::PredicateKind<I>>>
436+
+ Elaboratable<I>
436437
{
437438
fn as_clause(self) -> Option<I::Clause>;
438439

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

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ LL |
77
LL | impl<S: Iterator> MyTrait<S> for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {}
88
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)`
99
|
10+
= note: upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions
1011
= note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
1112

1213
error: aborting due to 1 previous error

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

+1
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+
//[next]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions
2122

2223
fn main() {}
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-1.rs:16:1
3+
|
4+
LL | impl<T, U: Sub<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 `Sub<_>` for type `()`
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0119`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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+
//@[next] 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+
//[current]~^ ERROR conflicting implementations
18+
19+
fn main() {}
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() {}
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-3.rs:19:1
3+
|
4+
LL | impl<T, U: Bound<W<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 `Sub<_>` for type `()`
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0119`.
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 so this would not
3+
// compile if we were to only elaborate root goals.
4+
5+
//@ revisions: current next
6+
//@ ignore-compare-mode-next-solver (explicit revisions)
7+
//@[next] compile-flags: -Znext-solver
8+
//@[next] check-pass
9+
10+
trait Super {}
11+
trait Sub<T>: Super {}
12+
13+
struct W<T>(T);
14+
trait Bound<T> {}
15+
impl<T: Sub<U>, U> Bound<W<U>> for T {}
16+
17+
trait Overlap<T> {}
18+
impl<T, U: Bound<W<T>>> Overlap<T> for U {}
19+
impl<T> Overlap<T> for () {}
20+
//[current]~^ ERROR conflicting implementations of trait `Overlap<_>` for type `()`
21+
22+
fn main() {}

tests/ui/issues/issue-48728.stderr tests/ui/issues/issue-48728.current.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0119]: conflicting implementations of trait `Clone` for type `Node<[_]>`
2-
--> $DIR/issue-48728.rs:4:10
2+
--> $DIR/issue-48728.rs:9:10
33
|
44
LL | #[derive(Clone)]
55
| ^^^^^ conflicting implementation for `Node<[_]>`

tests/ui/issues/issue-48728.rs

+6-1
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+
//@[next] check-pass
8+
9+
#[derive(Clone)] //[current]~ ERROR conflicting implementations of trait `Clone`
510
struct Node<T: ?Sized>(Box<T>);
611

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

0 commit comments

Comments
 (0)