Skip to content

Commit 31d9aee

Browse files
committed
Auto merge of #26394 - arielb1:implement-rfc401-part2, r=nrc
This makes them compliant with the new version of RFC 401 (i.e. RFC 1052). Fixes #26391. I *hope* the tests I have are enough. This is a [breaking-change] r? @nrc
2 parents 4a788a2 + 5133606 commit 31d9aee

File tree

4 files changed

+25
-9
lines changed

4 files changed

+25
-9
lines changed

src/librustc_typeck/check/cast.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@
2727
//!
2828
//! where `&.T` and `*T` are references of either mutability,
2929
//! and where unsize_kind(`T`) is the kind of the unsize info
30-
//! in `T` - a vtable or a length (or `()` if `T: Sized`).
30+
//! in `T` - the vtable for a trait definition (e.g. `fmt::Display` or
31+
//! `Iterator`, not `Iterator<Item=u8>`) or a length (or `()` if `T: Sized`).
32+
//!
33+
//! Note that lengths are not adjusted when casting raw slices -
34+
//! `T: *const [u16] as *const [u8]` creates a slice that only includes
35+
//! half of the original memory.
3136
//!
3237
//! Casting is not transitive, that is, even if `e as U1 as U2` is a valid
3338
//! expression, `e as U2` is not necessarily so (in fact it will only be valid if
@@ -59,7 +64,7 @@ pub struct CastCheck<'tcx> {
5964
/// fat pointers if their unsize-infos have the same kind.
6065
#[derive(Copy, Clone, PartialEq, Eq)]
6166
enum UnsizeKind<'tcx> {
62-
Vtable,
67+
Vtable(ast::DefId),
6368
Length,
6469
/// The unsize info of this projection
6570
OfProjection(&'tcx ty::ProjectionTy<'tcx>),
@@ -74,7 +79,7 @@ fn unsize_kind<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
7479
-> Option<UnsizeKind<'tcx>> {
7580
match t.sty {
7681
ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length),
77-
ty::TyTrait(_) => Some(UnsizeKind::Vtable),
82+
ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal_def_id())),
7883
ty::TyStruct(did, substs) => {
7984
match ty::struct_fields(fcx.tcx(), did, substs).pop() {
8085
None => None,

src/test/compile-fail/cast-rfc0401.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ fn illegal_cast_2<U:?Sized>(u: *const U) -> *const str
2121
trait Foo { fn foo(&self) {} }
2222
impl<T> Foo for T {}
2323

24+
trait Bar { fn foo(&self) {} }
25+
impl<T> Bar for T {}
26+
2427
enum E {
2528
A, B
2629
}
@@ -72,4 +75,7 @@ fn main()
7275
// check no error cascade
7376
let _ = main.f as *const u32; //~ ERROR attempted access of field
7477

78+
let cf: *const Foo = &0;
79+
let _ = cf as *const [u8]; //~ ERROR vtable kinds
80+
let _ = cf as *const Bar; //~ ERROR vtable kinds
7581
}

src/test/run-pass/cast-rfc0401-vtable-kinds.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,11 @@ impl<T> Foo<T> for () {}
2323
impl Foo<u32> for u32 { fn foo(&self, _: u32) -> u32 { self+43 } }
2424
impl Bar for () {}
2525

26-
unsafe fn fool<'a>(t: *const (Foo<u32>+'a)) -> u32 {
27-
let bar : *const Bar = t as *const Bar;
26+
unsafe fn round_trip_and_call<'a>(t: *const (Foo<u32>+'a)) -> u32 {
2827
let foo_e : *const Foo<u16> = t as *const _;
2928
let r_1 = foo_e as *mut Foo<u32>;
3029

31-
(&*r_1).foo(0)*(&*(bar as *const Foo<u32>)).foo(0)
30+
(&*r_1).foo(0)
3231
}
3332

3433
#[repr(C)]
@@ -43,8 +42,8 @@ fn foo_to_bar<T:?Sized>(u: *const FooS<T>) -> *const BarS<T> {
4342
fn main() {
4443
let x = 4u32;
4544
let y : &Foo<u32> = &x;
46-
let fl = unsafe { fool(y as *const Foo<u32>) };
47-
assert_eq!(fl, (43+4)*(43+4));
45+
let fl = unsafe { round_trip_and_call(y as *const Foo<u32>) };
46+
assert_eq!(fl, (43+4));
4847

4948
let s = FooS([0,1,2]);
5049
let u: &FooS<[u32]> = &s;

src/test/run-pass/cast-rfc0401.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ fn main()
8888
assert_eq!(u as *const u8, p as *const u8);
8989
assert_eq!(u as *const u16, p as *const u16);
9090

91-
// ptr-ptr-cast (both vk=Length)
91+
// ptr-ptr-cast (Length vtables)
9292
let mut l : [u8; 2] = [0,1];
9393
let w: *mut [u16; 2] = &mut l as *mut [u8; 2] as *mut _;
9494
let w: *mut [u16] = unsafe {&mut *w};
@@ -99,6 +99,12 @@ fn main()
9999
let l_via_str = unsafe{&*(s as *const [u8])};
100100
assert_eq!(&l, l_via_str);
101101

102+
// ptr-ptr-cast (Length vtables, check length is preserved)
103+
let l: [[u8; 3]; 2] = [[3, 2, 6], [4, 5, 1]];
104+
let p: *const [[u8; 3]] = &l;
105+
let p: &[[u8; 2]] = unsafe {&*(p as *const [[u8; 2]])};
106+
assert_eq!(p, [[3, 2], [6, 4]]);
107+
102108
// enum-cast
103109
assert_eq!(Simple::A as u8, 0);
104110
assert_eq!(Simple::B as u8, 1);

0 commit comments

Comments
 (0)