1
Fork 0

Decouple structure kinds from NodeIds

This commit is contained in:
Vadim Petrochenkov 2015-10-02 03:53:28 +03:00
parent 2314ab29c2
commit 495566ee61
29 changed files with 113 additions and 131 deletions

View file

@ -150,8 +150,8 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
} }
ItemStruct(ref struct_def, _) => { ItemStruct(ref struct_def, _) => {
// If this is a tuple-like struct, register the constructor. // If this is a tuple-like struct, register the constructor.
if let Some(ctor_id) = struct_def.ctor_id { if struct_def.kind != VariantKind::Dict {
self.insert_def(ctor_id, self.insert_def(struct_def.id,
NodeStructCtor(&**struct_def), NodeStructCtor(&**struct_def),
DefPathData::StructCtor); DefPathData::StructCtor);
} }

View file

@ -480,8 +480,8 @@ impl<'ast> Map<'ast> {
} }
} }
Some(NodeVariant(variant)) => { Some(NodeVariant(variant)) => {
match variant.node.def.ctor_id { match variant.node.def.kind {
None => &variant.node.def, VariantKind::Dict => &variant.node.def,
_ => panic!("struct ID bound to enum variant that isn't struct-like"), _ => panic!("struct ID bound to enum variant that isn't struct-like"),
} }
} }

View file

