Deeply normalize in the new solver in WF

This commit is contained in:
Michael Goulet 2025-05-05 15:47:50 +00:00
parent 0eb0b8cb67
commit 12d3021ef0
13 changed files with 137 additions and 64 deletions

View file

@ -76,6 +76,36 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
)
}
/// Convenience function to *deeply* normalize during wfcheck. In the old solver,
/// this just dispatches to [`WfCheckingCtxt::normalize`], but in the new solver
/// this calls `deeply_normalize` and reports errors if they are encountered.
///
/// This function should be called in favor of `normalize` in cases where we will
/// then check the well-formedness of the type, since we only use the normalized
/// signature types for implied bounds when checking regions.
// FIXME(-Znext-solver): This should be removed when we compute implied outlives
// bounds using the unnormalized signature of the function we're checking.
fn deeply_normalize<T>(&self, span: Span, loc: Option<WellFormedLoc>, value: T) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
if self.infcx.next_trait_solver() {
match self.ocx.deeply_normalize(
&ObligationCause::new(span, self.body_def_id, ObligationCauseCode::WellFormed(loc)),
self.param_env,
value.clone(),
) {
Ok(value) => value,
Err(errors) => {
self.infcx.err_ctxt().report_fulfillment_errors(errors);
value
}
}
} else {
self.normalize(span, loc, value)
}
}
fn register_wf_obligation(&self, span: Span, loc: Option<WellFormedLoc>, term: ty::Term<'tcx>) {
let cause = traits::ObligationCause::new(
span,
@ -297,7 +327,8 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
{
let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
let ty = tcx.type_of(def_id).instantiate_identity();
let item_ty = wfcx.normalize(hir_ty.span, Some(WellFormedLoc::Ty(def_id)), ty);
let item_ty =
wfcx.deeply_normalize(hir_ty.span, Some(WellFormedLoc::Ty(def_id)), ty);
wfcx.register_wf_obligation(
hir_ty.span,
Some(WellFormedLoc::Ty(def_id)),
@ -1073,7 +1104,7 @@ fn check_associated_item(
match item.kind {
ty::AssocKind::Const { .. } => {
let ty = tcx.type_of(item.def_id).instantiate_identity();
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
wfcx.register_wf_obligation(span, loc, ty.into());
check_sized_if_body(
wfcx,
@ -1102,7 +1133,7 @@ fn check_associated_item(
}
if item.defaultness(tcx).has_value() {
let ty = tcx.type_of(item.def_id).instantiate_identity();
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
wfcx.register_wf_obligation(span, loc, ty.into());
}
Ok(())
@ -1149,7 +1180,7 @@ fn check_type_defn<'tcx>(
let field_id = field.did.expect_local();
let hir::FieldDef { ty: hir_ty, .. } =
tcx.hir_node_by_def_id(field_id).expect_field();
let ty = wfcx.normalize(
let ty = wfcx.deeply_normalize(
hir_ty.span,
None,
tcx.type_of(field.did).instantiate_identity(),
@ -1310,7 +1341,7 @@ fn check_item_type(
enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
let ty = tcx.type_of(item_id).instantiate_identity();
let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
let item_ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
let forbid_unsized = match unsized_handling {
UnsizedHandling::Forbid => true,
@ -1375,7 +1406,7 @@ fn check_impl<'tcx>(
// other `Foo` impls are incoherent.
tcx.ensure_ok().coherent_trait(trait_ref.def_id)?;
let trait_span = hir_trait_ref.path.span;
let trait_ref = wfcx.normalize(
let trait_ref = wfcx.deeply_normalize(
trait_span,
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
trait_ref,
@ -1435,7 +1466,7 @@ fn check_impl<'tcx>(
}
None => {
let self_ty = tcx.type_of(item.owner_id).instantiate_identity();
let self_ty = wfcx.normalize(
let self_ty = wfcx.deeply_normalize(
item.span,
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
self_ty,
@ -1640,7 +1671,7 @@ fn check_fn_or_method<'tcx>(
sig.inputs_and_output =
tcx.mk_type_list_from_iter(sig.inputs_and_output.iter().enumerate().map(|(idx, ty)| {
wfcx.normalize(
wfcx.deeply_normalize(
arg_span(idx),
Some(WellFormedLoc::Param {
function: def_id,

View file

@ -1,13 +0,0 @@
error[E0277]: the size for values of type `[u32]` cannot be known at compilation time
--> $DIR/wf-check-skipped.rs:17:25
|
LL | fn main() -> Foo::Bar::<Vec<[u32]>> {}
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u32]`
note: required by an implicit `Sized` bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,8 +1,8 @@
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[current] known-bug: #100041
//@[current] check-pass
//@ known-bug: #100041
//@ check-pass
// FIXME(inherent_associated_types): This should fail.
#![feature(inherent_associated_types)]
@ -15,4 +15,3 @@ impl Foo {
}
fn main() -> Foo::Bar::<Vec<[u32]>> {}
//[next]~^ ERROR the size for values of type `[u32]` cannot be known at compilation time

View file

@ -7,7 +7,7 @@ LL | type Loop = Loop;
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
error[E0275]: overflow normalizing the type alias `Loop`
--> $DIR/inherent-impls-overflow.rs:10:1
--> $DIR/inherent-impls-overflow.rs:12:1
|
LL | impl Loop {}
| ^^^^^^^^^^^^
@ -15,7 +15,7 @@ LL | impl Loop {}
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
error[E0275]: overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>`
--> $DIR/inherent-impls-overflow.rs:14:17
--> $DIR/inherent-impls-overflow.rs:17:17
|
LL | type Poly0<T> = Poly1<(T,)>;
| ^^^^^^^^^^^
@ -23,7 +23,7 @@ LL | type Poly0<T> = Poly1<(T,)>;
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
--> $DIR/inherent-impls-overflow.rs:17:17
--> $DIR/inherent-impls-overflow.rs:21:17
|
LL | type Poly1<T> = Poly0<(T,)>;
| ^^^^^^^^^^^
@ -31,7 +31,7 @@ LL | type Poly1<T> = Poly0<(T,)>;
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
--> $DIR/inherent-impls-overflow.rs:21:1
--> $DIR/inherent-impls-overflow.rs:26:1
|
LL | impl Poly0<()> {}
| ^^^^^^^^^^^^^^^^^

View file

@ -1,11 +1,31 @@
error[E0271]: type mismatch resolving `Loop normalizes-to _`
--> $DIR/inherent-impls-overflow.rs:10:6
--> $DIR/inherent-impls-overflow.rs:8:13
|
LL | type Loop = Loop;
| ^^^^ types differ
error[E0271]: type mismatch resolving `Loop normalizes-to _`
--> $DIR/inherent-impls-overflow.rs:12:1
|
LL | impl Loop {}
| ^^^^^^^^^^^^ types differ
error[E0271]: type mismatch resolving `Loop normalizes-to _`
--> $DIR/inherent-impls-overflow.rs:12:6
|
LL | impl Loop {}
| ^^^^ types differ
error[E0275]: overflow evaluating the requirement `Poly1<(T,)> == _`
--> $DIR/inherent-impls-overflow.rs:17:17
|
LL | type Poly0<T> = Poly1<(T,)>;
| ^^^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`)
error: type parameter `T` is only used recursively
--> $DIR/inherent-impls-overflow.rs:14:24
--> $DIR/inherent-impls-overflow.rs:17:24
|
LL | type Poly0<T> = Poly1<(T,)>;
| - ^
@ -15,8 +35,16 @@ LL | type Poly0<T> = Poly1<(T,)>;
= help: consider removing `T` or referring to it in the body of the type alias
= note: all type parameters must be used in a non-recursive way in order to constrain their variance
error[E0275]: overflow evaluating the requirement `Poly0<(T,)> == _`
--> $DIR/inherent-impls-overflow.rs:21:17
|
LL | type Poly1<T> = Poly0<(T,)>;
| ^^^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`)
error: type parameter `T` is only used recursively
--> $DIR/inherent-impls-overflow.rs:17:24
--> $DIR/inherent-impls-overflow.rs:21:24
|
LL | type Poly1<T> = Poly0<(T,)>;
| - ^
@ -27,14 +55,22 @@ LL | type Poly1<T> = Poly0<(T,)>;
= note: all type parameters must be used in a non-recursive way in order to constrain their variance
error[E0275]: overflow evaluating the requirement `Poly0<()> == _`
--> $DIR/inherent-impls-overflow.rs:21:6
--> $DIR/inherent-impls-overflow.rs:26:1
|
LL | impl Poly0<()> {}
| ^^^^^^^^^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`)
error[E0275]: overflow evaluating the requirement `Poly0<()> == _`
--> $DIR/inherent-impls-overflow.rs:26:6
|
LL | impl Poly0<()> {}
| ^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`)
error: aborting due to 4 previous errors
error: aborting due to 9 previous errors
Some errors have detailed explanations: E0271, E0275.
For more information about an error, try `rustc --explain E0271`.

View file

@ -5,21 +5,27 @@
#![feature(lazy_type_alias)]
#![allow(incomplete_features)]
type Loop = Loop; //[current]~ ERROR overflow normalizing the type alias `Loop`
type Loop = Loop;
//[current]~^ ERROR overflow normalizing the type alias `Loop`
//[next]~^^ ERROR type mismatch resolving `Loop normalizes-to _`
impl Loop {}
//[current]~^ ERROR overflow normalizing the type alias `Loop`
//[next]~^^ ERROR type mismatch resolving `Loop normalizes-to _`
//[next]~| ERROR type mismatch resolving `Loop normalizes-to _`
type Poly0<T> = Poly1<(T,)>;
//[current]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>`
//[next]~^^ ERROR type parameter `T` is only used recursively
//[next]~| ERROR overflow evaluating the requirement
type Poly1<T> = Poly0<(T,)>;
//[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
//[next]~^^ ERROR type parameter `T` is only used recursively
//[next]~| ERROR overflow evaluating the requirement
impl Poly0<()> {}
//[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
//[next]~^^ ERROR overflow evaluating the requirement `Poly0<()> == _`
//[next]~| ERROR overflow evaluating the requirement
fn main() {}

View file

@ -1,8 +1,8 @@
error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:7:11
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:7:22
|
LL | fn foo(x: for<'a> fn(<() as Trait<'a>>::Assoc)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a>` is not implemented for `()`
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a>` is not implemented for `()`
|
help: this trait has no implementations, consider adding one
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1

View file

@ -19,5 +19,6 @@ impl<T> Overlap<T> for T {}
impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {}
//~^ ERROR cannot find type `Missing` in this scope
//~| ERROR the trait bound `T: Overlap<for<'a> fn(Assoc<'a, T>)>` is not satisfied
//~| ERROR the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied
fn main() {}

View file

@ -26,6 +26,18 @@ LL | trait ToUnit<'a> {
| ^^^^^^^^^^^^^^^^
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. }
error[E0277]: the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied
--> $DIR/issue-118950-root-region.rs:19:9
|
LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `*const T`
|
help: this trait has no implementations, consider adding one
--> $DIR/issue-118950-root-region.rs:8:1
|
LL | trait ToUnit<'a> {
| ^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `T: Overlap<for<'a> fn(Assoc<'a, T>)>` is not satisfied
--> $DIR/issue-118950-root-region.rs:19:47
|
@ -37,7 +49,7 @@ help: consider further restricting type parameter `T` with trait `Overlap`
LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T>, T: Overlap<for<'a> fn(Assoc<'a, T>)> {}
| ++++++++++++++++++++++++++++++++++++++
error: aborting due to 3 previous errors; 1 warning emitted
error: aborting due to 4 previous errors; 1 warning emitted
Some errors have detailed explanations: E0277, E0412.
For more information about an error, try `rustc --explain E0277`.

View file

@ -1,8 +1,8 @@
error[E0277]: the trait bound `(): Wf` is not satisfied
--> $DIR/non-wf-in-coerce-pointers.rs:8:17
--> $DIR/non-wf-in-coerce-pointers.rs:8:8
|
LL | f: &'static <() as Wf>::Assoc,
| ^^^^^^^^^^^^^^^^^ the trait `Wf` is not implemented for `()`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Wf` is not implemented for `()`
|
help: this trait has no implementations, consider adding one
--> $DIR/non-wf-in-coerce-pointers.rs:3:1

View file

@ -0,0 +1,24 @@
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@ ignore-compare-mode-next-solver (explicit revisions)
//@ check-pass
// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/194>.
// Ensure that we check the well-formedness of `<Check as Mode>::Output<T>` after normalizing
// the type to `()`, since we only imply outlives bounds from the normalized signature, so we
// don't know (e.g.) that `&mut T` is WF.
trait Mode {
type Output<T>;
fn from_mut<T>(_r: &mut Self::Output<T>) -> Self::Output<&mut T>;
}
struct Check;
impl Mode for Check {
type Output<T> = ();
fn from_mut<T>(_r: &mut Self::Output<T>) -> Self::Output<&mut T> {}
}
fn main() {}

View file

@ -8,7 +8,7 @@ LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = ();
= note: slice and array elements must have `Sized` type
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/wf-normalization-sized.rs:22:11
--> $DIR/wf-normalization-sized.rs:21:11
|
LL | const _: <Vec<str> as WellUnformed>::RequestNormalize = ();
| ^^^^^^^^ doesn't have a size known at compile-time
@ -17,27 +17,6 @@ LL | const _: <Vec<str> as WellUnformed>::RequestNormalize = ();
note: required by an implicit `Sized` bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
error[E0277]: the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time
--> $DIR/wf-normalization-sized.rs:19:11
|
LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = ();
| ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[[[[[u8]]]]]`
= note: slice and array elements must have `Sized` type
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/wf-normalization-sized.rs:22:11
|
LL | const _: <Vec<str> as WellUnformed>::RequestNormalize = ();
| ^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
note: required by an implicit `Sized` bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 4 previous errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -18,9 +18,7 @@ impl<T: ?Sized> WellUnformed for T {
const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = ();
//[next]~^ ERROR the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time
//[next]~| ERROR the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time
const _: <Vec<str> as WellUnformed>::RequestNormalize = ();
//[next]~^ ERROR the size for values of type `str` cannot be known at compilation time
//[next]~| ERROR the size for values of type `str` cannot be known at compilation time
fn main() {}