Skip to content
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

Add UnnamedField type and refactor FieldDef to allow unnamed fields #84415

Closed
wants to merge 5 commits into from
Closed
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
28 changes: 24 additions & 4 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2471,19 +2471,39 @@ impl VisibilityKind {
}
}

/// Named field type
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct NamedField {
// FIXME: Maybe remove option and use UnnamedField::Type instead of NamedField?
pub ident: Option<Ident>,
pub ty: P<Ty>,
}

/// Unnamed field type
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum UnnamedField {
Struct(Vec<FieldDef>),
Union(Vec<FieldDef>),
Type(P<Ty>),
}

#[derive(Clone, Encodable, Decodable, Debug)]
pub enum FieldVariant {
Named(NamedField),
Unnamed(UnnamedField),
}

/// Field definition in a struct, variant or union.
///
/// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FieldDef {
pub attrs: Vec<Attribute>,
pub id: NodeId,
pub span: Span,
pub vis: Visibility,
pub ident: Option<Ident>,

pub ty: P<Ty>,
pub id: NodeId,
pub is_placeholder: bool,
pub variant: FieldVariant,
}

/// Fields and constructor ids of enum variants and structs.
Expand Down
12 changes: 9 additions & 3 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -909,13 +909,19 @@ pub fn noop_flat_map_field_def<T: MutVisitor>(
mut fd: FieldDef,
visitor: &mut T,
) -> SmallVec<[FieldDef; 1]> {
let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut fd;
let FieldDef { span, vis, id, attrs, is_placeholder: _, variant } = &mut fd;
visitor.visit_span(span);
visit_opt(ident, |ident| visitor.visit_ident(ident));
visitor.visit_vis(vis);
visitor.visit_id(id);
visitor.visit_ty(ty);
visit_attrs(attrs, visitor);
match variant {
FieldVariant::Named(NamedField { ident, ty }) => {
visit_opt(ident, |ident| visitor.visit_ident(ident));
visitor.visit_ty(ty);
}
// FIXME: Handle Unnamed variant
_ => {}
}
smallvec![fd]
}

Expand Down
12 changes: 9 additions & 3 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -673,10 +673,16 @@ pub fn walk_struct_def<'a, V: Visitor<'a>>(visitor: &mut V, struct_definition: &

pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) {
visitor.visit_vis(&field.vis);
if let Some(ident) = field.ident {
visitor.visit_ident(ident);
match &field.variant {
FieldVariant::Named(NamedField { ident, ty }) => {
if let Some(ident) = ident {
visitor.visit_ident(*ident);
}
visitor.visit_ty(&ty);
}
// FIXME: Handle Unnamed variant
_ => {}
}
visitor.visit_ty(&field.ty);
walk_list!(visitor, visit_attribute, &field.attrs);
}

Expand Down
57 changes: 34 additions & 23 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -792,31 +792,42 @@ impl<'hir> LoweringContext<'_, 'hir> {
}

fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'hir> {
let ty = if let TyKind::Path(ref qself, ref path) = f.ty.kind {
let t = self.lower_path_ty(
&f.ty,
qself,
path,
ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124)
ImplTraitContext::disallowed(),
);
self.arena.alloc(t)
} else {
self.lower_ty(&f.ty, ImplTraitContext::disallowed())
};
let hir_id = self.lower_node_id(f.id);

let (ident, ty) = match &f.variant {
FieldVariant::Named(NamedField { ident, ty }) => {
let ident = match ident {
Some(ident) => *ident,
// FIXME(jseyfried): positional field hygiene.
None => Ident::new(sym::integer(index), f.span),
};

let ty = if let TyKind::Path(ref qself, ref path) = ty.kind {
let t = self.lower_path_ty(
ty,
qself,
path,
ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124)
ImplTraitContext::disallowed(),
);
self.arena.alloc(t)
} else {
self.lower_ty(&ty, ImplTraitContext::disallowed())
};

(ident, ty)
}
// FIXME: Handle Unnamed variant. Currently creates useless data to pass the typecheck
_ => {
let ident = Ident::from_str_and_span("", f.span);
let ty = self.arena.alloc(hir::Ty { hir_id, kind: hir::TyKind::Err, span: f.span });
(ident, &*ty)
}
};

