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)
|
||||
}
|
||||
Node::TyPat(_) => Some(parent_did),
|
||||
// Field default values inherit the ADT's generics.
|
||||
Node::Field(_) => Some(parent_did),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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