Skip to content

Commit e6cf3bd

Browse files
authored
Rollup merge of #130645 - compiler-errors:normalize-gce-writeback, r=BoxyUwU
Normalize consts in writeback when GCE is enabled GCE lazily normalizes its unevaluated consts. This PR ensures that, like the new solver with its lazy norm types, we can assume that the writeback results are fully normalized. This is important since we're trying to eliminate unnecessary calls to `ty::Const::{eval,normalize}` since they won't work with mGCE. Previously, we'd keep those consts unnormalized in writeback all the way through MIR build, and they'd only get normalized if we explicitly called `ty::Const::{eval,normalize}`, or during codegen since that calls `normalize_erasing_regions` (which invokes the `QueryNormalizer`, which evaluates the const accordingly). This hack can (hopefully obviously) be removed when mGCE is implemented and we yeet the old GCE; it's only reachable with the GCE flag anyways, so I'm not worried about the implications here. r? `@BoxyUwU`
2 parents ff6cd18 + 920a973 commit e6cf3bd

File tree

8 files changed

+44
-70
lines changed

8 files changed

+44
-70
lines changed

Diff for: compiler/rustc_hir_typeck/src/pat.rs

+1-12
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
1111
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
1212
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, LangItem, Mutability, Pat, PatKind};
1313
use rustc_infer::infer;
14-
use rustc_middle::mir::interpret::ErrorHandled;
1514
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
1615
use rustc_middle::{bug, span_bug};
1716
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
@@ -2413,17 +2412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24132412
len: ty::Const<'tcx>,
24142413
min_len: u64,
24152414
) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
2416-
let len = match len.eval(self.tcx, self.param_env, span) {
2417-
Ok((_, val)) => val
2418-
.try_to_scalar()
2419-
.and_then(|scalar| scalar.try_to_scalar_int().ok())
2420-
.map(|int| int.to_target_usize(self.tcx)),
2421-
Err(ErrorHandled::Reported(..)) => {
2422-
let guar = self.error_scrutinee_unfixed_length(span);
2423-
return (Some(Ty::new_error(self.tcx, guar)), arr_ty);
2424-
}
2425-
Err(ErrorHandled::TooGeneric(..)) => None,
2426-
};
2415+
let len = len.try_eval_target_usize(self.tcx, self.param_env);
24272416

24282417
let guar = if let Some(len) = len {
24292418
// Now we know the length...

Diff for: compiler/rustc_hir_typeck/src/writeback.rs

+33-4
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
803803
// We must deeply normalize in the new solver, since later lints
804804
// expect that types that show up in the typeck are fully
805805
// normalized.
806-
let value = if self.should_normalize {
806+
let mut value = if self.should_normalize {
807807
let body_id = tcx.hir().body_owner_def_id(self.body.id());
808808
let cause = ObligationCause::misc(self.span.to_span(tcx), body_id);
809809
let at = self.fcx.at(&cause, self.fcx.param_env);
@@ -818,12 +818,27 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
818818
value
819819
};
820820

821+
// Bail if there are any non-region infer.
821822
if value.has_non_region_infer() {
822823
let guar = self.report_error(value);
823-
new_err(tcx, guar)
824-
} else {
825-
tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased)
824+
value = new_err(tcx, guar);
825+
}
826+
827+
// Erase the regions from the ty, since it's not really meaningful what
828+
// these region values are; there's not a trivial correspondence between
829+
// regions in the HIR and MIR, so when we turn the body into MIR, there's
830+
// no reason to keep regions around. They will be repopulated during MIR
831+
// borrowck, and specifically region constraints will be populated during
832+
// MIR typeck which is run on the new body.
833+
value = tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased);
834+
835+
// Normalize consts in writeback, because GCE doesn't normalize eagerly.
836+
if tcx.features().generic_const_exprs {
837+
value =
838+
value.fold_with(&mut EagerlyNormalizeConsts { tcx, param_env: self.fcx.param_env });
826839
}
840+
841+
value
827842
}
828843
}
829844

@@ -858,3 +873,17 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
858873
predicate
859874
}
860875
}
876+
877+
struct EagerlyNormalizeConsts<'tcx> {
878+
tcx: TyCtxt<'tcx>,
879+
param_env: ty::ParamEnv<'tcx>,
880+
}
881+
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerlyNormalizeConsts<'tcx> {
882+
fn cx(&self) -> TyCtxt<'tcx> {
883+
self.tcx
884+
}
885+
886+
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
887+
self.tcx.try_normalize_erasing_regions(self.param_env, ct).unwrap_or(ct)
888+
}
889+
}

Diff for: tests/ui/const-generics/generic_const_exprs/issue-109141.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
impl EntriesBuffer {
55
fn a(&self) -> impl Iterator {
6-
self.0.iter_mut() //~ ERROR: cannot borrow `*self.0` as mutable, as it is behind a `&` reference
7-
//~| ERROR captures lifetime that does not appear in bounds
6+
self.0.iter_mut()
87
}
98
}
109

Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0425]: cannot find value `HashesEntryLEN` in this scope
2-
--> $DIR/issue-109141.rs:11:32
2+
--> $DIR/issue-109141.rs:10:32
33
|
44
LL | struct EntriesBuffer(Box<[[u8; HashesEntryLEN]; 5]>);
55
| ^^^^^^^^^^^^^^ not found in this scope
@@ -9,33 +9,6 @@ help: you might be missing a const parameter
99
LL | struct EntriesBuffer<const HashesEntryLEN: /* Type */>(Box<[[u8; HashesEntryLEN]; 5]>);
1010
| ++++++++++++++++++++++++++++++++++
1111

12-
error[E0596]: cannot borrow `*self.0` as mutable, as it is behind a `&` reference
13-
--> $DIR/issue-109141.rs:6:9
14-
|
15-
LL | self.0.iter_mut()
16-
| ^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
17-
|
18-
help: consider changing this to be a mutable reference
19-
|
20-
LL | fn a(&mut self) -> impl Iterator {
21-
| ~~~~~~~~~
22-
23-
error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds
24-
--> $DIR/issue-109141.rs:6:9
25-
|
26-
LL | fn a(&self) -> impl Iterator {
27-
| ----- ------------- opaque type defined here
28-
| |
29-
| hidden type `std::slice::IterMut<'_, [u8; {const error}]>` captures the anonymous lifetime defined here
30-
LL | self.0.iter_mut()
31-
| ^^^^^^^^^^^^^^^^^
32-
|
33-
help: add a `use<...>` bound to explicitly capture `'_`
34-
|
35-
LL | fn a(&self) -> impl Iterator + use<'_> {
36-
| +++++++++
37-
38-
error: aborting due to 3 previous errors
12+
error: aborting due to 1 previous error
3913

40-
Some errors have detailed explanations: E0425, E0596, E0700.
41-
For more information about an error, try `rustc --explain E0425`.
14+
For more information about this error, try `rustc --explain E0425`.

Diff for: tests/ui/const-generics/generic_const_exprs/opaque_type.rs

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#![allow(incomplete_features)]
33

44
type Foo = impl Sized;
5-
//~^ ERROR: unconstrained opaque type
65

76
fn with_bound<const N: usize>() -> Foo
87
where
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0308]: mismatched types
2-
--> $DIR/opaque_type.rs:11:17
2+
--> $DIR/opaque_type.rs:10:17
33
|
44
LL | type Foo = impl Sized;
55
| ---------- the found opaque type
@@ -11,20 +11,12 @@ LL | let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
1111
found opaque type `Foo`
1212

1313
error[E0605]: non-primitive cast: `usize` as `Foo`
14-
--> $DIR/opaque_type.rs:11:17
14+
--> $DIR/opaque_type.rs:10:17
1515
|
1616
LL | let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
1717
| ^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
1818

19-
error: unconstrained opaque type
20-
--> $DIR/opaque_type.rs:4:12
21-
|
22-
LL | type Foo = impl Sized;
23-
| ^^^^^^^^^^
24-
|
25-
= note: `Foo` must be used in combination with a concrete type within the same module
26-
27-
error: aborting due to 3 previous errors
19+
error: aborting due to 2 previous errors
2820

2921
Some errors have detailed explanations: E0308, E0605.
3022
For more information about an error, try `rustc --explain E0308`.

Diff for: tests/ui/consts/issue-116186.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
fn something(path: [usize; N]) -> impl Clone {
55
//~^ ERROR cannot find value `N` in this scope
66
match path {
7-
[] => 0, //~ ERROR cannot pattern-match on an array without a fixed length
7+
[] => 0,
88
_ => 1,
99
};
1010
}

Diff for: tests/ui/consts/issue-116186.stderr

+2-9
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,6 @@ help: you might be missing a const parameter
99
LL | fn something<const N: /* Type */>(path: [usize; N]) -> impl Clone {
1010
| +++++++++++++++++++++
1111

12-
error[E0730]: cannot pattern-match on an array without a fixed length
13-
--> $DIR/issue-116186.rs:7:9
14-
|
15-
LL | [] => 0,
16-
| ^^
17-
18-
error: aborting due to 2 previous errors
12+
error: aborting due to 1 previous error
1913

20-
Some errors have detailed explanations: E0425, E0730.
21-
For more information about an error, try `rustc --explain E0425`.
14+
For more information about this error, try `rustc --explain E0425`.

0 commit comments

Comments
 (0)