Skip to content

Commit cb404dd

Browse files
committed
librustc: Emit enum variant constructor at callsite instead of via a call to a function.
1 parent 9c9bdfd commit cb404dd

File tree

2 files changed

+77
-5
lines changed

2 files changed

+77
-5
lines changed

src/librustc/middle/trans/base.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,6 +1704,61 @@ pub fn trans_enum_variant(ccx: &CrateContext,
17041704
llfndecl);
17051705
}
17061706

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

src/librustc/middle/trans/callee.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ pub struct MethodData {
6464
pub enum CalleeData {
6565
Closure(Datum<Lvalue>),
6666

67+
// Constructor for enum variant/tuple-like-struct
68+
// i.e. Some, Ok
69+
TupleVariantConstructor(subst::Substs, ty::Disr),
70+
6771
// Represents a (possibly monomorphized) top-level fn item or method
6872
// item. Note that this is just the fn-ptr and is not a Rust closure
6973
// value (which is a pair).
@@ -158,11 +162,16 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
158162
ref_expr.id))
159163
}
160164
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)))
165+
let vinfo = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
166+
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
167+
168+
// Nullary variants are not callable
169+
assert!(vinfo.args.len() > 0u);
170+
171+
Callee {
172+
bcx: bcx,
173+
data: TupleVariantConstructor(substs, vinfo.disr_val)
174+
}
166175
}
167176
def::DefStruct(def_id) => {
168177
fn_callee(bcx, trans_fn_ref(bcx, def_id, ExprId(ref_expr.id)))
@@ -710,6 +719,14 @@ pub fn trans_call_inner<'a>(
710719
arg_cleanup_scope, args,
711720
dest.unwrap(), substs);
712721
}
722+
TupleVariantConstructor(substs, disr) => {
723+
assert!(dest.is_some());
724+
fcx.pop_custom_cleanup_scope(arg_cleanup_scope);
725+
726+
let ctor_ty = callee_ty.subst(bcx.tcx(), &substs);
727+
return base::trans_enum_variant_constructor(bcx, ctor_ty, disr,
728+
args, dest.unwrap());
729+
}
713730
};
714731

715732
// Intrinsics should not become actual functions.

0 commit comments

Comments
 (0)