@ -381,12 +381,8 @@ fn each_auxiliary_node_id<F>(item: &hir::Item, callback: F) -> bool where
match item.node { match item.node {
hir::ItemStruct(ref struct_def, _) => { hir::ItemStruct(ref struct_def, _) => {
// If this is a newtype struct, return the constructor. // If this is a newtype struct, return the constructor.
match struct_def.ctor_id { if struct_def.kind == hir::VariantKind::Tuple {
Some(ctor_id) if !struct_def.fields.is_empty() && continue_ = callback(struct_def.id);
struct_def.fields[0].node.kind.is_unnamed() => {
continue_ = callback(ctor_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 this is a tuple-like struct, encode the type of the constructor.
if let Some(ctor_id) = struct_def.ctor_id { if struct_def.kind != hir::VariantKind::Dict {
encode_info_for_struct_ctor(ecx, rbml_w, item.name, encode_info_for_struct_ctor(ecx, rbml_w, item.name, struct_def.id, index, item.id);
ctor_id, index, item.id);
} }
} }
hir::ItemDefaultImpl(unsafety, _) => { hir::ItemDefaultImpl(unsafety, _) => {

View file

@ -426,7 +426,9 @@ fn find_live(tcx: &ty::ctxt,
fn get_struct_ctor_id(item: &hir::Item) -> Option<ast::NodeId> { fn get_struct_ctor_id(item: &hir::Item) -> Option<ast::NodeId> {
match item.node { 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 _ => None
} }
} }

View file

@ -185,9 +185,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> {
|v| visit::walk_item(v, i), required); |v| visit::walk_item(v, i), required);
if let hir::ItemStruct(ref sd, _) = i.node { if let hir::ItemStruct(ref sd, _) = i.node {
sd.ctor_id.map(|id| { if sd.kind != hir::VariantKind::Dict {
self.annotate(id, true, &i.attrs, i.span, |_| {}, true) self.annotate(sd.id, true, &i.attrs, i.span, |_| {}, true)
}); }
} }
} }

View file

@ -699,10 +699,11 @@ pub fn noop_fold_where_predicate<T: Folder>(pred: WherePredicate, fld: &mut T) -
} }
pub fn noop_fold_struct_def<T: Folder>(struct_def: P<StructDef>, fld: &mut T) -> P<StructDef> { pub fn noop_fold_struct_def<T: Folder>(struct_def: P<StructDef>, fld: &mut T) -> P<StructDef> {
struct_def.map(|StructDef { fields, ctor_id }| { struct_def.map(|StructDef { fields, id, kind }| {
StructDef { StructDef {
fields: fields.move_map(|f| fld.fold_struct_field(f)), 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,
} }
}) })
} }

View file

@ -33,7 +33,6 @@ pub use self::Ty_::*;
pub use self::TyParamBound::*; pub use self::TyParamBound::*;
pub use self::UnOp::*; pub use self::UnOp::*;
pub use self::UnsafeSource::*; pub use self::UnsafeSource::*;
pub use self::VariantKind::*;
pub use self::ViewPath_::*; pub use self::ViewPath_::*;
pub use self::Visibility::*; pub use self::Visibility::*;
pub use self::PathParameters::*; pub use self::PathParameters::*;
@ -1021,14 +1020,6 @@ pub struct VariantArg {
pub id: NodeId, pub id: NodeId,
} }
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum VariantKind {
/// Tuple variant, e.g. `Foo(A, B)`
TupleVariantKind(Vec<VariantArg>),
/// Struct variant, e.g. `Foo {x: A, y: B}`
StructVariantKind(P<StructDef>),
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct EnumDef { pub struct EnumDef {
pub variants: Vec<P<Variant>>, pub variants: Vec<P<Variant>>,
@ -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)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct StructDef { pub struct StructDef {
/// Fields, not including ctor /// Fields, not including ctor
pub fields: Vec<StructField>, pub fields: Vec<StructField>,
/// ID of the constructor. This is only used for tuple- or enum-like /// ID of the constructor. This is only used for tuple- or enum-like
/// structs. /// structs.
pub ctor_id: Option<NodeId>, pub id: NodeId,
pub kind: VariantKind,
} }
/* /*

View file

@ -502,7 +502,12 @@ pub fn lower_where_predicate(_lctx: &LoweringContext,
pub fn lower_struct_def(_lctx: &LoweringContext, sd: &StructDef) -> P<hir::StructDef> { pub fn lower_struct_def(_lctx: &LoweringContext, sd: &StructDef) -> P<hir::StructDef> {
P(hir::StructDef { P(hir::StructDef {
fields: sd.fields.iter().map(|f| lower_struct_field(_lctx, f)).collect(), 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,
}
}) })
} }

View file

@ -896,8 +896,8 @@ impl<'a> State<'a> {
-> io::Result<()> { -> io::Result<()> {
try!(self.print_name(name)); try!(self.print_name(name));
try!(self.print_generics(generics)); try!(self.print_generics(generics));
if ::util::struct_def_is_tuple_like(struct_def) { if struct_def.kind != hir::VariantKind::Dict {
if !struct_def.fields.is_empty() { if struct_def.kind == hir::VariantKind::Tuple {
try!(self.popen()); try!(self.popen());
try!(self.commasep(Inconsistent, try!(self.commasep(Inconsistent,
&struct_def.fields, &struct_def.fields,

View file

@ -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 { pub fn stmt_id(s: &Stmt) -> NodeId {
match s.node { match s.node {
StmtDecl(_, id) => id, StmtDecl(_, id) => id,
@ -298,7 +292,7 @@ impl<'a, 'v, O: ast_util::IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O>
_: &hir::Generics, _: &hir::Generics,
id: NodeId) { id: NodeId) {
self.operation.visit_id(id); 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); visit::walk_struct_def(self, struct_def);
} }

View file

@ -132,9 +132,8 @@ impl<'v> Visitor<'v> for ParentVisitor {
_: &'v hir::Generics, n: ast::NodeId) { _: &'v hir::Generics, n: ast::NodeId) {
// Struct constructors are parented to their struct definitions because // Struct constructors are parented to their struct definitions because
// they essentially are the struct definitions. // they essentially are the struct definitions.
match s.ctor_id { if s.kind != hir::VariantKind::Dict {
Some(id) => { self.parents.insert(id, n); } self.parents.insert(s.id, n);
None => {}
} }
// While we have the id of the struct definition, go ahead and parent // 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. // Struct constructors are public if the struct is all public.
hir::ItemStruct(ref def, _) if public_first => { hir::ItemStruct(ref def, _) if public_first => {
match def.ctor_id { if def.kind != hir::VariantKind::Dict {
Some(id) => { self.exported_items.insert(id); } self.exported_items.insert(def.id);
None => {}
} }
// fields can be public or private, so lets check // fields can be public or private, so lets check
for field in &def.fields { for field in &def.fields {

View file

@ -492,9 +492,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
// These items live in both the type and value namespaces. // These items live in both the type and value namespaces.
ItemStruct(ref struct_def, _) => { ItemStruct(ref struct_def, _) => {
// Adding to both Type and Value namespaces or just Type? // Adding to both Type and Value namespaces or just Type?
let (forbid, ctor_id) = match struct_def.ctor_id { let (forbid, ctor_id) = match struct_def.kind {
Some(ctor_id) => (ForbidDuplicateTypesAndValues, Some(ctor_id)), hir::VariantKind::Dict => (ForbidDuplicateTypesAndModules, None),
None => (ForbidDuplicateTypesAndModules, None) _ => (ForbidDuplicateTypesAndValues, Some(struct_def.id)),
}; };
let name_bindings = self.add_child(name, parent, forbid, sp); 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, item_id: DefId,
parent: &Rc<Module>) { parent: &Rc<Module>) {
let name = variant.node.name; let name = variant.node.name;
let is_exported = match variant.node.def.ctor_id { let is_exported = match variant.node.def.kind {
Some(_) => false, hir::VariantKind::Dict => {
None => {
// Not adding fields for variants as they are not accessed with a self receiver // 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); let variant_def_id = self.ast_map.local_def_id(variant.node.id);
self.structs.insert(variant_def_id, Vec::new()); self.structs.insert(variant_def_id, Vec::new());
true true
} }
_ => false,
}; };
let child = self.add_child(name, parent, let child = self.add_child(name, parent,

View file

@ -462,16 +462,12 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
ty_params: &ast::Generics) { ty_params: &ast::Generics) {
let qualname = format!("::{}", self.tcx.map.path_to_string(item.id)); 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 val = self.span.snippet(item.span);
let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct); let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct);
self.fmt.struct_str(item.span, self.fmt.struct_str(item.span,
sub_span, sub_span,
item.id, item.id,
ctor_id, def.id,
&qualname, &qualname,
self.cur_scope, self.cur_scope,
&val); &val);
@ -505,11 +501,10 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
qualname.push_str(name); qualname.push_str(name);
let val = self.span.snippet(variant.span); 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.fmt.struct_variant_str(variant.span,
self.span.span_for_first_ident(variant.span), self.span.span_for_first_ident(variant.span),
variant.node.id, variant.node.id,
ctor_id, variant.node.def.id,
&qualname, &qualname,
&enum_data.qualname, &enum_data.qualname,
&val, &val,

View file

@ -2428,7 +2428,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
hir_map::NodeVariant(ref v) => { hir_map::NodeVariant(ref v) => {
let llfn; 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") ccx.sess().bug("struct variant kind unexpected in get_item_val")
} else { } else {
&v.node.def.fields &v.node.def.fields
@ -2454,12 +2454,12 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
hir_map::NodeStructCtor(struct_def) => { hir_map::NodeStructCtor(struct_def) => {
// Only register the constructor if this is a tuple-like struct. // Only register the constructor if this is a tuple-like struct.
let ctor_id = match struct_def.ctor_id { let ctor_id = match struct_def.kind {
None => { hir::VariantKind::Dict => {
ccx.sess().bug("attempt to register a constructor of \ ccx.sess().bug("attempt to register a constructor of \
a non-tuple-like struct") a non-tuple-like struct")
} }
Some(ctor_id) => ctor_id, _ => struct_def.id,
}; };
let parent = ccx.tcx().map.get_parent(id); let parent = ccx.tcx().map.get_parent(id);
let struct_item = ccx.tcx().map.expect_item(parent); let struct_item = ccx.tcx().map.expect_item(parent);

View file

@ -418,7 +418,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
match map_node { match map_node {
hir_map::NodeVariant(v) => { 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, hir_map::NodeStructCtor(_) => true,
_ => false _ => false

View file

@ -115,12 +115,12 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId)
} }
} }
hir::ItemStruct(ref struct_def, _) => { hir::ItemStruct(ref struct_def, _) => {
match struct_def.ctor_id { match struct_def.kind {
None => ccx.sess().bug("instantiate_inline: called on a \ hir::VariantKind::Dict => ccx.sess().bug("instantiate_inline: called on a \
non-tuple struct"), non-tuple struct"),
Some(ctor_id) => { _ => {
ccx.external().borrow_mut().insert(fn_id, Some(ctor_id)); ccx.external().borrow_mut().insert(fn_id, Some(struct_def.id));
my_id = ctor_id; my_id = struct_def.id;
} }
} }
} }

View file

@ -246,9 +246,11 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
hir_map::NodeStructCtor(struct_def) => { hir_map::NodeStructCtor(struct_def) => {
let d = mk_lldecl(abi::Rust); let d = mk_lldecl(abi::Rust);
attributes::inline(d, attributes::InlineAttr::Hint); 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, base::trans_tuple_struct(ccx,
struct_def.ctor_id.expect("ast-mapped tuple struct \ struct_def.id,
didn't have a ctor id"),
psubsts, psubsts,
d); d);
d d

View file

@ -1014,8 +1014,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
convert_field(ccx, &scheme.generics, &predicates, f, ty_f) convert_field(ccx, &scheme.generics, &predicates, f, ty_f)
} }
if let Some(ctor_id) = struct_def.ctor_id { if struct_def.kind != hir::VariantKind::Dict {
convert_variant_ctor(tcx, ctor_id, variant, scheme, predicates); convert_variant_ctor(tcx, struct_def.id, variant, scheme, predicates);
} }
}, },
hir::ItemTy(_, ref generics) => { hir::ItemTy(_, ref generics) => {

View file

@ -1917,25 +1917,10 @@ pub enum VariantKind {
StructVariant(VariantStruct), StructVariant(VariantStruct),
} }
impl Clean<VariantKind> 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 { 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)) StructVariant(struct_def.clean(cx))
} else if struct_def.fields.is_empty() { } else if struct_def.kind == hir::VariantKind::Unit {
CLikeVariant CLikeVariant
} else { } else {
TupleVariant(struct_def.fields.iter().map(|x| x.node.ty.clean(cx)).collect()) TupleVariant(struct_def.fields.iter().map(|x| x.node.ty.clean(cx)).collect())

View file

@ -235,7 +235,7 @@ pub struct Import {
} }
pub fn struct_type_from_def(sd: &hir::StructDef) -> StructType { 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 // We are in a tuple-struct
match sd.fields.len() { match sd.fields.len() {
0 => Unit, 0 => Unit,

View file

@ -44,7 +44,6 @@ pub use self::TyParamBound::*;
pub use self::UintTy::*; pub use self::UintTy::*;
pub use self::UnOp::*; pub use self::UnOp::*;
pub use self::UnsafeSource::*; pub use self::UnsafeSource::*;
pub use self::VariantKind::*;
pub use self::ViewPath_::*; pub use self::ViewPath_::*;
pub use self::Visibility::*; pub use self::Visibility::*;
pub use self::PathParameters::*; pub use self::PathParameters::*;
@ -1577,14 +1576,6 @@ pub struct VariantArg {
pub id: NodeId, pub id: NodeId,
} }
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum VariantKind {
/// Tuple variant, e.g. `Foo(A, B)`
TupleVariantKind(Vec<VariantArg>),
/// Struct variant, e.g. `Foo {x: A, y: B}`
StructVariantKind(P<StructDef>),
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct EnumDef { pub struct EnumDef {
pub variants: Vec<P<Variant>>, pub variants: Vec<P<Variant>>,
@ -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)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct StructDef { pub struct StructDef {
/// Fields, not including ctor /// Fields, not including ctor
pub fields: Vec<StructField>, pub fields: Vec<StructField>,
/// ID of the constructor. This is only used for tuple- or enum-like /// ID of the constructor. This is only used for tuple- or enum-like
/// structs. /// structs.
pub ctor_id: Option<NodeId>, pub id: NodeId,
pub kind: VariantKind,
} }
/* /*

View file

@ -463,7 +463,7 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
_: &ast::Generics, _: &ast::Generics,
id: NodeId) { id: NodeId) {
self.operation.visit_id(id); 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); 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 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 /// Returns true if the given pattern consists solely of an identifier
/// and false otherwise. /// and false otherwise.
pub fn pat_is_ident(pat: P<ast::Pat>) -> bool { pub fn pat_is_ident(pat: P<ast::Pat>) -> bool {

View file

@ -168,12 +168,13 @@ fn fold_item_underscore<F>(cx: &mut Context<F>, item: ast::Item_) -> ast::Item_
fn fold_struct<F>(cx: &mut Context<F>, def: P<ast::StructDef>) -> P<ast::StructDef> where fn fold_struct<F>(cx: &mut Context<F>, def: P<ast::StructDef>) -> P<ast::StructDef> where
F: FnMut(&[ast::Attribute]) -> bool F: FnMut(&[ast::Attribute]) -> bool
{ {
def.map(|ast::StructDef { fields, ctor_id }| { def.map(|ast::StructDef { fields, id, kind }| {
ast::StructDef { ast::StructDef {
fields: fields.into_iter().filter(|m| { fields: fields.into_iter().filter(|m| {
(cx.in_cfg)(&m.node.attrs) (cx.in_cfg)(&m.node.attrs)
}).collect(), }).collect(),
ctor_id: ctor_id, id: id,
kind: kind,
} }
}) })
} }

View file

@ -993,7 +993,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
} }
fn variant(&self, span: Span, name: Ident, tys: Vec<P<ast::Ty>> ) -> ast::Variant { fn variant(&self, span: Span, name: Ident, tys: Vec<P<ast::Ty>> ) -> ast::Variant {
let fields = tys.into_iter().map(|ty| { let fields: Vec<_> = tys.into_iter().map(|ty| {
Spanned { span: ty.span, node: ast::StructField_ { Spanned { span: ty.span, node: ast::StructField_ {
ty: ty, ty: ty,
kind: ast::UnnamedField(ast::Inherited), kind: ast::UnnamedField(ast::Inherited),
@ -1002,11 +1002,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
}} }}
}).collect(); }).collect();
let kind = if fields.is_empty() { ast::VariantKind::Unit } else { ast::VariantKind::Tuple };
respan(span, respan(span,
ast::Variant_ { ast::Variant_ {
name: name, name: name,
attrs: Vec::new(), 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, id: ast::DUMMY_NODE_ID,
disr_expr: None, disr_expr: None,
}) })

View file

@ -95,7 +95,7 @@ fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure
for variant in &enum_def.variants { for variant in &enum_def.variants {
let def = &variant.node.def; 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 \ cx.span_err(trait_span, "`FromPrimitive` cannot be derived \
for enums with non-unit variants"); for enums with non-unit variants");
return cx.expr_fail(trait_span, return cx.expr_fail(trait_span,

View file

@ -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, self.gate_feature("braced_empty_structs", i.span,
"empty structs with braces are unstable"); "empty structs with braces are unstable");
} }

View file

@ -820,9 +820,10 @@ pub fn noop_fold_where_predicate<T: Folder>(
} }
pub fn noop_fold_struct_def<T: Folder>(struct_def: P<StructDef>, fld: &mut T) -> P<StructDef> { pub fn noop_fold_struct_def<T: Folder>(struct_def: P<StructDef>, fld: &mut T) -> P<StructDef> {
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)), 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,
}) })
} }

View file

@ -45,7 +45,7 @@ use ast::{PatRegion, PatStruct, PatTup, PatVec, PatWild, PatWildMulti};
use ast::PatWildSingle; use ast::PatWildSingle;
use ast::{PolyTraitRef, QSelf}; use ast::{PolyTraitRef, QSelf};
use ast::{Return, BiShl, BiShr, Stmt, StmtDecl}; 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::{BiSub, StrStyle};
use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue}; use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef}; 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 // Otherwise if we look ahead and see a paren we parse a tuple-style
// struct. // 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()); generics.where_clause = try!(self.parse_where_clause());
if try!(self.eat(&token::Semi)) { if try!(self.eat(&token::Semi)) {
// If we see a: `struct Foo<T> where T: Copy;` style decl. // If we see a: `struct Foo<T> where T: Copy;` style decl.
(Vec::new(), Some(ast::DUMMY_NODE_ID)) (Vec::new(), VariantKind::Unit)
} else { } else {
// If we see: `struct Foo<T> where T: Copy { ... }` // If we see: `struct Foo<T> where T: Copy { ... }`
(try!(self.parse_record_struct_body()), None) (try!(self.parse_record_struct_body()), VariantKind::Dict)
} }
// No `where` so: `struct Foo<T>;` // No `where` so: `struct Foo<T>;`
} else if try!(self.eat(&token::Semi) ){ } else if try!(self.eat(&token::Semi) ){
(Vec::new(), Some(ast::DUMMY_NODE_ID)) (Vec::new(), VariantKind::Unit)
// Record-style struct definition // Record-style struct definition
} else if self.token == token::OpenDelim(token::Brace) { } else if self.token == token::OpenDelim(token::Brace) {
let fields = try!(self.parse_record_struct_body()); let fields = try!(self.parse_record_struct_body());
(fields, None) (fields, VariantKind::Dict)
// Tuple-style struct definition with optional where-clause. // Tuple-style struct definition with optional where-clause.
} else if self.token == token::OpenDelim(token::Paren) { } else if self.token == token::OpenDelim(token::Paren) {
let fields = try!(self.parse_tuple_struct_body(class_name, &mut generics)); let fields = try!(self.parse_tuple_struct_body(class_name, &mut generics));
(fields, Some(ast::DUMMY_NODE_ID)) (fields, VariantKind::Tuple)
} else { } else {
let token_str = self.this_token_to_string(); let token_str = self.this_token_to_string();
return Err(self.fatal(&format!("expected `where`, `{{`, `(`, or `;` after struct \ return Err(self.fatal(&format!("expected `where`, `{{`, `(`, or `;` after struct \
@ -4669,7 +4669,8 @@ impl<'a> Parser<'a> {
Ok((class_name, Ok((class_name,
ItemStruct(P(ast::StructDef { ItemStruct(P(ast::StructDef {
fields: fields, fields: fields,
ctor_id: ctor_id, id: ast::DUMMY_NODE_ID,
kind: kind,
}), generics), }), generics),
None)) None))
} }
@ -5118,7 +5119,8 @@ impl<'a> Parser<'a> {
Ok(P(StructDef { Ok(P(StructDef {
fields: fields, 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, 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) ){ } else if try!(self.eat(&token::Eq) ){
disr_expr = Some(try!(self.parse_expr_nopanic())); disr_expr = Some(try!(self.parse_expr_nopanic()));
any_disr = disr_expr.as_ref().map(|expr| expr.span); any_disr = disr_expr.as_ref().map(|expr| expr.span);
struct_def = P(StructDef { fields: Vec::new(), struct_def = P(StructDef { fields: Vec::new(),
ctor_id: Some(ast::DUMMY_NODE_ID) }); id: ast::DUMMY_NODE_ID,
kind: ast::VariantKind::Unit });
} else { } else {
struct_def = P(StructDef { fields: Vec::new(), 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_ { let vr = ast::Variant_ {

View file

@ -1392,8 +1392,8 @@ impl<'a> State<'a> {
print_finalizer: bool) -> io::Result<()> { print_finalizer: bool) -> io::Result<()> {
try!(self.print_ident(ident)); try!(self.print_ident(ident));
try!(self.print_generics(generics)); try!(self.print_generics(generics));
if ast_util::struct_def_is_tuple_like(struct_def) { if struct_def.kind != ast::VariantKind::Dict {
if !struct_def.fields.is_empty() { if struct_def.kind == ast::VariantKind::Tuple {
try!(self.popen()); try!(self.popen());
try!(self.commasep( try!(self.commasep(
Inconsistent, &struct_def.fields, Inconsistent, &struct_def.fields,
@ -3119,7 +3119,9 @@ mod tests {
name: ident, name: ident,
attrs: Vec::new(), attrs: Vec::new(),
// making this up as I go.... ? // 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, id: 0,
disr_expr: None, disr_expr: None,
}); });