Skip to content

Commit a5d2c7b

Browse files
Deeply normalize signature in new solver
1 parent 4c36935 commit a5d2c7b

File tree

8 files changed

+129
-9
lines changed

8 files changed

+129
-9
lines changed

compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

+57-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use rustc_infer::infer::{
99
};
1010
use rustc_infer::traits::ObligationCause;
1111
use rustc_infer::traits::query::{
12-
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpNormalizeGoal,
13-
CanonicalTypeOpProvePredicateGoal,
12+
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpDeeplyNormalizeGoal,
13+
CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal,
1414
};
1515
use rustc_middle::ty::error::TypeError;
1616
use rustc_middle::ty::{
@@ -109,6 +109,14 @@ impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUnivers
109109
}
110110
}
111111

112+
impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUniverseInfo<'tcx>
113+
for CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T>
114+
{
115+
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
116+
UniverseInfo::TypeOp(Rc::new(DeeplyNormalizeQuery { canonical_query: self, base_universe }))
117+
}
118+
}
119+
112120
impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpAscribeUserTypeGoal<'tcx> {
113121
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
114122
UniverseInfo::TypeOp(Rc::new(AscribeUserTypeQuery { canonical_query: self, base_universe }))
@@ -284,6 +292,53 @@ where
284292
}
285293
}
286294

295+
struct DeeplyNormalizeQuery<'tcx, T> {
296+
canonical_query: CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T>,
297+
base_universe: ty::UniverseIndex,
298+
}
299+
300+
impl<'tcx, T> TypeOpInfo<'tcx> for DeeplyNormalizeQuery<'tcx, T>
301+
where
302+
T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx,
303+
{
304+
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> Diag<'tcx> {
305+
tcx.dcx().create_err(HigherRankedLifetimeError {
306+
cause: Some(HigherRankedErrorCause::CouldNotNormalize {
307+
value: self.canonical_query.canonical.value.value.value.to_string(),
308+
}),
309+
span,
310+
})
311+
}
312+
313+
fn base_universe(&self) -> ty::UniverseIndex {
314+
self.base_universe
315+
}
316+
317+
fn nice_error<'infcx>(
318+
&self,
319+
mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>,
320+
cause: ObligationCause<'tcx>,
321+
placeholder_region: ty::Region<'tcx>,
322+
error_region: Option<ty::Region<'tcx>>,
323+
) -> Option<Diag<'infcx>> {
324+
let (infcx, key, _) =
325+
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
326+
let ocx = ObligationCtxt::new(&infcx);
327+
328+
let (param_env, value) = key.into_parts();
329+
let _ = ocx.deeply_normalize(&cause, param_env, value.value);
330+
331+
let diag = try_extract_error_from_fulfill_cx(
332+
&ocx,
333+
mbcx.mir_def_id(),
334+
placeholder_region,
335+
error_region,
336+
)?
337+
.with_dcx(mbcx.dcx());
338+
Some(diag)
339+
}
340+
}
341+
287342
struct AscribeUserTypeQuery<'tcx> {
288343
canonical_query: CanonicalTypeOpAscribeUserTypeGoal<'tcx>,
289344
base_universe: ty::UniverseIndex,

compiler/rustc_borrowck/src/type_check/canonical.rs

+12
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
149149
self.normalize_with_category(value, location, ConstraintCategory::Boring)
150150
}
151151

152+
pub(super) fn deeply_normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
153+
where
154+
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
155+
{
156+
let result: Result<_, ErrorGuaranteed> = self.fully_perform_op(
157+
location.to_locations(),
158+
ConstraintCategory::Boring,
159+
self.infcx.param_env.and(type_op::normalize::DeeplyNormalize { value }),
160+
);
161+
result.unwrap_or(value)
162+
}
163+
152164
#[instrument(skip(self), level = "debug")]
153165
pub(super) fn normalize_with_category<T>(
154166
&mut self,

compiler/rustc_borrowck/src/type_check/free_region_relations.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
300300
// Add implied bounds from impl header.
301301
if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
302302
for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
303-
let result: Result<_, ErrorGuaranteed> = param_env
304-
.and(DeeplyNormalize { value: ty })
305-
.fully_perform(self.infcx, span);
303+
let result: Result<_, ErrorGuaranteed> =
304+
param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, span);
306305
let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else {
307306
continue;
308307
};

