Eliminate match checks in trans and typeck

This commit is contained in:
Tim Chevalier 2012-08-23 17:39:07 -07:00
parent 18180fd5da
commit 0dad78e03d
15 changed files with 216 additions and 132 deletions

@ -1 +1 @@
Subproject commit b55be285d18e9b3537fc9d29af44e83be2171326
Subproject commit ab9efdacc290b24955561eda222363217578a908

View file

@ -189,7 +189,7 @@ impl session {
}
// This exists to help with refactoring to eliminate impossible
// cases later on
fn impossible_case(sp: span, msg: ~str) -> ! {
fn impossible_case(sp: span, msg: &str) -> ! {
self.span_bug(sp, #fmt("Impossible case reached: %s", msg));
}
fn ppregions() -> bool { self.debugging_opt(ppregions) }

View file

@ -305,10 +305,10 @@ fn extract_variant_args(bcx: block, pat_id: ast::node_id,
{vals: ~[ValueRef], bcx: block} {
let _icx = bcx.insn_ctxt("alt::extract_variant_args");
let ccx = bcx.fcx.ccx;
let enum_ty_substs = match check ty::get(node_id_type(bcx, pat_id))
let enum_ty_substs = match ty::get(node_id_type(bcx, pat_id))
.struct {
ty::ty_enum(id, substs) => { assert id == vdefs.enm; substs.tps }
_ => bcx.sess().bug(~"extract_variant_args: pattern has non-enum type")
};
let mut blobptr = val;
let variants = ty::enum_variants(ccx.tcx, vdefs.enm);
@ -667,11 +667,13 @@ fn compile_submatch(bcx: block, m: match_, vals: ~[ValueRef],
match kind {
single => Br(bcx, opt_cx.llbb),
switch => {
match check trans_opt(bcx, opt) {
match trans_opt(bcx, opt) {
single_result(r) => {
llvm::LLVMAddCase(sw, r.val, opt_cx.llbb);
bcx = r.bcx;
}
_ => bcx.sess().bug(~"in compile_submatch, expected \
trans_opt to return a single_result")
}
}
compare => {
@ -892,7 +894,8 @@ fn trans_alt_inner(scope_cx: block, expr: @ast::expr, arms: ~[ast::arm],
let arm_dest = dup_for_join(dest);
vec::push(arm_dests, arm_dest);
let mut arm_cx = trans_block(body_cx, a.body, arm_dest);
arm_cx = trans_block_cleanups(arm_cx, body_cx);
arm_cx = trans_block_cleanups(arm_cx,
block_cleanups(body_cx));
vec::push(arm_cxs, arm_cx);
}
}

View file

@ -1962,7 +1962,7 @@ fn trans_if(cx: block, cond: @ast::expr, thn: ast::blk,
let else_cx = scope_block(bcx, els.info(), ~"else");
CondBr(bcx, cond_val, then_cx.llbb, else_cx.llbb);
let then_bcx = trans_block(then_cx, thn, then_dest);
let then_bcx = trans_block_cleanups(then_bcx, then_cx);
let then_bcx = trans_block_cleanups(then_bcx, block_cleanups(then_cx));
// Calling trans_block directly instead of trans_expr
// because trans_expr will create another scope block
// context for the block, but we've already got the
@ -1983,7 +1983,7 @@ fn trans_if(cx: block, cond: @ast::expr, thn: ast::blk,
}
_ => else_cx
};
let else_bcx = trans_block_cleanups(else_bcx, else_cx);
let else_bcx = trans_block_cleanups(else_bcx, block_cleanups(else_cx));
return join_returns(cx,
~[then_bcx, else_bcx], ~[then_dest, else_dest], dest);
}
@ -1998,7 +1998,8 @@ fn trans_while(cx: block, cond: @ast::expr, body: ast::blk)
Br(cx, loop_cx.llbb);
Br(loop_cx, cond_cx.llbb);
let cond_res = trans_temp_expr(cond_cx, cond);
let cond_bcx = trans_block_cleanups(cond_res.bcx, cond_cx);
let cond_bcx = trans_block_cleanups(cond_res.bcx,
block_cleanups(cond_cx));
CondBr(cond_bcx, cond_res.val, body_cx.llbb, next_cx.llbb);
let body_end = trans_block(body_cx, body, ignore);
cleanup_and_Br(body_end, body_cx, cond_cx.llbb);
@ -2113,19 +2114,19 @@ fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t],
_ => ()
}
}
mono_precise(subst, if v.len() > 0u { some(v) } else { none })
(subst, if v.len() > 0u { some(v) } else { none })
})
}
none => {
vec::map(substs, |subst| mono_precise(subst, none))
vec::map(substs, |subst| (subst, none))
}
};
let param_ids = match param_uses {
some(uses) => {
vec::map2(precise_param_ids, uses, |id, uses| {
match check id {
mono_precise(_, some(_)) => id,
mono_precise(subst, none) => {
match id {
(a, b@some(_)) => mono_precise(a, b),
(subst, none) => {
if uses == 0u { mono_any }
else if uses == type_use::use_repr &&
!ty::type_needs_drop(ccx.tcx, subst) {
@ -2137,12 +2138,13 @@ fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t],
if size == 1u && ty::type_is_nil(subst) {
mono_repr(0u, 0u)
} else { mono_repr(size, align) }
} else { id }
} else { mono_precise(subst, none) }
}
}
})
}
none => precise_param_ids
none => precise_param_ids.map(|x| { let (a, b) = x;
mono_precise(a, b) })
};
@{def: item, params: param_ids}
}
@ -2367,7 +2369,7 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
csearch::found_parent(parent_id, ast::ii_item(item)) => {
ccx.external.insert(parent_id, some(item.id));
let mut my_id = 0;
match check item.node {
match item.node {
ast::item_enum(_, _) => {
let vs_here = ty::enum_variants(ccx.tcx, local_def(item.id));
let vs_there = ty::enum_variants(ccx.tcx, parent_id);
@ -2376,6 +2378,8 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
ccx.external.insert(there.id, some(here.id.node));
}
}
_ => ccx.sess.bug(~"maybe_instantiate_inline: item has a \
non-enum parent")
}
trans_item(ccx, *item);
local_def(my_id)
@ -2756,7 +2760,7 @@ fn trans_lval(cx: block, e: @ast::expr) -> lval_result {
let ccx = cx.ccx();
let sub = trans_temp_expr(cx, base);
let t = expr_ty(cx, base);
let val = match check ty::get(t).struct {
let val = match ty::get(t).struct {
ty::ty_box(_) => {
let non_gc_val = non_gc_box_cast(sub.bcx, sub.val);
GEPi(sub.bcx, non_gc_val, ~[0u, abi::box_field_body])
@ -2770,7 +2774,9 @@ fn trans_lval(cx: block, e: @ast::expr) -> lval_result {
let ellty = T_ptr(type_of(ccx, ety));
PointerCast(sub.bcx, sub.val, ellty)
}
ty::ty_ptr(_) | ty::ty_rptr(_,_) => sub.val
ty::ty_ptr(_) | ty::ty_rptr(_,_) => sub.val,
_ => cx.sess().impossible_case(e.span, #fmt("unary operand \
may not have type %s", cx.ty_to_str(t)))
};
return lval_owned(sub.bcx, val);
}
@ -2917,22 +2923,13 @@ fn trans_cast(cx: block, e: @ast::expr, id: ast::node_id,
return store_in_dest(e_res.bcx, newval, dest);
}
fn trans_loop_body(bcx: block, e: @ast::expr, ret_flag: option<ValueRef>,
fn trans_loop_body(bcx: block, id: ast::node_id,
decl: ast::fn_decl, body: ast::blk,
proto: ty::fn_proto, cap: ast::capture_clause,
ret_flag: option<ValueRef>,
dest: dest) -> block {
match check e.node {
ast::expr_loop_body(b@@{
node: ast::expr_fn_block(decl, body, cap),
_
}) => {
match check ty::get(expr_ty(bcx, e)).struct {
ty::ty_fn({proto, _}) => {
closure::trans_expr_fn(bcx, proto, decl, body, b.id,
cap, some(ret_flag),
dest)
}
}
}
}
closure::trans_expr_fn(bcx, proto, decl, body, id,
cap, some(ret_flag), dest)
}
// temp_cleanups: cleanups that should run only if failure occurs before the
@ -2950,12 +2947,21 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
// translate the arg expr as an lvalue
let lv = match ret_flag {
// If there is a ret_flag, this *must* be a loop body
some(_) => match check e.node {
ast::expr_loop_body(blk) => {
some(_) => match e.node {
ast::expr_loop_body(blk@@{node:
ast::expr_fn_block(decl, body, cap),_}) => {
let scratch = alloc_ty(cx, expr_ty(cx, blk));
let bcx = trans_loop_body(cx, e, ret_flag, save_in(scratch));
let proto = match ty::get(expr_ty(cx, e)).struct {
ty::ty_fn({proto, _}) => proto,
_ => cx.sess().impossible_case(e.span, ~"Loop body has \
non-fn ty")
};
let bcx = trans_loop_body(cx, blk.id, decl, body, proto,
cap, ret_flag, save_in(scratch));
{bcx: bcx, val: scratch, kind: lv_temporary}
}
_ => cx.sess().impossible_case(e.span, ~"ret_flag with non-loop-\
body expr")
},
none => {
trans_temp_lval(cx, e)
@ -3462,21 +3468,25 @@ fn trans_tup(bcx: block, elts: ~[@ast::expr], dest: dest) -> block {
fn trans_rec(bcx: block, fields: ~[ast::field],
base: option<@ast::expr>, id: ast::node_id,
dest: dest) -> block {
// none = ignore; some(x) = save_in(x)
dest: option<ValueRef>) -> block {
let _icx = bcx.insn_ctxt("trans_rec");
let t = node_id_type(bcx, id);
let mut bcx = bcx;
let addr = match check dest {
ignore => {
let addr = match dest {
none => {
for vec::each(fields) |fld| {
bcx = trans_expr(bcx, fld.node.expr, ignore);
}
return bcx;
}
save_in(pos) => pos
some(pos) => pos
};
let ty_fields = match check ty::get(t).struct { ty::ty_rec(f) => f };
let ty_fields = match ty::get(t).struct {
ty::ty_rec(f) => f,
_ => bcx.sess().bug(~"trans_rec: record has non-record type")
};
let mut temp_cleanups = ~[];
for fields.each |fld| {
@ -3797,7 +3807,13 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
};
}
ast::expr_rec(args, base) => {
return trans_rec(bcx, args, base, e.id, dest);
let d = match dest {
ignore => none,
save_in(p) => some(p),
_ => bcx.sess().impossible_case(e.span,
"trans_expr::unrooted: can't pass a record by val")
};
return trans_rec(bcx, args, base, e.id, d);
}
ast::expr_struct(_, fields, base) => {
return trans_struct(bcx, e.span, fields, base, e.id, dest);
@ -3849,7 +3865,7 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
dest);
}
ast::expr_fn_block(decl, body, cap_clause) => {
match check ty::get(expr_ty(bcx, e)).struct {
match ty::get(expr_ty(bcx, e)).struct {
ty::ty_fn({proto, _}) => {
debug!("translating fn_block %s with type %s",
expr_to_str(e, tcx.sess.intr()),
@ -3857,10 +3873,25 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
return closure::trans_expr_fn(bcx, proto, decl, body,
e.id, cap_clause, none, dest);
}
_ => bcx.sess().impossible_case(e.span, "fn_block has \
body with a non-fn type")
}
}
ast::expr_loop_body(_) => {
return trans_loop_body(bcx, e, none, dest);
ast::expr_loop_body(blk) => {
match ty::get(expr_ty(bcx, e)).struct {
ty::ty_fn({proto, _}) => {
match blk.node {
ast::expr_fn_block(decl, body, cap) =>
return trans_loop_body(bcx, blk.id, decl, body,
proto, cap, none, dest),
_ => bcx.sess().impossible_case(e.span, "loop_body \
has the wrong kind of contents")
}
}
_ => bcx.sess().impossible_case(e.span, "loop_body has \
body with a non-fn type")
}
}
ast::expr_do_body(blk) => {
return trans_expr(bcx, blk, dest);
@ -4436,19 +4467,18 @@ fn raw_block(fcx: fn_ctxt, is_lpad: bool, llbb: BasicBlockRef) -> block {
// need to make sure those variables go out of scope when the block ends. We
// do that by running a 'cleanup' function for each variable.
// trans_block_cleanups runs all the cleanup functions for the block.
fn trans_block_cleanups(bcx: block, cleanup_cx: block) -> block {
trans_block_cleanups_(bcx, cleanup_cx, false)
fn trans_block_cleanups(bcx: block, +cleanups: ~[cleanup]) -> block {
trans_block_cleanups_(bcx, cleanups, false)
}
fn trans_block_cleanups_(bcx: block, cleanup_cx: block, is_lpad: bool) ->
fn trans_block_cleanups_(bcx: block,
+cleanups: ~[cleanup],
/* cleanup_cx: block, */ is_lpad: bool) ->
block {
let _icx = bcx.insn_ctxt("trans_block_cleanups");
if bcx.unreachable { return bcx; }
let mut bcx = bcx;
match check cleanup_cx.kind {
block_scope({cleanups, _}) => {
let cleanups = copy cleanups;
do vec::riter(cleanups) |cu| {
do vec::riter(cleanups) |cu| {
match cu {
clean(cfn, cleanup_type) | clean_temp(_, cfn, cleanup_type) => {
// Some types don't need to be cleaned up during
@ -4458,9 +4488,7 @@ fn trans_block_cleanups_(bcx: block, cleanup_cx: block, is_lpad: bool) ->
}
}
}
}
}
}
}
return bcx;
}
@ -4491,7 +4519,7 @@ fn cleanup_and_leave(bcx: block, upto: option<BasicBlockRef>,
let sub_cx = sub_block(bcx, ~"cleanup");
Br(bcx, sub_cx.llbb);
vec::push(inf.cleanup_paths, {target: leave, dest: sub_cx.llbb});
bcx = trans_block_cleanups_(sub_cx, cur, is_lpad);
bcx = trans_block_cleanups_(sub_cx, block_cleanups(cur), is_lpad);
}
_ => ()
}
@ -4906,8 +4934,9 @@ fn trans_enum_variant(ccx: @crate_ctxt,
// If this argument to this function is a enum, it'll have come in to
// this function as an opaque blob due to the way that type_of()
// works. So we have to cast to the destination's view of the type.
let llarg = match check fcx.llargs.find(va.id) {
some(local_mem(x)) => x
let llarg = match fcx.llargs.find(va.id) {
some(local_mem(x)) => x,
_ => fail ~"trans_enum_variant: how do we know this works?",
};
let arg_ty = arg_tys[i].ty;
memmove_ty(bcx, lldestptr, llarg, arg_ty);
@ -5052,8 +5081,10 @@ fn trans_enum_def(ccx: @crate_ctxt, enum_definition: ast::enum_def,
fn trans_item(ccx: @crate_ctxt, item: ast::item) {
let _icx = ccx.insn_ctxt("trans_item");
let path = match check ccx.tcx.items.get(item.id) {
ast_map::node_item(_, p) => p
let path = match ccx.tcx.items.get(item.id) {
ast_map::node_item(_, p) => p,
// tjc: ?
_ => fail ~"trans_item",
};
match item.node {
ast::item_fn(decl, purity, tps, body) => {
@ -5288,8 +5319,10 @@ fn fill_fn_pair(bcx: block, pair: ValueRef, llfn: ValueRef,
fn item_path(ccx: @crate_ctxt, i: @ast::item) -> path {
vec::append(
*match check ccx.tcx.items.get(i.id) {
ast_map::node_item(_, p) => p
*match ccx.tcx.items.get(i.id) {
ast_map::node_item(_, p) => p,
// separate map for paths?
_ => fail ~"item_path"
},
~[path_name(i.ident)])
}
@ -5340,7 +5373,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
let val = match ccx.tcx.items.get(id) {
ast_map::node_item(i, pth) => {
let my_path = vec::append(*pth, ~[path_name(i.ident)]);
match check i.node {
match i.node {
ast::item_const(_, _) => {
let typ = ty::node_id_to_type(ccx.tcx, i.id);
let s = mangle_exported_name(ccx, my_path, typ);
@ -5359,6 +5392,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
set_inline_hint_if_appr(i.attrs, llfn);
llfn
}
_ => fail ~"get_item_val: weird result in table"
}
}
ast_map::node_trait_method(trait_method, _, pth) => {
@ -5417,10 +5451,11 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
let pth = vec::append(*pth,
~[path_name(enm.ident),
path_name(v.node.name)]);
llfn = match check enm.node {
llfn = match enm.node {
ast::item_enum(_, _) => {
register_fn(ccx, v.span, pth, id)
}
_ => fail ~"node_variant, shouldn't happen"
};
}
ast::struct_variant_kind(_) => {
@ -5733,11 +5768,11 @@ fn crate_ctxt_to_encode_parms(cx: @crate_ctxt)
for cx.exp_map.each |exp_id, defs| {
for defs.each |def| {
if !def.reexp { again; }
let path = match check cx.tcx.items.get(exp_id) {
ast_map::node_export(_, path) => {
ast_map::path_to_str(*path,
cx.sess.parse_sess.interner)
}
let path = match cx.tcx.items.get(exp_id) {
ast_map::node_export(_, path) => {
ast_map::path_to_str(*path, cx.sess.parse_sess.interner)
}
_ => fail ~"reexports"
};
vec::push(reexports, (path, def.id));
}

View file

@ -368,6 +368,13 @@ fn revoke_clean(cx: block, val: ValueRef) {
}
}
fn block_cleanups(bcx: block) -> ~[cleanup] {
match bcx.kind {
block_non_scope => ~[],
block_scope(inf) => inf.cleanups
}
}
enum block_kind {
// A scope at the end of which temporary values created inside of it are
// cleaned up. May correspond to an actual block in the language, but also

View file

@ -399,7 +399,7 @@ fn create_record(cx: @crate_ctxt, t: ty::t, fields: ~[ast::ty_field],
line_from_span(cx.sess.codemap,
span) as int);
for fields.each |field| {
let field_t = ty::get_field(t, field.node.ident).mt.ty;
let field_t = ty::get_field(cx.tcx, t, field.node.ident).mt.ty;
let ty_md = create_ty(cx, field_t, field.node.mt.ty);
let (size, align) = size_and_align_of(cx, field_t);
add_member(scx, cx.sess.str_of(field.node.ident),

View file

@ -925,8 +925,9 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
let tp_sz = shape::llsize_of_real(ccx, lltp_ty),
out_sz = shape::llsize_of_real(ccx, llout_ty);
if tp_sz != out_sz {
let sp = match check ccx.tcx.items.get(option::get(ref_id)) {
ast_map::node_expr(e) => e.span
let sp = match ccx.tcx.items.get(option::get(ref_id)) {
ast_map::node_expr(e) => e.span,
_ => fail ~"reinterpret_cast or forget has non-expr arg"
};
ccx.sess.span_fatal(
sp, fmt!("reinterpret_cast called on types \
@ -981,6 +982,8 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
arg_vals(~[frameaddress_val]), ignore);
}
_ => {
// Could we make this an enum rather than a string? does it get
// checked earlier?
ccx.sess.span_bug(item.span, ~"unknown intrinsic");
}
}
@ -1171,8 +1174,10 @@ fn register_foreign_fn(ccx: @crate_ctxt, sp: span,
fn abi_of_foreign_fn(ccx: @crate_ctxt, i: @ast::foreign_item)
-> ast::foreign_abi {
match attr::first_attr_value_str_by_name(i.attrs, ~"abi") {
none => match check ccx.tcx.items.get(i.id) {
ast_map::node_foreign_item(_, abi, _) => abi
none => match ccx.tcx.items.get(i.id) {
ast_map::node_foreign_item(_, abi, _) => abi,
// ??
_ => fail ~"abi_of_foreign_fn: not foreign"
},
some(_) => match attr::foreign_abi(i.attrs) {
either::Right(abi) => abi,

View file

@ -125,12 +125,14 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id,
}
typeck::method_param({trait_id:trait_id, method_num:off,
param_num:p, bound_num:b}) => {
match check bcx.fcx.param_substs {
match bcx.fcx.param_substs {
some(substs) => {
let vtbl = find_vtable_in_fn_ctxt(substs, p, b);
trans_monomorphized_callee(bcx, callee_id, self, mentry,
trait_id, off, vtbl)
}
// how to get rid of this?
none => fail ~"trans_method_callee: missing param_substs"
}
}
typeck::method_trait(_, off) => {
@ -150,10 +152,11 @@ fn trans_static_method_callee(bcx: block, method_id: ast::def_id,
let ccx = bcx.ccx();
let mname = if method_id.crate == ast::local_crate {
match check bcx.tcx().items.get(method_id.node) {
match bcx.tcx().items.get(method_id.node) {
ast_map::node_trait_method(trait_method, _, _) => {
ast_util::trait_method_to_ty_method(*trait_method).ident
}
_ => fail ~"callee is not a trait method"
}
} else {
let path = csearch::get_item_path(bcx.tcx(), method_id);
@ -200,7 +203,7 @@ fn method_from_methods(ms: ~[@ast::method], name: ast::ident)
fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
name: ast::ident) -> ast::def_id {
if impl_id.crate == ast::local_crate {
match check ccx.tcx.items.get(impl_id.node) {
match ccx.tcx.items.get(impl_id.node) {
ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) => {
method_from_methods(ms, name)
}
@ -208,6 +211,7 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
ast::item_class(struct_def, _), _}, _) => {
method_from_methods(struct_def.methods, name)
}
_ => fail ~"method_with_name"
}
} else {
csearch::get_impl_method(ccx.sess.cstore, impl_id, name)
@ -217,8 +221,9 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
fn method_ty_param_count(ccx: @crate_ctxt, m_id: ast::def_id,
i_id: ast::def_id) -> uint {
if m_id.crate == ast::local_crate {
match check ccx.tcx.items.get(m_id.node) {
match ccx.tcx.items.get(m_id.node) {
ast_map::node_method(m, _, _) => vec::len(m.tps),
_ => fail ~"method_ty_param_count"
}
} else {
csearch::get_type_param_count(ccx.sess.cstore, m_id) -
@ -321,10 +326,11 @@ fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin)
resolve_vtables_in_fn_ctxt(fcx, sub))
}
typeck::vtable_param(n_param, n_bound) => {
match check fcx.param_substs {
match fcx.param_substs {
some(substs) => {
find_vtable_in_fn_ctxt(substs, n_param, n_bound)
}
_ => fail ~"resolve_vtable_in_fn_ctxt: no substs"
}
}
_ => vt
@ -332,7 +338,7 @@ fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin)
}
fn vtable_id(ccx: @crate_ctxt, origin: typeck::vtable_origin) -> mono_id {
match check origin {
match origin {
typeck::vtable_static(impl_id, substs, sub_vtables) => {
make_mono_id(ccx, impl_id, substs,
if (*sub_vtables).len() == 0u { none }
@ -342,6 +348,8 @@ fn vtable_id(ccx: @crate_ctxt, origin: typeck::vtable_origin) -> mono_id {
@{def: trait_id,
params: vec::map(substs, |t| mono_precise(t, none))}
}
// can't this be checked at the callee?
_ => fail ~"vtable_id"
}
}
@ -350,10 +358,11 @@ fn get_vtable(ccx: @crate_ctxt, origin: typeck::vtable_origin)
let hash_id = vtable_id(ccx, origin);
match ccx.vtables.find(hash_id) {
some(val) => val,
none => match check origin {
none => match origin {
typeck::vtable_static(id, substs, sub_vtables) => {
make_impl_vtable(ccx, id, substs, sub_vtables)
}
_ => fail ~"get_vtable: expected a static origin"
}
}
}

View file

@ -95,13 +95,13 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
ty::ty_estr(ty::vstore_uniq) => {
T_unique_ptr(T_unique(cx, T_vec(cx, T_i8())))
}
ty::ty_enum(*) => {
ty::ty_enum(did, substs) => {
// Only create the named struct, but don't fill it in. We
// fill it in *after* placing it into the type cache. This
// avoids creating more than one copy of the enum when one
// of the enum's variants refers to the enum itself.
common::T_named_struct(llvm_type_name(cx, t))
common::T_named_struct(llvm_type_name(cx, an_enum, did, substs.tps))
}
ty::ty_estr(ty::vstore_box) => {
T_box_ptr(T_box(cx, T_vec(cx, T_i8())))
@ -158,12 +158,12 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
T_struct(tys)
}
ty::ty_opaque_closure_ptr(_) => T_opaque_box_ptr(cx),
ty::ty_class(*) => {
ty::ty_class(did, substs) => {
// Only create the named struct, but don't fill it in. We fill it
// in *after* placing it into the type cache. This prevents
// infinite recursion with recursive class types.
common::T_named_struct(llvm_type_name(cx, t))
common::T_named_struct(llvm_type_name(cx, a_class, did, substs.tps))
}
ty::ty_self => cx.tcx.sess.unimpl(~"type_of: ty_self"),
ty::ty_var(_) => cx.tcx.sess.bug(~"type_of with ty_var"),
@ -223,14 +223,18 @@ fn fill_type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t,
common::set_struct_body(llty, lltys);
}
fn llvm_type_name(cx: @crate_ctxt, t: ty::t) -> ~str {
let (name, did, tps) = match check ty::get(t).struct {
ty::ty_enum(did, substs) => (~"enum", did, substs.tps),
ty::ty_class(did, substs) => (~"class", did, substs.tps)
};
// Want refinements! (Or case classes, I guess
enum named_ty { a_class, an_enum }
fn llvm_type_name(cx: @crate_ctxt,
what: named_ty,
did: ast::def_id,
tps: ~[ty::t]
) -> ~str {
let name = match what { a_class => { "~class" } an_enum => { "~enum" } };
return fmt!(
"%s %s[#%d]",
name,
name,
util::ppaux::parameterized(
cx.tcx,
ty::item_path_str(cx.tcx, did),

View file

@ -97,6 +97,7 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
~"visit_tydesc" | ~"forget" | ~"addr_of" => {
0u
}
// would be cool to make these an enum instead of strings!
_ => fail ~"unknown intrinsic in type_use"
};
for uint::range(0u, n_tps) |n| { cx.uses[n] |= flags;}
@ -255,8 +256,8 @@ fn mark_for_expr(cx: ctx, e: @expr) {
}
})
}
expr_match(_, _, _) | expr_block(_) | expr_if(_, _, _) |
expr_while(_, _) | expr_fail(_) | expr_break(_) | expr_again(_) |
expr_match(*) | expr_block(_) | expr_if(*) |
expr_while(*) | expr_fail(_) | expr_break(_) | expr_again(_) |
expr_unary(_, _) | expr_lit(_) | expr_assert(_) |
expr_mac(_) | expr_addr_of(_, _) |
expr_ret(_) | expr_loop(_, _) |

View file

@ -2503,15 +2503,20 @@ fn field_idx(id: ast::ident, fields: ~[field]) -> option<uint> {
return none;
}
fn get_field(rec_ty: t, id: ast::ident) -> field {
match check vec::find(get_fields(rec_ty), |f| f.ident == id) {
some(f) => f
fn get_field(tcx: ctxt, rec_ty: t, id: ast::ident) -> field {
match vec::find(get_fields(rec_ty), |f| f.ident == id) {
some(f) => f,
// Do we only call this when we know the field is legit?
none => fail (#fmt("get_field: ty doesn't have a field %s",
tcx.sess.str_of(id)))
}
}
fn get_fields(rec_ty:t) -> ~[field] {
match check get(rec_ty).struct {
ty_rec(fields) => fields
match get(rec_ty).struct {
ty_rec(fields) => fields,
// Can we check at the caller?
_ => fail ~"get_fields: not a record type"
}
}
@ -2805,6 +2810,9 @@ fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
}
}
/*
Could this return a list of (def_id, substs) pairs?
*/
fn impl_traits(cx: ctxt, id: ast::def_id) -> ~[t] {
if id.crate == ast::local_crate {
debug!("(impl_traits) searching for trait impl %?", id);

View file

@ -177,10 +177,12 @@ fn check_bare_fn(ccx: @crate_ctxt,
id: ast::node_id,
self_info: option<self_info>) {
let fty = ty::node_id_to_type(ccx.tcx, id);
match check ty::get(fty).struct {
match ty::get(fty).struct {
ty::ty_fn(ref fn_ty) => {
check_fn(ccx, self_info, fn_ty, decl, body, false, none)
}
_ => ccx.tcx.sess.impossible_case(body.span,
"check_bare_fn: function type expected")
}
}
@ -803,7 +805,7 @@ fn impl_self_ty(fcx: @fn_ctxt,
let {n_tps, region_param, raw_ty} = if did.crate == ast::local_crate {
let region_param = fcx.tcx().region_paramd_items.find(did.node);
match check tcx.items.find(did.node) {
match tcx.items.find(did.node) {
some(ast_map::node_item(@{node: ast::item_impl(ts, _, st, _),
_}, _)) => {
{n_tps: ts.len(),
@ -1597,7 +1599,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
fcx.write_ty(id, ty::mk_nil(tcx));
bot = !may_break(body);
}
ast::expr_match(discrim, arms, _) => {
ast::expr_match(discrim, arms, mode) => {
bot = alt::check_alt(fcx, expr, discrim, arms);
}
ast::expr_fn(proto, decl, body, cap_clause) => {
@ -1640,7 +1642,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
type");
}
};
match check b.node {
match b.node {
ast::expr_fn_block(decl, body, cap_clause) => {
check_expr_fn(fcx, b, none,
decl, body, true,
@ -1648,14 +1650,17 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b));
capture::check_capture_clause(tcx, b.id, cap_clause);
}
// argh
_ => fail ~"expr_fn_block"
}
let block_ty = structurally_resolved_type(
fcx, expr.span, fcx.node_ty(b.id));
match check ty::get(block_ty).struct {
match ty::get(block_ty).struct {
ty::ty_fn(fty) => {
fcx.write_ty(expr.id, ty::mk_fn(tcx, {output: ty::mk_bool(tcx)
with fty}));
}
_ => fail ~"expected fn type"
}
}
ast::expr_do_body(b) => {
@ -1670,7 +1675,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
passed to a `do` function");
}
};
match check b.node {
match b.node {
ast::expr_fn_block(decl, body, cap_clause) => {
check_expr_fn(fcx, b, none,
decl, body, true,
@ -1678,13 +1683,16 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b));
capture::check_capture_clause(tcx, b.id, cap_clause);
}
// argh
_ => fail ~"expected fn ty"
}
let block_ty = structurally_resolved_type(
fcx, expr.span, fcx.node_ty(b.id));
match check ty::get(block_ty).struct {
match ty::get(block_ty).struct {
ty::ty_fn(fty) => {
fcx.write_ty(expr.id, ty::mk_fn(tcx, fty));
}
_ => fail ~"expected fn ty"
}
}
ast::expr_block(b) => {

View file

@ -222,8 +222,9 @@ struct lookup {
fn report_static_candidate(idx: uint, did: ast::def_id) {
let span = if did.crate == ast::local_crate {
match check self.tcx().items.get(did.node) {
match self.tcx().items.get(did.node) {
ast_map::node_method(m, _, _) => m.span,
_ => fail ~"report_static_candidate: bad item"
}
} else {
self.expr.span
@ -297,8 +298,9 @@ struct lookup {
again; /* ok */
}
ty::bound_trait(bound_t) => {
match check ty::get(bound_t).struct {
ty::ty_trait(i, substs, _) => (i, substs)
match ty::get(bound_t).struct {
ty::ty_trait(i, substs, _) => (i, substs),
_ => fail ~"add_candidates_from_param: non-trait bound"
}
}
};
@ -402,11 +404,12 @@ struct lookup {
}
fn ty_from_did(did: ast::def_id) -> ty::t {
match check ty::get(ty::lookup_item_type(self.tcx(), did).ty).struct {
match ty::get(ty::lookup_item_type(self.tcx(), did).ty).struct {
ty::ty_fn(fty) => {
ty::mk_fn(self.tcx(),
{proto: ty::proto_vstore(ty::vstore_box) with fty})
}
_ => fail ~"ty_from_did: not function ty"
}
/*
if did.crate == ast::local_crate {

View file

@ -15,9 +15,9 @@ fn replace_bound_regions_in_fn_ty(
// Take self_info apart; the self_ty part is the only one we want
// to update here.
let self_ty = match self_info {
some(s) => some(s.self_ty),
none => none
let (self_ty, rebuild_self_info) = match self_info {
some(s) => (some(s.self_ty), |t| some({self_ty: t with s})),
none => (none, |_t| none)
};
let mut all_tys = ty::tys_in_fn_ty(fn_ty);
@ -59,22 +59,15 @@ fn replace_bound_regions_in_fn_ty(
// Glue updated self_ty back together with its original def_id.
let new_self_info = match self_info {
some(s) => {
match t_self {
some(t) => some({self_ty: t with s}),
none => {
tcx.sess.bug(~"unexpected t_self in \
replace_bound_regions_in_fn_ty()");
}
}
},
none => none
let new_self_info: option<self_info> = match t_self {
none => none,
some(t) => rebuild_self_info(t)
};
return {isr: isr,
self_info: new_self_info,
fn_ty: match check ty::get(t_fn).struct { ty::ty_fn(o) => o }};
fn_ty: match ty::get(t_fn).struct { ty::ty_fn(o) => o,
_ => tcx.sess.bug(~"replace_bound_regions_in_fn_ty: impossible")}};
// Takes `isr`, a (possibly empty) mapping from in-scope region

View file

@ -59,8 +59,9 @@ fn fixup_substs(fcx: @fn_ctxt, expr: @ast::expr,
// use a dummy type just to package up the substs that need fixing up
let t = ty::mk_trait(tcx, id, substs, ty::vstore_slice(ty::re_static));
do fixup_ty(fcx, expr, t, is_early).map |t_f| {
match check ty::get(t_f).struct {
match ty::get(t_f).struct {
ty::ty_trait(_, substs_f, _) => substs_f,
_ => fail ~"t_f should be a trait"
}
}
}
@ -88,8 +89,10 @@ fn lookup_vtable(fcx: @fn_ctxt,
let _i = indenter();
let tcx = fcx.ccx.tcx;
let (trait_id, trait_substs) = match check ty::get(trait_ty).struct {
ty::ty_trait(did, substs, _) => (did, substs)
let (trait_id, trait_substs) = match ty::get(trait_ty).struct {
ty::ty_trait(did, substs, _) => (did, substs),
_ => tcx.sess.impossible_case(expr.span, "lookup_vtable: \
don't know how to handle a non-trait ty")
};
let ty = match fixup_ty(fcx, expr, ty, is_early) {
some(ty) => ty,
@ -105,7 +108,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
match ty::get(ty).struct {
ty::ty_param({idx: n, def_id: did}) => {
let mut n_bound = 0u;
let mut n_bound = 0;
for vec::each(*tcx.ty_param_bounds.get(did.node)) |bound| {
match bound {
ty::bound_send | ty::bound_copy | ty::bound_const |
@ -113,7 +116,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
/* ignore */
}
ty::bound_trait(ity) => {
match check ty::get(ity).struct {
match ty::get(ity).struct {
ty::ty_trait(idid, substs, _) => {
if trait_id == idid {
debug!("(checking vtable) @0 relating ty to trait ty
@ -122,6 +125,9 @@ fn lookup_vtable(fcx: @fn_ctxt,
return vtable_param(n, n_bound);
}
}
_ => tcx.sess.impossible_case(expr.span,
"lookup_vtable: in loop, \
don't know how to handle a non-trait ity")
}
n_bound += 1u;
}
@ -277,11 +283,13 @@ fn connect_trait_tps(fcx: @fn_ctxt, expr: @ast::expr, impl_tys: ~[ty::t],
let trait_ty = ty::subst_tps(tcx, impl_tys, ity);
debug!("(connect trait tps) trait type is %?, impl did is %?",
ty::get(trait_ty).struct, impl_did);
match check ty::get(trait_ty).struct {
ty::ty_trait(_, substs, _) => {
match ty::get(trait_ty).struct {
ty::ty_trait(_, substs, _) => {
vec::iter2(substs.tps, trait_tys,
|a, b| demand::suptype(fcx, expr.span, a, b));
}
_ => tcx.sess.impossible_case(expr.span, "connect_trait_tps: \
don't know how to handle a non-trait ty")
}
}