From 01b5777c8b6e4c3f580aa9e256de96b4b4b92739 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 1 Jun 2012 19:47:04 -0700 Subject: [PATCH] prohibit type parameters in native fns and other minor fixes trans now can safely assert that it never sees a type param --- src/libcore/comm.rs | 6 +- src/libcore/sys.rs | 13 +++-- src/libcore/vec.rs | 21 ++++--- src/libstd/dbg.rs | 32 +++++++---- src/rustc/middle/trans/base.rs | 6 +- src/rustc/middle/trans/closure.rs | 2 - src/rustc/middle/trans/type_of.rs | 4 +- src/rustc/middle/typeck/check.rs | 71 ++++++++++++++++++++++++ src/rustc/middle/typeck/collect.rs | 63 +-------------------- src/test/run-pass/conditional-compile.rs | 4 +- 10 files changed, 125 insertions(+), 97 deletions(-) diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs index f91dfa06ff3..88fef46a3eb 100644 --- a/src/libcore/comm.rs +++ b/src/libcore/comm.rs @@ -156,7 +156,8 @@ whereupon the caller loses access to it. "] fn send(ch: chan, -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(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); diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index be3bab6ac2e..93f204cb58f 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -17,9 +17,9 @@ enum type_desc = { #[abi = "cdecl"] native mod rustrt { - fn refcount(t: @T) -> libc::intptr_t; + fn refcount(t: *()) -> libc::intptr_t; fn unsupervise(); - fn shape_log_str(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() -> uint unsafe { #[doc = "Returns the refcount of a shared box"] fn refcount(t: @T) -> uint { - ret rustrt::refcount::(t) as uint; + unsafe { + ret rustrt::refcount(unsafe::reinterpret_cast(t)) as uint; + } } fn log_str(t: T) -> str { - rustrt::shape_log_str(get_type_desc::(), t) + unsafe { + let data_ptr: *() = unsafe::reinterpret_cast(ptr::addr_of(t)); + rustrt::shape_log_str(get_type_desc::(), data_ptr) + } } #[cfg(test)] diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 8613f378d7a..aa823ee8050 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -82,12 +82,12 @@ export extensions; #[abi = "cdecl"] native mod rustrt { - fn vec_reserve_shared(t: *sys::type_desc, - &v: [const T], - n: libc::size_t); - fn vec_from_buf_shared(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(&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::(), v, n); + let ptr = ptr::addr_of(v) as **unsafe::vec_repr; + rustrt::vec_reserve_shared(sys::get_type_desc::(), ptr, n); } } @@ -1209,8 +1210,10 @@ mod unsafe { "] #[inline(always)] unsafe fn from_buf(ptr: *T, elts: uint) -> [T] { - ret rustrt::vec_from_buf_shared(sys::get_type_desc::(), - ptr, elts); + ret ::unsafe::reinterpret_cast( + rustrt::vec_from_buf_shared(sys::get_type_desc::(), + ptr as *(), + elts)); } #[doc = " diff --git a/src/libstd/dbg.rs b/src/libstd/dbg.rs index 5278caf867e..6b8a4f36002 100644 --- a/src/libstd/dbg.rs +++ b/src/libstd/dbg.rs @@ -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(td: *sys::type_desc, x: T); - fn debug_box(td: *sys::type_desc, x: @T); - fn debug_tag(td: *sys::type_desc, x: T); - fn debug_fn(td: *sys::type_desc, x: T); - fn debug_ptrcast(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() { @@ -15,23 +25,25 @@ fn debug_tydesc() { } fn debug_opaque(x: T) { - rustrt::debug_opaque::(sys::get_type_desc::(), x); + rustrt::debug_opaque(sys::get_type_desc::(), ptr::addr_of(x) as *()); } fn debug_box(x: @T) { - rustrt::debug_box::(sys::get_type_desc::(), x); + rustrt::debug_box(sys::get_type_desc::(), ptr::addr_of(x) as *()); } fn debug_tag(x: T) { - rustrt::debug_tag::(sys::get_type_desc::(), x); + rustrt::debug_tag(sys::get_type_desc::(), ptr::addr_of(x) as *()); } fn debug_fn(x: T) { - rustrt::debug_fn::(sys::get_type_desc::(), x); + rustrt::debug_fn(sys::get_type_desc::(), ptr::addr_of(x) as *()); } unsafe fn ptr_cast(x: @T) -> @U { - ret rustrt::debug_ptrcast::(sys::get_type_desc::(), x); + reinterpret_cast( + rustrt::debug_ptrcast(sys::get_type_desc::(), + reinterpret_cast(x))) } fn refcount(a: @T) -> uint unsafe { diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index df1f21ce735..bc2295d2dbd 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -2850,7 +2850,7 @@ fn trans_loop_body(bcx: block, e: @ast::expr, ret_flag: option, 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); } } diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs index a3b2ab85d58..9057c9ef630 100644 --- a/src/rustc/middle/trans/closure.rs +++ b/src/rustc/middle/trans/closure.rs @@ -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>, @@ -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( diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs index 7ce9b5885b4..e1628a705fb 100644 --- a/src/rustc/middle/trans/type_of.rs +++ b/src/rustc/middle/trans/type_of.rs @@ -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"); } diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index f8c2f1c36eb..2649dc6c675 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -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)]}); + } +} + + diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index 55bdc8cbb37..7087abfcd9e 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -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 diff --git a/src/test/run-pass/conditional-compile.rs b/src/test/run-pass/conditional-compile.rs index a68f83afb04..8f4bd22f75d 100644 --- a/src/test/run-pass/conditional-compile.rs +++ b/src/test/run-pass/conditional-compile.rs @@ -81,7 +81,7 @@ mod test_native_items { #[abi = "cdecl"] native mod rustrt { #[cfg(bogus)] - fn vec_from_buf_shared(ptr: *T, count: uint) -> [T]; - fn vec_from_buf_shared(ptr: *T, count: uint) -> [T]; + fn vec_from_buf_shared(); + fn vec_from_buf_shared(); } }