Detect struct S(ty = val);
Emit a specific error for unsupported default field value syntax in tuple structs.
This commit is contained in:
parent
9ac95c10c0
commit
550bcae8aa
6 changed files with 63 additions and 11 deletions
|
@ -53,6 +53,9 @@ ast_lowering_closure_cannot_be_static = closures cannot be static
|
||||||
ast_lowering_coroutine_too_many_parameters =
|
ast_lowering_coroutine_too_many_parameters =
|
||||||
too many parameters for a coroutine (expected 0 or 1 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 =
|
ast_lowering_does_not_support_modifiers =
|
||||||
the `{$class_name}` register class does not support template modifiers
|
the `{$class_name}` register class does not support template modifiers
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,14 @@ pub(crate) struct InvalidAbi {
|
||||||
pub suggestion: Option<InvalidAbiSuggestion>,
|
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);
|
pub(crate) struct InvalidAbiReason(pub &'static str);
|
||||||
|
|
||||||
impl Subdiagnostic for InvalidAbiReason {
|
impl Subdiagnostic for InvalidAbiReason {
|
||||||
|
|
|
@ -17,7 +17,10 @@ use smallvec::{SmallVec, smallvec};
|
||||||
use thin_vec::ThinVec;
|
use thin_vec::ThinVec;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
use super::errors::{InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
|
use super::errors::{
|
||||||
|
InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound,
|
||||||
|
TupleStructWithDefault,
|
||||||
|
};
|
||||||
use super::{
|
use super::{
|
||||||
AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
|
AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
|
||||||
ResolverAstLoweringExt,
|
ResolverAstLoweringExt,
|
||||||
|
@ -690,13 +693,27 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
VariantData::Tuple(fields, id) => {
|
VariantData::Tuple(fields, id) => {
|
||||||
let ctor_id = self.lower_node_id(*id);
|
let ctor_id = self.lower_node_id(*id);
|
||||||
self.alias_attrs(ctor_id, parent_id);
|
self.alias_attrs(ctor_id, parent_id);
|
||||||
hir::VariantData::Tuple(
|
let fields = self
|
||||||
self.arena.alloc_from_iter(
|
.arena
|
||||||
fields.iter().enumerate().map(|f| self.lower_field_def(f)),
|
.alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f)));
|
||||||
),
|
for field in &fields[..] {
|
||||||
ctor_id,
|
if let Some(default) = field.default {
|
||||||
self.local_def_id(*id),
|
// 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) => {
|
VariantData::Unit(id) => {
|
||||||
let ctor_id = self.lower_node_id(*id);
|
let ctor_id = self.lower_node_id(*id);
|
||||||
|
|
|
@ -1836,6 +1836,22 @@ impl<'a> Parser<'a> {
|
||||||
return Err(err);
|
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((
|
Ok((
|
||||||
FieldDef {
|
FieldDef {
|
||||||
|
@ -1845,7 +1861,7 @@ impl<'a> Parser<'a> {
|
||||||
ident: None,
|
ident: None,
|
||||||
id: DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
ty,
|
ty,
|
||||||
default: None,
|
default,
|
||||||
attrs,
|
attrs,
|
||||||
is_placeholder: false,
|
is_placeholder: false,
|
||||||
},
|
},
|
||||||
|
|
|
@ -23,6 +23,8 @@ pub struct Qux<const C: i32> {
|
||||||
bay: i32 = C,
|
bay: i32 = C,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Rak(i32 = 42); //~ ERROR default field in tuple struct
|
||||||
|
|
||||||
impl<const C: i32> Qux<C> {
|
impl<const C: i32> Qux<C> {
|
||||||
const S: S = S;
|
const S: S = S;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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: const parameters may only be used as standalone arguments, i.e. `C`
|
||||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
= 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
|
error[E0277]: the trait bound `S: Default` is not satisfied
|
||||||
--> $DIR/default-field-values-failures.rs:14:5
|
--> $DIR/default-field-values-failures.rs:14:5
|
||||||
|
|
|
|
||||||
|
@ -24,7 +30,7 @@ LL | pub struct S;
|
||||||
|
|
|
|
||||||
|
|
||||||
error: missing mandatory field `bar`
|
error: missing mandatory field `bar`
|
||||||
--> $DIR/default-field-values-failures.rs:45:21
|
--> $DIR/default-field-values-failures.rs:47:21
|
||||||
|
|
|
|
||||||
LL | let _ = Bar { .. };
|
LL | let _ = Bar { .. };
|
||||||
| ^
|
| ^
|
||||||
|
@ -35,6 +41,6 @@ error: generic `Self` types are currently not permitted in anonymous constants
|
||||||
LL | bar: S = Self::S,
|
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`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue