diff --git a/src/librustc/front/map/collector.rs b/src/librustc/front/map/collector.rs index 3edeaaccbde4..51ba799c5d11 100644 --- a/src/librustc/front/map/collector.rs +++ b/src/librustc/front/map/collector.rs @@ -150,8 +150,8 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { } ItemStruct(ref struct_def, _) => { // If this is a tuple-like struct, register the constructor. - if let Some(ctor_id) = struct_def.ctor_id { - self.insert_def(ctor_id, + if struct_def.kind != VariantKind::Dict { + self.insert_def(struct_def.id, NodeStructCtor(&**struct_def), DefPathData::StructCtor); } diff --git a/src/librustc/front/map/mod.rs b/src/librustc/front/map/mod.rs index 96e103aa4f4b..b183f12a092c 100644 --- a/src/librustc/front/map/mod.rs +++ b/src/librustc/front/map/mod.rs @@ -480,8 +480,8 @@ impl<'ast> Map<'ast> { } } Some(NodeVariant(variant)) => { - match variant.node.def.ctor_id { - None => &variant.node.def, + match variant.node.def.kind { + VariantKind::Dict => &variant.node.def, _ => panic!("struct ID bound to enum variant that isn't struct-like"), } } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 9d2b1548f29d..7c08d7618d79 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -381,12 +381,8 @@ fn each_auxiliary_node_id(item: &hir::Item, callback: F) -> bool where match item.node { hir::ItemStruct(ref struct_def, _) => { // If this is a newtype struct, return the constructor. - match struct_def.ctor_id { - Some(ctor_id) if !struct_def.fields.is_empty() && - struct_def.fields[0].node.kind.is_unnamed() => { - continue_ = callback(ctor_id); - } - _ => {} + if struct_def.kind == hir::VariantKind::Tuple { + continue_ = callback(struct_def.id); } } _ => {} @@ -1085,9 +1081,8 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, } // If this is a tuple-like struct, encode the type of the constructor. - if let Some(ctor_id) = struct_def.ctor_id { - encode_info_for_struct_ctor(ecx, rbml_w, item.name, - ctor_id, index, item.id); + if struct_def.kind != hir::VariantKind::Dict { + encode_info_for_struct_ctor(ecx, rbml_w, item.name, struct_def.id, index, item.id); } } hir::ItemDefaultImpl(unsafety, _) => { diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 6e31b733254b..f977992e735f 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -426,7 +426,9 @@ fn find_live(tcx: &ty::ctxt, fn get_struct_ctor_id(item: &hir::Item) -> Option { match item.node { - hir::ItemStruct(ref struct_def, _) => struct_def.ctor_id, + hir::ItemStruct(ref struct_def, _) if struct_def.kind != hir::VariantKind::Dict => { + Some(struct_def.id) + } _ => None } } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index c2235591ceef..8476adf68381 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -185,9 +185,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> { |v| visit::walk_item(v, i), required); if let hir::ItemStruct(ref sd, _) = i.node { - sd.ctor_id.map(|id| { - self.annotate(id, true, &i.attrs, i.span, |_| {}, true) - }); + if sd.kind != hir::VariantKind::Dict { + self.annotate(sd.id, true, &i.attrs, i.span, |_| {}, true) + } } } diff --git a/src/librustc_front/fold.rs b/src/librustc_front/fold.rs index 876ec804e278..325180817940 100644 --- a/src/librustc_front/fold.rs +++ b/src/librustc_front/fold.rs @@ -699,10 +699,11 @@ pub fn noop_fold_where_predicate(pred: WherePredicate, fld: &mut T) - } pub fn noop_fold_struct_def(struct_def: P, fld: &mut T) -> P { - struct_def.map(|StructDef { fields, ctor_id }| { + struct_def.map(|StructDef { fields, id, kind }| { StructDef { fields: fields.move_map(|f| fld.fold_struct_field(f)), - ctor_id: ctor_id.map(|cid| fld.new_id(cid)), + id: fld.new_id(id), + kind: kind, } }) } diff --git a/src/librustc_front/hir.rs b/src/librustc_front/hir.rs index 8f5f95b11046..b93224165418 100644 --- a/src/librustc_front/hir.rs +++ b/src/librustc_front/hir.rs @@ -33,7 +33,6 @@ pub use self::Ty_::*; pub use self::TyParamBound::*; pub use self::UnOp::*; pub use self::UnsafeSource::*; -pub use self::VariantKind::*; pub use self::ViewPath_::*; pub use self::Visibility::*; pub use self::PathParameters::*; @@ -1021,14 +1020,6 @@ pub struct VariantArg { pub id: NodeId, } -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum VariantKind { - /// Tuple variant, e.g. `Foo(A, B)` - TupleVariantKind(Vec), - /// Struct variant, e.g. `Foo {x: A, y: B}` - StructVariantKind(P), -} - #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct EnumDef { pub variants: Vec>, @@ -1176,13 +1167,21 @@ impl StructFieldKind { } } +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum VariantKind { + Dict, + Tuple, + Unit, +} + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct StructDef { /// Fields, not including ctor pub fields: Vec, /// ID of the constructor. This is only used for tuple- or enum-like /// structs. - pub ctor_id: Option, + pub id: NodeId, + pub kind: VariantKind, } /* diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs index 0350c9ff1144..1539613070fc 100644 --- a/src/librustc_front/lowering.rs +++ b/src/librustc_front/lowering.rs @@ -502,7 +502,12 @@ pub fn lower_where_predicate(_lctx: &LoweringContext, pub fn lower_struct_def(_lctx: &LoweringContext, sd: &StructDef) -> P { P(hir::StructDef { fields: sd.fields.iter().map(|f| lower_struct_field(_lctx, f)).collect(), - ctor_id: sd.ctor_id, + id: sd.id, + kind: match sd.kind { + VariantKind::Dict => hir::VariantKind::Dict, + VariantKind::Tuple => hir::VariantKind::Tuple, + VariantKind::Unit => hir::VariantKind::Unit, + } }) } diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs index ee6be06428e1..8d4422011f00 100644 --- a/src/librustc_front/print/pprust.rs +++ b/src/librustc_front/print/pprust.rs @@ -896,8 +896,8 @@ impl<'a> State<'a> { -> io::Result<()> { try!(self.print_name(name)); try!(self.print_generics(generics)); - if ::util::struct_def_is_tuple_like(struct_def) { - if !struct_def.fields.is_empty() { + if struct_def.kind != hir::VariantKind::Dict { + if struct_def.kind == hir::VariantKind::Tuple { try!(self.popen()); try!(self.commasep(Inconsistent, &struct_def.fields, diff --git a/src/librustc_front/util.rs b/src/librustc_front/util.rs index c6b2a2acc2b8..05a548a8c662 100644 --- a/src/librustc_front/util.rs +++ b/src/librustc_front/util.rs @@ -81,12 +81,6 @@ pub fn binop_to_string(op: BinOp_) -> &'static str { } } -/// Returns true if the given struct def is tuple-like; i.e. that its fields -/// are unnamed. -pub fn struct_def_is_tuple_like(struct_def: &hir::StructDef) -> bool { - struct_def.ctor_id.is_some() -} - pub fn stmt_id(s: &Stmt) -> NodeId { match s.node { StmtDecl(_, id) => id, @@ -298,7 +292,7 @@ impl<'a, 'v, O: ast_util::IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> _: &hir::Generics, id: NodeId) { self.operation.visit_id(id); - struct_def.ctor_id.map(|ctor_id| self.operation.visit_id(ctor_id)); + self.operation.visit_id(struct_def.id); visit::walk_struct_def(self, struct_def); } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index ca5411f9c790..4e4609fb083c 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -132,9 +132,8 @@ impl<'v> Visitor<'v> for ParentVisitor { _: &'v hir::Generics, n: ast::NodeId) { // Struct constructors are parented to their struct definitions because // they essentially are the struct definitions. - match s.ctor_id { - Some(id) => { self.parents.insert(id, n); } - None => {} + if s.kind != hir::VariantKind::Dict { + self.parents.insert(s.id, n); } // While we have the id of the struct definition, go ahead and parent @@ -320,9 +319,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { // Struct constructors are public if the struct is all public. hir::ItemStruct(ref def, _) if public_first => { - match def.ctor_id { - Some(id) => { self.exported_items.insert(id); } - None => {} + if def.kind != hir::VariantKind::Dict { + self.exported_items.insert(def.id); } // fields can be public or private, so lets check for field in &def.fields { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index a3f40efa4833..6b4b33341664 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -492,9 +492,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { // These items live in both the type and value namespaces. ItemStruct(ref struct_def, _) => { // Adding to both Type and Value namespaces or just Type? - let (forbid, ctor_id) = match struct_def.ctor_id { - Some(ctor_id) => (ForbidDuplicateTypesAndValues, Some(ctor_id)), - None => (ForbidDuplicateTypesAndModules, None) + let (forbid, ctor_id) = match struct_def.kind { + hir::VariantKind::Dict => (ForbidDuplicateTypesAndModules, None), + _ => (ForbidDuplicateTypesAndValues, Some(struct_def.id)), }; let name_bindings = self.add_child(name, parent, forbid, sp); @@ -587,14 +587,14 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { item_id: DefId, parent: &Rc) { let name = variant.node.name; - let is_exported = match variant.node.def.ctor_id { - Some(_) => false, - None => { + let is_exported = match variant.node.def.kind { + hir::VariantKind::Dict => { // Not adding fields for variants as they are not accessed with a self receiver let variant_def_id = self.ast_map.local_def_id(variant.node.id); self.structs.insert(variant_def_id, Vec::new()); true } + _ => false, }; let child = self.add_child(name, parent, diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index 983f04643c36..fb1c494ffd44 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -462,16 +462,12 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { ty_params: &ast::Generics) { let qualname = format!("::{}", self.tcx.map.path_to_string(item.id)); - let ctor_id = match def.ctor_id { - Some(node_id) => node_id, - None => ast::DUMMY_NODE_ID, - }; let val = self.span.snippet(item.span); let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct); self.fmt.struct_str(item.span, sub_span, item.id, - ctor_id, + def.id, &qualname, self.cur_scope, &val); @@ -505,11 +501,10 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { qualname.push_str(name); let val = self.span.snippet(variant.span); - let ctor_id = variant.node.def.ctor_id.unwrap_or(ast::DUMMY_NODE_ID); self.fmt.struct_variant_str(variant.span, self.span.span_for_first_ident(variant.span), variant.node.id, - ctor_id, + variant.node.def.id, &qualname, &enum_data.qualname, &val, diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 6baa3c5e0db6..06cb8de05422 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -2428,7 +2428,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { hir_map::NodeVariant(ref v) => { let llfn; - let fields = if v.node.def.ctor_id.is_none() { + let fields = if v.node.def.kind == hir::VariantKind::Dict { ccx.sess().bug("struct variant kind unexpected in get_item_val") } else { &v.node.def.fields @@ -2454,12 +2454,12 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { hir_map::NodeStructCtor(struct_def) => { // Only register the constructor if this is a tuple-like struct. - let ctor_id = match struct_def.ctor_id { - None => { + let ctor_id = match struct_def.kind { + hir::VariantKind::Dict => { ccx.sess().bug("attempt to register a constructor of \ a non-tuple-like struct") } - Some(ctor_id) => ctor_id, + _ => struct_def.id, }; let parent = ccx.tcx().map.get_parent(id); let struct_item = ccx.tcx().map.expect_item(parent); diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index debd4d232b8d..fdcc2623ef10 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -418,7 +418,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( match map_node { hir_map::NodeVariant(v) => { - v.node.def.ctor_id.is_some() && !v.node.def.fields.is_empty() + v.node.def.kind == hir::VariantKind::Tuple } hir_map::NodeStructCtor(_) => true, _ => false diff --git a/src/librustc_trans/trans/inline.rs b/src/librustc_trans/trans/inline.rs index b8f75df8c11c..9cb4b271742c 100644 --- a/src/librustc_trans/trans/inline.rs +++ b/src/librustc_trans/trans/inline.rs @@ -115,12 +115,12 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) } } hir::ItemStruct(ref struct_def, _) => { - match struct_def.ctor_id { - None => ccx.sess().bug("instantiate_inline: called on a \ - non-tuple struct"), - Some(ctor_id) => { - ccx.external().borrow_mut().insert(fn_id, Some(ctor_id)); - my_id = ctor_id; + match struct_def.kind { + hir::VariantKind::Dict => ccx.sess().bug("instantiate_inline: called on a \ + non-tuple struct"), + _ => { + ccx.external().borrow_mut().insert(fn_id, Some(struct_def.id)); + my_id = struct_def.id; } } } diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index 33f798be85e8..49009378bb97 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -246,9 +246,11 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, hir_map::NodeStructCtor(struct_def) => { let d = mk_lldecl(abi::Rust); attributes::inline(d, attributes::InlineAttr::Hint); + if struct_def.kind == hir::VariantKind::Dict { + panic!("ast-mapped struct didn't have a ctor id") + } base::trans_tuple_struct(ccx, - struct_def.ctor_id.expect("ast-mapped tuple struct \ - didn't have a ctor id"), + struct_def.id, psubsts, d); d diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 4217b0d481f1..879432d89c8c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1014,8 +1014,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { convert_field(ccx, &scheme.generics, &predicates, f, ty_f) } - if let Some(ctor_id) = struct_def.ctor_id { - convert_variant_ctor(tcx, ctor_id, variant, scheme, predicates); + if struct_def.kind != hir::VariantKind::Dict { + convert_variant_ctor(tcx, struct_def.id, variant, scheme, predicates); } }, hir::ItemTy(_, ref generics) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0d2d1118883b..a5ed0ea6c095 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1917,25 +1917,10 @@ pub enum VariantKind { StructVariant(VariantStruct), } -impl Clean for hir::VariantKind { - fn clean(&self, cx: &DocContext) -> VariantKind { - match self { - &hir::TupleVariantKind(ref args) => { - if args.is_empty() { - CLikeVariant - } else { - TupleVariant(args.iter().map(|x| x.ty.clean(cx)).collect()) - } - }, - &hir::StructVariantKind(ref sd) => StructVariant(sd.clean(cx)), - } - } -} - fn struct_def_to_variant_kind(struct_def: &hir::StructDef, cx: &DocContext) -> VariantKind { - if struct_def.ctor_id.is_none() { + if struct_def.kind == hir::VariantKind::Dict { StructVariant(struct_def.clean(cx)) - } else if struct_def.fields.is_empty() { + } else if struct_def.kind == hir::VariantKind::Unit { CLikeVariant } else { TupleVariant(struct_def.fields.iter().map(|x| x.node.ty.clean(cx)).collect()) diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 4296c79be50f..c65c31e6c3cc 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -235,7 +235,7 @@ pub struct Import { } pub fn struct_type_from_def(sd: &hir::StructDef) -> StructType { - if sd.ctor_id.is_some() { + if sd.kind != hir::VariantKind::Dict { // We are in a tuple-struct match sd.fields.len() { 0 => Unit, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 57d9837e1aac..66c0d858e3c7 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -44,7 +44,6 @@ pub use self::TyParamBound::*; pub use self::UintTy::*; pub use self::UnOp::*; pub use self::UnsafeSource::*; -pub use self::VariantKind::*; pub use self::ViewPath_::*; pub use self::Visibility::*; pub use self::PathParameters::*; @@ -1577,14 +1576,6 @@ pub struct VariantArg { pub id: NodeId, } -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum VariantKind { - /// Tuple variant, e.g. `Foo(A, B)` - TupleVariantKind(Vec), - /// Struct variant, e.g. `Foo {x: A, y: B}` - StructVariantKind(P), -} - #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct EnumDef { pub variants: Vec>, @@ -1756,13 +1747,21 @@ impl StructFieldKind { } } +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum VariantKind { + Dict, + Tuple, + Unit, +} + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct StructDef { /// Fields, not including ctor pub fields: Vec, /// ID of the constructor. This is only used for tuple- or enum-like /// structs. - pub ctor_id: Option, + pub id: NodeId, + pub kind: VariantKind, } /* diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 905a83b050ed..87f05f7f41e3 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -463,7 +463,7 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { _: &ast::Generics, id: NodeId) { self.operation.visit_id(id); - struct_def.ctor_id.map(|ctor_id| self.operation.visit_id(ctor_id)); + self.operation.visit_id(struct_def.id); visit::walk_struct_def(self, struct_def); } @@ -529,12 +529,6 @@ pub fn compute_id_range_for_fn_body(fk: FnKind, id_visitor.operation.result } -/// Returns true if the given struct def is tuple-like; i.e. that its fields -/// are unnamed. -pub fn struct_def_is_tuple_like(struct_def: &ast::StructDef) -> bool { - struct_def.ctor_id.is_some() -} - /// Returns true if the given pattern consists solely of an identifier /// and false otherwise. pub fn pat_is_ident(pat: P) -> bool { diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 0accf34202ed..d47072d477e8 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -168,12 +168,13 @@ fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ fn fold_struct(cx: &mut Context, def: P) -> P where F: FnMut(&[ast::Attribute]) -> bool { - def.map(|ast::StructDef { fields, ctor_id }| { + def.map(|ast::StructDef { fields, id, kind }| { ast::StructDef { fields: fields.into_iter().filter(|m| { (cx.in_cfg)(&m.node.attrs) }).collect(), - ctor_id: ctor_id, + id: id, + kind: kind, } }) } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index d448eb63204e..132ab6e67fee 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -993,7 +993,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn variant(&self, span: Span, name: Ident, tys: Vec> ) -> ast::Variant { - let fields = tys.into_iter().map(|ty| { + let fields: Vec<_> = tys.into_iter().map(|ty| { Spanned { span: ty.span, node: ast::StructField_ { ty: ty, kind: ast::UnnamedField(ast::Inherited), @@ -1002,11 +1002,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> { }} }).collect(); + let kind = if fields.is_empty() { ast::VariantKind::Unit } else { ast::VariantKind::Tuple }; + respan(span, ast::Variant_ { name: name, attrs: Vec::new(), - def: P(ast::StructDef { fields: fields, ctor_id: Some(ast::DUMMY_NODE_ID) }), + def: P(ast::StructDef { fields: fields, + id: ast::DUMMY_NODE_ID, + kind: kind }), id: ast::DUMMY_NODE_ID, disr_expr: None, }) diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index 2fdaa9b7550b..7b64e5522a4f 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -95,7 +95,7 @@ fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure for variant in &enum_def.variants { let def = &variant.node.def; - if def.ctor_id.is_none() || !def.fields.is_empty() { + if def.kind != ast::VariantKind::Unit { cx.span_err(trait_span, "`FromPrimitive` cannot be derived \ for enums with non-unit variants"); return cx.expr_fail(trait_span, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 1d545268e57d..0b3af659a7b2 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -828,7 +828,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { } } } - if def.fields.is_empty() && def.ctor_id.is_none() { + if def.fields.is_empty() && def.kind == ast::VariantKind::Dict { self.gate_feature("braced_empty_structs", i.span, "empty structs with braces are unstable"); } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 88781c3664ab..8156ef20faf0 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -820,9 +820,10 @@ pub fn noop_fold_where_predicate( } pub fn noop_fold_struct_def(struct_def: P, fld: &mut T) -> P { - struct_def.map(|StructDef { fields, ctor_id }| StructDef { + struct_def.map(|StructDef { fields, id, kind }| StructDef { fields: fields.move_map(|f| fld.fold_struct_field(f)), - ctor_id: ctor_id.map(|cid| fld.new_id(cid)), + id: fld.new_id(id), + kind: kind, }) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 0748c898a828..1b446fb9902a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -45,7 +45,7 @@ use ast::{PatRegion, PatStruct, PatTup, PatVec, PatWild, PatWildMulti}; use ast::PatWildSingle; use ast::{PolyTraitRef, QSelf}; use ast::{Return, BiShl, BiShr, Stmt, StmtDecl}; -use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField}; +use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField, VariantKind}; use ast::{BiSub, StrStyle}; use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue}; use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef}; @@ -4640,26 +4640,26 @@ impl<'a> Parser<'a> { // Otherwise if we look ahead and see a paren we parse a tuple-style // struct. - let (fields, ctor_id) = if self.token.is_keyword(keywords::Where) { + let (fields, kind) = if self.token.is_keyword(keywords::Where) { generics.where_clause = try!(self.parse_where_clause()); if try!(self.eat(&token::Semi)) { // If we see a: `struct Foo where T: Copy;` style decl. - (Vec::new(), Some(ast::DUMMY_NODE_ID)) + (Vec::new(), VariantKind::Unit) } else { // If we see: `struct Foo where T: Copy { ... }` - (try!(self.parse_record_struct_body()), None) + (try!(self.parse_record_struct_body()), VariantKind::Dict) } // No `where` so: `struct Foo;` } else if try!(self.eat(&token::Semi) ){ - (Vec::new(), Some(ast::DUMMY_NODE_ID)) + (Vec::new(), VariantKind::Unit) // Record-style struct definition } else if self.token == token::OpenDelim(token::Brace) { let fields = try!(self.parse_record_struct_body()); - (fields, None) + (fields, VariantKind::Dict) // Tuple-style struct definition with optional where-clause. } else if self.token == token::OpenDelim(token::Paren) { let fields = try!(self.parse_tuple_struct_body(class_name, &mut generics)); - (fields, Some(ast::DUMMY_NODE_ID)) + (fields, VariantKind::Tuple) } else { let token_str = self.this_token_to_string(); return Err(self.fatal(&format!("expected `where`, `{{`, `(`, or `;` after struct \ @@ -4669,7 +4669,8 @@ impl<'a> Parser<'a> { Ok((class_name, ItemStruct(P(ast::StructDef { fields: fields, - ctor_id: ctor_id, + id: ast::DUMMY_NODE_ID, + kind: kind, }), generics), None)) } @@ -5118,7 +5119,8 @@ impl<'a> Parser<'a> { Ok(P(StructDef { fields: fields, - ctor_id: None, + id: ast::DUMMY_NODE_ID, + kind: VariantKind::Dict, })) } @@ -5156,15 +5158,18 @@ impl<'a> Parser<'a> { }}); } struct_def = P(StructDef { fields: fields, - ctor_id: Some(ast::DUMMY_NODE_ID) }); + id: ast::DUMMY_NODE_ID, + kind: ast::VariantKind::Tuple }); } else if try!(self.eat(&token::Eq) ){ disr_expr = Some(try!(self.parse_expr_nopanic())); any_disr = disr_expr.as_ref().map(|expr| expr.span); struct_def = P(StructDef { fields: Vec::new(), - ctor_id: Some(ast::DUMMY_NODE_ID) }); + id: ast::DUMMY_NODE_ID, + kind: ast::VariantKind::Unit }); } else { struct_def = P(StructDef { fields: Vec::new(), - ctor_id: Some(ast::DUMMY_NODE_ID) }); + id: ast::DUMMY_NODE_ID, + kind: ast::VariantKind::Unit }); } let vr = ast::Variant_ { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 678b8e048974..2d6829c5e75b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1392,8 +1392,8 @@ impl<'a> State<'a> { print_finalizer: bool) -> io::Result<()> { try!(self.print_ident(ident)); try!(self.print_generics(generics)); - if ast_util::struct_def_is_tuple_like(struct_def) { - if !struct_def.fields.is_empty() { + if struct_def.kind != ast::VariantKind::Dict { + if struct_def.kind == ast::VariantKind::Tuple { try!(self.popen()); try!(self.commasep( Inconsistent, &struct_def.fields, @@ -3119,7 +3119,9 @@ mod tests { name: ident, attrs: Vec::new(), // making this up as I go.... ? - def: P(ast::StructDef { fields: Vec::new(), ctor_id: Some(ast::DUMMY_NODE_ID) }), + def: P(ast::StructDef { fields: Vec::new(), + id: ast::DUMMY_NODE_ID, + kind: ast::VariantKind::Unit }), id: 0, disr_expr: None, });