self.lower_attrs(hir_id, &f.attrs);
hir::FieldDef {
span: f.span,
hir_id,
ident: match f.ident {
Some(ident) => ident,
// FIXME(jseyfried): positional field hygiene.
None => Ident::new(sym::integer(index), f.span),
},
vis: self.lower_visibility(&f.vis, None),
ty,
}

hir::FieldDef { span: f.span, hir_id, ident, vis: self.lower_visibility(&f.vis, None), ty }
}

fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
Expand Down
16 changes: 16 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,21 @@ impl<'a> PostExpansionVisitor<'a> {
}

impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
fn visit_field_def(&mut self, s: &'a ast::FieldDef) {
match s.variant {
ast::FieldVariant::Unnamed(_) => {
gate_feature_post!(
&self,
unnamed_fields,
s.span,
"unnamed fields are not yet fully implemented"
)
}
_ => {}
}
visit::walk_field_def(self, s);
}

fn visit_attribute(&mut self, attr: &ast::Attribute) {
let attr_info =
attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a);
Expand Down Expand Up @@ -692,6 +707,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(destructuring_assignment, "destructuring assignments are unstable");
}
gate_all!(pub_macro_rules, "`pub` on `macro_rules` items is unstable");
gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");

// All uses of `gate_all!` below this point were added in #65742,
// and subsequently disabled (with the non-early gating readded).
Expand Down
21 changes: 16 additions & 5 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1408,7 +1408,13 @@ impl<'a> State<'a> {
s.maybe_print_comment(field.span.lo());
s.print_outer_attributes(&field.attrs);
s.print_visibility(&field.vis);
s.print_type(&field.ty)
match &field.variant {
ast::FieldVariant::Named(ast::NamedField { ident: _, ty }) => {
s.print_type(ty)
}
// FIXME: Handle Unnamed variant
_ => {}
}
});
self.pclose();
}
Expand All @@ -1430,10 +1436,15 @@ impl<'a> State<'a> {
self.maybe_print_comment(field.span.lo());
self.print_outer_attributes(&field.attrs);
self.print_visibility(&field.vis);
self.print_ident(field.ident.unwrap());
self.word_nbsp(":");
self.print_type(&field.ty);
self.s.word(",");
match &field.variant {
ast::FieldVariant::Named(ast::NamedField { ident, ty }) => {
self.print_ident(ident.unwrap());
self.word_nbsp(":");
self.print_type(ty);
self.s.word(",");
}
_ => {}
}
}

