From 3e5fddc95ea2d8851def90b940030d1c97bd5b00 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 3 Mar 2025 05:25:46 +0000 Subject: [PATCH] Allow struct field default values to reference struct's generics --- .../src/collect/generics_of.rs | 2 ++ compiler/rustc_resolve/src/late.rs | 4 ++- .../structs/default-field-values/failures.rs | 4 +-- .../default-field-values/failures.stderr | 17 +---------- .../field-references-param.rs | 29 +++++++++++++++++++ .../post-mono.direct.stderr | 23 +++++++++++++++ .../post-mono.indirect.stderr | 29 +++++++++++++++++++ .../structs/default-field-values/post-mono.rs | 23 +++++++++++++++ 8 files changed, 112 insertions(+), 19 deletions(-) create mode 100644 tests/ui/structs/default-field-values/field-references-param.rs create mode 100644 tests/ui/structs/default-field-values/post-mono.direct.stderr create mode 100644 tests/ui/structs/default-field-values/post-mono.indirect.stderr create mode 100644 tests/ui/structs/default-field-values/post-mono.rs diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index af1338e50d007..a153ce8ea902d 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -187,6 +187,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { Some(parent_did) } Node::TyPat(_) => Some(parent_did), + // Field default values inherit the ADT's generics. + Node::Field(_) => Some(parent_did), _ => None, } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index f119ed55e7d1b..3e8946d9291c6 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -78,6 +78,7 @@ struct IsNeverPattern; #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum AnonConstKind { EnumDiscriminant, + FieldDefaultValue, InlineConst, ConstArg(IsRepeatExpr), } @@ -1406,7 +1407,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r visit_opt!(self, visit_ident, ident); try_visit!(self.visit_ty(ty)); 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 => { ConstantHasGenerics::No(NoConstantGenericsReason::IsEnumDiscriminant) } + AnonConstKind::FieldDefaultValue => ConstantHasGenerics::Yes, AnonConstKind::InlineConst => ConstantHasGenerics::Yes, AnonConstKind::ConstArg(_) => { if self.r.tcx.features().generic_const_exprs() || is_trivial_const_arg { diff --git a/tests/ui/structs/default-field-values/failures.rs b/tests/ui/structs/default-field-values/failures.rs index 0ac071d91d65e..1e94eecb4f870 100644 --- a/tests/ui/structs/default-field-values/failures.rs +++ b/tests/ui/structs/default-field-values/failures.rs @@ -17,9 +17,9 @@ pub struct Bar { #[derive(Default)] pub struct Qux { - bar: S = Self::S, //~ ERROR generic `Self` types are currently not permitted in anonymous constants + bar: S = Self::S, baz: i32 = foo(), - bat: i32 = as T>::K, //~ ERROR generic parameters may not be used in const operations + bat: i32 = as T>::K, bay: i32 = C, } diff --git a/tests/ui/structs/default-field-values/failures.stderr b/tests/ui/structs/default-field-values/failures.stderr index 65ec100fe2ea3..50553816462d1 100644 --- a/tests/ui/structs/default-field-values/failures.stderr +++ b/tests/ui/structs/default-field-values/failures.stderr @@ -6,27 +6,12 @@ LL | Variant {} | = 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 = 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 --> $DIR/failures.rs:26:22 | LL | pub struct Rak(i32 = 42); | ^^ 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 --> $DIR/failures.rs:14:5 | @@ -112,7 +97,7 @@ 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. For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/structs/default-field-values/field-references-param.rs b/tests/ui/structs/default-field-values/field-references-param.rs new file mode 100644 index 0000000000000..ecee37edd42c0 --- /dev/null +++ b/tests/ui/structs/default-field-values/field-references-param.rs @@ -0,0 +1,29 @@ +//@ build-pass + +#![feature(default_field_values)] + +struct W; + +impl W { + const fn new() -> Self { W } +} + +struct Z { + // No inference. + one: W = W::::new(), + + // Inference works too. + two: W = W::new(), + + // An anon const that is too generic before substitution. + too_generic: usize = X + 1, +} + +fn use_generically() { + let x: Z = Z { .. }; +} + +fn main() { + let x: Z<0> = Z { .. }; + use_generically::<0>(); +} diff --git a/tests/ui/structs/default-field-values/post-mono.direct.stderr b/tests/ui/structs/default-field-values/post-mono.direct.stderr new file mode 100644 index 0000000000000..cdd80620c48a9 --- /dev/null +++ b/tests/ui/structs/default-field-values/post-mono.direct.stderr @@ -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`. diff --git a/tests/ui/structs/default-field-values/post-mono.indirect.stderr b/tests/ui/structs/default-field-values/post-mono.indirect.stderr new file mode 100644 index 0000000000000..56c27a6e5dc81 --- /dev/null +++ b/tests/ui/structs/default-field-values/post-mono.indirect.stderr @@ -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 = Z { .. }; + | ^^^^^^^^ + +note: erroneous constant encountered + --> $DIR/post-mono.rs:12:19 + | +LL | let x: Z = 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`. diff --git a/tests/ui/structs/default-field-values/post-mono.rs b/tests/ui/structs/default-field-values/post-mono.rs new file mode 100644 index 0000000000000..4de31f6e2fbac --- /dev/null +++ b/tests/ui/structs/default-field-values/post-mono.rs @@ -0,0 +1,23 @@ +//@ build-fail +//@ revisions: direct indirect + +#![feature(default_field_values)] + +struct Z { + post_mono: usize = X / 0, + //~^ ERROR evaluation of `Z::<1>::post_mono::{constant#0}` failed +} + +fn indirect() { + let x: Z = Z { .. }; +} + +#[cfg(direct)] +fn main() { + let x: Z<1> = Z { .. }; +} + +#[cfg(indirect)] +fn main() { + indirect::<1>(); +}