Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b3d7c14

Browse files
authoredMar 5, 2025
Rollup merge of #137913 - compiler-errors:struct-field-default-generic, r=BoxyUwU
Allow struct field default values to reference struct's generics Right now, the default field value feature (#132162) lowers anon consts whose types may reference ADT params that the const doesn't inherit. This PR fixes this, so that these defaults can reference ADTs' generics, and sets the `generics_of` parenting up correctly. There doesn't seem to be a good reason not to support this, since the anon const has a well-defined type from the field, and the anon const doesn't interact with the type system like generic parameter defaults do. r? `````@boxyuwu````` or reassign I could also make this into an error if this seems problematic (https://github.com/rust-lang/rust/compare/master...compiler-errors:rust:default-field-value-implicit-param?expand=1)...... but I'd rather make this work and register an open question on the tracking issue about validating that this is well-vetted. Fixes #137896
2 parents 99efb42 + 3e5fddc commit b3d7c14

File tree

8 files changed

+112
-19
lines changed

8 files changed

+112
-19
lines changed
 

‎compiler/rustc_hir_analysis/src/collect/generics_of.rs

+2
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
187187
Some(parent_did)
188188
}
189189
Node::TyPat(_) => Some(parent_did),
190+
// Field default values inherit the ADT's generics.
191+
Node::Field(_) => Some(parent_did),
190192
_ => None,
191193
}
192194
}

‎compiler/rustc_resolve/src/late.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ struct IsNeverPattern;
7878
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
7979
enum AnonConstKind {
8080
EnumDiscriminant,
81+
FieldDefaultValue,
8182
InlineConst,
8283
ConstArg(IsRepeatExpr),
8384
}
@@ -1406,7 +1407,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
14061407
visit_opt!(self, visit_ident, ident);
14071408
try_visit!(self.visit_ty(ty));
14081409
if let Some(v) = &default {
1409-
self.resolve_anon_const(v, AnonConstKind::ConstArg(IsRepeatExpr::No));
1410+
self.resolve_anon_const(v, AnonConstKind::FieldDefaultValue);
14101411
}
14111412
}
14121413
}
@@ -4659,6 +4660,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46594660
AnonConstKind::EnumDiscriminant => {
46604661
ConstantHasGenerics::No(NoConstantGenericsReason::IsEnumDiscriminant)
46614662
}
4663+
AnonConstKind::FieldDefaultValue => ConstantHasGenerics::Yes,
46624664
AnonConstKind::InlineConst => ConstantHasGenerics::Yes,
46634665
AnonConstKind::ConstArg(_) => {
46644666
if self.r.tcx.features().generic_const_exprs() || is_trivial_const_arg {

‎tests/ui/structs/default-field-values/failures.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ pub struct Bar {
1717

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

‎tests/ui/structs/default-field-values/failures.stderr

+1-16
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,12 @@ LL | Variant {}
66
|
77
= help: consider a manual implementation of `Default`
88

9-
error: generic parameters may not be used in const operations
10-
--> $DIR/failures.rs:22:23
11-
|
12-
LL | bat: i32 = <Qux<{ C }> as T>::K,
13-
| ^ cannot perform const operation using `C`
14-
|
15-
= help: const parameters may only be used as standalone arguments, i.e. `C`
16-
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
17-
189
error: default fields are not supported in tuple structs
1910
--> $DIR/failures.rs:26:22
2011
|
2112
LL | pub struct Rak(i32 = 42);
2213
| ^^ default fields are only supported on structs
2314

24-
error: generic `Self` types are currently not permitted in anonymous constants
25-
--> $DIR/failures.rs:20:14
26-
|
27-
LL | bar: S = Self::S,
28-
| ^^^^
29-
3015
error[E0277]: the trait bound `S: Default` is not satisfied
3116
--> $DIR/failures.rs:14:5
3217
|
@@ -112,7 +97,7 @@ LL - let _ = Rak(.., 0);
11297
LL + let _ = Rak(0);
11398
|
11499

115-
error: aborting due to 9 previous errors
100+
error: aborting due to 7 previous errors
116101

117102
Some errors have detailed explanations: E0061, E0277, E0308.
118103
For more information about an error, try `rustc --explain E0061`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//@ build-pass
2+
3+
#![feature(default_field_values)]
4+
5+
struct W<const X: usize>;
6+
7+
impl<const X: usize> W<X> {
8+
const fn new() -> Self { W }
9+
}
10+
11+
struct Z<const X: usize> {
12+
// No inference.
13+
one: W<X> = W::<X>::new(),
14+
15+
// Inference works too.
16+
two: W<X> = W::new(),
17+
18+
// An anon const that is too generic before substitution.
19+
too_generic: usize = X + 1,
20+
}
21+
22+
fn use_generically<const X: usize>() {
23+
let x: Z<X> = Z { .. };
24+
}
25+
26+
fn main() {
27+
let x: Z<0> = Z { .. };
28+
use_generically::<0>();
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0080]: evaluation of `Z::<1>::post_mono::{constant#0}` failed
2+
--> $DIR/post-mono.rs:7:24
3+
|
4+
LL | post_mono: usize = X / 0,
5+
| ^^^^^ attempt to divide `1_usize` by zero
6+
7+
note: erroneous constant encountered
8+
--> $DIR/post-mono.rs:17:19
9+
|
10+
LL | let x: Z<1> = Z { .. };
11+
| ^^^^^^^^
12+
13+
note: erroneous constant encountered
14+
--> $DIR/post-mono.rs:17:19
15+
|
16+
LL | let x: Z<1> = Z { .. };
17+
| ^^^^^^^^
18+
|
19+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
20+
21+
error: aborting due to 1 previous error
22+
23+
For more information about this error, try `rustc --explain E0080`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error[E0080]: evaluation of `Z::<1>::post_mono::{constant#0}` failed
2+
--> $DIR/post-mono.rs:7:24
3+
|
4+
LL | post_mono: usize = X / 0,
5+
| ^^^^^ attempt to divide `1_usize` by zero
6+
7+
note: erroneous constant encountered
8+
--> $DIR/post-mono.rs:12:19
9+
|
10+
LL | let x: Z<X> = Z { .. };
11+
| ^^^^^^^^
12+
13+
note: erroneous constant encountered
14+
--> $DIR/post-mono.rs:12:19
15+
|
16+
LL | let x: Z<X> = Z { .. };
17+
| ^^^^^^^^
18+
|
19+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
20+
21+
note: the above error was encountered while instantiating `fn indirect::<1>`
22+
--> $DIR/post-mono.rs:22:5
23+
|
24+
LL | indirect::<1>();
25+
| ^^^^^^^^^^^^^^^
26+
27+
error: aborting due to 1 previous error
28+
29+
For more information about this error, try `rustc --explain E0080`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@ build-fail
2+
//@ revisions: direct indirect
3+
4+
#![feature(default_field_values)]
5+
6+
struct Z<const X: usize> {
7+
post_mono: usize = X / 0,
8+
//~^ ERROR evaluation of `Z::<1>::post_mono::{constant#0}` failed
9+
}
10+
11+
fn indirect<const X: usize>() {
12+
let x: Z<X> = Z { .. };
13+
}
14+
15+
#[cfg(direct)]
16+
fn main() {
17+
let x: Z<1> = Z { .. };
18+
}
19+
20+
#[cfg(indirect)]
21+
fn main() {
22+
indirect::<1>();
23+
}

0 commit comments

Comments
 (0)
Failed to load comments.