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:
parent
b2ae333917
commit
01b5777c8b
@ -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);
|
||||
|
@ -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)]
|
||||
|
@ -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 = "
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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)]});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user