Skip to content

Commit

Permalink
auto merge of #16953 : nick29581/rust/dst-bug-7, r=pcwalton
Browse files Browse the repository at this point in the history
Closes #16947 

r?
  • Loading branch information
bors committed Sep 3, 2014
2 parents 821afc4 + 7d72bdb commit 3b5d92c
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 6 deletions.
21 changes: 20 additions & 1 deletion src/librustc/middle/trans/expr.rs
Expand Up @@ -1859,6 +1859,19 @@ pub fn cast_type_kind(tcx: &ty::ctxt, t: ty::t) -> cast_kind {
}
}

fn cast_is_noop(t_in: ty::t, t_out: ty::t) -> bool {
if ty::type_is_boxed(t_in) || ty::type_is_boxed(t_out) {
return false;
}

match (ty::deref(t_in, true), ty::deref(t_out, true)) {
(Some(ty::mt{ ty: t_in, .. }), Some(ty::mt{ ty: t_out, .. })) => {
t_in == t_out
}
_ => false
}
}

fn trans_imm_cast<'a>(bcx: &'a Block<'a>,
expr: &ast::Expr,
id: ast::NodeId)
Expand All @@ -1877,7 +1890,13 @@ fn trans_imm_cast<'a>(bcx: &'a Block<'a>,

// Convert the value to be cast into a ValueRef, either by-ref or
// by-value as appropriate given its type:
let datum = unpack_datum!(bcx, trans(bcx, expr));
let mut datum = unpack_datum!(bcx, trans(bcx, expr));

if cast_is_noop(datum.ty, t_out) {
datum.ty = t_out;
return DatumBlock::new(bcx, datum);
}

let newval = match (k_in, k_out) {
(cast_integral, cast_integral) => {
let llexpr = datum.to_llscalarish(bcx);
Expand Down
9 changes: 4 additions & 5 deletions src/librustc/middle/typeck/check/mod.rs
Expand Up @@ -1502,10 +1502,9 @@ fn check_cast(fcx: &FnCtxt,
} else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
fn types_compatible(fcx: &FnCtxt, sp: Span,
t1: ty::t, t2: ty::t) -> bool {
if !ty::type_is_vec(t1) {
// If the type being casted from is not a vector, this special
// case does not apply.
return false
match ty::get(t1).sty {
ty::ty_vec(_, Some(_)) => {}
_ => return false
}
if ty::type_needs_infer(t2) {
// This prevents this special case from going off when casting
Expand All @@ -1529,7 +1528,7 @@ fn check_cast(fcx: &FnCtxt,
// need to special-case obtaining an unsafe pointer
// from a region pointer to a vector.

/* this cast is only allowed from &[T] to *T or
/* this cast is only allowed from &[T, ..n] to *T or
&T to *T. */
match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
(&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
Expand Down
17 changes: 17 additions & 0 deletions src/test/run-pass/dst-raw.rs
Expand Up @@ -53,6 +53,15 @@ pub fn main() {
assert!(len == 3);
}

// raw slice with explicit cast
let a = &[1i, 2, 3] as *const [_];
unsafe {
let b = (*a)[2];
assert!(b == 3);
let len = (*a).len();
assert!(len == 3);
}

// raw DST struct with slice
let c: *const Foo<[_]> = &Foo {f: [1i, 2, 3]};
unsafe {
Expand Down Expand Up @@ -85,6 +94,14 @@ pub fn main() {
assert!(len == 3);
}

let a = &mut [1i, 2, 3] as *mut [_];
unsafe {
let b = (*a)[2];
assert!(b == 3);
let len = (*a).len();
assert!(len == 3);
}

let c: *mut Foo<[_]> = &mut Foo {f: [1i, 2, 3]};
unsafe {
let b = (&*c).f[0];
Expand Down

0 comments on commit 3b5d92c

Please sign in to comment.