Skip to content

Commit 5378c1c

Browse files
committed
Auto merge of rust-lang#119821 - oli-obk:reveal_all_const_evals, r=lcnr
Always use RevealAll for const eval queries implements what is described in rust-lang#116803 (comment) Using `UserFacing` for const eval does not make sense anymore, unless we significantly change things like avoiding revealing opaque types. New tests are copied from rust-lang#101478
2 parents 128148d + 867831a commit 5378c1c

32 files changed

+363
-108
lines changed

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+9-29
Original file line numberDiff line numberDiff line change
@@ -225,17 +225,10 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
225225
tcx: TyCtxt<'tcx>,
226226
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
227227
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
228-
// see comment in eval_to_allocation_raw_provider for what we're doing here
229-
if key.param_env.reveal() == Reveal::All {
230-
let mut key = key;
231-
key.param_env = key.param_env.with_user_facing();
232-
match tcx.eval_to_const_value_raw(key) {
233-
// try again with reveal all as requested
234-
Err(ErrorHandled::TooGeneric(_)) => {}
235-
// deduplicate calls
236-
other => return other,
237-
}
238-
}
228+
// Const eval always happens in Reveal::All mode in order to be able to use the hidden types of
229+
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
230+
// types that are not specified in the opaque type.
231+
assert_eq!(key.param_env.reveal(), Reveal::All);
239232

