about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-03-03 05:25:46 +0000
committerMichael Goulet <michael@errs.io>2025-03-04 01:00:55 +0000
commit3e5fddc95ea2d8851def90b940030d1c97bd5b00 (patch)
treed8b30553c2a6a4f93627374ad8b9e22d5436d08b
parente16a049adbf94d610787430b6efdf31d896dc5b6 (diff)
downloadrust-3e5fddc95ea2d8851def90b940030d1c97bd5b00.tar.gz
rust-3e5fddc95ea2d8851def90b940030d1c97bd5b00.zip
Allow struct field default values to reference struct's generics
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs4
-rw-r--r--tests/ui/structs/default-field-values/failures.rs4
-rw-r--r--tests/ui/structs/default-field-values/failures.stderr17
-rw-r--r--tests/ui/structs/default-field-values/field-references-param.rs29
-rw-r--r--tests/ui/structs/default-field-values/post-mono.direct.stderr23
-rw-r--r--tests/ui/structs/default-field-values/post-mono.indirect.stderr29
-rw-r--r--tests/ui/structs/default-field-values/post-mono.rs23
8 files changed, 112 insertions, 19 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index af1338e50d0..a153ce8ea90 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 f119ed55e7d..3e8946d9291 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 0ac071d91d6..1e94eecb4f8 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<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(),
-    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,
 }
 
diff --git a/tests/ui/structs/default-field-values/failures.stderr b/tests/ui/structs/default-field-values/failures.stderr
index 65ec100fe2e..50553816462 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 = <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
   --> $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 00000000000..ecee37edd42
--- /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<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>();
+}
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 00000000000..cdd80620c48
--- /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 00000000000..56c27a6e5dc
--- /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<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`.
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 00000000000..4de31f6e2fb
--- /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<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>();
+}