Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Walk into alias-eq nested goals even if normalization fails #125688

Merged
merged 3 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 6 additions & 0 deletions compiler/rustc_trait_selection/src/solve/alias_relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
rhs
};

// Add a `make_canonical_response` probe step so that we treat this as
// a candidate, even if `try_evaluate_added_goals` bails due to an error.
// It's `Certainty::AMBIGUOUS` because this candidate is not "finished",
// since equating the normalized terms will lead to additional constraints.
self.inspect.make_canonical_response(Certainty::AMBIGUOUS);

// Apply the constraints.
self.try_evaluate_added_goals()?;
let lhs = self.resolve_vars_if_possible(lhs);
Expand Down
11 changes: 6 additions & 5 deletions compiler/rustc_trait_selection/src/solve/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,9 +460,10 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
polarity: ty::PredicatePolarity::Positive,
}))
}
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => {
ChildMode::WellFormedObligation
}
ty::PredicateKind::Clause(
ty::ClauseKind::WellFormed(_) | ty::ClauseKind::Projection(..),
)
| ty::PredicateKind::AliasRelate(..) => ChildMode::PassThrough,
_ => {
return ControlFlow::Break(self.obligation.clone());
}
Expand Down Expand Up @@ -496,7 +497,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
(_, GoalSource::InstantiateHigherRanked) => {
obligation = self.obligation.clone();
}
(ChildMode::WellFormedObligation, _) => {
(ChildMode::PassThrough, _) => {
obligation = make_obligation(self.obligation.cause.clone());
}
}
Expand Down Expand Up @@ -527,7 +528,7 @@ enum ChildMode<'tcx> {
// Skip trying to derive an `ObligationCause` from this obligation, and
// report *all* sub-obligations as if they came directly from the parent
// obligation.
WellFormedObligation,
PassThrough,
}

fn derive_cause<'tcx>(
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_macros::extension;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{inspect, QueryResult};
use rustc_middle::traits::solve::{Certainty, Goal};
use rustc_middle::traits::solve::{Certainty, Goal, MaybeCause};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{TyCtxt, TypeFoldable};
use rustc_middle::{bug, ty};
Expand Down Expand Up @@ -291,7 +291,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
steps.push(step)
}
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
assert_eq!(shallow_certainty.replace(c), None);
assert!(matches!(
shallow_certainty.replace(c),
None | Some(Certainty::Maybe(MaybeCause::Ambiguity))
));
}
inspect::ProbeStep::NestedProbe(ref probe) => {
match probe.kind {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2705,6 +2705,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
),
);
}

ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })
if term.is_infer() =>
{
if let Some(e) = self.tainted_by_errors() {
return e;
}
struct_span_code_err!(
self.dcx(),
span,
E0284,
"type annotations needed: cannot normalize `{alias}`",
)
.with_span_label(span, format!("cannot normalize `{alias}`"))
}

