Skip to content

Commit e0a6e2b

Browse files
committed
auto merge of #15765 : luqmana/rust/iec, r=pcwalton
Fixes #15400.
2 parents f05a2c9 + 61ded48 commit e0a6e2b

File tree

7 files changed

+144
-89
lines changed

7 files changed

+144
-89
lines changed

src/librustc/metadata/encoder.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
314314
ebml_w: &mut Encoder,
315315
id: NodeId,
316316
variants: &[P<Variant>],
317-
index: &mut Vec<entry<i64>>,
318-
generics: &ast::Generics) {
317+
index: &mut Vec<entry<i64>>) {
319318
debug!("encode_enum_variant_info(id={:?})", id);
320319

321320
let mut disr_val = 0;
@@ -343,10 +342,6 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
343342
encode_stability(ebml_w, stab);
344343

345344
match variant.node.kind {
346-
ast::TupleVariantKind(ref args)
347-
if args.len() > 0 && generics.ty_params.len() == 0 => {
348-
encode_symbol(ecx, ebml_w, variant.node.id);
349-
}
350345
ast::TupleVariantKind(_) => {},
351346
ast::StructVariantKind(_) => {
352347
let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
@@ -1019,7 +1014,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
10191014
encode_stability(ebml_w, stab);
10201015
ebml_w.end_tag();
10211016
}
1022-
ItemEnum(ref enum_definition, ref generics) => {
1017+
ItemEnum(ref enum_definition, _) => {
10231018
add_to_index(item, ebml_w, index);
10241019

10251020
ebml_w.start_tag(tag_items_data_item);
@@ -1046,8 +1041,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
10461041
ebml_w,
10471042
item.id,
10481043
(*enum_definition).variants.as_slice(),
1049-
index,
1050-
generics);
1044+
index);
10511045
}
10521046
ItemStruct(struct_def, _) => {
10531047
let fields = ty::lookup_struct_fields(tcx, def_id);

src/librustc/middle/trans/adt.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -674,11 +674,10 @@ pub fn trans_case<'a>(bcx: &'a Block<'a>, r: &Repr, discr: Disr)
674674
}
675675

676676
/**
677-
* Begin initializing a new value of the given case of the given
678-
* representation. The fields, if any, should then be initialized via
679-
* `trans_field_ptr`.
677+
* Set the discriminant for a new value of the given case of the given
678+
* representation.
680679
*/
681-
pub fn trans_start_init(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
680+
pub fn trans_set_discr(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
682681
match *r {
683682
CEnum(ity, min, max) => {
684683
assert_discr_in_range(ity, min, max, discr);

src/librustc/middle/trans/base.rs

+56-52
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ use std::c_str::ToCStr;
8080
use std::cell::{Cell, RefCell};
8181
use std::rc::Rc;
8282
use std::{i8, i16, i32, i64};
83-
use std::gc::Gc;
8483
use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel, Rust, RustCall};
8584
use syntax::abi::{RustIntrinsic, Abi};
8685
use syntax::ast_util::{local_def, is_local};
@@ -1704,6 +1703,59 @@ pub fn trans_enum_variant(ccx: &CrateContext,
17041703
llfndecl);
17051704
}
17061705

1706+
pub fn trans_named_tuple_constructor<'a>(mut bcx: &'a Block<'a>,
1707+
ctor_ty: ty::t,
1708+
disr: ty::Disr,
1709+
args: callee::CallArgs,
1710+
dest: expr::Dest) -> Result<'a> {
1711+
1712+
let ccx = bcx.fcx.ccx;
1713+
let tcx = &ccx.tcx;
1714+
1715+
let result_ty = match ty::get(ctor_ty).sty {
1716+
ty::ty_bare_fn(ref bft) => bft.sig.output,
1717+
_ => ccx.sess().bug(
1718+
format!("trans_enum_variant_constructor: \
1719+
unexpected ctor return type {}",
1720+
ctor_ty.repr(tcx)).as_slice())
1721+
};
1722+
1723+
// Get location to store the result. If the user does not care about
1724+
// the result, just make a stack slot
1725+
let llresult = match dest {
1726+
expr::SaveIn(d) => d,
1727+
expr::Ignore => {
1728+
if !type_is_zero_size(ccx, result_ty) {
1729+
alloc_ty(bcx, result_ty, "constructor_result")
1730+
} else {
1731+
C_undef(type_of::type_of(ccx, result_ty))
1732+
}
1733+
}
1734+
};
1735+
1736+
if !type_is_zero_size(ccx, result_ty) {
1737+
let repr = adt::represent_type(ccx, result_ty);
1738+
1739+
match args {
1740+
callee::ArgExprs(exprs) => {
1741+
let fields = exprs.iter().map(|x| *x).enumerate().collect::<Vec<_>>();
1742+
bcx = expr::trans_adt(bcx, &*repr, disr, fields.as_slice(),
1743+
None, expr::SaveIn(llresult));
1744+
}
1745+
_ => ccx.sess().bug("expected expr as arguments for variant/struct tuple constructor")
1746+
}
1747+
}
1748+
1749+
// If the caller doesn't care about the result
1750+
// drop the temporary we made
1751+
let bcx = match dest {
1752+
expr::SaveIn(_) => bcx,
1753+
expr::Ignore => glue::drop_ty(bcx, llresult, result_ty)
1754+
};
1755+
1756+
Result::new(bcx, llresult)
1757+
}
1758+
17071759
pub fn trans_tuple_struct(ccx: &CrateContext,
17081760
_fields: &[ast::StructField],
17091761
ctor_id: ast::NodeId,
@@ -1746,7 +1798,6 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
17461798

17471799
if !type_is_zero_size(fcx.ccx, result_ty) {
17481800
let repr = adt::represent_type(ccx, result_ty);
1749-
adt::trans_start_init(bcx, &*repr, fcx.llretptr.get().unwrap(), disr);
17501801
for (i, arg_datum) in arg_datums.move_iter().enumerate() {
17511802
let lldestptr = adt::trans_field_ptr(bcx,
17521803
&*repr,
@@ -1755,36 +1806,12 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
17551806
i);
17561807
arg_datum.store_to(bcx, lldestptr);
17571808
}
1809+
adt::trans_set_discr(bcx, &*repr, fcx.llretptr.get().unwrap(), disr);
17581810
}
17591811

17601812
finish_fn(&fcx, bcx, result_ty);
17611813
}
17621814

1763-
fn trans_enum_def(ccx: &CrateContext, enum_definition: &ast::EnumDef,
1764-
sp: Span, id: ast::NodeId, vi: &[Rc<ty::VariantInfo>],
1765-
i: &mut uint) {
1766-
for variant in enum_definition.variants.iter() {
1767-
let disr_val = vi[*i].disr_val;
1768-
*i += 1;
1769-
1770-
match variant.node.kind {
1771-
ast::TupleVariantKind(ref args) if args.len() > 0 => {
1772-
let llfn = get_item_val(ccx, variant.node.id);
1773-
trans_enum_variant(ccx, id, &**variant, args.as_slice(),
1774-
disr_val, &param_substs::empty(), llfn);
1775-
}
1776-
ast::TupleVariantKind(_) => {
1777-
// Nothing to do.
1778-
}
1779-
ast::StructVariantKind(struct_def) => {
1780-
trans_struct_def(ccx, struct_def);
1781-
}
1782-
}
1783-
}
1784-
1785-
enum_variant_size_lint(ccx, enum_definition, sp, id);
1786-
}
1787-
17881815
fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span, id: ast::NodeId) {
17891816
let mut sizes = Vec::new(); // does no allocation if no pushes, thankfully
17901817

@@ -1877,12 +1904,8 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
18771904
ast::ItemMod(ref m) => {
18781905
trans_mod(ccx, m);
18791906
}
1880-
ast::ItemEnum(ref enum_definition, ref generics) => {
1881-
if !generics.is_type_parameterized() {
1882-
let vi = ty::enum_variants(ccx.tcx(), local_def(item.id));
1883-
let mut i = 0;
1884-
trans_enum_def(ccx, enum_definition, item.span, item.id, vi.as_slice(), &mut i);
1885-
}
1907+
ast::ItemEnum(ref enum_definition, _) => {
1908+
enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
18861909
}
18871910
ast::ItemStatic(_, m, ref expr) => {
18881911
// Recurse on the expression to catch items in blocks
@@ -1909,11 +1932,6 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
19091932
ast::ItemForeignMod(ref foreign_mod) => {
19101933
foreign::trans_foreign_mod(ccx, foreign_mod);
19111934
}
1912-
ast::ItemStruct(struct_def, ref generics) => {
1913-
if !generics.is_type_parameterized() {
1914-
trans_struct_def(ccx, struct_def);
1915-
}
1916-
}
19171935
ast::ItemTrait(..) => {
19181936
// Inside of this trait definition, we won't be actually translating any
19191937
// functions, but the trait still needs to be walked. Otherwise default
@@ -1926,20 +1944,6 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
19261944
}
19271945
}
19281946

1929-
pub fn trans_struct_def(ccx: &CrateContext, struct_def: Gc<ast::StructDef>) {
1930-
// If this is a tuple-like struct, translate the constructor.
1931-
match struct_def.ctor_id {
1932-
// We only need to translate a constructor if there are fields;
1933-
// otherwise this is a unit-like struct.
1934-
Some(ctor_id) if struct_def.fields.len() > 0 => {
1935-
let llfndecl = get_item_val(ccx, ctor_id);
1936-
trans_tuple_struct(ccx, struct_def.fields.as_slice(),
1937-
ctor_id, &param_substs::empty(), llfndecl);
1938-
}
1939-
Some(_) | None => {}
1940-
}
1941-
}
1942-
19431947
// Translate a module. Doing this amounts to translating the items in the
19441948
// module; there ends up being no artifact (aside from linkage names) of
19451949
// separate modules in the compiled program. That's because modules exist

src/librustc/middle/trans/callee.rs

+68-9
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use arena::TypedArena;
2020
use back::abi;
2121
use back::link;
22+
use driver::session;
2223
use llvm::{ValueRef, get_param};
2324
use llvm;
2425
use metadata::csearch;
@@ -54,6 +55,7 @@ use util::ppaux::Repr;
5455

5556
use std::gc::Gc;
5657
use syntax::ast;
58+
use syntax::ast_map;
5759
use synabi = syntax::abi;
5860

5961
pub struct MethodData {
@@ -64,6 +66,10 @@ pub struct MethodData {
6466
pub enum CalleeData {
6567
Closure(Datum<Lvalue>),
6668

69+
// Constructor for enum variant/tuple-like-struct
70+
// i.e. Some, Ok
71+
NamedTupleConstructor(subst::Substs, ty::Disr),
72+
6773
// Represents a (possibly monomorphized) top-level fn item or method
6874
// item. Note that this is just the fn-ptr and is not a Rust closure
6975
// value (which is a pair).
@@ -134,6 +140,23 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
134140
debug!("trans_def(def={}, ref_expr={})", def.repr(bcx.tcx()), ref_expr.repr(bcx.tcx()));
135141
let expr_ty = node_id_type(bcx, ref_expr.id);
136142
match def {
143+
def::DefFn(did, _) if {
144+
let def_id = if did.krate != ast::LOCAL_CRATE {
145+
inline::maybe_instantiate_inline(bcx.ccx(), did)
146+
} else {
147+
did
148+
};
149+
match bcx.tcx().map.find(def_id.node) {
150+
Some(ast_map::NodeStructCtor(_)) => true,
151+
_ => false
152+
}
153+
} => {
154+
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
155+
Callee {
156+
bcx: bcx,
157+
data: NamedTupleConstructor(substs, 0)
158+
}
159+
}
137160
def::DefFn(did, _) if match ty::get(expr_ty).sty {
138161
ty::ty_bare_fn(ref f) => f.abi == synabi::RustIntrinsic,
139162
_ => false
@@ -158,14 +181,23 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
158181
ref_expr.id))
159182
}
160183
def::DefVariant(tid, vid, _) => {
161-
// nullary variants are not callable
162-
assert!(ty::enum_variant_with_id(bcx.tcx(),
163-
tid,
164-
vid).args.len() > 0u);
165-
fn_callee(bcx, trans_fn_ref(bcx, vid, ExprId(ref_expr.id)))
184+
let vinfo = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
185+
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
186+
187+
// Nullary variants are not callable
188+
assert!(vinfo.args.len() > 0u);
189+
190+
Callee {
191+
bcx: bcx,
192+
data: NamedTupleConstructor(substs, vinfo.disr_val)
193+
}
166194
}
167-
def::DefStruct(def_id) => {
168-
fn_callee(bcx, trans_fn_ref(bcx, def_id, ExprId(ref_expr.id)))
195+
def::DefStruct(_) => {
196+
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
197+
Callee {
198+
bcx: bcx,
199+
data: NamedTupleConstructor(substs, 0)
200+
}
169201
}
170202
def::DefStatic(..) |
171203
def::DefArg(..) |
@@ -490,8 +522,27 @@ pub fn trans_fn_ref_with_vtables(
490522
}
491523
};
492524

493-
// We must monomorphise if the fn has type parameters or is a default method.
494-
let must_monomorphise = !substs.types.is_empty() || is_default;
525+
// We must monomorphise if the fn has type parameters, is a default method,
526+
// or is a named tuple constructor.
527+
let must_monomorphise = if !substs.types.is_empty() || is_default {
528+
true
529+
} else if def_id.krate == ast::LOCAL_CRATE {
530+
let map_node = session::expect(
531+
ccx.sess(),
532+
tcx.map.find(def_id.node),
533+
|| "local item should be in ast map".to_string());
534+
535+
match map_node {
536+
ast_map::NodeVariant(v) => match v.node.kind {
537+
ast::TupleVariantKind(ref args) => args.len() > 0,
538+
_ => false
539+
},
540+
ast_map::NodeStructCtor(_) => true,
541+
_ => false
542+
}
543+
} else {
544+
false
545+
};
495546

496547
// Create a monomorphic version of generic functions
497548
if must_monomorphise {
@@ -710,6 +761,14 @@ pub fn trans_call_inner<'a>(
710761
arg_cleanup_scope, args,
711762
dest.unwrap(), substs);
712763
}
764+
NamedTupleConstructor(substs, disr) => {
765+
assert!(dest.is_some());
766+
fcx.pop_custom_cleanup_scope(arg_cleanup_scope);
767+
768+
let ctor_ty = callee_ty.subst(bcx.tcx(), &substs);
769+
return base::trans_named_tuple_constructor(bcx, ctor_ty, disr,
770+
args, dest.unwrap());
771+
}
713772
};
714773

715774
// Intrinsics should not become actual functions.

src/librustc/middle/trans/closure.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,6 @@ pub fn trans_unboxed_closure<'a>(
502502
let repr = adt::represent_type(bcx.ccx(), node_id_type(bcx, id));
503503

504504
// Create the closure.
505-
adt::trans_start_init(bcx, &*repr, dest_addr, 0);
506505
for freevar in freevars_ptr.iter() {
507506
let datum = expr::trans_local_var(bcx, freevar.def);
508507
let upvar_slot_dest = adt::trans_field_ptr(bcx,
@@ -512,6 +511,7 @@ pub fn trans_unboxed_closure<'a>(
512511
0);
513512
bcx = datum.store_to(bcx, upvar_slot_dest);
514513
}
514+
adt::trans_set_discr(bcx, &*repr, dest_addr, 0);
515515

516516
bcx
517517
}

0 commit comments

Comments
 (0)