self.bclose(span)
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_builtin_macros/src/deriving/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,13 @@ fn cs_clone_shallow(
fn process_variant(cx: &mut ExtCtxt<'_>, stmts: &mut Vec<ast::Stmt>, variant: &VariantData) {
for field in variant.fields() {
// let _: AssertParamIsClone<FieldTy>;
assert_ty_bounds(cx, stmts, field.ty.clone(), field.span, "AssertParamIsClone");
match &field.variant {
ast::FieldVariant::Named(ast::NamedField { ident: _, ty }) => {
assert_ty_bounds(cx, stmts, ty.clone(), field.span, "AssertParamIsClone")
}
// FIXME: Handle Unnamed variant
_ => {}
}
}
}

Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,13 @@ fn cs_total_eq_assert(
) {
for field in variant.fields() {
// let _: AssertParamIsEq<FieldTy>;
assert_ty_bounds(cx, stmts, field.ty.clone(), field.span, "AssertParamIsEq");
match &field.variant {
ast::FieldVariant::Named(ast::NamedField { ident: _, ty }) => {
assert_ty_bounds(cx, stmts, ty.clone(), field.span, "AssertParamIsEq")
}
// FIXME: Handle Unnamed variant
_ => {}
}
}
}

Expand Down
34 changes: 28 additions & 6 deletions compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -720,8 +720,15 @@ impl<'a> TraitDef<'a> {
from_scratch: bool,
use_temporaries: bool,
) -> P<ast::Item> {
let field_tys: Vec<P<ast::Ty>> =
struct_def.fields().iter().map(|field| field.ty.clone()).collect();
let field_tys: Vec<P<ast::Ty>> = struct_def
.fields()
.iter()
.filter_map(|field| match &field.variant {
ast::FieldVariant::Named(ast::NamedField { ident: _, ty }) => Some(ty.clone()),
// FIXME: Handle Unnamed variant
_ => None,
})
.collect();

let methods = self
.methods
Expand Down Expand Up @@ -769,7 +776,13 @@ impl<'a> TraitDef<'a> {
let mut field_tys = Vec::new();

for variant in &enum_def.variants {
field_tys.extend(variant.data.fields().iter().map(|field| field.ty.clone()));
field_tys.extend(variant.data.fields().iter().filter_map(
|field| match &field.variant {
ast::FieldVariant::Named(ast::NamedField { ident: _, ty }) => Some(ty.clone()),
// FIXME: Handle Unnamed variant
_ => None,
},
))
}

let methods = self
Expand Down Expand Up @@ -1515,8 +1528,11 @@ impl<'a> TraitDef<'a> {
let mut just_spans = Vec::new();
for field in struct_def.fields() {
let sp = field.span.with_ctxt(self.span.ctxt());
match field.ident {
Some(ident) => named_idents.push((ident, sp)),
match field.variant {
ast::FieldVariant::Named(ast::NamedField { ident: Some(ident), ty: _ }) => {
named_idents.push((ident, sp))
}
// FIXME: Handle Unnamed variant
_ => just_spans.push(sp),
}
}
Expand Down Expand Up @@ -1576,7 +1592,13 @@ impl<'a> TraitDef<'a> {
let val = if use_temporaries { val } else { cx.expr_deref(sp, val) };
let val = cx.expr(sp, ast::ExprKind::Paren(val));

ident_exprs.push((sp, struct_field.ident, val, &struct_field.attrs[..]));
match struct_field.variant {
ast::FieldVariant::Named(ast::NamedField { ident, ty: _ }) => {
ident_exprs.push((sp, ident, val, &struct_field.attrs[..]))
}
// FIXME: Handle Unnamed variant
_ => {}
}
}

let subpats = self.create_subpatterns(cx, paths, mutbl, use_temporaries);
Expand Down
12 changes: 8 additions & 4 deletions compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,11 +328,15 @@ impl InvocationKind {
// and it holds because only inert attributes are supported in this position.
match self {
InvocationKind::Attr { item: Annotatable::FieldDef(field), .. }
| InvocationKind::Derive { item: Annotatable::FieldDef(field), .. }
if field.ident.is_none() =>
| InvocationKind::Derive { item: Annotatable::FieldDef(field), .. } => match field
.variant
{
Some(field.vis.clone())
}
ast::FieldVariant::Named(ast::NamedField { ident, ty: _ }) if ident.is_none() => {
Some(field.vis.clone())
}
// FIXME: Handle Unnamed variant
_ => None,
},
_ => None,
}
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_expand/src/placeholders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,12 @@ pub fn placeholder(
}]),
AstFragmentKind::StructFields => AstFragment::StructFields(smallvec![ast::FieldDef {
attrs: Default::default(),
id,
ident: None,
span,
ty: ty(),
vis,
id,
is_placeholder: true,
// FIXME: Maybe change to UnnamedField?
variant: ast::FieldVariant::Named(ast::NamedField { ident: None, ty: ty() })
}]),
AstFragmentKind::Variants => AstFragment::Variants(smallvec![ast::Variant {
attrs: Default::default(),
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,9 @@ declare_features! (
/// Allows `extern "wasm" fn`
(active, wasm_abi, "1.53.0", Some(83788), None),

/// Allows unnamed fields of struct and union type
(active, unnamed_fields, "1.53.0", Some(49804), None),

// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
Expand Down Expand Up @@ -669,6 +672,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
sym::const_generics_defaults,
sym::inherent_associated_types,
sym::type_alias_impl_trait,
sym::unnamed_fields,
];

/// Some features are not allowed to be used together at the same time, if
Expand Down
Loading