1
Fork 0

Allow struct field default values to reference struct's generics

This commit is contained in:
Michael Goulet 2025-03-03 05:25:46 +00:00
parent e16a049adb
commit 3e5fddc95e
8 changed files with 112 additions and 19 deletions

View file

@ -187,6 +187,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
Some(parent_did) Some(parent_did)
} }
Node::TyPat(_) => Some(parent_did), Node::TyPat(_) => Some(parent_did),
// Field default values inherit the ADT's generics.
Node::Field(_) => Some(parent_did),
_ => None, _ => None,
} }
} }

View file

@ -78,6 +78,7 @@ struct IsNeverPattern;
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum AnonConstKind { enum AnonConstKind {
EnumDiscriminant, EnumDiscriminant,
FieldDefaultValue,
InlineConst, InlineConst,
ConstArg(IsRepeatExpr), ConstArg(IsRepeatExpr),
} }
@ -1406,7 +1407,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
visit_opt!(self, visit_ident, ident); visit_opt!(self, visit_ident, ident);
try_visit!(self.visit_ty(ty)); try_visit!(self.visit_ty(ty));
if let Some(v) = &default { if let Some(v) = &default {
self.resolve_anon_const(v, AnonConstKind::ConstArg(IsRepeatExpr::No)); self.resolve_anon_const(v, AnonConstKind::FieldDefaultValue);
} }
} }
} }
@ -4658,6 +4659,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
AnonConstKind::EnumDiscriminant => { AnonConstKind::EnumDiscriminant => {
ConstantHasGenerics::No(NoConstantGenericsReason::IsEnumDiscriminant) ConstantHasGenerics::No(NoConstantGenericsReason::IsEnumDiscriminant)
} }
AnonConstKind::FieldDefaultValue => ConstantHasGenerics::Yes,
AnonConstKind::InlineConst => ConstantHasGenerics::Yes, AnonConstKind::InlineConst => ConstantHasGenerics::Yes,
AnonConstKind::ConstArg(_) => { AnonConstKind::ConstArg(_) => {
if self.r.tcx.features().generic_const_exprs() || is_trivial_const_arg { if self.r.tcx.features().generic_const_exprs() || is_trivial_const_arg {

View file

@ -17,9 +17,9 @@ pub struct Bar {
#[derive(Default)] #[derive(Default)]
pub struct Qux<const C: i32> { pub struct Qux<const C: i32> {
bar: S = Self::S, //~ ERROR generic `Self` types are currently not permitted in anonymous constants bar: S = Self::S,
baz: i32 = foo(), baz: i32 = foo(),
bat: i32 = <Qux<{ C }> as T>::K, //~ ERROR generic parameters may not be used in const operations bat: i32 = <Qux<{ C }> as T>::K,
bay: i32 = C, bay: i32 = C,
} }

View file

@ -6,27 +6,12 @@ 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
--> $DIR/failures.rs:22:23
|
LL | bat: i32 = <Qux<{ C }> as T>::K,
| ^ cannot perform const operation using `C`
|
= help: const parameters may only be used as standalone arguments, i.e. `C`
= 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/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
--> $DIR/failures.rs:20:14
|
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/failures.rs:14:5 --> $DIR/failures.rs:14:5
| |
@ -112,7 +97,7 @@ LL - let _ = Rak(.., 0);
LL + let _ = Rak(0); LL + let _ = Rak(0);
| |
error: aborting due to 9 previous errors error: aborting due to 7 previous errors
Some errors have detailed explanations: E0061, E0277, E0308. Some errors have detailed explanations: E0061, E0277, E0308.
For more information about an error, try `rustc --explain E0061`. For more information about an error, try `rustc --explain E0061`.

View file

@ -0,0 +1,29 @@
//@ build-pass
#![feature(default_field_values)]
struct W<const X: usize>;
impl<const X: usize> W<X> {
const fn new() -> Self { W }
}
struct Z<const X: usize> {
// No inference.
one: W<X> = W::<X>::new(),
// Inference works too.
two: W<X> = W::new(),
// An anon const that is too generic before substitution.
too_generic: usize = X + 1,
}
fn use_generically<const X: usize>() {
let x: Z<X> = Z { .. };
}
fn main() {
let x: Z<0> = Z { .. };
use_generically::<0>();
}

View file

@ -0,0 +1,23 @@
error[E0080]: evaluation of `Z::<1>::post_mono::{constant#0}` failed
--> $DIR/post-mono.rs:7:24
|
LL | post_mono: usize = X / 0,
| ^^^^^ attempt to divide `1_usize` by zero
note: erroneous constant encountered
--> $DIR/post-mono.rs:17:19
|
LL | let x: Z<1> = Z { .. };
| ^^^^^^^^
note: erroneous constant encountered
--> $DIR/post-mono.rs:17:19
|
LL | let x: Z<1> = Z { .. };
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0080`.

View file

@ -0,0 +1,29 @@
error[E0080]: evaluation of `Z::<1>::post_mono::{constant#0}` failed
--> $DIR/post-mono.rs:7:24
|
LL | post_mono: usize = X / 0,
| ^^^^^ attempt to divide `1_usize` by zero
note: erroneous constant encountered
--> $DIR/post-mono.rs:12:19
|
LL | let x: Z<X> = Z { .. };
| ^^^^^^^^
note: erroneous constant encountered
--> $DIR/post-mono.rs:12:19
|
LL | let x: Z<X> = Z { .. };
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
note: the above error was encountered while instantiating `fn indirect::<1>`
--> $DIR/post-mono.rs:22:5
|
LL | indirect::<1>();
| ^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0080`.

View file

@ -0,0 +1,23 @@
//@ build-fail
//@ revisions: direct indirect
#![feature(default_field_values)]
struct Z<const X: usize> {
post_mono: usize = X / 0,
//~^ ERROR evaluation of `Z::<1>::post_mono::{constant#0}` failed
}
fn indirect<const X: usize>() {
let x: Z<X> = Z { .. };
}
#[cfg(direct)]
fn main() {
let x: Z<1> = Z { .. };
}
#[cfg(indirect)]
fn main() {
indirect::<1>();
}