Rollup merge of #125688 - compiler-errors:alias-reporting, r=lcnr

Walk into alias-eq nested goals even if normalization fails

Somewhat broken due to the fact that we don't handle aliases well, nor do we handle ambiguities well. Still want to put up this incremental piece, since it improves type errors for projections whose trait refs are not satisfied.

r? lcnr
This commit is contained in:
Jubilee 2024-06-12 20:03:19 -07:00 committed by GitHub
commit 8719cc2579
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 114 additions and 40 deletions

View File

@ -48,6 +48,12 @@ pub(super) fn compute_alias_relate_goal(
rhs 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. // Apply the constraints.
self.try_evaluate_added_goals()?; self.try_evaluate_added_goals()?;
let lhs = self.resolve_vars_if_possible(lhs); let lhs = self.resolve_vars_if_possible(lhs);

View File

@ -460,9 +460,10 @@ fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result
polarity: ty::PredicatePolarity::Positive, polarity: ty::PredicatePolarity::Positive,
})) }))
} }
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => { ty::PredicateKind::Clause(
ChildMode::WellFormedObligation ty::ClauseKind::WellFormed(_) | ty::ClauseKind::Projection(..),
} )
| ty::PredicateKind::AliasRelate(..) => ChildMode::PassThrough,
_ => { _ => {
return ControlFlow::Break(self.obligation.clone()); return ControlFlow::Break(self.obligation.clone());
} }
@ -496,7 +497,7 @@ fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result
(_, GoalSource::InstantiateHigherRanked) => { (_, GoalSource::InstantiateHigherRanked) => {
obligation = self.obligation.clone(); obligation = self.obligation.clone();
} }
(ChildMode::WellFormedObligation, _) => { (ChildMode::PassThrough, _) => {
obligation = make_obligation(self.obligation.cause.clone()); obligation = make_obligation(self.obligation.cause.clone());
} }
} }
@ -527,7 +528,7 @@ enum ChildMode<'tcx> {
// Skip trying to derive an `ObligationCause` from this obligation, and // Skip trying to derive an `ObligationCause` from this obligation, and
// report *all* sub-obligations as if they came directly from the parent // report *all* sub-obligations as if they came directly from the parent
// obligation. // obligation.
WellFormedObligation, PassThrough,
} }
fn derive_cause<'tcx>( fn derive_cause<'tcx>(

View File

@ -15,7 +15,7 @@
use rustc_macros::extension; use rustc_macros::extension;
use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{inspect, QueryResult}; 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::traits::ObligationCause;
use rustc_middle::ty::{TyCtxt, TypeFoldable}; use rustc_middle::ty::{TyCtxt, TypeFoldable};
use rustc_middle::{bug, ty}; use rustc_middle::{bug, ty};
@ -291,7 +291,10 @@ fn candidates_recur(
steps.push(step) steps.push(step)
} }
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => { 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) => { inspect::ProbeStep::NestedProbe(ref probe) => {
match probe.kind { match probe.kind {

View File

@ -2705,6 +2705,22 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> Erro
), ),
); );
} }
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() { if let Some(e) = self.tainted_by_errors() {
return e; return e;

View File

@ -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 --> $DIR/indirect-impl-for-trait-obj-coherence.rs:25:41
| |
LL | foo::<dyn Object<U, Output = T>, U>(x) 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 error: aborting due to 1 previous error

View File

@ -23,7 +23,7 @@ fn foo<T: ?Sized, U>(x: <T as Object<U>>::Output) -> U {
#[allow(dead_code)] #[allow(dead_code)]
fn transmute<T, U>(x: T) -> U { fn transmute<T, U>(x: T) -> U {
foo::<dyn Object<U, Output = T>, U>(x) 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() {} fn main() {}

View File

@ -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 = 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 --> $DIR/associated-type.rs:44:59
| |
LL | foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); 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 error: aborting due to 2 previous errors

View File

@ -42,5 +42,5 @@ fn foo<T: Overlap<U>, U>(x: T::Assoc) -> T::Assoc {
fn main() { fn main() {
foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize);
//[next]~^ ERROR: cannot satisfy //[next]~^ ERROR: cannot normalize
} }

View File

@ -25,7 +25,7 @@ LL | SelectInt.check("bar");
= help: the trait `AsExpression<Text>` is implemented for `&str` = help: the trait `AsExpression<Text>` is implemented for `&str`
= help: for that trait implementation, expected `Text`, found `Integer` = 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 --> $DIR/as_expression.rs:57:5
| |
LL | SelectInt.check("bar"); LL | SelectInt.check("bar");

View File

@ -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 --> $DIR/rigid-equate-projections-in-higher-ranked-fn-signature.rs:27:50
| |
LL | let _: for<'a> fn(<_ as Trait<'a>>::Assoc) = foo::<T>(); 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 error: aborting due to 1 previous error

View File

@ -18,3 +18,4 @@ fn weird1() -> impl !Sized + Sized {}
//~^ ERROR type mismatch resolving `impl !Sized + Sized == ()` //~^ ERROR type mismatch resolving `impl !Sized + Sized == ()`
fn weird2() -> impl !Sized {} fn weird2() -> impl !Sized {}
//~^ ERROR type mismatch resolving `impl !Sized == ()` //~^ ERROR type mismatch resolving `impl !Sized == ()`
//~| ERROR the size for values of type `impl !Sized` cannot be known at compilation time

View File

@ -16,6 +16,15 @@ error[E0271]: type mismatch resolving `impl !Sized == ()`
LL | fn weird2() -> impl !Sized {} LL | fn weird2() -> impl !Sized {}
| ^^^^^^^^^^^ types differ | ^^^^^^^^^^^ 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 error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied
--> $DIR/opaque-type-unsatisfied-bound.rs:12:13 --> $DIR/opaque-type-unsatisfied-bound.rs:12:13
| |
@ -30,7 +39,7 @@ note: required by a bound in `consume`
LL | fn consume(_: impl Trait) {} LL | fn consume(_: impl Trait) {}
| ^^^^^ required by this bound in `consume` | ^^^^^ 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. Some errors have detailed explanations: E0271, E0277.
For more information about an error, try `rustc --explain E0271`. For more information about an error, try `rustc --explain E0271`.

View File

@ -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 --> $DIR/const-region-infer-to-static-in-binder.rs:4:10
| |
LL | struct X<const FN: fn() = { || {} }>; LL | struct X<const FN: fn() = { || {} }>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `{ || {} } == _` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `X::{constant#0}`
error: using function pointers as const generic parameters is forbidden error: using function pointers as const generic parameters is forbidden
--> $DIR/const-region-infer-to-static-in-binder.rs:4:20 --> $DIR/const-region-infer-to-static-in-binder.rs:4:20

View File

@ -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() {}

View File

@ -0,0 +1,26 @@
error[E0277]: the trait bound `T: Trait` is not satisfied
--> $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`.

View File

@ -2,13 +2,8 @@ error[E0271]: type mismatch resolving `<T as Foo>::Assoc == i32`
--> $DIR/param-candidate-shadows-project.rs:27:19 --> $DIR/param-candidate-shadows-project.rs:27:19
| |
LL | require_bar::<T>(); 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` note: required for `T` to implement `Bar`
--> $DIR/param-candidate-shadows-project.rs:13:9 --> $DIR/param-candidate-shadows-project.rs:13:9
| |

View File

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

View File

@ -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 --> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17
| |
LL | needs_bar::<T>(); LL | needs_bar::<T>();
| ^ cannot satisfy `<T as Foo>::Assoc == i32` | ^ cannot normalize `<T as Foo>::Assoc`
| |
note: required for `T` to implement `Bar` note: required for `T` to implement `Bar`
--> $DIR/two-projection-param-candidates-are-ambiguous.rs:21:9 --> $DIR/two-projection-param-candidates-are-ambiguous.rs:21:9

View File

@ -10,23 +10,23 @@ LL | #![feature(specialization)]
error: cannot normalize `<T as Default>::Id: '_` 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 --> $DIR/specialization-transmute.rs:15:23
| |
LL | fn intu(&self) -> &Self::Id { 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 --> $DIR/specialization-transmute.rs:17:9
| |
LL | self 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 --> $DIR/specialization-transmute.rs:28:13
| |
LL | let s = transmute::<u8, Option<NonZero<u8>>>(0); 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` note: required by a bound in `transmute`
--> $DIR/specialization-transmute.rs:21:25 --> $DIR/specialization-transmute.rs:21:25

View File

@ -18,5 +18,5 @@ fn test<T: Default<Id = U>, U>() {}
fn main() { fn main() {
test::<u32, ()>(); test::<u32, ()>();
//~^ ERROR cannot satisfy `<u32 as Default>::Id == ()` //~^ ERROR cannot satisfy `<u32 as Default>::Id normalizes-to ()`
} }

View File

@ -8,11 +8,11 @@ LL | #![feature(specialization)]
= help: consider using `min_specialization` instead, which is more stable and complete = help: consider using `min_specialization` instead, which is more stable and complete
= note: `#[warn(incomplete_features)]` on by default = 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 --> $DIR/specialization-unconstrained.rs:20:5
| |
LL | test::<u32, ()>(); LL | test::<u32, ()>();
| ^^^^^^^^^^^^^^^^^ cannot satisfy `<u32 as Default>::Id == ()` | ^^^^^^^^^^^^^^^^^ cannot satisfy `<u32 as Default>::Id normalizes-to ()`
| |
note: required by a bound in `test` note: required by a bound in `test`
--> $DIR/specialization-unconstrained.rs:17:20 --> $DIR/specialization-unconstrained.rs:17:20

View File

@ -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 --> $DIR/issue-84660-unsoundness.rs:22:37
| |
LL | fn convert(_i: In) -> Self::Out { LL | fn convert(_i: In) -> Self::Out {
@ -7,7 +7,7 @@ LL | |
LL | | LL | |
LL | | unreachable!(); LL | | unreachable!();
LL | | } LL | | }
| |_____^ cannot satisfy `<Out as Trait<Bar, In>>::Out == ()` | |_____^ cannot satisfy `Bar == _`
error[E0119]: conflicting implementations of trait `Trait<Bar, _>` error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
--> $DIR/issue-84660-unsoundness.rs:29:1 --> $DIR/issue-84660-unsoundness.rs:29:1

View File

@ -20,7 +20,7 @@ trait Trait<T, In> {
impl<In, Out> Trait<Bar, In> for Out { impl<In, Out> Trait<Bar, In> for Out {
type Out = Out; type Out = Out;
fn convert(_i: In) -> Self::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 //[current]~^^ ERROR: item does not constrain `Bar::{opaque#0}`, but has it in its signature
unreachable!(); unreachable!();
} }