Auto merge of #119821 - oli-obk:reveal_all_const_evals, r=lcnr
Always use RevealAll for const eval queries implements what is described in https://github.com/rust-lang/rust/pull/116803#discussion_r1364089471 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 https://github.com/rust-lang/rust/pull/101478
This commit is contained in:
commit
5378c1cf07
@ -225,17 +225,10 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
|
||||
// see comment in eval_to_allocation_raw_provider for what we're doing here
|
||||
if key.param_env.reveal() == Reveal::All {
|
||||
let mut key = key;
|
||||
key.param_env = key.param_env.with_user_facing();
|
||||
match tcx.eval_to_const_value_raw(key) {
|
||||
// try again with reveal all as requested
|
||||
Err(ErrorHandled::TooGeneric(_)) => {}
|
||||
// deduplicate calls
|
||||
other => return other,
|
||||
}
|
||||
}
|
||||
// Const eval always happens in Reveal::All mode in order to be able to use the hidden types of
|
||||
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
|
||||
// types that are not specified in the opaque type.
|
||||
assert_eq!(key.param_env.reveal(), Reveal::All);
|
||||
|
||||
// We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
|
||||
// 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>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||
) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
|
||||
// Because the constant is computed twice (once per value of `Reveal`), we are at risk of
|
||||
// reporting the same error twice here. To resolve this, we check whether we can evaluate the
|
||||
// constant in the more restrictive `Reveal::UserFacing`, which most likely already was
|
||||
// computed. For a large percentage of constants that will already have succeeded. Only
|
||||
// associated constants of generic functions will fail due to not enough monomorphization
|
||||
// information being available.
|
||||
// Const eval always happens in Reveal::All mode in order to be able to use the hidden types of
|
||||
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
|
||||
// types that are not specified in the opaque type.
|
||||
|
||||
// In case we fail in the `UserFacing` variant, we just do the real computation.
|
||||
if key.param_env.reveal() == Reveal::All {
|
||||
let mut key = key;
|
||||
key.param_env = key.param_env.with_user_facing();
|
||||
match tcx.eval_to_allocation_raw(key) {
|
||||
// try again with reveal all as requested
|
||||
Err(ErrorHandled::TooGeneric(_)) => {}
|
||||
// deduplicate calls
|
||||
other => return other,
|
||||
}
|
||||
}
|
||||
assert_eq!(key.param_env.reveal(), Reveal::All);
|
||||
if cfg!(debug_assertions) {
|
||||
// Make sure we format the instance even if we do not print it.
|
||||
// This serves as a regression test against an ICE on printing.
|
||||
|
@ -145,7 +145,7 @@ pub fn const_eval_global_id(
|
||||
) -> EvalToConstValueResult<'tcx> {
|
||||
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
|
||||
// improve caching of queries.
|
||||
let inputs = self.erase_regions(param_env.and(cid));
|
||||
let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid));
|
||||
if let Some(span) = span {
|
||||
// The query doesn't know where it is being invoked, so we need to fix the span.
|
||||
self.at(span).eval_to_const_value_raw(inputs).map_err(|e| e.with_span(span))
|
||||
@ -164,7 +164,7 @@ pub fn const_eval_global_id_for_typeck(
|
||||
) -> EvalToValTreeResult<'tcx> {
|
||||
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
|
||||
// improve caching of queries.
|
||||
let inputs = self.erase_regions(param_env.and(cid));
|
||||
let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid));
|
||||
debug!(?inputs);
|
||||
if let Some(span) = span {
|
||||
// The query doesn't know where it is being invoked, so we need to fix the span.
|
||||
|
@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`.
|
||||
|
|
||||
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`...
|
||||
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
|
||||
|
|
||||
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating + checking `IMPL_REF_BAR`...
|
||||
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:27
|
||||
|
|
||||
|
@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `DEFAULT_REF_BA
|
||||
|
|
||||
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires simplifying constant for the type system `DEFAULT_REF_BAR`...
|
||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
|
||||
|
|
||||
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`...
|
||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:30
|
||||
|
|
||||
|
@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`
|
||||
|
|
||||
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`...
|
||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
|
||||
|
|
||||
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`...
|
||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:28
|
||||
|
|
||||
|
@ -7,7 +7,6 @@ LL | const X: i32 = 1 / 0;
|
||||
query stack during panic:
|
||||
#0 [eval_to_allocation_raw] const-evaluating + checking `X`
|
||||
#1 [eval_to_const_value_raw] simplifying constant for the type system `X`
|
||||
#2 [eval_to_const_value_raw] simplifying constant for the type system `X`
|
||||
#3 [lint_mod] linting top-level module
|
||||
#4 [analysis] running analysis passes on this crate
|
||||
#2 [lint_mod] linting top-level module
|
||||
#3 [analysis] running analysis passes on this crate
|
||||
end of query stack
|
||||
|
@ -7,11 +7,6 @@ LL | bytes: [u8; std::mem::size_of::<Foo>()]
|
||||
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
|
||||
--> $DIR/const-size_of-cycle.rs:4:17
|
||||
|
|
||||
LL | bytes: [u8; std::mem::size_of::<Foo>()]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
|
||||
--> $DIR/const-size_of-cycle.rs:4:17
|
||||
|
|
||||
LL | bytes: [u8; std::mem::size_of::<Foo>()]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which requires computing layout of `Foo`...
|
||||
|
@ -20,11 +20,17 @@ note: ...which requires const-evaluating + checking `A`...
|
||||
LL | const A: isize = Foo::B as isize;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
= note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle
|
||||
note: cycle used when simplifying constant for the type system `Foo::B::{constant#0}`
|
||||
--> $DIR/issue-36163.rs:4:9
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/issue-36163.rs:1:1
|
||||
|
|
||||
LL | B = A,
|
||||
| ^
|
||||
LL | / const A: isize = Foo::B as isize;
|
||||
LL | |
|
||||
LL | | enum Foo {
|
||||
LL | | B = A,
|
||||
LL | | }
|
||||
LL | |
|
||||
LL | | fn main() {}
|
||||
| |____________^
|
||||
= 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
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -7,11 +7,6 @@ LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
||||
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
|
||||
--> $DIR/issue-44415.rs:6:17
|
||||
|
|
||||
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
|
||||
--> $DIR/issue-44415.rs:6:17
|
||||
|
|
||||
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which requires computing layout of `Foo`...
|
||||
|
@ -1,15 +1,10 @@
|
||||
error[E0391]: cycle detected when const-evaluating + checking `FOO`
|
||||
--> $DIR/recursive-zst-static.rs:10:1
|
||||
|
|
||||
LL | static FOO: () = FOO;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires const-evaluating + checking `FOO`...
|
||||
--> $DIR/recursive-zst-static.rs:10:18
|
||||
|
|
||||
LL | static FOO: () = FOO;
|
||||
| ^^^
|
||||
= note: ...which again requires const-evaluating + checking `FOO`, completing the cycle
|
||||
|
|
||||
= note: ...which immediately requires const-evaluating + checking `FOO` again
|
||||
note: cycle used when linting top-level module
|
||||
--> $DIR/recursive-zst-static.rs:10:1
|
||||
|
|
||||
|
@ -1,15 +1,10 @@
|
||||
error[E0391]: cycle detected when const-evaluating + checking `FOO`
|
||||
--> $DIR/recursive-zst-static.rs:10:1
|
||||
|
|
||||
LL | static FOO: () = FOO;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires const-evaluating + checking `FOO`...
|
||||
--> $DIR/recursive-zst-static.rs:10:18
|
||||
|
|
||||
LL | static FOO: () = FOO;
|
||||
| ^^^
|
||||
= note: ...which again requires const-evaluating + checking `FOO`, completing the cycle
|
||||
|
|
||||
= note: ...which immediately requires const-evaluating + checking `FOO` again
|
||||
note: cycle used when linting top-level module
|
||||
--> $DIR/recursive-zst-static.rs:10:1
|
||||
|
|
||||
|
@ -5,17 +5,12 @@ LL | pub static mut B: () = unsafe { A = 1; };
|
||||
| ^^^^^ modifying a static's initial value from another static's initializer
|
||||
|
||||
error[E0391]: cycle detected when const-evaluating + checking `C`
|
||||
--> $DIR/write-to-static-mut-in-static.rs:5:1
|
||||
|
|
||||
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires const-evaluating + checking `C`...
|
||||
--> $DIR/write-to-static-mut-in-static.rs:5:34
|
||||
|
|
||||
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
|
||||
| ^^^^^
|
||||
= note: ...which again requires const-evaluating + checking `C`, completing the cycle
|
||||
|
|
||||
= note: ...which immediately requires const-evaluating + checking `C` again
|
||||
note: cycle used when linting top-level module
|
||||
--> $DIR/write-to-static-mut-in-static.rs:1:1
|
||||
|
|
||||
|
16
tests/ui/impl-trait/in-ctfe/array-len-size-of.rs
Normal file
16
tests/ui/impl-trait/in-ctfe/array-len-size-of.rs
Normal file
@ -0,0 +1,16 @@
|
||||
//! Check that const eval can use the size of opaque types.
|
||||
// check-pass
|
||||
use std::mem;
|
||||
fn returns_opaque() -> impl Sized {
|
||||
0u8
|
||||
}
|
||||
|
||||
struct NamedOpaqueType {
|
||||
data: [mem::MaybeUninit<u8>; size_of_fut(returns_opaque)],
|
||||
}
|
||||
|
||||
const fn size_of_fut<FUT>(x: fn() -> FUT) -> usize {
|
||||
mem::size_of::<FUT>()
|
||||
}
|
||||
|
||||
fn main() {}
|
22
tests/ui/impl-trait/in-ctfe/array-len.rs
Normal file
22
tests/ui/impl-trait/in-ctfe/array-len.rs
Normal file
@ -0,0 +1,22 @@
|
||||
//! Check that array lengths can observe associated types of opaque types
|
||||
// check-pass
|
||||
trait MyTrait: Copy {
|
||||
const ASSOC: usize;
|
||||
}
|
||||
|
||||
impl MyTrait for u8 {
|
||||
const ASSOC: usize = 32;
|
||||
}
|
||||
|
||||
const fn yeet() -> impl MyTrait {
|
||||
0u8
|
||||
}
|
||||
|
||||
const fn output<T: MyTrait>(_: T) -> usize {
|
||||
<T as MyTrait>::ASSOC
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = [0u8; output(yeet())];
|
||||
println!("{:?}", x);
|
||||
}
|
26
tests/ui/impl-trait/in-ctfe/enum-discr.rs
Normal file
26
tests/ui/impl-trait/in-ctfe/enum-discr.rs
Normal file
@ -0,0 +1,26 @@
|
||||
//! check that const eval can observe associated types of opaque types.
|
||||
// check-pass
|
||||
trait MyTrait: Copy {
|
||||
const ASSOC: usize;
|
||||
}
|
||||
|
||||
impl MyTrait for u8 {
|
||||
const ASSOC: usize = 32;
|
||||
}
|
||||
|
||||
const fn yeet() -> impl MyTrait {
|
||||
0u8
|
||||
}
|
||||
|
||||
const fn output<T: MyTrait>(_: T) -> usize {
|
||||
<T as MyTrait>::ASSOC
|
||||
}
|
||||
|
||||
#[repr(usize)]
|
||||
enum Foo {
|
||||
Bar = output(yeet()),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{}", Foo::Bar as usize);
|
||||
}
|
29
tests/ui/impl-trait/in-ctfe/fully_monomorphic_const_eval.rs
Normal file
29
tests/ui/impl-trait/in-ctfe/fully_monomorphic_const_eval.rs
Normal file
@ -0,0 +1,29 @@
|
||||
//! This test ensures that we do look at the hidden types of
|
||||
//! opaque types during const eval in order to obtain the exact type
|
||||
//! of associated types.
|
||||
|
||||
// check-pass
|
||||
|
||||
trait MyTrait: Copy {
|
||||
const ASSOC: usize;
|
||||
}
|
||||
|
||||
impl MyTrait for u8 {
|
||||
const ASSOC: usize = 32;
|
||||
}
|
||||
|
||||
const fn yeet() -> impl MyTrait {
|
||||
0u8
|
||||
}
|
||||
|
||||
const fn output<T: MyTrait>(_: T) -> usize {
|
||||
<T as MyTrait>::ASSOC
|
||||
}
|
||||
|
||||
struct Foo<'a>(&'a ());
|
||||
const NEED_REVEAL_ALL: usize = output(yeet());
|
||||
|
||||
fn promote_div() -> &'static usize {
|
||||
&(10 / NEED_REVEAL_ALL)
|
||||
}
|
||||
fn main() {}
|
24
tests/ui/impl-trait/in-ctfe/match-arm-exhaustive.rs
Normal file
24
tests/ui/impl-trait/in-ctfe/match-arm-exhaustive.rs
Normal file
@ -0,0 +1,24 @@
|
||||
//! Check that pattern matching can observe the hidden type of opaque types.
|
||||
// check-pass
|
||||
trait MyTrait: Copy {
|
||||
const ASSOC: u8;
|
||||
}
|
||||
|
||||
impl MyTrait for () {
|
||||
const ASSOC: u8 = 0;
|
||||
}
|
||||
|
||||
const fn yeet() -> impl MyTrait {}
|
||||
|
||||
const fn output<T: MyTrait>(_: T) -> u8 {
|
||||
<T as MyTrait>::ASSOC
|
||||
}
|
||||
|
||||
const CT: u8 = output(yeet());
|
||||
|
||||
fn main() {
|
||||
match 0 {
|
||||
CT => (),
|
||||
1.. => (),
|
||||
}
|
||||
}
|
14
tests/ui/impl-trait/transmute/in-defining-scope.rs
Normal file
14
tests/ui/impl-trait/transmute/in-defining-scope.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// This causes a query cycle due to using `Reveal::All`,
|
||||
// in #119821 const eval was changed to always use `Reveal::All`
|
||||
//
|
||||
// See that PR for more details.
|
||||
use std::mem::transmute;
|
||||
fn foo() -> impl Sized {
|
||||
//~^ ERROR cycle detected when computing type of
|
||||
unsafe {
|
||||
transmute::<_, u8>(foo());
|
||||
}
|
||||
0u8
|
||||
}
|
||||
|
||||
fn main() {}
|
29
tests/ui/impl-trait/transmute/in-defining-scope.stderr
Normal file
29
tests/ui/impl-trait/transmute/in-defining-scope.stderr
Normal file
@ -0,0 +1,29 @@
|
||||
error[E0391]: cycle detected when computing type of `foo::{opaque#0}`
|
||||
--> $DIR/in-defining-scope.rs:6:13
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires computing type of opaque `foo::{opaque#0}`...
|
||||
--> $DIR/in-defining-scope.rs:6:13
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^
|
||||
note: ...which requires type-checking `foo`...
|
||||
--> $DIR/in-defining-scope.rs:6:1
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which requires computing layout of `foo::{opaque#0}`...
|
||||
= note: ...which requires normalizing `foo::{opaque#0}`...
|
||||
= note: ...which again requires computing type of `foo::{opaque#0}`, completing the cycle
|
||||
note: cycle used when checking that `foo::{opaque#0}` is well-formed
|
||||
--> $DIR/in-defining-scope.rs:6:13
|
||||
|
|
||||
LL | fn foo() -> impl Sized {
|
||||
| ^^^^^^^^^^
|
||||
= 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
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
12
tests/ui/impl-trait/transmute/outside-of-defining-scope.rs
Normal file
12
tests/ui/impl-trait/transmute/outside-of-defining-scope.rs
Normal file
@ -0,0 +1,12 @@
|
||||
//! Check that typeck can observe the size of an opaque type.
|
||||
// check-pass
|
||||
use std::mem::transmute;
|
||||
fn foo() -> impl Sized {
|
||||
0u8
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
transmute::<_, u8>(foo());
|
||||
}
|
||||
}
|
@ -10,11 +10,15 @@ note: ...which requires const-evaluating + checking `X::A::{constant#0}`...
|
||||
LL | A = X::A as isize,
|
||||
| ^^^^^^^^^^^^^
|
||||
= note: ...which again requires simplifying constant for the type system `X::A::{constant#0}`, completing the cycle
|
||||
note: cycle used when simplifying constant for the type system `X::A::{constant#0}`
|
||||
--> $DIR/issue-23302-1.rs:4:9
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/issue-23302-1.rs:3:1
|
||||
|
|
||||
LL | A = X::A as isize,
|
||||
| ^^^^^^^^^^^^^
|
||||
LL | / enum X {
|
||||
LL | | A = X::A as isize,
|
||||
LL | | }
|
||||
LL | |
|
||||
LL | | fn main() { }
|
||||
| |_____________^
|
||||
= 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
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -10,11 +10,16 @@ note: ...which requires const-evaluating + checking `Y::A::{constant#0}`...
|
||||
LL | A = Y::B as isize,
|
||||
| ^^^^^^^^^^^^^
|
||||
= note: ...which again requires simplifying constant for the type system `Y::A::{constant#0}`, completing the cycle
|
||||
note: cycle used when simplifying constant for the type system `Y::A::{constant#0}`
|
||||
--> $DIR/issue-23302-2.rs:4:9
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/issue-23302-2.rs:3:1
|
||||
|
|
||||
LL | A = Y::B as isize,
|
||||
| ^^^^^^^^^^^^^
|
||||
LL | / enum Y {
|
||||
LL | | A = Y::B as isize,
|
||||
LL | | B,
|
||||
LL | | }
|
||||
LL | |
|
||||
LL | | fn main() { }
|
||||
| |_____________^
|
||||
= 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
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -20,11 +20,15 @@ note: ...which requires const-evaluating + checking `B`...
|
||||
LL | const B: i32 = A;
|
||||
| ^
|
||||
= note: ...which again requires simplifying constant for the type system `A`, completing the cycle
|
||||
note: cycle used when simplifying constant for the type system `A`
|
||||
note: cycle used when linting top-level module
|
||||
--> $DIR/issue-23302-3.rs:1:1
|
||||
|
|
||||
LL | const A: i32 = B;
|
||||
| ^^^^^^^^^^^^
|
||||
LL | / const A: i32 = B;
|
||||
LL | |
|
||||
LL | | const B: i32 = A;
|
||||
LL | |
|
||||
LL | | fn main() { }
|
||||
| |_____________^
|
||||
= 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
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -1,15 +1,10 @@
|
||||
error[E0391]: cycle detected when const-evaluating + checking `FOO`
|
||||
--> $DIR/recursive-static-definition.rs:1:1
|
||||
|
|
||||
LL | pub static FOO: u32 = FOO;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires const-evaluating + checking `FOO`...
|
||||
--> $DIR/recursive-static-definition.rs:1:23
|
||||
|
|
||||
LL | pub static FOO: u32 = FOO;
|
||||
| ^^^
|
||||
= note: ...which again requires const-evaluating + checking `FOO`, completing the cycle
|
||||
|
|
||||
= note: ...which immediately requires const-evaluating + checking `FOO` again
|
||||
note: cycle used when linting top-level module
|
||||
--> $DIR/recursive-static-definition.rs:1:1
|
||||
|
|
||||
|
18
tests/ui/specialization/ctfe/default-assoc-const.rs
Normal file
18
tests/ui/specialization/ctfe/default-assoc-const.rs
Normal file
@ -0,0 +1,18 @@
|
||||
//! Regression test for revealing associated types through specialization during const eval.
|
||||
// check-pass
|
||||
#![feature(specialization)]
|
||||
//~^ WARNING the feature `specialization` is incomplete and may not be safe to use
|
||||
|
||||
trait Foo {
|
||||
const ASSOC: usize;
|
||||
}
|
||||
|
||||
impl Foo for u32 {
|
||||
default const ASSOC: usize = 0;
|
||||
}
|
||||
|
||||
fn foo() -> [u8; 0] {
|
||||
[0; <u32 as Foo>::ASSOC]
|
||||
}
|
||||
|
||||
fn main() {}
|
12
tests/ui/specialization/ctfe/default-assoc-const.stderr
Normal file
12
tests/ui/specialization/ctfe/default-assoc-const.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/default-assoc-const.rs:3:12
|
||||
|
|
||||
LL | #![feature(specialization)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: consider using `min_specialization` instead, which is more stable and complete
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
27
tests/ui/specialization/ctfe/default-assoc-type.rs
Normal file
27
tests/ui/specialization/ctfe/default-assoc-type.rs
Normal file
@ -0,0 +1,27 @@
|
||||
//! Regression test showing that we can access associated types during const eval,
|
||||
//! even if they rely on specialization.
|
||||
// check-pass
|
||||
#![feature(specialization)]
|
||||
//~^ WARNING the feature `specialization` is incomplete and may not be safe to use
|
||||
|
||||
trait Foo {
|
||||
type Assoc: Trait;
|
||||
}
|
||||
|
||||
impl<T> Foo for Vec<T> {
|
||||
default type Assoc = u32;
|
||||
}
|
||||
|
||||
trait Trait {
|
||||
const ASSOC: usize;
|
||||
}
|
||||
|
||||
impl Trait for u32 {
|
||||
const ASSOC: usize = 0;
|
||||
}
|
||||
|
||||
fn foo() -> [u8; 0] {
|
||||
[0; <<Vec<u32> as Foo>::Assoc as Trait>::ASSOC]
|
||||
}
|
||||
|
||||
fn main() {}
|
12
tests/ui/specialization/ctfe/default-assoc-type.stderr
Normal file
12
tests/ui/specialization/ctfe/default-assoc-type.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/default-assoc-type.rs:4:12
|
||||
|
|
||||
LL | #![feature(specialization)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: consider using `min_specialization` instead, which is more stable and complete
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
@ -8,5 +8,5 @@ error: the compiler unexpectedly panicked. this is a bug.
|
||||
|
||||
query stack during panic:
|
||||
#0 [eval_to_allocation_raw] const-evaluating + checking `C`
|
||||
#1 [eval_to_allocation_raw] const-evaluating + checking `C`
|
||||
#1 [lint_mod] linting top-level module
|
||||
end of query stack
|
||||
|
@ -4,11 +4,6 @@ error[E0391]: cycle detected when simplifying constant for the type system `Alph
|
||||
LL | V3 = Self::V1 {} as u8 + 2,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires simplifying constant for the type system `Alpha::V3::{constant#0}`...
|
||||
--> $DIR/self-in-enum-definition.rs:5:10
|
||||
|
|
||||
LL | V3 = Self::V1 {} as u8 + 2,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`...
|
||||
--> $DIR/self-in-enum-definition.rs:5:10
|
||||
|
|
||||
|
16
tests/ui/type-alias-impl-trait/in-where-clause.rs
Normal file
16
tests/ui/type-alias-impl-trait/in-where-clause.rs
Normal file
@ -0,0 +1,16 @@
|
||||
//! We evaluate `1 + 2` with `Reveal::All` during typeck, causing
|
||||
//! us to to get the concrete type of `Bar` while computing it.
|
||||
//! This again requires type checking `foo`.
|
||||
#![feature(type_alias_impl_trait)]
|
||||
type Bar = impl Sized;
|
||||
//~^ ERROR: cycle
|
||||
//~| ERROR: cycle
|
||||
|
||||
fn foo() -> Bar
|
||||
where
|
||||
Bar: Send,
|
||||
{
|
||||
[0; 1 + 2]
|
||||
}
|
||||
|
||||
fn main() {}
|
50
tests/ui/type-alias-impl-trait/in-where-clause.stderr
Normal file
50
tests/ui/type-alias-impl-trait/in-where-clause.stderr
Normal file
@ -0,0 +1,50 @@
|
||||
error[E0391]: cycle detected when computing type of `Bar::{opaque#0}`
|
||||
--> $DIR/in-where-clause.rs:5:12
|
||||
|
|
||||
LL | type Bar = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires computing type of opaque `Bar::{opaque#0}`...
|
||||
--> $DIR/in-where-clause.rs:5:12
|
||||
|
|
||||
LL | type Bar = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
note: ...which requires type-checking `foo`...
|
||||
--> $DIR/in-where-clause.rs:9:1
|
||||
|
|
||||
LL | / fn foo() -> Bar
|
||||
LL | | where
|
||||
LL | | Bar: Send,
|
||||
| |______________^
|
||||
= note: ...which requires revealing opaque types in `[Binder { value: TraitPredicate(<Bar as core::marker::Send>, polarity:Positive), bound_vars: [] }]`...
|
||||
= note: ...which again requires computing type of `Bar::{opaque#0}`, completing the cycle
|
||||
note: cycle used when checking that `Bar::{opaque#0}` is well-formed
|
||||
--> $DIR/in-where-clause.rs:5:12
|
||||
|
|
||||
LL | type Bar = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
= 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
|
||||
|
||||
error[E0391]: cycle detected when computing type of opaque `Bar::{opaque#0}`
|
||||
--> $DIR/in-where-clause.rs:5:12
|
||||
|
|
||||
LL | type Bar = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires type-checking `foo`...
|
||||
--> $DIR/in-where-clause.rs:13:9
|
||||
|
|
||||
LL | [0; 1 + 2]
|
||||
| ^^^^^
|
||||
= note: ...which requires evaluating trait selection obligation `Bar: core::marker::Send`...
|
||||
= note: ...which again requires computing type of opaque `Bar::{opaque#0}`, completing the cycle
|
||||
note: cycle used when computing type of `Bar::{opaque#0}`
|
||||
--> $DIR/in-where-clause.rs:5:12
|
||||
|
|
||||
LL | type Bar = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
= 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
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
Loading…
Reference in New Issue
Block a user