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:
parent
31c5cec55b
commit
948172b93f
9 changed files with 54 additions and 14 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
fn main() {
|
||||
let x = 3;
|
||||
debug!{"&x=%x", &x as uint};
|
||||
debug!{"&x=%x", ptr::to_uint(&x)};
|
||||
}
|
||||
|
|
@ -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"]
|
||||
|
|
|
|||
5
src/test/run-pass/issue-3091.rs
Normal file
5
src/test/run-pass/issue-3091.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
fn main() {
|
||||
let x = 1;
|
||||
let y = 1;
|
||||
assert &x == &y;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue