Decouple structure kinds from NodeIds
This commit is contained in:
parent
2314ab29c2
commit
495566ee61
29 changed files with 113 additions and 131 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -381,12 +381,8 @@ fn each_auxiliary_node_id<F>(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, _) => {
|
||||
|
|
|
@ -426,7 +426,9 @@ fn find_live(tcx: &ty::ctxt,
|
|||
|
||||
fn get_struct_ctor_id(item: &hir::Item) -> Option<ast::NodeId> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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> {
|
||||
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,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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<VariantArg>),
|
||||
/// Struct variant, e.g. `Foo {x: A, y: B}`
|
||||
StructVariantKind(P<StructDef>),
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct EnumDef {
|
||||
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)]
|
||||
pub struct StructDef {
|
||||
/// Fields, not including ctor
|
||||
pub fields: Vec<StructField>,
|
||||
/// ID of the constructor. This is only used for tuple- or enum-like
|
||||
/// structs.
|
||||
pub ctor_id: Option<NodeId>,
|
||||
pub id: NodeId,
|
||||
pub kind: VariantKind,
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -502,7 +502,12 @@ pub fn lower_where_predicate(_lctx: &LoweringContext,
|
|||
pub fn lower_struct_def(_lctx: &LoweringContext, sd: &StructDef) -> P<hir::StructDef> {
|
||||
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,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<Module>) {
|
||||
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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -1917,25 +1917,10 @@ pub enum VariantKind {
|
|||
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 {
|
||||
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())
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<VariantArg>),
|
||||
/// Struct variant, e.g. `Foo {x: A, y: B}`
|
||||
StructVariantKind(P<StructDef>),
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct EnumDef {
|
||||
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)]
|
||||
pub struct StructDef {
|
||||
/// Fields, not including ctor
|
||||
pub fields: Vec<StructField>,
|
||||
/// ID of the constructor. This is only used for tuple- or enum-like
|
||||
/// structs.
|
||||
pub ctor_id: Option<NodeId>,
|
||||
pub id: NodeId,
|
||||
pub kind: VariantKind,
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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<ast::Pat>) -> bool {
|
||||
|
|
|
@ -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
|
||||
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,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -993,7 +993,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
}
|
||||
|
||||
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_ {
|
||||
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,
|
||||
})
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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<T> where T: Copy;` style decl.
|
||||
(Vec::new(), Some(ast::DUMMY_NODE_ID))
|
||||
(Vec::new(), VariantKind::Unit)
|
||||
} else {
|
||||
// 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>;`
|
||||
} 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_ {
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue