Skip to content

Allow struct field default values to reference struct's generics #137913

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_hir_analysis/src/collect/generics_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ struct IsNeverPattern;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum AnonConstKind {
EnumDiscriminant,
FieldDefaultValue,
InlineConst,
ConstArg(IsRepeatExpr),
}
Expand Down Expand Up @@ -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);
}
}
}
Expand Down Expand Up @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/structs/default-field-values/failures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down
17 changes: 1 addition & 16 deletions tests/ui/structs/default-field-values/failures.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
|
Expand Down Expand Up @@ -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`.
29 changes: 29 additions & 0 deletions tests/ui/structs/default-field-values/field-references-param.rs
Original file line number Diff line number Diff line change
@@ -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>();
}
23 changes: 23 additions & 0 deletions tests/ui/structs/default-field-values/post-mono.direct.stderr
Original file line number Diff line number Diff line change
@@ -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`.
29 changes: 29 additions & 0 deletions tests/ui/structs/default-field-values/post-mono.indirect.stderr
Original file line number Diff line number Diff line change
@@ -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`.
23 changes: 23 additions & 0 deletions tests/ui/structs/default-field-values/post-mono.rs
Original file line number Diff line number Diff line change
@@ -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>();
}
Loading