From 5c3d1e5d76fdc6d9f40ab13a6a342e1f7ceb4f17 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 21 Mar 2019 23:38:50 +0100 Subject: Separate variant id and variant constructor id. This commit makes two changes - separating the `NodeId` that identifies an enum variant from the `NodeId` that identifies the variant's constructor; and no longer creating a `NodeId` for `Struct`-style enum variants and structs. Separation of the variant id and variant constructor id will allow the rest of RFC 2008 to be implemented by lowering the visibility of the variant's constructor without lowering the visbility of the variant itself. No longer creating a `NodeId` for `Struct`-style enum variants and structs mostly simplifies logic as previously this `NodeId` wasn't used. There were various cases where the `NodeId` wouldn't be used unless there was an unit or tuple struct or enum variant but not all uses of this `NodeId` had that condition, by removing this `NodeId`, this must be explicitly dealt with. This change mostly applied cleanly, but there were one or two cases in name resolution and one case in type check where the existing logic required a id for `Struct`-style enum variants and structs. --- src/libsyntax/ast.rs | 33 +++++++++++++++++++-------------- src/libsyntax/config.rs | 5 ++--- src/libsyntax/ext/build.rs | 1 + src/libsyntax/mut_visit.rs | 7 ++++--- src/libsyntax/parse/parser.rs | 11 ++++++----- src/libsyntax/print/pprust.rs | 1 + 6 files changed, 33 insertions(+), 25 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2cbd2dfeb25..c64ffb1232f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1956,8 +1956,13 @@ pub struct EnumDef { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Variant_ { + /// Name of the variant. pub ident: Ident, + /// Attributes of the variant. pub attrs: Vec, + /// Id of the variant (not the constructor, see `VariantData::ctor_id()`). + pub id: NodeId, + /// Fields and constructor id of the variant. pub data: VariantData, /// Explicit discriminant, e.g., `Foo = 1`. pub disr_expr: Option, @@ -2117,23 +2122,13 @@ pub struct StructField { pub attrs: Vec, } -/// Fields and Ids of enum variants and structs -/// -/// For enum variants: `NodeId` represents both an Id of the variant itself (relevant for all -/// variant kinds) and an Id of the variant's constructor (not relevant for `Struct`-variants). -/// One shared Id can be successfully used for these two purposes. -/// Id of the whole enum lives in `Item`. -/// -/// For structs: `NodeId` represents an Id of the structure's constructor, so it is not actually -/// used for `Struct`-structs (but still presents). Structures don't have an analogue of "Id of -/// the variant itself" from enum variants. -/// Id of the whole struct lives in `Item`. +/// Fields and constructor ids of enum variants and structs. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum VariantData { /// Struct variant. /// /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`. - Struct(Vec, NodeId, bool), + Struct(Vec, bool), /// Tuple variant. /// /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`. @@ -2145,17 +2140,23 @@ pub enum VariantData { } impl VariantData { + /// Return the fields of this variant. pub fn fields(&self) -> &[StructField] { match *self { VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, _) => fields, _ => &[], } } - pub fn id(&self) -> NodeId { + + /// Return the `NodeId` of this variant's constructor, if it has one. + pub fn ctor_id(&self) -> Option { match *self { - VariantData::Struct(_, id, _) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id, + VariantData::Struct(..) => None, + VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id), } } + + /// Does this `VariantData` represent a `Struct`-struct/variant? pub fn is_struct(&self) -> bool { if let VariantData::Struct(..) = *self { true @@ -2163,6 +2164,8 @@ impl VariantData { false } } + + /// Does this `VariantData` represent a tuple struct/variant? pub fn is_tuple(&self) -> bool { if let VariantData::Tuple(..) = *self { true @@ -2170,6 +2173,8 @@ impl VariantData { false } } + + /// Does this `VariantData` represent a unit struct/variant? pub fn is_unit(&self) -> bool { if let VariantData::Unit(..) = *self { true diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 7159c949513..18173628a26 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -225,10 +225,9 @@ impl<'a> StripUnconfigured<'a> { fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) { match vdata { - ast::VariantData::Struct(fields, _id, _) | - ast::VariantData::Tuple(fields, _id) => + ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) => fields.flat_map_in_place(|field| self.configure(field)), - ast::VariantData::Unit(_id) => {} + ast::VariantData::Unit(_) => {} } } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index e95f0589449..614967bdeb4 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -1062,6 +1062,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { respan(span, ast::Variant_ { ident, + id: ast::DUMMY_NODE_ID, attrs: Vec::new(), data: vdata, disr_expr: None, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 5bb1d8a4b94..784d0049ac5 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -450,9 +450,10 @@ pub fn noop_visit_foreign_mod(foreign_mod: &mut ForeignMod, vis: } pub fn noop_visit_variant(variant: &mut Variant, vis: &mut T) { - let Spanned { node: Variant_ { ident, attrs, data, disr_expr }, span } = variant; + let Spanned { node: Variant_ { ident, attrs, id, data, disr_expr }, span } = variant; vis.visit_ident(ident); visit_attrs(attrs, vis); + vis.visit_id(id); vis.visit_variant_data(data); visit_opt(disr_expr, |disr_expr| vis.visit_anon_const(disr_expr)); vis.visit_span(span); @@ -765,11 +766,11 @@ pub fn noop_visit_where_predicate(pred: &mut WherePredicate, vis: pub fn noop_visit_variant_data(vdata: &mut VariantData, vis: &mut T) { match vdata { - VariantData::Struct(fields, id, _) | + VariantData::Struct(fields, ..) => visit_vec(fields, |field| vis.visit_struct_field(field)), VariantData::Tuple(fields, id) => { visit_vec(fields, |field| vis.visit_struct_field(field)); vis.visit_id(id); - } + }, VariantData::Unit(id) => vis.visit_id(id), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 99260314054..d7a2170342d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6844,7 +6844,7 @@ impl<'a> Parser<'a> { } else { // If we see: `struct Foo where T: Copy { ... }` let (fields, recovered) = self.parse_record_struct_body()?; - VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered) + VariantData::Struct(fields, recovered) } // No `where` so: `struct Foo;` } else if self.eat(&token::Semi) { @@ -6852,7 +6852,7 @@ impl<'a> Parser<'a> { // Record-style struct definition } else if self.token == token::OpenDelim(token::Brace) { let (fields, recovered) = self.parse_record_struct_body()?; - VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered) + VariantData::Struct(fields, recovered) // Tuple-style struct definition with optional where-clause. } else if self.token == token::OpenDelim(token::Paren) { let body = VariantData::Tuple(self.parse_tuple_struct_body()?, ast::DUMMY_NODE_ID); @@ -6881,10 +6881,10 @@ impl<'a> Parser<'a> { let vdata = if self.token.is_keyword(keywords::Where) { generics.where_clause = self.parse_where_clause()?; let (fields, recovered) = self.parse_record_struct_body()?; - VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered) + VariantData::Struct(fields, recovered) } else if self.token == token::OpenDelim(token::Brace) { let (fields, recovered) = self.parse_record_struct_body()?; - VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered) + VariantData::Struct(fields, recovered) } else { let token_str = self.this_token_descr(); let mut err = self.fatal(&format!( @@ -7708,7 +7708,7 @@ impl<'a> Parser<'a> { // Parse a struct variant. all_nullary = false; let (fields, recovered) = self.parse_record_struct_body()?; - struct_def = VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered); + struct_def = VariantData::Struct(fields, recovered); } else if self.check(&token::OpenDelim(token::Paren)) { all_nullary = false; struct_def = VariantData::Tuple( @@ -7730,6 +7730,7 @@ impl<'a> Parser<'a> { let vr = ast::Variant_ { ident, + id: ast::DUMMY_NODE_ID, attrs: variant_attrs, data: struct_def, disr_expr, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 07df14ddc72..946fdc0c469 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -3266,6 +3266,7 @@ mod tests { let var = source_map::respan(syntax_pos::DUMMY_SP, ast::Variant_ { ident, attrs: Vec::new(), + id: ast::DUMMY_NODE_ID, // making this up as I go.... ? data: ast::VariantData::Unit(ast::DUMMY_NODE_ID), disr_expr: None, -- cgit 1.4.1-3-g733a5 From c667c2fc0896b2a58a363d2c535881e5b983857a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 24 Mar 2019 00:06:58 +0300 Subject: Remove methods is_struct/is_tuple/is_unit from VariantData --- src/librustc/hir/mod.rs | 27 --------- src/librustc/hir/print.rs | 67 ++++++++++----------- src/librustc_passes/ast_validation.rs | 2 +- src/librustdoc/clean/mod.rs | 11 ++-- src/libsyntax/ast.rs | 27 --------- src/libsyntax/print/pprust.rs | 73 ++++++++++++----------- src/libsyntax_ext/deriving/debug.rs | 96 +++++++++++++++---------------- src/libsyntax_ext/deriving/generic/mod.rs | 8 ++- 8 files changed, 130 insertions(+), 181 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 6ce7c347c99..7895919e150 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2208,33 +2208,6 @@ impl VariantData { VariantData::Tuple(_, hir_id) | VariantData::Unit(hir_id) => Some(hir_id), } } - - /// Does this `VariantData` represent a `Struct`-struct/variant? - pub fn is_struct(&self) -> bool { - if let VariantData::Struct(..) = *self { - true - } else { - false - } - } - - /// Does this `VariantData` represent a tuple struct/variant? - pub fn is_tuple(&self) -> bool { - if let VariantData::Tuple(..) = *self { - true - } else { - false - } - } - - /// Does this `VariantData` represent a unit struct/variant? - pub fn is_unit(&self) -> bool { - if let VariantData::Unit(..) = *self { - true - } else { - false - } - } } // The bodies for items are stored "out of line", in a separate diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index bff4190ae79..cdd4043f4bc 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -860,41 +860,44 @@ impl<'a> State<'a> { -> io::Result<()> { self.print_name(name)?; self.print_generic_params(&generics.params)?; - if !struct_def.is_struct() { - if struct_def.is_tuple() { - self.popen()?; - self.commasep(Inconsistent, struct_def.fields(), |s, field| { - s.maybe_print_comment(field.span.lo())?; - s.print_outer_attributes(&field.attrs)?; - s.print_visibility(&field.vis)?; - s.print_type(&field.ty) - })?; - self.pclose()?; - } - self.print_where_clause(&generics.where_clause)?; - if print_finalizer { - self.s.word(";")?; + match struct_def { + hir::VariantData::Tuple(..) | hir::VariantData::Unit(..) => { + if let hir::VariantData::Tuple(..) = struct_def { + self.popen()?; + self.commasep(Inconsistent, struct_def.fields(), |s, field| { + s.maybe_print_comment(field.span.lo())?; + s.print_outer_attributes(&field.attrs)?; + s.print_visibility(&field.vis)?; + s.print_type(&field.ty) + })?; + self.pclose()?; + } + self.print_where_clause(&generics.where_clause)?; + if print_finalizer { + self.s.word(";")?; + } + self.end()?; + self.end() // close the outer-box } - self.end()?; - self.end() // close the outer-box - } else { - self.print_where_clause(&generics.where_clause)?; - self.nbsp()?; - self.bopen()?; - self.hardbreak_if_not_bol()?; - - for field in struct_def.fields() { + hir::VariantData::Struct(..) => { + self.print_where_clause(&generics.where_clause)?; + self.nbsp()?; + self.bopen()?; self.hardbreak_if_not_bol()?; - self.maybe_print_comment(field.span.lo())?; - self.print_outer_attributes(&field.attrs)?; - self.print_visibility(&field.vis)?; - self.print_ident(field.ident)?; - self.word_nbsp(":")?; - self.print_type(&field.ty)?; - self.s.word(",")?; - } - self.bclose(span) + for field in struct_def.fields() { + self.hardbreak_if_not_bol()?; + self.maybe_print_comment(field.span.lo())?; + self.print_outer_attributes(&field.attrs)?; + self.print_visibility(&field.vis)?; + self.print_ident(field.ident)?; + self.word_nbsp(":")?; + self.print_type(&field.ty)?; + self.s.word(",")?; + } + + self.bclose(span) + } } } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index b85429cd3cf..4e2aefe6231 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -661,7 +661,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } ItemKind::Union(ref vdata, _) => { - if !vdata.is_struct() { + if let VariantData::Tuple(..) | VariantData::Unit(..) = vdata { self.err_handler().span_err(item.span, "tuple and unit unions are not permitted"); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3ebca05f7dd..ddd68c48379 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3192,12 +3192,11 @@ pub enum VariantKind { impl Clean for hir::VariantData { fn clean(&self, cx: &DocContext<'_>) -> VariantKind { - if self.is_struct() { - VariantKind::Struct(self.clean(cx)) - } else if self.is_unit() { - VariantKind::CLike - } else { - VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect()) + match self { + hir::VariantData::Struct(..) => VariantKind::Struct(self.clean(cx)), + hir::VariantData::Tuple(..) => + VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect()), + hir::VariantData::Unit(..) => VariantKind::CLike, } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index c64ffb1232f..bcc8fdf8cd4 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2155,33 +2155,6 @@ impl VariantData { VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id), } } - - /// Does this `VariantData` represent a `Struct`-struct/variant? - pub fn is_struct(&self) -> bool { - if let VariantData::Struct(..) = *self { - true - } else { - false - } - } - - /// Does this `VariantData` represent a tuple struct/variant? - pub fn is_tuple(&self) -> bool { - if let VariantData::Tuple(..) = *self { - true - } else { - false - } - } - - /// Does this `VariantData` represent a unit struct/variant? - pub fn is_unit(&self) -> bool { - if let VariantData::Unit(..) = *self { - true - } else { - false - } - } } /// An item. diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 946fdc0c469..f5a9aded845 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1550,44 +1550,47 @@ impl<'a> State<'a> { print_finalizer: bool) -> io::Result<()> { self.print_ident(ident)?; self.print_generic_params(&generics.params)?; - if !struct_def.is_struct() { - if struct_def.is_tuple() { - self.popen()?; - self.commasep( - Inconsistent, struct_def.fields(), - |s, field| { - s.maybe_print_comment(field.span.lo())?; - s.print_outer_attributes(&field.attrs)?; - s.print_visibility(&field.vis)?; - s.print_type(&field.ty) - } - )?; - self.pclose()?; - } - self.print_where_clause(&generics.where_clause)?; - if print_finalizer { - self.s.word(";")?; + match struct_def { + ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => { + if let ast::VariantData::Tuple(..) = struct_def { + self.popen()?; + self.commasep( + Inconsistent, struct_def.fields(), + |s, field| { + s.maybe_print_comment(field.span.lo())?; + s.print_outer_attributes(&field.attrs)?; + s.print_visibility(&field.vis)?; + s.print_type(&field.ty) + } + )?; + self.pclose()?; + } + self.print_where_clause(&generics.where_clause)?; + if print_finalizer { + self.s.word(";")?; + } + self.end()?; + self.end() // close the outer-box } - self.end()?; - self.end() // close the outer-box - } else { - self.print_where_clause(&generics.where_clause)?; - self.nbsp()?; - self.bopen()?; - self.hardbreak_if_not_bol()?; - - for field in struct_def.fields() { + ast::VariantData::Struct(..) => { + self.print_where_clause(&generics.where_clause)?; + self.nbsp()?; + self.bopen()?; self.hardbreak_if_not_bol()?; - 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(",")?; - } - self.bclose(span) + for field in struct_def.fields() { + self.hardbreak_if_not_bol()?; + 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(",")?; + } + + self.bclose(span) + } } } diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index 7dc2d007d73..7c47c6ff79a 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -51,9 +51,9 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> // build fmt.debug_struct().field(, &)....build() // or fmt.debug_tuple().field(&)....build() // based on the "shape". - let (ident, is_struct) = match *substr.fields { - Struct(vdata, _) => (substr.type_ident, vdata.is_struct()), - EnumMatching(_, _, v, _) => (v.node.ident, v.node.data.is_struct()), + let (ident, vdata, fields) = match substr.fields { + Struct(vdata, fields) => (substr.type_ident, *vdata, fields), + EnumMatching(_, _, v, fields) => (v.node.ident, &v.node.data, fields), EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"), @@ -67,55 +67,51 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> let fmt = substr.nonself_args[0].clone(); - let mut stmts = match *substr.fields { - Struct(_, ref fields) | - EnumMatching(.., ref fields) => { - let mut stmts = vec![]; - if !is_struct { - // tuple struct/"normal" variant - let expr = - cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]); - stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr)); - - for field in fields { - // Use double indirection to make sure this works for unsized types - let field = cx.expr_addr_of(field.span, field.self_.clone()); - let field = cx.expr_addr_of(field.span, field); - - let expr = cx.expr_method_call(span, - builder_expr.clone(), - Ident::from_str("field"), - vec![field]); - - // Use `let _ = expr;` to avoid triggering the - // unused_results lint. - stmts.push(stmt_let_undescore(cx, span, expr)); - } - } else { - // normal struct/struct variant - let expr = - cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]); - stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr)); - - for field in fields { - let name = cx.expr_lit(field.span, - ast::LitKind::Str(field.name.unwrap().name, - ast::StrStyle::Cooked)); - - // Use double indirection to make sure this works for unsized types - let field = cx.expr_addr_of(field.span, field.self_.clone()); - let field = cx.expr_addr_of(field.span, field); - let expr = cx.expr_method_call(span, - builder_expr.clone(), - Ident::from_str("field"), - vec![name, field]); - stmts.push(stmt_let_undescore(cx, span, expr)); - } + let mut stmts = vec![]; + match vdata { + ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => { + // tuple struct/"normal" variant + let expr = + cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]); + stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr)); + + for field in fields { + // Use double indirection to make sure this works for unsized types + let field = cx.expr_addr_of(field.span, field.self_.clone()); + let field = cx.expr_addr_of(field.span, field); + + let expr = cx.expr_method_call(span, + builder_expr.clone(), + Ident::from_str("field"), + vec![field]); + + // Use `let _ = expr;` to avoid triggering the + // unused_results lint. + stmts.push(stmt_let_undescore(cx, span, expr)); } - stmts } - _ => unreachable!(), - }; + ast::VariantData::Struct(..) => { + // normal struct/struct variant + let expr = + cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]); + stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr)); + + for field in fields { + let name = cx.expr_lit(field.span, + ast::LitKind::Str(field.name.unwrap().name, + ast::StrStyle::Cooked)); + + // Use double indirection to make sure this works for unsized types + let field = cx.expr_addr_of(field.span, field.self_.clone()); + let field = cx.expr_addr_of(field.span, field); + let expr = cx.expr_method_call(span, + builder_expr.clone(), + Ident::from_str("field"), + vec![name, field]); + stmts.push(stmt_let_undescore(cx, span, expr)); + } + } + } let expr = cx.expr_method_call(span, builder_expr, Ident::from_str("finish"), vec![]); diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 2bb98c1bf62..dc0d72a7830 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -1539,6 +1539,7 @@ impl<'a> TraitDef<'a> { } } + let is_tuple = if let ast::VariantData::Tuple(..) = struct_def { true } else { false }; match (just_spans.is_empty(), named_idents.is_empty()) { (false, false) => { cx.span_bug(self.span, @@ -1547,9 +1548,10 @@ impl<'a> TraitDef<'a> { } // named fields (_, false) => Named(named_idents), - // empty structs - _ if struct_def.is_struct() => Named(named_idents), - _ => Unnamed(just_spans, struct_def.is_tuple()), + // unnamed fields + (false, _) => Unnamed(just_spans, is_tuple), + // empty + _ => Named(Vec::new()), } } -- cgit 1.4.1-3-g733a5