Allow struct field default values to reference struct's generics
This commit is contained in:
parent
e16a049adb
commit
3e5fddc95e
8 changed files with 112 additions and 19 deletions
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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>();
|
||||||
|
}
|
|
@ -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`.
|
|
@ -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
tests/ui/structs/default-field-values/post-mono.rs
Normal file
23
tests/ui/structs/default-field-values/post-mono.rs
Normal 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>();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue