Skip to content

Commit cbee778

Browse files
committed
elaborate obligations in coherence
1 parent 146f637 commit cbee778

File tree

6 files changed

+66
-8
lines changed

6 files changed

+66
-8
lines changed

compiler/rustc_trait_selection/src/traits/coherence.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,8 @@ use crate::solve::{deeply_normalize_for_diagnostics, inspect, FulfillmentCtxt};
1212
use crate::traits::engine::TraitEngineExt as _;
1313
use crate::traits::select::IntercrateAmbiguityCause;
1414
use crate::traits::structural_normalize::StructurallyNormalizeExt;
15-
use crate::traits::NormalizeExt;
16-
use crate::traits::SkipLeakCheck;
17-
use crate::traits::{
18-
Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext,
19-
};
15+
use crate::traits::{NormalizeExt, SelectionContext, SkipLeakCheck};
16+
use crate::traits::{Obligation, ObligationCause, PredicateObligation, PredicateObligations};
2017
use rustc_data_structures::fx::FxIndexSet;
2118
use rustc_errors::{Diag, EmissionGuarantee};
2219
use rustc_hir::def::DefKind;
@@ -346,9 +343,12 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
346343
) -> IntersectionHasImpossibleObligations<'tcx> {
347344
let infcx = selcx.infcx;
348345

346+
// Elaborate obligations in case the current obligation is unknowable,
347+
// but its super trait bound is not. See #124532 for more details.
348+
let obligations = util::elaborate(infcx.tcx, obligations.iter().cloned());
349349
if infcx.next_trait_solver() {
350350
let mut fulfill_cx = FulfillmentCtxt::new(infcx);
351-
fulfill_cx.register_predicate_obligations(infcx, obligations.iter().cloned());
351+
fulfill_cx.register_predicate_obligations(infcx, obligations);
352352

353353
// We only care about the obligations that are *definitely* true errors.
354354
// Ambiguities do not prove the disjointness of two impls.
@@ -371,7 +371,7 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
371371
for obligation in obligations {
372372
// We use `evaluate_root_obligation` to correctly track intercrate
373373
// ambiguity clauses.
374-
let evaluation_result = selcx.evaluate_root_obligation(obligation);
374+
let evaluation_result = selcx.evaluate_root_obligation(&obligation);
375375

376376
match evaluation_result {
377377
Ok(result) => {

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

+1
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

+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+
//[current]~| 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,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() {}
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
10+
// 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() {}

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+
//@ 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)