Unify structures and enum variants in HIR

This commit is contained in:
Vadim Petrochenkov 2015-10-02 00:03:22 +03:00
parent ea47c2b6b3
commit 2314ab29c2
17 changed files with 62 additions and 219 deletions

View File

@ -138,22 +138,11 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
NodeVariant(&**v),
DefPathData::EnumVariant(v.node.name));
match v.node.kind {
TupleVariantKind(ref args) => {
for arg in args {
self.create_def_with_parent(Some(variant_def_index),
arg.id,
DefPathData::PositionalField);
}
}
StructVariantKind(ref def) => {
for field in &def.fields {
self.create_def_with_parent(
Some(variant_def_index),
field.node.id,
DefPathData::Field(field.node.kind));
}
}
for field in &v.node.def.fields {
self.create_def_with_parent(
Some(variant_def_index),
field.node.id,
DefPathData::Field(field.node.kind));
}
}
}

View File

@ -475,13 +475,13 @@ impl<'ast> Map<'ast> {
match self.find(id) {
Some(NodeItem(i)) => {
match i.node {
ItemStruct(ref struct_def, _) => &**struct_def,
ItemStruct(ref struct_def, _) => struct_def,
_ => panic!("struct ID bound to non-struct")
}
}
Some(NodeVariant(variant)) => {
match variant.node.kind {
StructVariantKind(ref struct_def) => &**struct_def,
match variant.node.def.ctor_id {
None => &variant.node.def,
_ => panic!("struct ID bound to enum variant that isn't struct-like"),
}
}

View File

@ -435,24 +435,15 @@ pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod { abi, items }: ForeignMod,
}
pub fn noop_fold_variant<T: Folder>(v: P<Variant>, fld: &mut T) -> P<Variant> {
v.map(|Spanned { node: Variant_ { id, name, attrs, kind, disr_expr }, span }| {
Spanned {
node: Variant_ {
id: fld.new_id(id),
name: name,
attrs: fold_attrs(attrs, fld),
kind: match kind {
TupleVariantKind(variant_args) => {
TupleVariantKind(variant_args.move_map(|x| fld.fold_variant_arg(x)))
}
StructVariantKind(struct_def) => {
StructVariantKind(fld.fold_struct_def(struct_def))
}
},
disr_expr: disr_expr.map(|e| fld.fold_expr(e)),
},
span: fld.new_span(span),
}
v.map(|Spanned {node: Variant_ {id, name, attrs, def, disr_expr}, span}| Spanned {
node: Variant_ {
id: fld.new_id(id),
name: name,
attrs: fold_attrs(attrs, fld),
def: fld.fold_struct_def(def),
disr_expr: disr_expr.map(|e| fld.fold_expr(e)),
},
span: fld.new_span(span),
})
}

View File

@ -1038,7 +1038,7 @@ pub struct EnumDef {
pub struct Variant_ {
pub name: Name,
pub attrs: Vec<Attribute>,
pub kind: VariantKind,
pub def: P<StructDef>,
pub id: NodeId,
/// Explicit discriminant, eg `Foo = 1`
pub disr_expr: Option<P<Expr>>,

View File

@ -267,16 +267,8 @@ pub fn lower_variant(_lctx: &LoweringContext, v: &Variant) -> P<hir::Variant> {
id: v.node.id,
name: v.node.name.name,
attrs: v.node.attrs.clone(),
kind: {
if v.node.def.ctor_id.is_none() {
hir::StructVariantKind(lower_struct_def(_lctx, &v.node.def))
} else {
hir::TupleVariantKind(v.node.def.fields.iter().map(|ref field| {
hir::VariantArg { id: field.node.id, ty: lower_ty(_lctx, &field.node.ty) }
}).collect())
}
},
disr_expr: v.node.disr_expr.as_ref().map(|e| lower_expr(_lctx, e)),
def: lower_struct_def(_lctx, &v.node.def),
disr_expr: v.node.disr_expr.as_ref().map(|e| lower_expr(e)),
},
span: v.span,
})

View File

@ -734,7 +734,7 @@ impl<'a> State<'a> {
}
hir::ItemStruct(ref struct_def, ref generics) => {
try!(self.head(&visibility_qualified(item.vis, "struct")));
try!(self.print_struct(&**struct_def, generics, item.name, item.span));
try!(self.print_struct(&**struct_def, generics, item.name, item.span, true));
}
hir::ItemDefaultImpl(unsafety, ref trait_ref) => {
@ -891,7 +891,8 @@ impl<'a> State<'a> {
struct_def: &hir::StructDef,
generics: &hir::Generics,
name: ast::Name,
span: codemap::Span)
span: codemap::Span,
print_finalizer: bool)
-> io::Result<()> {
try!(self.print_name(name));
try!(self.print_generics(generics));
@ -913,7 +914,9 @@ impl<'a> State<'a> {
try!(self.pclose());
}
try!(self.print_where_clause(&generics.where_clause));
try!(word(&mut self.s, ";"));
if print_finalizer {
try!(word(&mut self.s, ";"));
}
try!(self.end());
self.end() // close the outer-box
} else {
@ -943,21 +946,9 @@ impl<'a> State<'a> {
}
pub fn print_variant(&mut self, v: &hir::Variant) -> io::Result<()> {
match v.node.kind {
hir::TupleVariantKind(ref args) => {
try!(self.print_name(v.node.name));
if !args.is_empty() {
try!(self.popen());
try!(self.commasep(Consistent, &args[..], |s, arg| s.print_type(&*arg.ty)));
try!(self.pclose());
}
}
hir::StructVariantKind(ref struct_def) => {
try!(self.head(""));
let generics = ::util::empty_generics();
try!(self.print_struct(&**struct_def, &generics, v.node.name, v.span));
}
}
try!(self.head(""));
let generics = ::util::empty_generics();
try!(self.print_struct(&v.node.def, &generics, v.node.name, v.span, false));
match v.node.disr_expr {
Some(ref d) => {
try!(space(&mut self.s));

View File

@ -333,20 +333,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
variant: &'v Variant,
generics: &'v Generics) {
visitor.visit_name(variant.span, variant.node.name);
match variant.node.kind {
TupleVariantKind(ref variant_arguments) => {
for variant_argument in variant_arguments {
visitor.visit_ty(&variant_argument.ty)
}
}
StructVariantKind(ref struct_definition) => {
visitor.visit_struct_def(struct_definition,
variant.node.name,
generics,
variant.node.id)
}
}
visitor.visit_struct_def(&variant.node.def, variant.node.name, generics, variant.node.id);
walk_list!(visitor, visit_expr, &variant.node.disr_expr);
walk_list!(visitor, visit_attribute, &variant.node.attrs);
}

View File

@ -49,8 +49,6 @@ use rustc_front::hir::{ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaul
use rustc_front::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
use rustc_front::hir::{NamedField, PathListIdent, PathListMod, Public};
use rustc_front::hir::StmtDecl;
use rustc_front::hir::StructVariantKind;
use rustc_front::hir::TupleVariantKind;
use rustc_front::hir::UnnamedField;
use rustc_front::hir::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
use rustc_front::hir::Visibility;
@ -589,9 +587,9 @@ 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.kind {
TupleVariantKind(_) => false,
StructVariantKind(_) => {
let is_exported = match variant.node.def.ctor_id {
Some(_) => false,
None => {
// 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());

View File

@ -501,19 +501,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
}
// `visit::walk_variant` without the discriminant expression.
match variant.node.kind {
hir::TupleVariantKind(ref variant_arguments) => {
for variant_argument in variant_arguments {
self.visit_ty(&*variant_argument.ty);
}
}
hir::StructVariantKind(ref struct_definition) => {
self.visit_struct_def(&**struct_definition,
variant.node.name,
generics,
variant.node.id);
}
}
self.visit_struct_def(&variant.node.def, variant.node.name, generics, variant.node.id);
}
fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem) {
execute_callback!(hir_map::Node::NodeForeignItem(foreign_item), self);

View File

@ -2428,13 +2428,12 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
hir_map::NodeVariant(ref v) => {
let llfn;
let args = match v.node.kind {
hir::TupleVariantKind(ref args) => args,
hir::StructVariantKind(_) => {
ccx.sess().bug("struct variant kind unexpected in get_item_val")
}
let fields = if v.node.def.ctor_id.is_none() {
ccx.sess().bug("struct variant kind unexpected in get_item_val")
} else {
&v.node.def.fields
};
assert!(!args.is_empty());
assert!(!fields.is_empty());
let ty = ccx.tcx().node_id_to_type(id);
let parent = ccx.tcx().map.get_parent(id);
let enm = ccx.tcx().map.expect_item(parent);

View File

@ -417,10 +417,9 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
|| "local item should be in ast map".to_string());
match map_node {
hir_map::NodeVariant(v) => match v.node.kind {
hir::TupleVariantKind(ref args) => !args.is_empty(),
_ => false
},
hir_map::NodeVariant(v) => {
v.node.def.ctor_id.is_some() && !v.node.def.fields.is_empty()
}
hir_map::NodeStructCtor(_) => true,
_ => false
}

View File

@ -647,41 +647,7 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
enum_def: &hir::EnumDef)
-> Vec<AdtVariant<'tcx>> {
enum_def.variants.iter()
.map(|variant| {
match variant.node.kind {
hir::TupleVariantKind(ref args) if !args.is_empty() => {
let ctor_ty = fcx.tcx().node_id_to_type(variant.node.id);
// the regions in the argument types come from the
// enum def'n, and hence will all be early bound
let arg_tys = fcx.tcx().no_late_bound_regions(&ctor_ty.fn_args()).unwrap();
AdtVariant {
fields: args.iter().enumerate().map(|(index, arg)| {
let arg_ty = arg_tys[index];
let arg_ty =
fcx.instantiate_type_scheme(variant.span,
&fcx.inh
.infcx
.parameter_environment
.free_substs,
&arg_ty);
AdtField {
ty: arg_ty,
span: arg.ty.span
}
}).collect()
}
}
hir::TupleVariantKind(_) => {
AdtVariant {
fields: Vec::new()
}
}
hir::StructVariantKind(ref struct_def) => {
struct_variant(fcx, &**struct_def)
}
}
})
.map(|variant| struct_variant(fcx, &variant.node.def))
.collect()
}

View File

@ -544,41 +544,7 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
enum_def: &hir::EnumDef)
-> Vec<AdtVariant<'tcx>> {
enum_def.variants.iter()
.map(|variant| {
match variant.node.kind {
hir::TupleVariantKind(ref args) if !args.is_empty() => {
let ctor_ty = fcx.tcx().node_id_to_type(variant.node.id);
// the regions in the argument types come from the
// enum def'n, and hence will all be early bound
let arg_tys = fcx.tcx().no_late_bound_regions(&ctor_ty.fn_args()).unwrap();
AdtVariant {
fields: args.iter().enumerate().map(|(index, arg)| {
let arg_ty = arg_tys[index];
let arg_ty =
fcx.instantiate_type_scheme(variant.span,
&fcx.inh
.infcx
.parameter_environment
.free_substs,
&arg_ty);
AdtField {
ty: arg_ty,
span: arg.ty.span
}
}).collect()
}
}
hir::TupleVariantKind(_) => {
AdtVariant {
fields: Vec::new()
}
}
hir::StructVariantKind(ref struct_def) => {
struct_variant(fcx, &**struct_def)
}
}
})
.map(|variant| struct_variant(fcx, &variant.node.def))
.collect()
}

View File

@ -1065,31 +1065,16 @@ fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
scheme: ty::TypeScheme<'tcx>,
predicates: ty::GenericPredicates<'tcx>,
variants: &[P<hir::Variant>]) {
let tcx = ccx.tcx;
let icx = ccx.icx(&predicates);
// fill the field types
for (variant, ty_variant) in variants.iter().zip(def.variants.iter()) {
match variant.node.kind {
hir::TupleVariantKind(ref args) => {
let rs = ExplicitRscope;
let input_tys: Vec<_> = args.iter().map(|va| icx.to_ty(&rs, &*va.ty)).collect();
for (field, &ty) in ty_variant.fields.iter().zip(input_tys.iter()) {
field.fulfill_ty(ty);
}
}
hir::StructVariantKind(ref struct_def) => {
for (f, ty_f) in struct_def.fields.iter().zip(ty_variant.fields.iter()) {
convert_field(ccx, &scheme.generics, &predicates, f, ty_f)
}
}
};
for (f, ty_f) in variant.node.def.fields.iter().zip(ty_variant.fields.iter()) {
convert_field(ccx, &scheme.generics, &predicates, f, ty_f)
}
// Convert the ctor, if any. This also registers the variant as
// an item.
convert_variant_ctor(
tcx,
ccx.tcx,
variant.node.id,
ty_variant,
scheme.clone(),
@ -1223,25 +1208,7 @@ fn convert_enum_def<'tcx>(tcx: &ty::ctxt<'tcx>,
{
let did = tcx.map.local_def_id(v.node.id);
let name = v.node.name;
match v.node.kind {
hir::TupleVariantKind(ref va) => {
ty::VariantDefData {
did: did,
name: name,
disr_val: disr,
fields: va.iter().map(|&hir::VariantArg { id, .. }| {
ty::FieldDefData::new(
tcx.map.local_def_id(id),
special_idents::unnamed_field.name,
hir::Visibility::Public
)
}).collect()
}
}
hir::StructVariantKind(ref def) => {
convert_struct_variant(tcx, did, name, disr, &def)
}
}
convert_struct_variant(tcx, did, name, disr, &v.node.def)
}
let did = tcx.map.local_def_id(it.id);
let repr_hints = tcx.lookup_repr_hints(did);

View File

@ -1855,7 +1855,7 @@ impl Clean<Item> for doctree::Variant {
stability: self.stab.clean(cx),
def_id: cx.map.local_def_id(self.id),
inner: VariantItem(Variant {
kind: self.kind.clean(cx),
kind: struct_def_to_variant_kind(&self.def, cx),
}),
}
}
@ -1932,6 +1932,16 @@ impl Clean<VariantKind> for hir::VariantKind {
}
}
fn struct_def_to_variant_kind(struct_def: &hir::StructDef, cx: &DocContext) -> VariantKind {
if struct_def.ctor_id.is_none() {
StructVariant(struct_def.clean(cx))
} else if struct_def.fields.is_empty() {
CLikeVariant
} else {
TupleVariant(struct_def.fields.iter().map(|x| x.node.ty.clean(cx)).collect())
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Span {
pub filename: String,

View File

@ -119,7 +119,7 @@ pub struct Enum {
pub struct Variant {
pub name: Name,
pub attrs: Vec<ast::Attribute>,
pub kind: hir::VariantKind,
pub def: P<hir::StructDef>,
pub id: ast::NodeId,
pub stab: Option<attr::Stability>,
pub whence: Span,

View File

@ -113,7 +113,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
attrs: v.node.attrs.clone(),
stab: self.stability(v.node.id),
id: v.node.id,
kind: v.node.kind.clone(),
def: v.node.def.clone(),
whence: v.span,
}).collect(),
vis: it.vis,