Skip to content

Commit

Permalink
Deeply normalize signature in new solver
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Jan 25, 2025
1 parent 87a4a73 commit 0eab7b0
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 12 deletions.
59 changes: 57 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use rustc_infer::infer::{
};
use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::query::{
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpNormalizeGoal,
CanonicalTypeOpProvePredicateGoal,
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpDeeplyNormalizeGoal,
CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal,
};
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{
Expand Down Expand Up @@ -109,6 +109,14 @@ impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUnivers
}
}

impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUniverseInfo<'tcx>
for CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T>
{
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
UniverseInfo::TypeOp(Rc::new(DeeplyNormalizeQuery { canonical_query: self, base_universe }))
}
}

impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpAscribeUserTypeGoal<'tcx> {
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
UniverseInfo::TypeOp(Rc::new(AscribeUserTypeQuery { canonical_query: self, base_universe }))
Expand Down Expand Up @@ -284,6 +292,53 @@ where
}
}

struct DeeplyNormalizeQuery<'tcx, T> {
canonical_query: CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T>,
base_universe: ty::UniverseIndex,
}

impl<'tcx, T> TypeOpInfo<'tcx> for DeeplyNormalizeQuery<'tcx, T>
where
T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx,
{
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> Diag<'tcx> {
tcx.dcx().create_err(HigherRankedLifetimeError {
cause: Some(HigherRankedErrorCause::CouldNotNormalize {
value: self.canonical_query.canonical.value.value.value.to_string(),
}),
span,
})
}

fn base_universe(&self) -> ty::UniverseIndex {
self.base_universe
}

fn nice_error<'infcx>(
&self,
mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<Diag<'infcx>> {
let (infcx, key, _) =
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
let ocx = ObligationCtxt::new(&infcx);

let (param_env, value) = key.into_parts();
let _ = ocx.deeply_normalize(&cause, param_env, value.value);

let diag = try_extract_error_from_fulfill_cx(
&ocx,
mbcx.mir_def_id(),
placeholder_region,
error_region,
)?
.with_dcx(mbcx.dcx());
Some(diag)
}
}

struct AscribeUserTypeQuery<'tcx> {
canonical_query: CanonicalTypeOpAscribeUserTypeGoal<'tcx>,
base_universe: ty::UniverseIndex,
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_borrowck/src/type_check/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.normalize_with_category(value, location, ConstraintCategory::Boring)
}

pub(super) fn deeply_normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
where
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
{
let result: Result<_, ErrorGuaranteed> = self.fully_perform_op(
location.to_locations(),
ConstraintCategory::Boring,
self.infcx.param_env.and(type_op::normalize::DeeplyNormalize { value }),
);
result.unwrap_or(value)
}

#[instrument(skip(self), level = "debug")]
pub(super) fn normalize_with_category<T>(
&mut self,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,9 +300,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
// Add implied bounds from impl header.
if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
let result: Result<_, ErrorGuaranteed> = param_env
.and(DeeplyNormalize { value: ty })
.fully_perform(self.infcx, span);
let result: Result<_, ErrorGuaranteed> =
param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, span);
let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else {
continue;
};
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,7 +1094,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ConstraintCategory::Boring,
);

let sig = self.normalize(unnormalized_sig, term_location);
let sig = self.deeply_normalize(unnormalized_sig, term_location);
// HACK(#114936): `WF(sig)` does not imply `WF(normalized(sig))`
// with built-in `Fn` implementations, since the impl may not be
// well-formed itself.
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_middle/src/traits/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;

pub type CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T> =
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::DeeplyNormalize<T>>>;

pub type CanonicalImpliedOutlivesBoundsGoal<'tcx> =
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ImpliedOutlivesBounds<'tcx>>>;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0733]: recursion in a coroutine requires boxing
--> $DIR/recursive-coroutine-indirect.rs:11:18
--> $DIR/recursive-coroutine-indirect.rs:13:18
|
LL | #[coroutine] move || {
| ^^^^^^^
Expand Down
6 changes: 4 additions & 2 deletions tests/ui/impl-trait/recursive-coroutine-indirect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver

//@[next] build-fail
//@[next] known-bug: unknown
//@[next] failure-status: 101
//@[next] dont-check-compiler-stderr
// Deeply normalizing writeback results of opaques makes this into a post-mono error :(

#![feature(coroutines)]
#![allow(unconditional_recursion)]
fn coroutine_hold() -> impl Sized {
#[coroutine] move || { //~ ERROR recursion in a coroutine requires boxing
#[coroutine] move || { //[current]~ ERROR recursion in a coroutine requires boxing
let x = coroutine_hold();
yield;
x;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0597]: `s` does not live long enough
--> $DIR/check-normalized-sig-for-wf.rs:7:7
--> $DIR/check-normalized-sig-for-wf.rs:11:7
|
LL | s: String,
| - binding `s` declared here
Expand All @@ -14,7 +14,7 @@ LL | }
| - `s` dropped here while still borrowed

error[E0521]: borrowed data escapes outside of function
--> $DIR/check-normalized-sig-for-wf.rs:15:5
--> $DIR/check-normalized-sig-for-wf.rs:19:5
|
LL | fn extend<T>(input: &T) -> &'static T {
| ----- - let's call the lifetime of this reference `'1`
Expand All @@ -28,7 +28,7 @@ LL | n(input).0
| argument requires that `'1` must outlive `'static`

error[E0521]: borrowed data escapes outside of function
--> $DIR/check-normalized-sig-for-wf.rs:23:5
--> $DIR/check-normalized-sig-for-wf.rs:27:5
|
LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T {
| -- ----- `input` is a reference that is only valid in the function body
Expand Down
47 changes: 47 additions & 0 deletions tests/ui/nll/check-normalized-sig-for-wf.next.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
error[E0597]: `s` does not live long enough
--> $DIR/check-normalized-sig-for-wf.rs:11:7
|
LL | s: String,
| - binding `s` declared here
...
LL | f(&s).0
| --^^-
| | |
| | borrowed value does not live long enough
| argument requires that `s` is borrowed for `'static`
LL |
LL | }
| - `s` dropped here while still borrowed

error[E0521]: borrowed data escapes outside of function
--> $DIR/check-normalized-sig-for-wf.rs:19:5
|
LL | fn extend<T>(input: &T) -> &'static T {
| ----- - let's call the lifetime of this reference `'1`
| |
| `input` is a reference that is only valid in the function body
...
LL | n(input).0
| ^^^^^^^^
| |
| `input` escapes the function body here
| argument requires that `'1` must outlive `'static`

error[E0521]: borrowed data escapes outside of function
--> $DIR/check-normalized-sig-for-wf.rs:27:5
|
LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T {
| -- ----- `input` is a reference that is only valid in the function body
| |
| lifetime `'a` defined here
...
LL | n(input).0
| ^^^^^^^^
| |
| `input` escapes the function body here
| argument requires that `'a` must outlive `'static`

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0521, E0597.
For more information about an error, try `rustc --explain E0521`.
4 changes: 4 additions & 0 deletions tests/ui/nll/check-normalized-sig-for-wf.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver

// <https://github.com/rust-lang/rust/issues/114936>
fn whoops(
s: String,
Expand Down

0 comments on commit 0eab7b0

Please sign in to comment.