auto merge of #9064 : SiegeLord/rust/external_struct_variants, r=luqmana

Fixes issues #5557 and #8746.

This patch adds an additional family for struct-like variants, and encodes some struct-like aspects of such variants that can then be properly decoded by resolve.

Note that I am not 100% sure how this fix works, but it fixes the issue without breaking any of the tests on my machine.
This commit is contained in:
bors 2013-09-11 14:56:00 -07:00
commit 7f0d261ae2
21 changed files with 128 additions and 64 deletions

View File

@ -115,7 +115,8 @@ enum Family {
Mod, // m
ForeignMod, // n
Enum, // t
Variant, // v
TupleVariant, // v
StructVariant, // V
Impl, // i
Trait, // I
Struct, // S
@ -139,7 +140,8 @@ fn item_family(item: ebml::Doc) -> Family {
'm' => Mod,
'n' => ForeignMod,
't' => Enum,
'v' => Variant,
'v' => TupleVariant,
'V' => StructVariant,
'i' => Impl,
'I' => Trait,
'S' => Struct,
@ -361,9 +363,13 @@ fn item_to_def_like(item: ebml::Doc, did: ast::DefId, cnum: ast::CrateNum)
Type | ForeignType => DlDef(ast::DefTy(did)),
Mod => DlDef(ast::DefMod(did)),
ForeignMod => DlDef(ast::DefForeignMod(did)),
Variant => {
StructVariant => {
let enum_did = item_reqd_and_translated_parent_item(cnum, item);
DlDef(ast::DefVariant(enum_did, did))
DlDef(ast::DefVariant(enum_did, did, true))
}
TupleVariant => {
let enum_did = item_reqd_and_translated_parent_item(cnum, item);
DlDef(ast::DefVariant(enum_did, did, false))
}
Trait => DlDef(ast::DefTrait(did)),
Enum => DlDef(ast::DefTy(did)),
@ -575,8 +581,8 @@ impl<'self> EachItemContext<'self> {
}
ImmStatic | MutStatic | Struct | UnsafeFn | Fn | ForeignFn |
UnsafeStaticMethod | StaticMethod | Type | ForeignType |
Variant | Enum | PublicField | PrivateField |
InheritedField => {}
TupleVariant | StructVariant | Enum | PublicField |
PrivateField | InheritedField => {}
}
}
@ -1268,7 +1274,8 @@ fn item_family_to_str(fam: Family) -> ~str {
Mod => ~"mod",
ForeignMod => ~"foreign mod",
Enum => ~"enum",
Variant => ~"variant",
StructVariant => ~"struct variant",
TupleVariant => ~"tuple variant",
Impl => ~"impl",
Trait => ~"trait",
Struct => ~"struct",

View File

@ -307,6 +307,27 @@ fn encode_parent_item(ebml_w: &mut writer::Encoder, id: DefId) {
ebml_w.end_tag();
}
fn encode_struct_fields(ecx: &EncodeContext,
ebml_w: &mut writer::Encoder,
def: @struct_def) {
for f in def.fields.iter() {
match f.node.kind {
named_field(ident, vis) => {
ebml_w.start_tag(tag_item_field);
encode_struct_field_family(ebml_w, vis);
encode_name(ecx, ebml_w, ident);
encode_def_id(ebml_w, local_def(f.node.id));
ebml_w.end_tag();
}
unnamed_field => {
ebml_w.start_tag(tag_item_unnamed_field);
encode_def_id(ebml_w, local_def(f.node.id));
ebml_w.end_tag();
}
}
}
}
fn encode_enum_variant_info(ecx: &EncodeContext,
ebml_w: &mut writer::Encoder,
id: NodeId,
@ -326,7 +347,10 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
pos: ebml_w.writer.tell()});
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, def_id);
encode_family(ebml_w, 'v');
match variant.node.kind {
ast::tuple_variant_kind(_) => encode_family(ebml_w, 'v'),
ast::struct_variant_kind(_) => encode_family(ebml_w, 'V')
}
encode_name(ecx, ebml_w, variant.node.name);
encode_parent_item(ebml_w, local_def(id));
encode_visibility(ebml_w, variant.node.vis);
@ -336,7 +360,14 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
if args.len() > 0 && generics.ty_params.len() == 0 => {
encode_symbol(ecx, ebml_w, variant.node.id);
}
ast::tuple_variant_kind(_) | ast::struct_variant_kind(_) => {}
ast::tuple_variant_kind(_) => {},
ast::struct_variant_kind(def) => {
let idx = encode_info_for_struct(ecx, ebml_w, path,
def.fields, index);
encode_struct_fields(ecx, ebml_w, def);
let bkts = create_index(idx);
encode_index(ebml_w, bkts, write_i64);
}
}
if vi[i].disr_val != disr_val {
encode_disr_val(ecx, ebml_w, vi[i].disr_val);
@ -986,22 +1017,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
/* Encode def_ids for each field and method
for methods, write all the stuff get_trait_method
needs to know*/
for f in struct_def.fields.iter() {
match f.node.kind {
named_field(ident, vis) => {
ebml_w.start_tag(tag_item_field);
encode_struct_field_family(ebml_w, vis);
encode_name(ecx, ebml_w, ident);
encode_def_id(ebml_w, local_def(f.node.id));
ebml_w.end_tag();
}
unnamed_field => {
ebml_w.start_tag(tag_item_unnamed_field);
encode_def_id(ebml_w, local_def(f.node.id));
ebml_w.end_tag();
}
}
}
encode_struct_fields(ecx, ebml_w, struct_def);
// Encode inherent implementations for this structure.
encode_inherent_implementations(ecx, ebml_w, def_id);

View File

@ -396,8 +396,8 @@ impl tr for ast::Def {
ast::DefStatic(did, m) => { ast::DefStatic(did.tr(xcx), m) }
ast::DefArg(nid, b) => { ast::DefArg(xcx.tr_id(nid), b) }
ast::DefLocal(nid, b) => { ast::DefLocal(xcx.tr_id(nid), b) }
ast::DefVariant(e_did, v_did) => {
ast::DefVariant(e_did.tr(xcx), v_did.tr(xcx))
ast::DefVariant(e_did, v_did, is_s) => {
ast::DefVariant(e_did.tr(xcx), v_did.tr(xcx), is_s)
},
ast::DefTrait(did) => ast::DefTrait(did.tr(xcx)),
ast::DefTy(did) => ast::DefTy(did.tr(xcx)),

View File

@ -149,7 +149,7 @@ pub fn check_expr(v: &mut CheckCrateVisitor,
match def_map.find(&e.id) {
Some(&DefStatic(*)) |
Some(&DefFn(_, _)) |
Some(&DefVariant(_, _)) |
Some(&DefVariant(_, _, _)) |
Some(&DefStruct(_)) => { }
Some(&def) => {

View File

@ -335,7 +335,7 @@ pub fn pat_ctor_id(cx: &MatchCheckCtxt, p: @Pat) -> Option<ctor> {
PatWild => { None }
PatIdent(_, _, _) | PatEnum(_, _) => {
match cx.tcx.def_map.find(&pat.id) {
Some(&DefVariant(_, id)) => Some(variant(id)),
Some(&DefVariant(_, id, _)) => Some(variant(id)),
Some(&DefStatic(did, false)) => {
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
Some(val(eval_const_expr(cx.tcx, const_expr)))
@ -349,7 +349,7 @@ pub fn pat_ctor_id(cx: &MatchCheckCtxt, p: @Pat) -> Option<ctor> {
}
PatStruct(*) => {
match cx.tcx.def_map.find(&pat.id) {
Some(&DefVariant(_, id)) => Some(variant(id)),
Some(&DefVariant(_, id, _)) => Some(variant(id)),
_ => Some(single)
}
}
@ -371,7 +371,7 @@ pub fn is_wild(cx: &MatchCheckCtxt, p: @Pat) -> bool {
PatWild => { true }
PatIdent(_, _, _) => {
match cx.tcx.def_map.find(&pat.id) {
Some(&DefVariant(_, _)) | Some(&DefStatic(*)) => { false }
Some(&DefVariant(_, _, _)) | Some(&DefStatic(*)) => { false }
_ => { true }
}
}
@ -547,7 +547,7 @@ pub fn specialize(cx: &MatchCheckCtxt,
}
PatIdent(_, _, _) => {
match cx.tcx.def_map.find(&pat_id) {
Some(&DefVariant(_, id)) => {
Some(&DefVariant(_, id, _)) => {
if variant(id) == *ctor_id {
Some(r.tail().to_owned())
} else {
@ -639,14 +639,14 @@ pub fn specialize(cx: &MatchCheckCtxt,
None
}
}
DefVariant(_, id) if variant(id) == *ctor_id => {
DefVariant(_, id, _) if variant(id) == *ctor_id => {
let args = match args {
Some(args) => args,
None => vec::from_elem(arity, wild())
};
Some(vec::append(args, r.tail()))
}
DefVariant(_, _) => None,
DefVariant(_, _, _) => None,
DefFn(*) |
DefStruct(*) => {
@ -664,7 +664,7 @@ pub fn specialize(cx: &MatchCheckCtxt,
PatStruct(_, ref flds, _) => {
// Is this a struct or an enum variant?
match cx.tcx.def_map.get_copy(&pat_id) {
DefVariant(_, variant_id) => {
DefVariant(_, variant_id, _) => {
if variant(variant_id) == *ctor_id {
// FIXME #4731: Is this right? --pcw
let args = flds.map(|ty_field| {
@ -835,7 +835,7 @@ pub fn check_fn(v: &mut CheckMatchVisitor,
pub fn is_refutable(cx: &MatchCheckCtxt, pat: &Pat) -> bool {
match cx.tcx.def_map.find(&pat.id) {
Some(&DefVariant(enum_id, _)) => {
Some(&DefVariant(enum_id, _, _)) => {
if ty::enum_variants(cx.tcx, enum_id).len() != 1u {
return true;
}

View File

@ -168,7 +168,7 @@ pub fn classify(e: &Expr,
pub fn lookup_const(tcx: ty::ctxt, e: &Expr) -> Option<@Expr> {
match tcx.def_map.find(&e.id) {
Some(&ast::DefStatic(def_id, false)) => lookup_const_by_id(tcx, def_id),
Some(&ast::DefVariant(enum_def, variant_def)) => lookup_variant_by_id(tcx,
Some(&ast::DefVariant(enum_def, variant_def, _)) => lookup_variant_by_id(tcx,
enum_def,
variant_def),
_ => None

View File

@ -416,7 +416,7 @@ fn is_nullary_variant(cx: Context, ex: @Expr) -> bool {
match ex.node {
ExprPath(_) => {
match cx.tcx.def_map.get_copy(&ex.id) {
DefVariant(edid, vdid) => {
DefVariant(edid, vdid, _) => {
ty::enum_variant_with_id(cx.tcx, edid, vdid).args.is_empty()
}
_ => false

View File

@ -889,7 +889,7 @@ impl mem_categorization_ctxt {
}
ast::PatEnum(_, Some(ref subpats)) => {
match self.tcx.def_map.find(&pat.id) {
Some(&ast::DefVariant(enum_did, _)) => {
Some(&ast::DefVariant(enum_did, _, _)) => {
// variant(x, y, z)
let downcast_cmt = {
@ -1074,7 +1074,7 @@ pub fn field_mutbl(tcx: ty::ctxt,
}
ty::ty_enum(*) => {
match tcx.def_map.get_copy(&node_id) {
ast::DefVariant(_, variant_id) => {
ast::DefVariant(_, variant_id, _) => {
let r = ty::lookup_struct_fields(tcx, variant_id);
for fld in r.iter() {
if fld.ident == f_name {

View File

@ -455,7 +455,7 @@ impl<'self> Visitor<&'self method_map> for PrivacyVisitor {
if id.crate != LOCAL_CRATE ||
!self.privileged_items.iter().any(|x| x == &(id.node)) {
match self.tcx.def_map.get_copy(&expr.id) {
DefVariant(_, variant_id) => {
DefVariant(_, variant_id, _) => {
for field in (*fields).iter() {
debug!("(privacy checking) \
checking field in \
@ -522,7 +522,7 @@ impl<'self> Visitor<&'self method_map> for PrivacyVisitor {
if enum_id.crate != LOCAL_CRATE ||
!self.privileged_items.iter().any(|x| x == &enum_id.node) {
match self.tcx.def_map.find(&pattern.id) {
Some(&DefVariant(_, variant_id)) => {
Some(&DefVariant(_, variant_id, _)) => {
for field in fields.iter() {
debug!("(privacy checking) \
checking field in \

View File

@ -1474,7 +1474,7 @@ impl Resolver {
variant.span);
child.define_value(privacy,
DefVariant(item_id,
local_def(variant.node.id)),
local_def(variant.node.id), false),
variant.span);
}
struct_variant_kind(_) => {
@ -1482,7 +1482,7 @@ impl Resolver {
variant.span);
child.define_type(privacy,
DefVariant(item_id,
local_def(variant.node.id)),
local_def(variant.node.id), true),
variant.span);
self.structs.insert(local_def(variant.node.id));
}
@ -1690,14 +1690,20 @@ impl Resolver {
match def {
DefMod(_) | DefForeignMod(_) => {}
DefVariant(*) => {
DefVariant(_, variant_id, is_struct) => {
debug!("(building reduced graph for external crate) building \
variant %s",
final_ident);
// We assume the parent is visible, or else we wouldn't have seen
// it.
let privacy = variant_visibility_to_privacy(visibility, true);
child_name_bindings.define_value(privacy, def, dummy_sp());
if is_struct {
child_name_bindings.define_type(privacy, def, dummy_sp());
self.structs.insert(variant_id);
}
else {
child_name_bindings.define_value(privacy, def, dummy_sp());
}
}
DefFn(*) | DefStaticMethod(*) | DefStatic(*) => {
debug!("(building reduced graph for external \
@ -4507,7 +4513,7 @@ impl Resolver {
assert!(self.structs.contains(&class_id));
self.record_def(pattern.id, definition);
}
Some(definition @ DefVariant(_, variant_id))
Some(definition @ DefVariant(_, variant_id, _))
if self.structs.contains(&variant_id) => {
self.record_def(pattern.id, definition);
}
@ -5123,7 +5129,7 @@ impl Resolver {
let class_def = DefStruct(class_id);
self.record_def(expr.id, class_def);
}
Some(definition @ DefVariant(_, class_id))
Some(definition @ DefVariant(_, class_id, _))
if self.structs.contains(&class_id) => {
self.record_def(expr.id, definition);
}

View File

@ -347,7 +347,7 @@ fn variant_opt(bcx: @mut Block, pat_id: ast::NodeId)
-> Opt {
let ccx = bcx.ccx();
match ccx.tcx.def_map.get_copy(&pat_id) {
ast::DefVariant(enum_id, var_id) => {
ast::DefVariant(enum_id, var_id, _) => {
let variants = ty::enum_variants(ccx.tcx, enum_id);
for v in (*variants).iter() {
if var_id == v.id {
@ -657,7 +657,7 @@ fn enter_opt<'r>(bcx: @mut Block,
// Look up the struct variant ID.
let struct_id;
match tcx.def_map.get_copy(&p.id) {
ast::DefVariant(_, found_struct_id) => {
ast::DefVariant(_, found_struct_id, _) => {
struct_id = found_struct_id;
}
_ => {
@ -2113,7 +2113,7 @@ fn bind_irrefutable_pat(bcx: @mut Block,
}
ast::PatEnum(_, ref sub_pats) => {
match bcx.tcx().def_map.find(&pat.id) {
Some(&ast::DefVariant(enum_id, var_id)) => {
Some(&ast::DefVariant(enum_id, var_id, _)) => {
let repr = adt::represent_node(bcx, pat.id);
let vinfo = ty::enum_variant_with_id(ccx.tcx,
enum_id,

View File

@ -128,7 +128,7 @@ pub fn trans(bcx: @mut Block, expr: @ast::Expr) -> Callee {
trait_did,
ref_expr.id))
}
ast::DefVariant(tid, vid) => {
ast::DefVariant(tid, vid, _) => {
// nullary variants are not callable
assert!(ty::enum_variant_with_id(bcx.tcx(),
tid,

View File

@ -577,7 +577,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef {
Some(&ast::DefStatic(def_id, false)) => {
get_const_val(cx, def_id)
}
Some(&ast::DefVariant(enum_did, variant_did)) => {
Some(&ast::DefVariant(enum_did, variant_did, _)) => {
let ety = ty::expr_ty(cx.tcx, e);
let repr = adt::represent_type(cx, ety);
let vinfo = ty::enum_variant_with_id(cx.tcx,
@ -604,7 +604,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef {
let arg_vals = args.map(|a| const_expr(cx, *a));
adt::trans_const(cx, repr, 0, arg_vals)
}
Some(&ast::DefVariant(enum_did, variant_did)) => {
Some(&ast::DefVariant(enum_did, variant_did, _)) => {
let ety = ty::expr_ty(cx.tcx, e);
let repr = adt::represent_type(cx, ety);
let vinfo = ty::enum_variant_with_id(cx.tcx,

View File

@ -782,7 +782,7 @@ fn trans_def_dps_unadjusted(bcx: @mut Block, ref_expr: &ast::Expr,
};
match def {
ast::DefVariant(tid, vid) => {
ast::DefVariant(tid, vid, _) => {
let variant_info = ty::enum_variant_with_id(ccx.tcx, tid, vid);
if variant_info.args.len() > 0u {
// N-ary variant.
@ -1140,7 +1140,7 @@ pub fn with_field_tys<R>(tcx: ty::ctxt,
}
Some(node_id) => {
match tcx.def_map.get_copy(&node_id) {
ast::DefVariant(enum_id, variant_id) => {
ast::DefVariant(enum_id, variant_id, _) => {
let variant_info = ty::enum_variant_with_id(
tcx, enum_id, variant_id);
op(variant_info.disr_val,

View File

@ -3630,7 +3630,7 @@ pub fn note_and_explain_type_err(cx: ctxt, err: &type_err) {
pub fn def_has_ty_params(def: ast::Def) -> bool {
match def {
ast::DefFn(_, _) | ast::DefVariant(_, _) | ast::DefStruct(_)
ast::DefFn(_, _) | ast::DefVariant(_, _, _) | ast::DefStruct(_)
=> true,
_ => false
}
@ -3840,7 +3840,6 @@ impl VariantInfo {
pub fn from_ast_variant(cx: ctxt,
ast_variant: &ast::variant,
discriminant: Disr) -> VariantInfo {
let ctor_ty = node_id_to_type(cx, ast_variant.node.id);
match ast_variant.node.kind {

View File

@ -384,7 +384,7 @@ pub fn check_struct_like_enum_variant_pat(pcx: &pat_ctxt,
// Find the variant that was specified.
match tcx.def_map.find(&pat_id) {
Some(&ast::DefVariant(found_enum_id, variant_id))
Some(&ast::DefVariant(found_enum_id, variant_id, _))
if found_enum_id == enum_id => {
// Get the struct fields from this struct-like enum variant.
let class_fields = ty::lookup_struct_fields(tcx, variant_id);

View File

@ -2825,7 +2825,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
check_struct_constructor(fcx, id, expr.span, type_def_id,
*fields, base_expr);
}
Some(&ast::DefVariant(enum_id, variant_id)) => {
Some(&ast::DefVariant(enum_id, variant_id, _)) => {
check_struct_enum_variant(fcx, id, expr.span, enum_id,
variant_id, *fields);
}
@ -3256,7 +3256,7 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt,
return no_params(typ);
}
ast::DefFn(id, _) | ast::DefStaticMethod(id, _, _) |
ast::DefStatic(id, _) | ast::DefVariant(_, id) |
ast::DefStatic(id, _) | ast::DefVariant(_, id, _) |
ast::DefStruct(id) => {
return ty::lookup_item_type(fcx.ccx.tcx, id);
}

View File

@ -233,7 +233,7 @@ pub enum Def {
DefStatic(DefId, bool /* is_mutbl */),
DefArg(NodeId, bool /* is_mutbl */),
DefLocal(NodeId, bool /* is_mutbl */),
DefVariant(DefId /* enum */, DefId /* variant */),
DefVariant(DefId /* enum */, DefId /* variant */, bool /* is_structure */),
DefTy(DefId),
DefTrait(DefId),
DefPrimTy(prim_ty),

View File

@ -52,7 +52,7 @@ pub fn stmt_id(s: &Stmt) -> NodeId {
pub fn variant_def_ids(d: Def) -> Option<(DefId, DefId)> {
match d {
DefVariant(enum_id, var_id) => {
DefVariant(enum_id, var_id, _) => {
Some((enum_id, var_id))
}
_ => None
@ -63,7 +63,7 @@ pub fn def_id_of_def(d: Def) -> DefId {
match d {
DefFn(id, _) | DefStaticMethod(id, _, _) | DefMod(id) |
DefForeignMod(id) | DefStatic(id, _) |
DefVariant(_, id) | DefTy(id) | DefTyParam(id, _) |
DefVariant(_, id, _) | DefTy(id) | DefTyParam(id, _) |
DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _) => {
id
}

View File

@ -0,0 +1,17 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[link(name = "struct_variant_xc_aux",
vers = "0.1")];
#[crate_type = "lib"];
pub enum Enum {
Variant { arg: u8 }
}

View File

@ -0,0 +1,19 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// xfail-fast - check-fast doesn't understand aux-build
// aux-build:struct_variant_xc_aux.rs
extern mod struct_variant_xc_aux;
use struct_variant_xc_aux::Variant;
fn main() {
let _ = Variant { arg: 1 };
}