1
Fork 0

Rollup merge of #134314 - compiler-errors:default-struct-value-const, r=estebank

Make sure to use normalized ty for unevaluated const in default struct value

This cleans up the way that we construct the `mir::Const::Unevaluated` for default struct values. We were previously using `from_unevaluated`, which doesn't normalize the type, and is really only used for inline assembly. Other codepaths (such as `ExprKind::NamedConst`) use the type from the body.

Also, let's stop using `literal_operand`, which also is really not meant for calls other than for literal comparisons in pattern lowering.

Also move all of the tests to a separate subdirectory so they don't need to have the same prefix on all the test files.

Fixes #134298
r? estebank or reassign
This commit is contained in:
Matthias Krüger 2024-12-16 08:03:32 +01:00 committed by GitHub
commit 050e0cc6eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 46 additions and 23 deletions

View file

@ -367,14 +367,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
.collect() .collect()
} }
AdtExprBase::DefaultFields(field_types) => { AdtExprBase::DefaultFields(field_types) => {
itertools::zip_eq(field_names, &**field_types) itertools::zip_eq(field_names, field_types)
.map(|(n, ty)| match fields_map.get(&n) { .map(|(n, &ty)| match fields_map.get(&n) {
Some(v) => v.clone(), Some(v) => v.clone(),
None => match variant.fields[n].value { None => match variant.fields[n].value {
Some(def) => { Some(def) => {
let value = Const::from_unevaluated(this.tcx, def) let value = Const::Unevaluated(
.instantiate(this.tcx, args); UnevaluatedConst::new(def, args),
this.literal_operand(expr_span, value) ty,
);
Operand::Constant(Box::new(ConstOperand {
span: expr_span,
user_ty: None,
const_: value,
}))
} }
None => { None => {
let name = variant.fields[n].name; let name = variant.fields[n].name;

View file

@ -1,5 +1,5 @@
error: the `#[default]` attribute may only be used on unit enum variants or variants where every field has a default value error: the `#[default]` attribute may only be used on unit enum variants or variants where every field has a default value
--> $DIR/default-field-values-failures.rs:47:5 --> $DIR/failures.rs:47:5
| |
LL | Variant {} LL | Variant {}
| ^^^^^^^ | ^^^^^^^
@ -7,7 +7,7 @@ LL | Variant {}
= help: consider a manual implementation of `Default` = help: consider a manual implementation of `Default`
error: generic parameters may not be used in const operations error: generic parameters may not be used in const operations
--> $DIR/default-field-values-failures.rs:22:23 --> $DIR/failures.rs:22:23
| |
LL | bat: i32 = <Qux<{ C }> as T>::K, LL | bat: i32 = <Qux<{ C }> as T>::K,
| ^ cannot perform const operation using `C` | ^ cannot perform const operation using `C`
@ -16,19 +16,19 @@ LL | bat: i32 = <Qux<{ C }> as T>::K,
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
error: default fields are not supported in tuple structs error: default fields are not supported in tuple structs
--> $DIR/default-field-values-failures.rs:26:22 --> $DIR/failures.rs:26:22
| |
LL | pub struct Rak(i32 = 42); LL | pub struct Rak(i32 = 42);
| ^^ default fields are only supported on structs | ^^ default fields are only supported on structs
error: generic `Self` types are currently not permitted in anonymous constants error: generic `Self` types are currently not permitted in anonymous constants
--> $DIR/default-field-values-failures.rs:20:14 --> $DIR/failures.rs:20:14
| |
LL | bar: S = Self::S, LL | bar: S = Self::S,
| ^^^^ | ^^^^
error[E0277]: the trait bound `S: Default` is not satisfied error[E0277]: the trait bound `S: Default` is not satisfied
--> $DIR/default-field-values-failures.rs:14:5 --> $DIR/failures.rs:14:5
| |
LL | #[derive(Debug, Default)] LL | #[derive(Debug, Default)]
| ------- in this derive macro expansion | ------- in this derive macro expansion
@ -44,13 +44,13 @@ LL | pub struct S;
| |
error: missing mandatory field `bar` error: missing mandatory field `bar`
--> $DIR/default-field-values-failures.rs:53:21 --> $DIR/failures.rs:53:21
| |
LL | let _ = Bar { .. }; LL | let _ = Bar { .. };
| ^ | ^
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/default-field-values-failures.rs:57:17 --> $DIR/failures.rs:57:17
| |
LL | let _ = Rak(..); LL | let _ = Rak(..);
| --- ^^ expected `i32`, found `RangeFull` | --- ^^ expected `i32`, found `RangeFull`
@ -58,29 +58,29 @@ LL | let _ = Rak(..);
| arguments to this struct are incorrect | arguments to this struct are incorrect
| |
note: tuple struct defined here note: tuple struct defined here
--> $DIR/default-field-values-failures.rs:26:12 --> $DIR/failures.rs:26:12
| |
LL | pub struct Rak(i32 = 42); LL | pub struct Rak(i32 = 42);
| ^^^ | ^^^
help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal
--> $DIR/default-field-values-failures.rs:57:17 --> $DIR/failures.rs:57:17
| |
LL | let _ = Rak(..); LL | let _ = Rak(..);
| ^^ | ^^
error[E0061]: this struct takes 1 argument but 2 arguments were supplied error[E0061]: this struct takes 1 argument but 2 arguments were supplied
--> $DIR/default-field-values-failures.rs:59:13 --> $DIR/failures.rs:59:13
| |
LL | let _ = Rak(0, ..); LL | let _ = Rak(0, ..);
| ^^^ -- unexpected argument #2 of type `RangeFull` | ^^^ -- unexpected argument #2 of type `RangeFull`
| |
help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal
--> $DIR/default-field-values-failures.rs:59:20 --> $DIR/failures.rs:59:20
| |
LL | let _ = Rak(0, ..); LL | let _ = Rak(0, ..);
| ^^ | ^^
note: tuple struct defined here note: tuple struct defined here
--> $DIR/default-field-values-failures.rs:26:12 --> $DIR/failures.rs:26:12
| |
LL | pub struct Rak(i32 = 42); LL | pub struct Rak(i32 = 42);
| ^^^ | ^^^
@ -91,18 +91,18 @@ LL + let _ = Rak(0);
| |
error[E0061]: this struct takes 1 argument but 2 arguments were supplied error[E0061]: this struct takes 1 argument but 2 arguments were supplied
--> $DIR/default-field-values-failures.rs:61:13 --> $DIR/failures.rs:61:13
| |
LL | let _ = Rak(.., 0); LL | let _ = Rak(.., 0);
| ^^^ -- unexpected argument #1 of type `RangeFull` | ^^^ -- unexpected argument #1 of type `RangeFull`
| |
help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal
--> $DIR/default-field-values-failures.rs:61:17 --> $DIR/failures.rs:61:17
| |
LL | let _ = Rak(.., 0); LL | let _ = Rak(.., 0);
| ^^ | ^^
note: tuple struct defined here note: tuple struct defined here
--> $DIR/default-field-values-failures.rs:26:12 --> $DIR/failures.rs:26:12
| |
LL | pub struct Rak(i32 = 42); LL | pub struct Rak(i32 = 42);
| ^^^ | ^^^

View file

@ -1,13 +1,13 @@
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/default-field-values-invalid-const.rs:5:19 --> $DIR/invalid-const.rs:5:19
| |
LL | pub bax: u8 = panic!("asdf"), LL | pub bax: u8 = panic!("asdf"),
| ^^^^^^^^^^^^^^ the evaluated program panicked at 'asdf', $DIR/default-field-values-invalid-const.rs:5:19 | ^^^^^^^^^^^^^^ the evaluated program panicked at 'asdf', $DIR/invalid-const.rs:5:19
| |
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of `Baz::<C>::bat::{constant#0}` failed error[E0080]: evaluation of `Baz::<C>::bat::{constant#0}` failed
--> $DIR/default-field-values-invalid-const.rs:11:19 --> $DIR/invalid-const.rs:11:19
| |
LL | pub bat: u8 = 130 + 130, LL | pub bat: u8 = 130 + 130,
| ^^^^^^^^^ attempt to compute `130_u8 + 130_u8`, which would overflow | ^^^^^^^^^ attempt to compute `130_u8 + 130_u8`, which would overflow

View file

@ -0,0 +1,17 @@
//@ check-pass
#![feature(default_field_values)]
struct Value<const VALUE: u8>;
impl<const VALUE: u8> Value<VALUE> {
pub const VALUE: Self = Self;
}
pub struct WithUse {
_use: Value<{ 0 + 0 }> = Value::VALUE
}
const _: WithUse = WithUse { .. };
fn main() {}