Skip to content

Commit 3b5d92c

Browse files
committed
auto merge of #16953 : nick29581/rust/dst-bug-7, r=pcwalton
Closes #16947 r?
2 parents 821afc4 + 7d72bdb commit 3b5d92c

File tree

3 files changed

+41
-6
lines changed

3 files changed

+41
-6
lines changed

src/librustc/middle/trans/expr.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1859,6 +1859,19 @@ pub fn cast_type_kind(tcx: &ty::ctxt, t: ty::t) -> cast_kind {
18591859
}
18601860
}
18611861

1862+
fn cast_is_noop(t_in: ty::t, t_out: ty::t) -> bool {
1863+
if ty::type_is_boxed(t_in) || ty::type_is_boxed(t_out) {
1864+
return false;
1865+
}
1866+
1867+
match (ty::deref(t_in, true), ty::deref(t_out, true)) {
1868+
(Some(ty::mt{ ty: t_in, .. }), Some(ty::mt{ ty: t_out, .. })) => {
1869+
t_in == t_out
1870+
}
1871+
_ => false
1872+
}
1873+
}
1874+
18621875
fn trans_imm_cast<'a>(bcx: &'a Block<'a>,
18631876
expr: &ast::Expr,
18641877
id: ast::NodeId)
@@ -1877,7 +1890,13 @@ fn trans_imm_cast<'a>(bcx: &'a Block<'a>,
18771890

18781891
// Convert the value to be cast into a ValueRef, either by-ref or
18791892
// by-value as appropriate given its type:
1880-
let datum = unpack_datum!(bcx, trans(bcx, expr));
1893+
let mut datum = unpack_datum!(bcx, trans(bcx, expr));
1894+
1895+
if cast_is_noop(datum.ty, t_out) {
1896+
datum.ty = t_out;
1897+
return DatumBlock::new(bcx, datum);
1898+
}
1899+
18811900
let newval = match (k_in, k_out) {
18821901
(cast_integral, cast_integral) => {
18831902
let llexpr = datum.to_llscalarish(bcx);

src/librustc/middle/typeck/check/mod.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,10 +1502,9 @@ fn check_cast(fcx: &FnCtxt,
15021502
} else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
15031503
fn types_compatible(fcx: &FnCtxt, sp: Span,
15041504
t1: ty::t, t2: ty::t) -> bool {
1505-
if !ty::type_is_vec(t1) {
1506-
// If the type being casted from is not a vector, this special
1507-
// case does not apply.
1508-
return false
1505+
match ty::get(t1).sty {
1506+
ty::ty_vec(_, Some(_)) => {}
1507+
_ => return false
15091508
}
15101509
if ty::type_needs_infer(t2) {
15111510
// This prevents this special case from going off when casting
@@ -1529,7 +1528,7 @@ fn check_cast(fcx: &FnCtxt,
15291528
// need to special-case obtaining an unsafe pointer
15301529
// from a region pointer to a vector.
15311530

1532-
/* this cast is only allowed from &[T] to *T or
1531+
/* this cast is only allowed from &[T, ..n] to *T or
15331532
&T to *T. */
15341533
match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
15351534
(&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),

src/test/run-pass/dst-raw.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ pub fn main() {
5353
assert!(len == 3);
5454
}
5555

56+
// raw slice with explicit cast
57+
let a = &[1i, 2, 3] as *const [_];
58+
unsafe {
59+
let b = (*a)[2];
60+
assert!(b == 3);
61+
let len = (*a).len();
62+
assert!(len == 3);
63+
}
64+
5665
// raw DST struct with slice
5766
let c: *const Foo<[_]> = &Foo {f: [1i, 2, 3]};
5867
unsafe {
@@ -85,6 +94,14 @@ pub fn main() {
8594
assert!(len == 3);
8695
}
8796

97+
let a = &mut [1i, 2, 3] as *mut [_];
98+
unsafe {
99+
let b = (*a)[2];
100+
assert!(b == 3);
101+
let len = (*a).len();
102+
assert!(len == 3);
103+
}
104+
88105
let c: *mut Foo<[_]> = &mut Foo {f: [1i, 2, 3]};
89106
unsafe {
90107
let b = (&*c).f[0];

0 commit comments

Comments
 (0)