_ => {
if let Some(e) = self.tainted_by_errors() {
return e;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0284]: type annotations needed: cannot satisfy `<dyn Object<U, Output = T> as Object<U>>::Output == T`
error[E0284]: type annotations needed: cannot normalize `<dyn Object<U, Output = T> as Object<U>>::Output`
--> $DIR/indirect-impl-for-trait-obj-coherence.rs:25:41
|
LL | foo::<dyn Object<U, Output = T>, U>(x)
| ^ cannot satisfy `<dyn Object<U, Output = T> as Object<U>>::Output == T`
| ^ cannot normalize `<dyn Object<U, Output = T> as Object<U>>::Output`

error: aborting due to 1 previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fn foo<T: ?Sized, U>(x: <T as Object<U>>::Output) -> U {
#[allow(dead_code)]
fn transmute<T, U>(x: T) -> U {
foo::<dyn Object<U, Output = T>, U>(x)
//[next]~^ ERROR type annotations needed: cannot satisfy `<dyn Object<U, Output = T> as Object<U>>::Output == T`
//[next]~^ ERROR type annotations needed: cannot normalize `<dyn Object<U, Output = T> as Object<U>>::Output`
}

fn main() {}
4 changes: 2 additions & 2 deletions tests/ui/coherence/occurs-check/associated-type.next.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ LL | | for<'a> *const T: ToUnit<'a>,
|
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details

error[E0284]: type annotations needed: cannot satisfy `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc == usize`
error[E0284]: type annotations needed: cannot normalize `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc`
--> $DIR/associated-type.rs:44:59
|
LL | foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize);
| ^^^^^^ cannot satisfy `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc == usize`
| ^^^^^^ cannot normalize `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc`

error: aborting due to 2 previous errors

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/coherence/occurs-check/associated-type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ fn foo<T: Overlap<U>, U>(x: T::Assoc) -> T::Assoc {

fn main() {
foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize);
//[next]~^ ERROR: cannot satisfy
//[next]~^ ERROR: cannot normalize
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ LL | SelectInt.check("bar");
= help: the trait `AsExpression<Text>` is implemented for `&str`
= help: for that trait implementation, expected `Text`, found `Integer`

error[E0271]: type mismatch resolving `<&str as AsExpression<<SelectInt as Expression>::SqlType>>::Expression == _`
error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Text`
--> $DIR/as_expression.rs:57:5
|
LL | SelectInt.check("bar");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0284]: type annotations needed: cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc <: <T as Trait<'_>>::Assoc`
error[E0284]: type annotations needed: cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc normalizes-to <T as Trait<'_>>::Assoc`
--> $DIR/rigid-equate-projections-in-higher-ranked-fn-signature.rs:27:50
|
LL | let _: for<'a> fn(<_ as Trait<'a>>::Assoc) = foo::<T>();
| ^^^^^^^^^^ cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc <: <T as Trait<'_>>::Assoc`
| ^^^^^^^^^^ cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc normalizes-to <T as Trait<'_>>::Assoc`

error: aborting due to 1 previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ fn weird1() -> impl !Sized + Sized {}
//~^ ERROR type mismatch resolving `impl !Sized + Sized == ()`
fn weird2() -> impl !Sized {}
//~^ ERROR type mismatch resolving `impl !Sized == ()`
//~| ERROR the size for values of type `impl !Sized` cannot be known at compilation time
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ error[E0271]: type mismatch resolving `impl !Sized == ()`
LL | fn weird2() -> impl !Sized {}
| ^^^^^^^^^^^ types differ

error[E0277]: the size for values of type `impl !Sized` cannot be known at compilation time
--> $DIR/opaque-type-unsatisfied-bound.rs:19:16
|
LL | fn weird2() -> impl !Sized {}
| ^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `impl !Sized`
= note: the return type of a function must have a statically known size

error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied
--> $DIR/opaque-type-unsatisfied-bound.rs:12:13
|
Expand All @@ -30,7 +39,7 @@ note: required by a bound in `consume`
LL | fn consume(_: impl Trait) {}
| ^^^^^ required by this bound in `consume`

error: aborting due to 4 previous errors
error: aborting due to 5 previous errors

Some errors have detailed explanations: E0271, E0277.
For more information about an error, try `rustc --explain E0271`.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0284]: type annotations needed: cannot satisfy `{ || {} } == _`
error[E0284]: type annotations needed: cannot normalize `X::{constant#0}`
--> $DIR/const-region-infer-to-static-in-binder.rs:4:10
|
LL | struct X<const FN: fn() = { || {} }>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `{ || {} } == _`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `X::{constant#0}`

error: using function pointers as const generic parameters is forbidden
--> $DIR/const-region-infer-to-static-in-binder.rs:4:20
Expand Down
17 changes: 17 additions & 0 deletions tests/ui/traits/next-solver/diagnostics/projection-trait-ref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//@ compile-flags: -Znext-solver

trait Trait {
type Assoc;
}

fn test_poly<T>() {
let x: <T as Trait>::Assoc = ();
//~^ ERROR the trait bound `T: Trait` is not satisfied
}

