prohibit type parameters in native fns and other minor fixes

trans now can safely assert that it never sees a type param
This commit is contained in:
Niko Matsakis 2012-06-01 19:47:04 -07:00
parent b2ae333917
commit 01b5777c8b
10 changed files with 125 additions and 97 deletions

View File

@ -156,7 +156,8 @@ whereupon the caller loses access to it.
"]
fn send<T: send>(ch: chan<T>, -data: T) {
let chan_t(p) = ch;
let res = rustrt::rust_port_id_send(p, data);
let data_ptr = ptr::addr_of(data) as *();
let res = rustrt::rust_port_id_send(p, data_ptr);
if res != 0u unsafe {
// Data sent successfully
unsafe::forget(data);
@ -250,8 +251,7 @@ type port_id = int;
#[abi = "cdecl"]
native mod rustrt {
fn rust_port_id_send<T: send>(target_port: port_id,
data: T) -> libc::uintptr_t;
fn rust_port_id_send(target_port: port_id, data: *()) -> libc::uintptr_t;
fn new_port(unit_sz: libc::size_t) -> *rust_port;
fn del_port(po: *rust_port);

View File

@ -17,9 +17,9 @@ enum type_desc = {
#[abi = "cdecl"]
native mod rustrt {
fn refcount<T>(t: @T) -> libc::intptr_t;
fn refcount(t: *()) -> libc::intptr_t;
fn unsupervise();
fn shape_log_str<T>(t: *sys::type_desc, data: T) -> str;
fn shape_log_str(t: *sys::type_desc, data: *()) -> str;
}
#[abi = "rust-intrinsic"]
@ -62,11 +62,16 @@ fn pref_align_of<T>() -> uint unsafe {
#[doc = "Returns the refcount of a shared box"]
fn refcount<T>(t: @T) -> uint {
ret rustrt::refcount::<T>(t) as uint;
unsafe {
ret rustrt::refcount(unsafe::reinterpret_cast(t)) as uint;
}
}
fn log_str<T>(t: T) -> str {
rustrt::shape_log_str(get_type_desc::<T>(), t)
unsafe {
let data_ptr: *() = unsafe::reinterpret_cast(ptr::addr_of(t));
rustrt::shape_log_str(get_type_desc::<T>(), data_ptr)
}
}
#[cfg(test)]

View File

@ -82,12 +82,12 @@ export extensions;
#[abi = "cdecl"]
native mod rustrt {
fn vec_reserve_shared<T>(t: *sys::type_desc,
&v: [const T],
n: libc::size_t);
fn vec_from_buf_shared<T>(t: *sys::type_desc,
ptr: *T,
count: libc::size_t) -> [T];
fn vec_reserve_shared(++t: *sys::type_desc,
++v: **unsafe::vec_repr,
++n: libc::size_t);
fn vec_from_buf_shared(++t: *sys::type_desc,
++ptr: *(),
++count: libc::size_t) -> *unsafe::vec_repr;
}
#[doc = "A function used to initialize the elements of a vector"]
@ -122,7 +122,8 @@ capacity, then no action is taken.
fn reserve<T>(&v: [const T], n: uint) {
// Only make the (slow) call into the runtime if we have to
if capacity(v) < n {
rustrt::vec_reserve_shared(sys::get_type_desc::<T>(), v, n);
let ptr = ptr::addr_of(v) as **unsafe::vec_repr;
rustrt::vec_reserve_shared(sys::get_type_desc::<T>(), ptr, n);
}
}
@ -1209,8 +1210,10 @@ mod unsafe {
"]
#[inline(always)]
unsafe fn from_buf<T>(ptr: *T, elts: uint) -> [T] {
ret rustrt::vec_from_buf_shared(sys::get_type_desc::<T>(),
ptr, elts);
ret ::unsafe::reinterpret_cast(
rustrt::vec_from_buf_shared(sys::get_type_desc::<T>(),
ptr as *(),
elts));
}
#[doc = "

View File

@ -1,13 +1,23 @@
#[doc = "Unsafe debugging functions for inspecting values."];
import unsafe::reinterpret_cast;
export debug_tydesc;
export debug_opaque;
export debug_box;
export debug_tag;
export debug_fn;
export ptr_cast;
export refcount;
#[abi = "cdecl"]
native mod rustrt {
fn debug_tydesc(td: *sys::type_desc);
fn debug_opaque<T>(td: *sys::type_desc, x: T);
fn debug_box<T>(td: *sys::type_desc, x: @T);
fn debug_tag<T>(td: *sys::type_desc, x: T);
fn debug_fn<T>(td: *sys::type_desc, x: T);
fn debug_ptrcast<T, U>(td: *sys::type_desc, x: @T) -> @U;
fn debug_opaque(td: *sys::type_desc, x: *());
fn debug_box(td: *sys::type_desc, x: *());
fn debug_tag(td: *sys::type_desc, x: *());
fn debug_fn(td: *sys::type_desc, x: *());
fn debug_ptrcast(td: *sys::type_desc, x: *()) -> *();
}
fn debug_tydesc<T>() {
@ -15,23 +25,25 @@ fn debug_tydesc<T>() {
}
fn debug_opaque<T>(x: T) {
rustrt::debug_opaque::<T>(sys::get_type_desc::<T>(), x);
rustrt::debug_opaque(sys::get_type_desc::<T>(), ptr::addr_of(x) as *());
}
fn debug_box<T>(x: @T) {
rustrt::debug_box::<T>(sys::get_type_desc::<T>(), x);
rustrt::debug_box(sys::get_type_desc::<T>(), ptr::addr_of(x) as *());
}
fn debug_tag<T>(x: T) {
rustrt::debug_tag::<T>(sys::get_type_desc::<T>(), x);
rustrt::debug_tag(sys::get_type_desc::<T>(), ptr::addr_of(x) as *());
}
fn debug_fn<T>(x: T) {
rustrt::debug_fn::<T>(sys::get_type_desc::<T>(), x);
rustrt::debug_fn(sys::get_type_desc::<T>(), ptr::addr_of(x) as *());
}
unsafe fn ptr_cast<T, U>(x: @T) -> @U {
ret rustrt::debug_ptrcast::<T, U>(sys::get_type_desc::<T>(), x);
reinterpret_cast(
rustrt::debug_ptrcast(sys::get_type_desc::<T>(),
reinterpret_cast(x)))
}
fn refcount<T>(a: @T) -> uint unsafe {

View File

@ -2850,7 +2850,7 @@ fn trans_loop_body(bcx: block, e: @ast::expr, ret_flag: option<ValueRef>,
ast::expr_loop_body(b@@{node: ast::expr_fn_block(decl, body, cap), _}) {
alt check ty::get(expr_ty(bcx, e)).struct {
ty::ty_fn({proto, _}) {
closure::trans_expr_fn(bcx, proto, decl, body, e.span, b.id,
closure::trans_expr_fn(bcx, proto, decl, body, b.id,
cap, some(ret_flag),
dest)
}
@ -3556,7 +3556,7 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
}
ast::expr_addr_of(_, x) { ret trans_addr_of(bcx, x, dest); }
ast::expr_fn(proto, decl, body, cap_clause) {
ret closure::trans_expr_fn(bcx, proto, decl, body, e.span, e.id,
ret closure::trans_expr_fn(bcx, proto, decl, body, e.id,
cap_clause, none, dest);
}
ast::expr_fn_block(decl, body, cap_clause) {
@ -3564,7 +3564,7 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
ty::ty_fn({proto, _}) {
#debug("translating fn_block %s with type %s",
expr_to_str(e), ty_to_str(tcx, expr_ty(bcx, e)));
ret closure::trans_expr_fn(bcx, proto, decl, body, e.span,
ret closure::trans_expr_fn(bcx, proto, decl, body,
e.id, cap_clause, none, dest);
}
}

View File

@ -380,7 +380,6 @@ fn trans_expr_fn(bcx: block,
proto: ast::proto,
decl: ast::fn_decl,
body: ast::blk,
sp: span,
id: ast::node_id,
cap_clause: ast::capture_clause,
is_loop_body: option<option<ValueRef>>,
@ -393,7 +392,6 @@ fn trans_expr_fn(bcx: block,
let sub_path = bcx.fcx.path + [path_name("anon")];
let s = mangle_internal_name_by_path(ccx, sub_path);
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
register_fn(ccx, sp, sub_path, id);
let trans_closure_env = fn@(ck: ty::closure_kind) -> ValueRef {
let cap_vars = capture::compute_capture_vars(

View File

@ -62,8 +62,6 @@ fn type_of_non_gc_box(cx: @crate_ctxt, t: ty::t) -> TypeRef {
}
fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
assert !ty::type_needs_infer(t);
#debug("type_of %?: %?", t, ty::get(t));
// Check the cache.
@ -133,7 +131,6 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
let sub1 = ty::subst(cx.tcx, substs, sub);
ret T_struct([T_i8(), type_of(cx, sub1)]);
}
ty::ty_param(_, _) { T_typaram(cx.tn) }
ty::ty_type { T_ptr(cx.tydesc_type) }
ty::ty_tup(elts) {
let mut tys = [];
@ -161,6 +158,7 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
}
ty::ty_self { cx.tcx.sess.unimpl("type_of: ty_self"); }
ty::ty_var(_) { cx.tcx.sess.bug("type_of shouldn't see a ty_var"); }
ty::ty_param(*) { cx.tcx.sess.bug("type_of with ty_param"); }
ty::ty_var_integral(_) {
cx.tcx.sess.bug("type_of shouldn't see a ty_var_integral");
}

View File

@ -393,6 +393,23 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
let tpt_ty = ty::node_id_to_type(ccx.tcx, it.id);
check_bounds_are_used(ccx, t.span, tps, rp, tpt_ty);
}
ast::item_native_mod(m) {
if syntax::attr::native_abi(it.attrs) ==
either::right(ast::native_abi_rust_intrinsic) {
for m.items.each { |item|
check_intrinsic_type(ccx, item);
}
} else {
for m.items.each { |item|
let tpt = ty::lookup_item_type(ccx.tcx, local_def(item.id));
if (*tpt.bounds).is_not_empty() {
ccx.tcx.sess.span_err(
item.span,
#fmt["native items may not have type parameters"]);
}
}
}
}
_ {/* nothing to do */ }
}
}
@ -2267,3 +2284,57 @@ fn check_bounds_are_used(ccx: @crate_ctxt,
}
}
fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::native_item) {
fn param(ccx: @crate_ctxt, n: uint) -> ty::t {
ty::mk_param(ccx.tcx, n, local_def(0))
}
fn arg(m: ast::rmode, ty: ty::t) -> ty::arg {
{mode: ast::expl(m), ty: ty}
}
let tcx = ccx.tcx;
let (n_tps, inputs, output) = alt it.ident {
"size_of" |
"pref_align_of" | "min_align_of" { (1u, [], ty::mk_uint(ccx.tcx)) }
"get_tydesc" { (1u, [], ty::mk_nil_ptr(tcx)) }
"init" { (1u, [], param(ccx, 0u)) }
"forget" { (1u, [arg(ast::by_move, param(ccx, 0u))],
ty::mk_nil(tcx)) }
"reinterpret_cast" { (2u, [arg(ast::by_ref, param(ccx, 0u))],
param(ccx, 1u)) }
"addr_of" { (1u, [arg(ast::by_ref, param(ccx, 0u))],
ty::mk_imm_ptr(tcx, param(ccx, 0u))) }
"needs_drop" { (1u, [], ty::mk_bool(tcx)) }
"visit_ty" {
assert ccx.tcx.intrinsic_ifaces.contains_key("ty_visitor");
let (_, visitor_iface) = ccx.tcx.intrinsic_ifaces.get("ty_visitor");
(1u, [arg(ast::by_ref, visitor_iface)], ty::mk_nil(tcx))
}
other {
tcx.sess.span_err(it.span, "unrecognized intrinsic function: `" +
other + "`");
ret;
}
};
let fty = ty::mk_fn(tcx, {purity: ast::impure_fn,
proto: ast::proto_bare,
inputs: inputs, output: output,
ret_style: ast::return_val,
constraints: []});
let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
let i_n_tps = (*i_ty.bounds).len();
if i_n_tps != n_tps {
tcx.sess.span_err(it.span, #fmt("intrinsic has wrong number \
of type parameters. found %u, \
expected %u", i_n_tps, n_tps));
} else {
require_same_types(
tcx, it.span, i_ty.ty, fty,
{|| #fmt["intrinsic has wrong type. \
expected %s",
ty_to_str(ccx.tcx, fty)]});
}
}

View File

@ -301,13 +301,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
let tcx = ccx.tcx;
alt it.node {
// These don't define types.
ast::item_mod(_) {}
ast::item_native_mod(m) {
if syntax::attr::native_abi(it.attrs) ==
either::right(ast::native_abi_rust_intrinsic) {
for m.items.each { |item| check_intrinsic_type(ccx, item); }
}
}
ast::item_native_mod(_) | ast::item_mod(_) {}
ast::item_enum(variants, ty_params, rp) {
let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty);
@ -465,6 +459,7 @@ fn convert_native(ccx: @crate_ctxt, i: @ast::native_item) {
alt i.node {
ast::native_item_fn(_, _) {
write_ty_to_tcx(ccx.tcx, i.id, tpt.ty);
ccx.tcx.tcache.insert(local_def(i.id), tpt);
}
}
}
@ -491,60 +486,6 @@ fn ty_of_ty_method(self: @crate_ctxt,
purity: m.decl.purity, vis: ast::public}
}
fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::native_item) {
fn param(ccx: @crate_ctxt, n: uint) -> ty::t {
ty::mk_param(ccx.tcx, n, local_def(0))
}
fn arg(m: ast::rmode, ty: ty::t) -> ty::arg {
{mode: ast::expl(m), ty: ty}
}
let tcx = ccx.tcx;
let (n_tps, inputs, output) = alt it.ident {
"size_of" |
"pref_align_of" | "min_align_of" { (1u, [], ty::mk_uint(ccx.tcx)) }
"get_tydesc" { (1u, [], ty::mk_nil_ptr(tcx)) }
"init" { (1u, [], param(ccx, 0u)) }
"forget" { (1u, [arg(ast::by_move, param(ccx, 0u))],
ty::mk_nil(tcx)) }
"reinterpret_cast" { (2u, [arg(ast::by_ref, param(ccx, 0u))],
param(ccx, 1u)) }
"addr_of" { (1u, [arg(ast::by_ref, param(ccx, 0u))],
ty::mk_imm_ptr(tcx, param(ccx, 0u))) }
"needs_drop" { (1u, [], ty::mk_bool(tcx)) }
"visit_ty" {
assert ccx.tcx.intrinsic_ifaces.contains_key("ty_visitor");
let (_, visitor_iface) = ccx.tcx.intrinsic_ifaces.get("ty_visitor");
(1u, [arg(ast::by_ref, visitor_iface)], ty::mk_nil(tcx))
}
other {
tcx.sess.span_err(it.span, "unrecognized intrinsic function: `" +
other + "`");
ret;
}
};
let fty = ty::mk_fn(tcx, {purity: ast::impure_fn,
proto: ast::proto_bare,
inputs: inputs, output: output,
ret_style: ast::return_val,
constraints: []});
let i_ty = ty_of_native_item(ccx, it);
let i_n_tps = (*i_ty.bounds).len();
if i_n_tps != n_tps {
tcx.sess.span_err(it.span, #fmt("intrinsic has wrong number \
of type parameters. found %u, \
expected %u", i_n_tps, n_tps));
} else {
require_same_types(
tcx, it.span, i_ty.ty, fty,
{|| #fmt["intrinsic has wrong type. \
expected %s",
ty_to_str(ccx.tcx, fty)]});
}
}
/*
Instantiates the path for the given iface reference, assuming that
it's bound to a valid iface type. Returns the def_id for the defining

View File

@ -81,7 +81,7 @@ mod test_native_items {
#[abi = "cdecl"]
native mod rustrt {
#[cfg(bogus)]
fn vec_from_buf_shared<T>(ptr: *T, count: uint) -> [T];
fn vec_from_buf_shared<T>(ptr: *T, count: uint) -> [T];
fn vec_from_buf_shared();
fn vec_from_buf_shared();
}
}