240233
// We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
241234
// Catch such calls and evaluate them instead of trying to load a constant's MIR.
@@ -265,24 +258,11 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
265258
tcx: TyCtxt<'tcx>,
266259
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
267260
) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
268-
// Because the constant is computed twice (once per value of `Reveal`), we are at risk of
269-
// reporting the same error twice here. To resolve this, we check whether we can evaluate the
270-
// constant in the more restrictive `Reveal::UserFacing`, which most likely already was
271-
// computed. For a large percentage of constants that will already have succeeded. Only
272-
// associated constants of generic functions will fail due to not enough monomorphization
273-
// information being available.
274-
275-
// In case we fail in the `UserFacing` variant, we just do the real computation.
276-
if key.param_env.reveal() == Reveal::All {
277-
let mut key = key;
278-
key.param_env = key.param_env.with_user_facing();
279-
match tcx.eval_to_allocation_raw(key) {
280-
// try again with reveal all as requested
281-
Err(ErrorHandled::TooGeneric(_)) => {}
282-
// deduplicate calls
283-
other => return other,
284-
}
285-
}
261+
// Const eval always happens in Reveal::All mode in order to be able to use the hidden types of
262+
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
263+
// types that are not specified in the opaque type.
264+
265+
assert_eq!(key.param_env.reveal(), Reveal::All);
286266
if cfg!(debug_assertions) {
287267
// Make sure we format the instance even if we do not print it.
288268
// This serves as a regression test against an ICE on printing.

compiler/rustc_middle/src/mir/interpret/queries.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ impl<'tcx> TyCtxt<'tcx> {
145145
) -> EvalToConstValueResult<'tcx> {
146146
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
147147
// improve caching of queries.
148-
let inputs = self.erase_regions(param_env.and(cid));
148+
let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid));
149149
if let Some(span) = span {
150150
// The query doesn't know where it is being invoked, so we need to fix the span.
151151
self.at(span).eval_to_const_value_raw(inputs).map_err(|e| e.with_span(span))
@@ -164,7 +164,7 @@ impl<'tcx> TyCtxt<'tcx> {
164164
) -> EvalToValTreeResult<'tcx> {
165165
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
166166
// improve caching of queries.
167-
let inputs = self.erase_regions(param_env.and(cid));
167+
let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid));
168168
debug!(?inputs);
169169
if let Some(span) = span {
170170
// The query doesn't know where it is being invoked, so we need to fix the span.

tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`.
99
|
1010
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
1111
| ^^^^^^^^^^^^^^^^^^^^^^^
12-
note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`...
13-
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
14-
|
15-
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
16-
| ^^^^^^^^^^^^^^^^^^^^^^^
1712
note: ...which requires const-evaluating + checking `IMPL_REF_BAR`...
1813
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:27
1914
|

tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `DEFAULT_REF_BA
99
|
1010
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
12-
note: ...which requires simplifying constant for the type system `DEFAULT_REF_BAR`...
13-
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
14-
|
15-
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
16-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1712
note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`...
1813
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:30
1914
|

tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`
99
|
1010
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^
12-
note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`...
13-
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
14-
|
15-
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
16-
| ^^^^^^^^^^^^^^^^^^^^^^^^
1712
note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`...
1813
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:28
1914
|

tests/ui/consts/const-eval/const-eval-query-stack.stderr

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ LL | const X: i32 = 1 / 0;
77
query stack during panic:
88
#0 [eval_to_allocation_raw] const-evaluating + checking `X`
99
#1 [eval_to_const_value_raw] simplifying constant for the type system `X`
10-
#2 [eval_to_const_value_raw] simplifying constant for the type system `X`
11-
#3 [lint_mod] linting top-level module
12-
#4 [analysis] running analysis passes on this crate
10+
#2 [lint_mod] linting top-level module
11+
#3 [analysis] running analysis passes on this crate
1312
end of query stack

tests/ui/consts/const-size_of-cycle.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@ LL | bytes: [u8; std::mem::size_of::<Foo>()]
77
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
88
--> $DIR/const-size_of-cycle.rs:4:17
99
|
10-
LL | bytes: [u8; std::mem::size_of::<Foo>()]
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
12-
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
13-
--> $DIR/const-size_of-cycle.rs:4:17
14-
|
1510
LL | bytes: [u8; std::mem::size_of::<Foo>()]
1611
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1712
= note: ...which requires computing layout of `Foo`...

tests/ui/consts/issue-36163.stderr

+10-4
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,17 @@ note: ...which requires const-evaluating + checking `A`...
2020
LL | const A: isize = Foo::B as isize;
2121
| ^^^^^^^^^^^^^^^
2222
= note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle
23-
note: cycle used when simplifying constant for the type system `Foo::B::{constant#0}`
24-
--> $DIR/issue-36163.rs:4:9
23+
note: cycle used when collecting item types in top-level module
24+
--> $DIR/issue-36163.rs:1:1
2525
|
26-
LL | B = A,
27-
| ^
26+
LL | / const A: isize = Foo::B as isize;
27+
LL | |
28+
LL | | enum Foo {
29+
LL | | B = A,
30+
LL | | }
31+
LL | |
32+
LL | | fn main() {}
33+
| |____________^
2834
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
2935

3036
error: aborting due to 1 previous error

tests/ui/consts/issue-44415.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@ LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
77
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
88
--> $DIR/issue-44415.rs:6:17
99
|
10-
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12-
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
13-
--> $DIR/issue-44415.rs:6:17
14-
|
1510
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
1611
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1712
= note: ...which requires computing layout of `Foo`...

tests/ui/consts/recursive-zst-static.default.stderr

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
error[E0391]: cycle detected when const-evaluating + checking `FOO`
2-
--> $DIR/recursive-zst-static.rs:10:1
3-
|
4-
LL | static FOO: () = FOO;
5-
| ^^^^^^^^^^^^^^
6-
|
7-
note: ...which requires const-evaluating + checking `FOO`...
82
--> $DIR/recursive-zst-static.rs:10:18
93
|
104
LL | static FOO: () = FOO;
115
| ^^^
12-
= note: ...which again requires const-evaluating + checking `FOO`, completing the cycle
6+
|
7+
= note: ...which immediately requires const-evaluating + checking `FOO` again
138
note: cycle used when linting top-level module
149
--> $DIR/recursive-zst-static.rs:10:1
1510
|

tests/ui/consts/recursive-zst-static.unleash.stderr

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
error[E0391]: cycle detected when const-evaluating + checking `FOO`
2-
--> $DIR/recursive-zst-static.rs:10:1
3-
|
4-
LL | static FOO: () = FOO;
5-
| ^^^^^^^^^^^^^^
6-
|
7-
note: ...which requires const-evaluating + checking `FOO`...
82
--> $DIR/recursive-zst-static.rs:10:18
93
|
104
LL | static FOO: () = FOO;
115
| ^^^
12-
= note: ...which again requires const-evaluating + checking `FOO`, completing the cycle
6+
|
7+
= note: ...which immediately requires const-evaluating + checking `FOO` again
138
note: cycle used when linting top-level module
149
--> $DIR/recursive-zst-static.rs:10:1
1510
|

tests/ui/consts/write-to-static-mut-in-static.stderr

+2-7
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,12 @@ LL | pub static mut B: () = unsafe { A = 1; };
55
| ^^^^^ modifying a static's initial value from another static's initializer
66

77
error[E0391]: cycle detected when const-evaluating + checking `C`
8-
--> $DIR/write-to-static-mut-in-static.rs:5:1
9-
|
10-
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
11-
| ^^^^^^^^^^^^^^^^^^^^^
12-
|
13-
note: ...which requires const-evaluating + checking `C`...
148
--> $DIR/write-to-static-mut-in-static.rs:5:34
159
|
1610
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
1711
| ^^^^^
18-
= note: ...which again requires const-evaluating + checking `C`, completing the cycle
12+
|
13+
= note: ...which immediately requires const-evaluating + checking `C` again
1914
note: cycle used when linting top-level module
2015
--> $DIR/write-to-static-mut-in-static.rs:1:1
2116
|
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//! Check that const eval can use the size of opaque types.
2+
// check-pass
3+
use std::mem;
4+
fn returns_opaque() -> impl Sized {
5+
0u8
6+
}
7+
8+
struct NamedOpaqueType {
9+
data: [mem::MaybeUninit<u8>; size_of_fut(returns_opaque)],
10+
}
11+
12+
const fn size_of_fut<FUT>(x: fn() -> FUT) -> usize {
13+
mem::size_of::<FUT>()
14+
}
15+
16+
fn main() {}
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//! Check that array lengths can observe associated types of opaque types
2+
// check-pass
3+
trait MyTrait: Copy {
4+
const ASSOC: usize;
5+
}
6+
7+
impl MyTrait for u8 {
8+
const ASSOC: usize = 32;
9+
}
10+
11+
const fn yeet() -> impl MyTrait {
12+
0u8
13+
}
14+
15+
const fn output<T: MyTrait>(_: T) -> usize {
16+
<T as MyTrait>::ASSOC
17+
}
18+
19+
fn main() {
20+
let x = [0u8; output(yeet())];
21+
println!("{:?}", x);
22+
}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//! check that const eval can observe associated types of opaque types.
2+
// check-pass
3+
trait MyTrait: Copy {
4+
const ASSOC: usize;
5+
}
6+
7+
impl MyTrait for u8 {
8+
const ASSOC: usize = 32;
9+
}
10+
11+
const fn yeet() -> impl MyTrait {
12+
0u8
13+
}
14+
15+
const fn output<T: MyTrait>(_: T) -> usize {
16+
<T as MyTrait>::ASSOC
17+
}
18+
19+
#[repr(usize)]
20+
enum Foo {
21+
Bar = output(yeet()),
22+
}
23+
24+
fn main() {
25+
println!("{}", Foo::Bar as usize);
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//! This test ensures that we do look at the hidden types of
2+
//! opaque types during const eval in order to obtain the exact type
3+
//! of associated types.
4+
5+
// check-pass
6+
7+
trait MyTrait: Copy {
8+
const ASSOC: usize;
9+
}
10+
11+
impl MyTrait for u8 {
12+
const ASSOC: usize = 32;
13+
}
14+
15+
const fn yeet() -> impl MyTrait {
16+
0u8
17+
}
18+
19+
const fn output<T: MyTrait>(_: T) -> usize {
20+
<T as MyTrait>::ASSOC
21+
}
22+
23+
struct Foo<'a>(&'a ());
24+
const NEED_REVEAL_ALL: usize = output(yeet());
25+
26+
fn promote_div() -> &'static usize {
27+
&(10 / NEED_REVEAL_ALL)
28+
}
29+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//! Check that pattern matching can observe the hidden type of opaque types.
2+
// check-pass
3+
trait MyTrait: Copy {
4+
const ASSOC: u8;
5+
}
6+
7+
impl MyTrait for () {
8+
const ASSOC: u8 = 0;
9+
}
10+
11+
const fn yeet() -> impl MyTrait {}
12+
13+
const fn output<T: MyTrait>(_: T) -> u8 {
14+
<T as MyTrait>::ASSOC
15+
}
16+
17+
const CT: u8 = output(yeet());
18+
19+
fn main() {
20+
match 0 {
21+
CT => (),
22+
1.. => (),
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// This causes a query cycle due to using `Reveal::All`,
2+
// in #119821 const eval was changed to always use `Reveal::All`
3+
//
4+
// See that PR for more details.
5+
use std::mem::transmute;
6+
fn foo() -> impl Sized {
7+
//~^ ERROR cycle detected when computing type of
8+
unsafe {
9+
transmute::<_, u8>(foo());
10+
}
11+
0u8
12+
}
13+
14+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error[E0391]: cycle detected when computing type of `foo::{opaque#0}`
2+
--> $DIR/in-defining-scope.rs:6:13
3+
|
4+
LL | fn foo() -> impl Sized {
5+
| ^^^^^^^^^^
6+
|
7+
note: ...which requires computing type of opaque `foo::{opaque#0}`...
8+
--> $DIR/in-defining-scope.rs:6:13
9+
|
10+
LL | fn foo() -> impl Sized {
11+
| ^^^^^^^^^^
12+
note: ...which requires type-checking `foo`...
13+
--> $DIR/in-defining-scope.rs:6:1
14+
|
15+
LL | fn foo() -> impl Sized {
16+
| ^^^^^^^^^^^^^^^^^^^^^^
17+
= note: ...which requires computing layout of `foo::{opaque#0}`...
18+
= note: ...which requires normalizing `foo::{opaque#0}`...
19+
= note: ...which again requires computing type of `foo::{opaque#0}`, completing the cycle
20+
note: cycle used when checking that `foo::{opaque#0}` is well-formed
21+
--> $DIR/in-defining-scope.rs:6:13
22+
|
23+
LL | fn foo() -> impl Sized {
24+
| ^^^^^^^^^^
25+
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
26+
27+
error: aborting due to 1 previous error
28+
29+
For more information about this error, try `rustc --explain E0391`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//! Check that typeck can observe the size of an opaque type.
2+
// check-pass
3+
use std::mem::transmute;
4+
fn foo() -> impl Sized {
5+
0u8
6+
}
7+
8+
fn main() {
9+
unsafe {
10+
transmute::<_, u8>(foo());
11+
}
12+
}

0 commit comments

Comments
 (0)