fn test() {
let x: <i32 as Trait>::Assoc = ();
//~^ ERROR the trait bound `i32: Trait` is not satisfied
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
error[E0277]: the trait bound `T: Trait` is not satisfied
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm so dumb -- this doesn't actually even test that this PR does anything :(

The error comes from i32: Trait WF obligation from <i32 as Trait>::Assoc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test also doesn't enable -Znext-solver

--> $DIR/projection-trait-ref.rs:8:12
|
LL | let x: <T as Trait>::Assoc = ();
| ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
|
help: consider restricting type parameter `T`
|
LL | fn test_poly<T: Trait>() {
| +++++++

error[E0277]: the trait bound `i32: Trait` is not satisfied
--> $DIR/projection-trait-ref.rs:13:12
|
LL | let x: <i32 as Trait>::Assoc = ();
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `i32`
|
help: this trait has no implementations, consider adding one
--> $DIR/projection-trait-ref.rs:3:1
|
LL | trait Trait {
| ^^^^^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@ error[E0271]: type mismatch resolving `<T as Foo>::Assoc == i32`
--> $DIR/param-candidate-shadows-project.rs:27:19
|
LL | require_bar::<T>();
| ^ type mismatch resolving `<T as Foo>::Assoc == i32`
| ^ types differ
|
note: types differ
--> $DIR/param-candidate-shadows-project.rs:10:18
|
LL | type Assoc = i32;
| ^^^
note: required for `T` to implement `Bar`
--> $DIR/param-candidate-shadows-project.rs:13:9
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ fn needs_bar<T: Bar>() {}

fn foo<T: Foo<Assoc = i32> + Foo<Assoc = u32>>() {
needs_bar::<T>();
//~^ ERROR type annotations needed: cannot satisfy `<T as Foo>::Assoc == i32`
//~^ ERROR type annotations needed: cannot normalize
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0284]: type annotations needed: cannot satisfy `<T as Foo>::Assoc == i32`
error[E0284]: type annotations needed: cannot normalize `<T as Foo>::Assoc`
--> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17
|
LL | needs_bar::<T>();
| ^ cannot satisfy `<T as Foo>::Assoc == i32`
| ^ cannot normalize `<T as Foo>::Assoc`
|
note: required for `T` to implement `Bar`
--> $DIR/two-projection-param-candidates-are-ambiguous.rs:21:9
Expand Down
12 changes: 6 additions & 6 deletions tests/ui/traits/next-solver/specialization-transmute.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,23 @@ LL | #![feature(specialization)]

error: cannot normalize `<T as Default>::Id: '_`

error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id == _`
error[E0284]: type annotations needed: cannot normalize `<T as Default>::Id`
--> $DIR/specialization-transmute.rs:15:23
|
LL | fn intu(&self) -> &Self::Id {
| ^^^^^^^^^ cannot satisfy `<T as Default>::Id == _`
| ^^^^^^^^^ cannot normalize `<T as Default>::Id`

error[E0284]: type annotations needed: cannot satisfy `T <: <T as Default>::Id`
error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id normalizes-to T`
--> $DIR/specialization-transmute.rs:17:9
|
LL | self
| ^^^^ cannot satisfy `T <: <T as Default>::Id`
| ^^^^ cannot satisfy `<T as Default>::Id normalizes-to T`

error[E0284]: type annotations needed: cannot satisfy `<u8 as Default>::Id == Option<NonZero<u8>>`
error[E0284]: type annotations needed: cannot satisfy `<u8 as Default>::Id normalizes-to Option<NonZero<u8>>`
--> $DIR/specialization-transmute.rs:28:13
|
LL | let s = transmute::<u8, Option<NonZero<u8>>>(0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<u8 as Default>::Id == Option<NonZero<u8>>`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<u8 as Default>::Id normalizes-to Option<NonZero<u8>>`
|
note: required by a bound in `transmute`
--> $DIR/specialization-transmute.rs:21:25
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ fn test<T: Default<Id = U>, U>() {}

fn main() {
test::<u32, ()>();
//~^ ERROR cannot satisfy `<u32 as Default>::Id == ()`
//~^ ERROR cannot satisfy `<u32 as Default>::Id normalizes-to ()`
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ LL | #![feature(specialization)]
= help: consider using `min_specialization` instead, which is more stable and complete
= note: `#[warn(incomplete_features)]` on by default

error[E0284]: type annotations needed: cannot satisfy `<u32 as Default>::Id == ()`
error[E0284]: type annotations needed: cannot satisfy `<u32 as Default>::Id normalizes-to ()`
--> $DIR/specialization-unconstrained.rs:20:5
|
LL | test::<u32, ()>();
| ^^^^^^^^^^^^^^^^^ cannot satisfy `<u32 as Default>::Id == ()`
| ^^^^^^^^^^^^^^^^^ cannot satisfy `<u32 as Default>::Id normalizes-to ()`
|
note: required by a bound in `test`
--> $DIR/specialization-unconstrained.rs:17:20
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0284]: type annotations needed: cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
error[E0284]: type annotations needed: cannot satisfy `Bar == _`
--> $DIR/issue-84660-unsoundness.rs:22:37
|
LL | fn convert(_i: In) -> Self::Out {
Expand All @@ -7,7 +7,7 @@ LL | |
LL | |
LL | | unreachable!();
LL | | }
| |_____^ cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
| |_____^ cannot satisfy `Bar == _`

error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
--> $DIR/issue-84660-unsoundness.rs:29:1
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ trait Trait<T, In> {
impl<In, Out> Trait<Bar, In> for Out {
type Out = Out;
fn convert(_i: In) -> Self::Out {
//[next]~^ ERROR: cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
//[next]~^ ERROR: cannot satisfy `Bar == _`
//[current]~^^ ERROR: item does not constrain `Bar::{opaque#0}`, but has it in its signature
unreachable!();
}
Expand Down
Loading