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.
This commit is contained in:
Tim Chevalier 2012-08-02 14:23:04 -07:00
parent 31c5cec55b
commit 948172b93f
9 changed files with 54 additions and 14 deletions

View file

@ -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<T>(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<T>(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<T>(thing: &T) -> uint unsafe {
unsafe::reinterpret_cast(thing)
}
trait ptr {
pure fn is_null() -> bool;
pure fn is_not_null() -> bool;

View file

@ -61,7 +61,7 @@ mod linear {
// FIXME(#2979) would allow us to use region type for k
unsafe fn borrow<K>(&&k: K) -> &K {
let p: *K = ptr::addr_of(k);
p as &K
unsafe::reinterpret_cast(p)
}
impl private_methods<K,V> for &const linear_map<K,V> {

View file

@ -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,

View file

@ -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;

View file

@ -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<ast::def_id> { 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 }
}
}

View file

@ -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;
}
}

View file

@ -1,4 +1,4 @@
fn main() {
let x = 3;
debug!{"&x=%x", &x as uint};
debug!{"&x=%x", ptr::to_uint(&x)};
}

View file

@ -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"]

View file

@ -0,0 +1,5 @@
fn main() {
let x = 1;
let y = 1;
assert &x == &y;
}