compiler/rustc_borrowck/src/type_check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
10941094
ConstraintCategory::Boring,
10951095
);
10961096

1097-
let sig = self.normalize(unnormalized_sig, term_location);
1097+
let sig = self.deeply_normalize(unnormalized_sig, term_location);
10981098
// HACK(#114936): `WF(sig)` does not imply `WF(normalized(sig))`
10991099
// with built-in `Fn` implementations, since the impl may not be
11001100
// well-formed itself.

compiler/rustc_middle/src/traits/query.rs

+3
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
8888
pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
8989
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
9090

91+
pub type CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T> =
92+
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::DeeplyNormalize<T>>>;
93+
9194
pub type CanonicalImpliedOutlivesBoundsGoal<'tcx> =
9295
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ImpliedOutlivesBounds<'tcx>>>;
9396

tests/ui/nll/check-normalized-sig-for-wf.stderr renamed to tests/ui/nll/check-normalized-sig-for-wf.current.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0597]: `s` does not live long enough
2-
--> $DIR/check-normalized-sig-for-wf.rs:7:7
2+
--> $DIR/check-normalized-sig-for-wf.rs:11:7
33
|
44
LL | s: String,
55
| - binding `s` declared here
@@ -14,7 +14,7 @@ LL | }
1414
| - `s` dropped here while still borrowed
1515

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

3030
error[E0521]: borrowed data escapes outside of function
31-
--> $DIR/check-normalized-sig-for-wf.rs:23:5
31+
--> $DIR/check-normalized-sig-for-wf.rs:27:5
3232
|
3333
LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T {
3434
| -- ----- `input` is a reference that is only valid in the function body
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
error[E0597]: `s` does not live long enough
2+
--> $DIR/check-normalized-sig-for-wf.rs:11:7
3+
|
4+
LL | s: String,
5+
| - binding `s` declared here
6+
...
7+
LL | f(&s).0
8+
| --^^-
9+
| | |
10+
| | borrowed value does not live long enough
11+
| argument requires that `s` is borrowed for `'static`
12+
LL |
13+
LL | }
14+
| - `s` dropped here while still borrowed
15+
16+
error[E0521]: borrowed data escapes outside of function
17+
--> $DIR/check-normalized-sig-for-wf.rs:19:5
18+
|
19+
LL | fn extend<T>(input: &T) -> &'static T {
20+
| ----- - let's call the lifetime of this reference `'1`
21+
| |
22+
| `input` is a reference that is only valid in the function body
23+
...
24+
LL | n(input).0
25+
| ^^^^^^^^
26+
| |
27+
| `input` escapes the function body here
28+
| argument requires that `'1` must outlive `'static`
29+
30+
error[E0521]: borrowed data escapes outside of function
31+
--> $DIR/check-normalized-sig-for-wf.rs:27:5
32+
|
33+
LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T {
34+
| -- ----- `input` is a reference that is only valid in the function body
35+
| |
36+
| lifetime `'a` defined here
37+
...
38+
LL | n(input).0
39+
| ^^^^^^^^
40+
| |
41+
| `input` escapes the function body here
42+
| argument requires that `'a` must outlive `'static`
43+
44+
error: aborting due to 3 previous errors
45+
46+
Some errors have detailed explanations: E0521, E0597.
47+
For more information about an error, try `rustc --explain E0521`.

tests/ui/nll/check-normalized-sig-for-wf.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
//@ revisions: current next
2+
//@ ignore-compare-mode-next-solver (explicit revisions)
3+
//@[next] compile-flags: -Znext-solver
4+
15
// <https://github.com/rust-lang/rust/issues/114936>
26
fn whoops(
37
s: String,

0 commit comments

Comments
 (0)