mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Rollup merge of #153614 - lcnr:find-param-in-clause-ambig, r=BoxyUwU
`FindParamInClause` handle edge-cases If normalization is ambiguous, we want to treat the where-bound as non-global. The affected code should pretty much always have other errors in that case. It does make reasoning about trait solver cycles and rerunning more confusing and just feels wrong ™️ I encountered this while looking into `ml-kem` (https://github.com/rust-lang/trait-system-refactor-initiative/issues/246). I don't know whether this matters in practice and don't care to look into it too deeply. We also want to properly handle concrete aliases which mention to something mentioning a generic parameter due to another where-bound. r? @BoxyUwU
This commit is contained in:
@@ -9,7 +9,6 @@
|
||||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::lang_items::SolverTraitLangItem;
|
||||
use rustc_type_ir::search_graph::CandidateHeadUsages;
|
||||
use rustc_type_ir::solve::Certainty::Maybe;
|
||||
use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind};
|
||||
use rustc_type_ir::{
|
||||
self as ty, Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
@@ -1286,28 +1285,34 @@ fn visit_ty(&mut self, ty: ty::Ty<I>) -> Self::Result {
|
||||
return ControlFlow::Break(Err(NoSolution));
|
||||
};
|
||||
|
||||
if let ty::Placeholder(p) = ty.kind() {
|
||||
if p.universe() == ty::UniverseIndex::ROOT {
|
||||
ControlFlow::Break(Ok(Certainty::Yes))
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
match ty.kind() {
|
||||
ty::Placeholder(p) => {
|
||||
if p.universe() == ty::UniverseIndex::ROOT {
|
||||
ControlFlow::Break(Ok(Certainty::Yes))
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
} else if ty.has_type_flags(TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_RE_INFER) {
|
||||
self.recursion_depth += 1;
|
||||
if self.recursion_depth > self.ecx.cx().recursion_limit() {
|
||||
return ControlFlow::Break(Ok(Maybe {
|
||||
cause: MaybeCause::Overflow {
|
||||
suggest_increasing_limit: true,
|
||||
keep_constraints: false,
|
||||
},
|
||||
opaque_types_jank: OpaqueTypesJank::AllGood,
|
||||
}));
|
||||
ty::Infer(_) => ControlFlow::Break(Ok(Certainty::AMBIGUOUS)),
|
||||
_ if ty.has_type_flags(
|
||||
TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_INFER | TypeFlags::HAS_ALIAS,
|
||||
) =>
|
||||
{
|
||||
self.recursion_depth += 1;
|
||||
if self.recursion_depth > self.ecx.cx().recursion_limit() {
|
||||
return ControlFlow::Break(Ok(Certainty::Maybe {
|
||||
cause: MaybeCause::Overflow {
|
||||
suggest_increasing_limit: true,
|
||||
keep_constraints: false,
|
||||
},
|
||||
opaque_types_jank: OpaqueTypesJank::AllGood,
|
||||
}));
|
||||
}
|
||||
let result = ty.super_visit_with(self);
|
||||
self.recursion_depth -= 1;
|
||||
result
|
||||
}
|
||||
let result = ty.super_visit_with(self);
|
||||
self.recursion_depth -= 1;
|
||||
result
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
_ => ControlFlow::Continue(()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1317,16 +1322,23 @@ fn visit_const(&mut self, ct: I::Const) -> Self::Result {
|
||||
return ControlFlow::Break(Err(NoSolution));
|
||||
};
|
||||
|
||||
if let ty::ConstKind::Placeholder(p) = ct.kind() {
|
||||
if p.universe() == ty::UniverseIndex::ROOT {
|
||||
ControlFlow::Break(Ok(Certainty::Yes))
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
match ct.kind() {
|
||||
ty::ConstKind::Placeholder(p) => {
|
||||
if p.universe() == ty::UniverseIndex::ROOT {
|
||||
ControlFlow::Break(Ok(Certainty::Yes))
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
} else if ct.has_type_flags(TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_RE_INFER) {
|
||||
ct.super_visit_with(self)
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
ty::ConstKind::Infer(_) => ControlFlow::Break(Ok(Certainty::AMBIGUOUS)),
|
||||
_ if ct.has_type_flags(
|
||||
TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_INFER | TypeFlags::HAS_ALIAS,
|
||||
) =>
|
||||
{
|
||||
// FIXME(mgca): we should also check the recursion limit here
|
||||
ct.super_visit_with(self)
|
||||
}
|
||||
_ => ControlFlow::Continue(()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/is-global-norm-concrete-alias-to-generic.rs:26:5
|
||||
|
|
||||
LL | fn foo<T>(x: <(*const T,) as Id>::This) -> (*const T,)
|
||||
| ----------- expected `(*const T,)` because of return type
|
||||
...
|
||||
LL | x
|
||||
| ^ expected `(*const T,)`, found associated type
|
||||
|
|
||||
= note: expected tuple `(*const T,)`
|
||||
found associated type `<(*const T,) as Id>::This`
|
||||
= help: consider constraining the associated type `<(*const T,) as Id>::This` to `(*const T,)`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
= note: the associated type `<(*const T,) as Id>::This` is defined as `(*const T,)` in the implementation, but the where-bound `(*const T,)` shadows this definition
|
||||
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/is-global-norm-concrete-alias-to-generic.rs:26:5
|
||||
|
|
||||
LL | fn foo<T>(x: <(*const T,) as Id>::This) -> (*const T,)
|
||||
| ----------- expected `(*const T,)` because of return type
|
||||
...
|
||||
LL | x
|
||||
| ^ types differ
|
||||
|
|
||||
= note: expected tuple `(*const T,)`
|
||||
found associated type `<(*const T,) as Id>::This`
|
||||
= help: consider constraining the associated type `<(*const T,) as Id>::This` to `(*const T,)`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
= note: the associated type `<(*const T,) as Id>::This` is defined as `(*const T,)` in the implementation, but the where-bound `(*const T,)` shadows this definition
|
||||
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
// A regression test making sure that where-bounds with concrete aliases
|
||||
// which normalize to something mentioning a generic parameters are
|
||||
// considered non-global.
|
||||
//
|
||||
// When checking this, we previously didn't recur into types if they didn't
|
||||
// mention any generic parameters, causing us to consider the `(<() as Id>::This,): Id`
|
||||
// where-bound as global, even though it normalizes to `(T,): Id`.
|
||||
|
||||
trait Id {
|
||||
type This;
|
||||
}
|
||||
|
||||
impl<T> Id for T {
|
||||
type This = T;
|
||||
}
|
||||
|
||||
fn foo<T>(x: <(*const T,) as Id>::This) -> (*const T,)
|
||||
where
|
||||
(): Id<This = *const T>,
|
||||
(<() as Id>::This,): Id,
|
||||
{
|
||||
x //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -4,6 +4,24 @@ error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: Trait`
|
||||
LL | <T as Trait>::Assoc: Trait,
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error[E0275]: overflow evaluating whether `<T as Trait>::Assoc` is well-formed
|
||||
--> $DIR/normalize-param-env-4.rs:19:26
|
||||
|
|
||||
LL | <T as Trait>::Assoc: Trait,
|
||||
| ^^^^^
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `T: Trait`
|
||||
--> $DIR/normalize-param-env-4.rs:32:19
|
||||
|
|
||||
LL | impls_trait::<T>();
|
||||
| ^
|
||||
|
|
||||
note: required by a bound in `impls_trait`
|
||||
--> $DIR/normalize-param-env-4.rs:15:19
|
||||
|
|
||||
LL | fn impls_trait<T: Trait>() {}
|
||||
| ^^^^^ required by this bound in `impls_trait`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
||||
Reference in New Issue
Block a user