From 948172b93fc5d31b7234ad98ff6bac466401a86a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 2 Aug 2012 14:23:04 -0700 Subject: [PATCH] Make comparisons between region pointers work Region pointers were considered a scalar type, so compare_scalar_type would get called to compare region pointers in trans. This would fail, since compare_scalar_type has no case for region pointers. Changed type_is_scalar to return false for region pointers. This had the side effect of breaking casts to types of the form &T. To ameliorate that, I added library functions ptr::assimilate (taking a &T to a *T) and ptr::to_uint (taking a &T to a uint), both of which use reinterpret_cast. While I was at it, I removed ty::type_has_resources, which is dead code. --- src/libcore/ptr.rs | 26 +++++++++++++++++++ src/libcore/send_map.rs | 2 +- src/libstd/uv_ll.rs | 5 ++-- src/rustc/middle/trans/base.rs | 4 +-- src/rustc/middle/ty.rs | 14 +++++----- .../borrowck-borrow-from-expr-block.rs | 4 ++- src/test/run-pass/cast-region-to-uint.rs | 2 +- src/test/run-pass/issue-2214.rs | 6 ++++- src/test/run-pass/issue-3091.rs | 5 ++++ 9 files changed, 54 insertions(+), 14 deletions(-) create mode 100644 src/test/run-pass/issue-3091.rs diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index d82c46832fe5..d63e1b755c00 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -1,6 +1,7 @@ //! Unsafe pointer utility functions export addr_of; +export assimilate; export mut_addr_of; export offset; export const_offset; @@ -11,6 +12,7 @@ export is_not_null; export memcpy; export memmove; export memset; +export to_uint; export buf_len; export position; export extensions; @@ -124,6 +126,30 @@ unsafe fn memset(dst: *mut T, c: int, count: uint) { libc_::memset(dst as *c_void, c as libc::c_int, n as size_t); } + +/** + Transform a region pointer - &T - to an unsafe pointer - *T. + This is safe, but is implemented with an unsafe block due to + reinterpret_cast. + + ("assimilate" because it makes the pointer forget its region.) +*/ +#[inline(always)] +fn assimilate(thing: &T) -> *T unsafe { + unsafe::reinterpret_cast(thing) +} +/** + Cast a region pointer - &T - to a uint. + This is safe, but is implemented with an unsafe block due to + reinterpret_cast. + + (I couldn't think of a cutesy name for this one.) +*/ +#[inline(always)] +fn to_uint(thing: &T) -> uint unsafe { + unsafe::reinterpret_cast(thing) +} + trait ptr { pure fn is_null() -> bool; pure fn is_not_null() -> bool; diff --git a/src/libcore/send_map.rs b/src/libcore/send_map.rs index df019f573978..f2976e67eebe 100644 --- a/src/libcore/send_map.rs +++ b/src/libcore/send_map.rs @@ -61,7 +61,7 @@ mod linear { // FIXME(#2979) would allow us to use region type for k unsafe fn borrow(&&k: K) -> &K { let p: *K = ptr::addr_of(k); - p as &K + unsafe::reinterpret_cast(p) } impl private_methods for &const linear_map { diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 7b4033d0ff3e..108abace1c97 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -21,6 +21,7 @@ */ import libc::size_t; +import ptr::assimilate; // libuv struct mappings type uv_ip4_addr = { @@ -822,7 +823,7 @@ unsafe fn ip4_name(src: &sockaddr_in) -> ~str { let dst: ~[u8] = ~[0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8]; do vec::as_buf(dst) |dst_buf, size| { - rustrt::rust_uv_ip4_name(src as *sockaddr_in, + rustrt::rust_uv_ip4_name(assimilate(src), dst_buf, size as libc::size_t); // seems that checking the result of uv_ip4_name // doesn't work too well.. @@ -842,7 +843,7 @@ unsafe fn ip6_name(src: &sockaddr_in6) -> ~str { 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, 0u8,0u8,0u8,0u8,0u8,0u8]; do vec::as_buf(dst) |dst_buf, size| { - let src_unsafe_ptr = src as *sockaddr_in6; + let src_unsafe_ptr = assimilate(src); log(debug, fmt!{"val of src *sockaddr_in6: %? sockaddr_in6: %?", src_unsafe_ptr, src}); let result = rustrt::rust_uv_ip6_name(src_unsafe_ptr, diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 78c24cdfdbf7..629f85c1a3c9 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -1347,7 +1347,7 @@ fn copy_val_no_check(bcx: block, action: copy_action, dst: ValueRef, let _icx = bcx.insn_ctxt(~"copy_val_no_check"); let ccx = bcx.ccx(); let mut bcx = bcx; - if ty::type_is_scalar(t) { + if ty::type_is_scalar(t) || ty::type_is_region_ptr(t) { Store(bcx, src, dst); return bcx; } @@ -1379,7 +1379,7 @@ fn move_val(cx: block, action: copy_action, dst: ValueRef, let mut src_val = src.val; let tcx = cx.tcx(); let mut cx = cx; - if ty::type_is_scalar(t) { + if ty::type_is_scalar(t) || ty::type_is_region_ptr(t) { if src.kind == lv_owned { src_val = Load(cx, src_val); } Store(cx, src_val, dst); return cx; diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 07e3897ede87..74dbdd01bd8a 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -101,7 +101,8 @@ export region, bound_region, encl_region; export re_bound, re_free, re_scope, re_static, re_var; export br_self, br_anon, br_named, br_cap_avoid; export get, type_has_params, type_needs_infer, type_has_regions; -export type_has_resources, type_id; +export type_is_region_ptr; +export type_id; export tbox_has_flag; export ty_var_id; export ty_to_def_id; @@ -268,7 +269,6 @@ enum tbox_flag { has_self = 2, needs_infer = 4, has_regions = 8, - has_resources = 16, // a meta-flag: subst may be required if the type has parameters, a self // type, or references bound regions @@ -302,9 +302,6 @@ pure fn type_has_params(t: t) -> bool { tbox_has_flag(get(t), has_params) } pure fn type_has_self(t: t) -> bool { tbox_has_flag(get(t), has_self) } pure fn type_needs_infer(t: t) -> bool { tbox_has_flag(get(t), needs_infer) } pure fn type_has_regions(t: t) -> bool { tbox_has_flag(get(t), has_regions) } -pure fn type_has_resources(t: t) -> bool { - tbox_has_flag(get(t), has_resources) -} pure fn type_def_id(t: t) -> option { get(t).o_def_id } pure fn type_id(t: t) -> uint { get(t).id } @@ -1227,10 +1224,15 @@ pure fn type_is_unique(ty: t) -> bool { } } +/* + A scalar type is one that denotes an atomic datum, with no sub-components. + (A ty_ptr is scalar because it represents a non-managed pointer, so its + contents are abstract to rustc.) +*/ pure fn type_is_scalar(ty: t) -> bool { alt get(ty).struct { ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) | - ty_var_integral(_) | ty_type | ty_ptr(_) | ty_rptr(_, _) { true } + ty_var_integral(_) | ty_type | ty_ptr(_) { true } _ { false } } } diff --git a/src/test/run-pass/borrowck-borrow-from-expr-block.rs b/src/test/run-pass/borrowck-borrow-from-expr-block.rs index 723d0079617a..dd545f29e4b9 100644 --- a/src/test/run-pass/borrowck-borrow-from-expr-block.rs +++ b/src/test/run-pass/borrowck-borrow-from-expr-block.rs @@ -1,3 +1,5 @@ +import ptr::to_uint; + fn borrow(x: &int, f: fn(x: &int)) { f(x) } @@ -6,7 +8,7 @@ fn test1(x: @~int) { // Right now, at least, this induces a copy of the unique pointer: do borrow({*x}) |p| { let x_a = ptr::addr_of(**x); - assert (x_a as uint) != (p as uint); + assert (x_a as uint) != to_uint(p); assert unsafe{*x_a} == *p; } } diff --git a/src/test/run-pass/cast-region-to-uint.rs b/src/test/run-pass/cast-region-to-uint.rs index 7372450f4964..72e16d78511c 100644 --- a/src/test/run-pass/cast-region-to-uint.rs +++ b/src/test/run-pass/cast-region-to-uint.rs @@ -1,4 +1,4 @@ fn main() { let x = 3; - debug!{"&x=%x", &x as uint}; + debug!{"&x=%x", ptr::to_uint(&x)}; } \ No newline at end of file diff --git a/src/test/run-pass/issue-2214.rs b/src/test/run-pass/issue-2214.rs index 1a986fa757ad..7625f2b74e0d 100644 --- a/src/test/run-pass/issue-2214.rs +++ b/src/test/run-pass/issue-2214.rs @@ -1,8 +1,12 @@ import libc::{c_double, c_int}; import f64::*; +fn to_c_int(v: &mut int) -> &mut c_int unsafe { + unsafe::reinterpret_cast(v) +} + fn lgamma(n: c_double, value: &mut int) -> c_double { - return m::lgamma(n, value as &mut c_int); + return m::lgamma(n, to_c_uint(value)); } #[link_name = "m"] diff --git a/src/test/run-pass/issue-3091.rs b/src/test/run-pass/issue-3091.rs new file mode 100644 index 000000000000..f37576cba7b8 --- /dev/null +++ b/src/test/run-pass/issue-3091.rs @@ -0,0 +1,5 @@ +fn main() { + let x = 1; + let y = 1; + assert &x == &y; +}