auto merge of #19568 : barosl/rust/enum-struct-variants-ice, r=alexcrichton

This pull request tries to fix #19340, which states two ICE cases related to enum struct variants.

It is my first attempt to fix the compiler. I found this solution by trial and error, so the method used to fix the issue looks very hacky. Please review it, and direct me to find a better solution.

I'm also to add test cases. Where should I put them? Maybe `src/test/run-pass/issue-19340.rs`?
This commit is contained in:
bors 2014-12-12 09:12:08 +00:00
commit d2e2bd1b44
5 changed files with 92 additions and 16 deletions

View File

@ -683,14 +683,22 @@ pub fn get_enum_variants<'tcx>(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::Nod
let ctor_ty = item_type(ast::DefId { krate: cdata.cnum, node: id},
item, tcx, cdata);
let name = item_name(&*intr, item);
let (ctor_ty, arg_tys) = match ctor_ty.sty {
let (ctor_ty, arg_tys, arg_names) = match ctor_ty.sty {
ty::ty_bare_fn(ref f) =>
(Some(ctor_ty), f.sig.inputs.clone()),
_ => // Nullary or struct enum variant.
(None, get_struct_fields(intr.clone(), cdata, did.node)
(Some(ctor_ty), f.sig.inputs.clone(), None),
_ => { // Nullary or struct enum variant.
let mut arg_names = Vec::new();
let arg_tys = get_struct_fields(intr.clone(), cdata, did.node)
.iter()
.map(|field_ty| get_type(cdata, field_ty.id.node, tcx).ty)
.collect())
.map(|field_ty| {
arg_names.push(ast::Ident::new(field_ty.name));
get_type(cdata, field_ty.id.node, tcx).ty
})
.collect();
let arg_names = if arg_names.len() == 0 { None } else { Some(arg_names) };
(None, arg_tys, arg_names)
}
};
match variant_disr_val(item) {
Some(val) => { disr_val = val; }
@ -700,7 +708,7 @@ pub fn get_enum_variants<'tcx>(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::Nod
disr_val += 1;
Rc::new(ty::VariantInfo {
args: arg_tys,
arg_names: None,
arg_names: arg_names,
ctor_ty: ctor_ty,
name: name,
// I'm not even sure if we encode visibility

View File

@ -346,9 +346,10 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
Rc<LoanPath<'tcx>>)>) {
let parent_ty = parent_lp.to_type();
let add_fragment_sibling_local = |field_name| {
let add_fragment_sibling_local = |field_name, variant_did| {
add_fragment_sibling_core(
this, tcx, gathered_fragments, parent_lp.clone(), mc, field_name, origin_lp);
this, tcx, gathered_fragments, parent_lp.clone(), mc, field_name, origin_lp,
variant_did);
};
match (&parent_ty.sty, enum_variant_info) {
@ -363,7 +364,7 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
for i in range(0, tuple_len) {
if i == tuple_idx { continue }
let field_name = mc::PositionalField(i);
add_fragment_sibling_local(field_name);
add_fragment_sibling_local(field_name, None);
}
}
@ -376,7 +377,7 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
continue;
}
let field_name = mc::NamedField(f.name);
add_fragment_sibling_local(field_name);
add_fragment_sibling_local(field_name, None);
}
}
mc::PositionalField(tuple_idx) => {
@ -385,7 +386,7 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
continue
}
let field_name = mc::PositionalField(i);
add_fragment_sibling_local(field_name);
add_fragment_sibling_local(field_name, None);
}
}
}
@ -414,7 +415,7 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
continue;
}
let field_name = mc::NamedField(variant_arg_ident.name);
add_fragment_sibling_local(field_name);
add_fragment_sibling_local(field_name, Some(variant_info.id));
}
}
mc::PositionalField(tuple_idx) => {
@ -424,7 +425,7 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
continue;
}
let field_name = mc::PositionalField(i);
add_fragment_sibling_local(field_name);
add_fragment_sibling_local(field_name, None);
}
}
}
@ -447,10 +448,11 @@ fn add_fragment_sibling_core<'tcx>(this: &MoveData<'tcx>,
parent: Rc<LoanPath<'tcx>>,
mc: mc::MutabilityCategory,
new_field_name: mc::FieldName,
origin_lp: &Rc<LoanPath<'tcx>>) -> MovePathIndex {
origin_lp: &Rc<LoanPath<'tcx>>,
enum_variant_did: Option<ast::DefId>) -> MovePathIndex {
let opt_variant_did = match parent.kind {
LpDowncast(_, variant_did) => Some(variant_did),
LpVar(..) | LpUpvar(..) | LpExtend(..) => None,
LpVar(..) | LpUpvar(..) | LpExtend(..) => enum_variant_did,
};
let loan_path_elem = LpInterior(mc::InteriorField(new_field_name));

View File

@ -0,0 +1,13 @@
// Copyright 2014 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.
pub enum Homura {
Madoka { name: String },
}

View File

@ -0,0 +1,23 @@
// Copyright 2014 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.
// aux-build:issue-19340-1.rs
extern crate "issue-19340-1" as lib;
use lib::Homura;
fn main() {
let homura = Homura::Madoka { name: "Kaname".into_string() };
match homura {
Homura::Madoka { name } => (),
};
}

View File

@ -0,0 +1,30 @@
// Copyright 2014 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.
enum Homura {
Madoka {
name: String,
age: u32,
},
}
fn main() {
let homura = Homura::Madoka {
name: "Akemi".into_string(),
age: 14,
};
match homura {
Homura::Madoka {
name,
age,
} => (),
};
}