Detect struct S(ty = val);

Emit a specific error for unsupported default field value syntax in tuple structs.
This commit is contained in:
Esteban Küber 2024-11-26 17:53:00 +00:00
parent 9ac95c10c0
commit 550bcae8aa
6 changed files with 63 additions and 11 deletions

View File

@ -53,6 +53,9 @@ ast_lowering_closure_cannot_be_static = closures cannot be static
ast_lowering_coroutine_too_many_parameters =
too many parameters for a coroutine (expected 0 or 1 parameters)
ast_lowering_default_field_in_tuple = default field in tuple struct
.label = default fields are only supported on structs
ast_lowering_does_not_support_modifiers =
the `{$class_name}` register class does not support template modifiers

View File

@ -38,6 +38,14 @@ pub(crate) struct InvalidAbi {
pub suggestion: Option<InvalidAbiSuggestion>,
}
#[derive(Diagnostic)]
#[diag(ast_lowering_default_field_in_tuple)]
pub(crate) struct TupleStructWithDefault {
#[primary_span]
#[label]
pub span: Span,
}
pub(crate) struct InvalidAbiReason(pub &'static str);
impl Subdiagnostic for InvalidAbiReason {

View File

@ -17,7 +17,10 @@ use smallvec::{SmallVec, smallvec};
use thin_vec::ThinVec;
use tracing::instrument;
use super::errors::{InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
use super::errors::{
InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound,
TupleStructWithDefault,
};
use super::{
AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
ResolverAstLoweringExt,
@ -690,13 +693,27 @@ impl<'hir> LoweringContext<'_, 'hir> {
VariantData::Tuple(fields, id) => {
let ctor_id = self.lower_node_id(*id);
self.alias_attrs(ctor_id, parent_id);
hir::VariantData::Tuple(
self.arena.alloc_from_iter(
fields.iter().enumerate().map(|f| self.lower_field_def(f)),
),
ctor_id,
self.local_def_id(*id),
)
let fields = self
.arena
.alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f)));
for field in &fields[..] {
if let Some(default) = field.default {
// Default values in tuple struct and tuple variants are not allowed by the
// RFC due to concerns about the syntax, both in the item definition and the
// expression. We could in the future allow `struct S(i32 = 0);` and force
// users to construct the value with `let _ = S { .. };`.
if self.tcx.features().default_field_values() {
self.dcx().emit_err(TupleStructWithDefault { span: default.span });
} else {
let _ = self.dcx().span_delayed_bug(
default.span,
"expected `default values on `struct` fields aren't supported` \
feature-gate error but none was produced",
);
}
}
}
hir::VariantData::Tuple(fields, ctor_id, self.local_def_id(*id))
}
VariantData::Unit(id) => {
let ctor_id = self.lower_node_id(*id);

View File

@ -1836,6 +1836,22 @@ impl<'a> Parser<'a> {
return Err(err);
}
};
let mut default = None;
if p.token == token::Eq {
let mut snapshot = p.create_snapshot_for_diagnostic();
snapshot.bump();
match snapshot.parse_expr_anon_const() {
Ok(const_expr) => {
let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
p.psess.gated_spans.gate(sym::default_field_values, sp);
p.restore_snapshot(snapshot);
default = Some(const_expr);
}
Err(err) => {
err.cancel();
}
}
}
Ok((
FieldDef {
@ -1845,7 +1861,7 @@ impl<'a> Parser<'a> {
ident: None,
id: DUMMY_NODE_ID,
ty,
default: None,
default,
attrs,
is_placeholder: false,
},

View File

@ -23,6 +23,8 @@ pub struct Qux<const C: i32> {
bay: i32 = C,
}
pub struct Rak(i32 = 42); //~ ERROR default field in tuple struct
impl<const C: i32> Qux<C> {
const S: S = S;
}

View File

@ -7,6 +7,12 @@ LL | bat: i32 = <Qux<{ C }> as T>::K,
= 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 field in tuple struct
--> $DIR/default-field-values-failures.rs:26:22
|
LL | pub struct Rak(i32 = 42);
| ^^ default fields are only supported on structs
error[E0277]: the trait bound `S: Default` is not satisfied
--> $DIR/default-field-values-failures.rs:14:5
|
@ -24,7 +30,7 @@ LL | pub struct S;
|
error: missing mandatory field `bar`
--> $DIR/default-field-values-failures.rs:45:21
--> $DIR/default-field-values-failures.rs:47:21
|
LL | let _ = Bar { .. };
| ^
@ -35,6 +41,6 @@ error: generic `Self` types are currently not permitted in anonymous constants
LL | bar: S = Self::S,
| ^^^^
error: aborting due to 4 previous errors
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0277`.