diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/dynamically-sized-types | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
17 files changed, 1095 insertions, 0 deletions
diff --git a/src/test/ui/dynamically-sized-types/dst-coerce-custom.rs b/src/test/ui/dynamically-sized-types/dst-coerce-custom.rs new file mode 100644 index 000000000..24d83eb53 --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-coerce-custom.rs @@ -0,0 +1,43 @@ +// run-pass +// Test a very simple custom DST coercion. + +#![feature(unsize, coerce_unsized)] + +use std::ops::CoerceUnsized; +use std::marker::Unsize; + +struct Bar<T: ?Sized> { + x: *const T, +} + +impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Bar<U>> for Bar<T> {} + +trait Baz { + fn get(&self) -> i32; +} + +impl Baz for i32 { + fn get(&self) -> i32 { + *self + } +} + +fn main() { + // Arrays. + let a: Bar<[i32; 3]> = Bar { x: &[1, 2, 3] }; + // This is the actual coercion. + let b: Bar<[i32]> = a; + + unsafe { + assert_eq!((*b.x)[0], 1); + assert_eq!((*b.x)[1], 2); + assert_eq!((*b.x)[2], 3); + } + + // Trait objects. + let a: Bar<i32> = Bar { x: &42 }; + let b: Bar<dyn Baz> = a; + unsafe { + assert_eq!((*b.x).get(), 42); + } +} diff --git a/src/test/ui/dynamically-sized-types/dst-coerce-rc.rs b/src/test/ui/dynamically-sized-types/dst-coerce-rc.rs new file mode 100644 index 000000000..683fa6850 --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-coerce-rc.rs @@ -0,0 +1,42 @@ +// run-pass +#![allow(unused_variables)] +#![allow(stable_features)] +// Test a very simple custom DST coercion. + +#![feature(core, rc_weak)] + +use std::cell::RefCell; +use std::rc::{Rc, Weak}; + +trait Baz { + fn get(&self) -> i32; +} + +impl Baz for i32 { + fn get(&self) -> i32 { + *self + } +} + +fn main() { + let a: Rc<[i32; 3]> = Rc::new([1, 2, 3]); + let b: Rc<[i32]> = a; + assert_eq!(b[0], 1); + assert_eq!(b[1], 2); + assert_eq!(b[2], 3); + + let a: Rc<i32> = Rc::new(42); + let b: Rc<dyn Baz> = a.clone(); + assert_eq!(b.get(), 42); + + let c: Weak<i32> = Rc::downgrade(&a); + let d: Weak<dyn Baz> = c.clone(); + + let _c = b.clone(); + + let a: Rc<RefCell<i32>> = Rc::new(RefCell::new(42)); + let b: Rc<RefCell<dyn Baz>> = a.clone(); + assert_eq!(b.borrow().get(), 42); + // FIXME + let c: Weak<RefCell<dyn Baz>> = Rc::downgrade(&a) as Weak<_>; +} diff --git a/src/test/ui/dynamically-sized-types/dst-coercions.rs b/src/test/ui/dynamically-sized-types/dst-coercions.rs new file mode 100644 index 000000000..66688e93f --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-coercions.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(unused_variables)] +// Test coercions involving DST and/or raw pointers + +// pretty-expanded FIXME #23616 + +struct S; +trait T { fn dummy(&self) { } } +impl T for S {} + +pub fn main() { + let x: &dyn T = &S; + // Test we can convert from &-ptr to *-ptr of trait objects + let x: *const dyn T = &S; + + // Test we can convert from &-ptr to *-ptr of struct pointer (not DST) + let x: *const S = &S; + + // As above, but mut + let x: &mut dyn T = &mut S; + let x: *mut dyn T = &mut S; + + let x: *mut S = &mut S; + + // Test we can change the mutability from mut to const. + let x: &dyn T = &mut S; + let x: *const dyn T = &mut S; +} diff --git a/src/test/ui/dynamically-sized-types/dst-deref-mut.rs b/src/test/ui/dynamically-sized-types/dst-deref-mut.rs new file mode 100644 index 000000000..1d62f42bd --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-deref-mut.rs @@ -0,0 +1,35 @@ +// run-pass +// Test that a custom deref with a fat pointer return type does not ICE + + +use std::ops::{Deref, DerefMut}; + +pub struct Arr { + ptr: Box<[usize]> +} + +impl Deref for Arr { + type Target = [usize]; + + fn deref(&self) -> &[usize] { + panic!(); + } +} + +impl DerefMut for Arr { + fn deref_mut(&mut self) -> &mut [usize] { + &mut *self.ptr + } +} + +pub fn foo(arr: &mut Arr) { + let x: &mut [usize] = &mut **arr; + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); +} + +fn main() { + let mut a = Arr { ptr: Box::new([1, 2, 3]) }; + foo(&mut a); +} diff --git a/src/test/ui/dynamically-sized-types/dst-deref.rs b/src/test/ui/dynamically-sized-types/dst-deref.rs new file mode 100644 index 000000000..0a350bac1 --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-deref.rs @@ -0,0 +1,30 @@ +// run-pass +// Test that a custom deref with a fat pointer return type does not ICE + + +use std::ops::Deref; + +pub struct Arr { + ptr: Box<[usize]> +} + +impl Deref for Arr { + type Target = [usize]; + + fn deref(&self) -> &[usize] { + &*self.ptr + } +} + +pub fn foo(arr: &Arr) { + assert_eq!(arr.len(), 3); + let x: &[usize] = &**arr; + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); +} + +fn main() { + let a = Arr { ptr: Box::new([1, 2, 3]) }; + foo(&a); +} diff --git a/src/test/ui/dynamically-sized-types/dst-field-align.rs b/src/test/ui/dynamically-sized-types/dst-field-align.rs new file mode 100644 index 000000000..6c338e999 --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-field-align.rs @@ -0,0 +1,67 @@ +// run-pass +#![allow(dead_code)] +struct Foo<T: ?Sized> { + a: u16, + b: T +} + +trait Bar { + fn get(&self) -> usize; +} + +impl Bar for usize { + fn get(&self) -> usize { *self } +} + +struct Baz<T: ?Sized> { + a: T +} + +struct HasDrop<T: ?Sized> { + ptr: Box<usize>, + data: T +} + +fn main() { + // Test that zero-offset works properly + let b : Baz<usize> = Baz { a: 7 }; + assert_eq!(b.a.get(), 7); + let b : &Baz<dyn Bar> = &b; + assert_eq!(b.a.get(), 7); + + // Test that the field is aligned properly + let f : Foo<usize> = Foo { a: 0, b: 11 }; + assert_eq!(f.b.get(), 11); + let ptr1 : *const u8 = &f.b as *const _ as *const u8; + + let f : &Foo<dyn Bar> = &f; + let ptr2 : *const u8 = &f.b as *const _ as *const u8; + assert_eq!(f.b.get(), 11); + + // The pointers should be the same + assert_eq!(ptr1, ptr2); + + // Test that nested DSTs work properly + let f : Foo<Foo<usize>> = Foo { a: 0, b: Foo { a: 1, b: 17 }}; + assert_eq!(f.b.b.get(), 17); + let f : &Foo<Foo<dyn Bar>> = &f; + assert_eq!(f.b.b.get(), 17); + + // Test that get the pointer via destructuring works + + let f : Foo<usize> = Foo { a: 0, b: 11 }; + let f : &Foo<dyn Bar> = &f; + let &Foo { a: _, b: ref bar } = f; + assert_eq!(bar.get(), 11); + + // Make sure that drop flags don't screw things up + + let d : HasDrop<Baz<[i32; 4]>> = HasDrop { + ptr: Box::new(0), + data: Baz { a: [1,2,3,4] } + }; + assert_eq!([1,2,3,4], d.data.a); + + let d : &HasDrop<Baz<[i32]>> = &d; + assert_eq!(&[1,2,3,4], &d.data.a); +} diff --git a/src/test/ui/dynamically-sized-types/dst-index.rs b/src/test/ui/dynamically-sized-types/dst-index.rs new file mode 100644 index 000000000..8aa65bbfd --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-index.rs @@ -0,0 +1,34 @@ +// run-pass +#![allow(unused_variables)] +// Test that overloaded index expressions with DST result types +// work and don't ICE. + +use std::ops::Index; +use std::fmt::Debug; + +struct S; + +impl Index<usize> for S { + type Output = str; + + fn index<'a>(&'a self, _: usize) -> &'a str { + "hello" + } +} + +struct T; + +impl Index<usize> for T { + type Output = dyn Debug + 'static; + + fn index<'a>(&'a self, idx: usize) -> &'a (dyn Debug + 'static) { + static X: usize = 42; + &X as &(dyn Debug + 'static) + } +} + +fn main() { + assert_eq!(&S[0], "hello"); + let _ = &T[0]; + // let x = &x as &Debug; +} diff --git a/src/test/ui/dynamically-sized-types/dst-irrefutable-bind.rs b/src/test/ui/dynamically-sized-types/dst-irrefutable-bind.rs new file mode 100644 index 000000000..0a6c49111 --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-irrefutable-bind.rs @@ -0,0 +1,27 @@ +// run-pass +#![feature(unsized_tuple_coercion)] + +struct Test<T: ?Sized>(T); + +fn main() { + let x = Test([1,2,3]); + let x : &Test<[i32]> = &x; + + let & ref _y = x; + + // Make sure binding to a fat pointer behind a reference + // still works + let slice = &[1,2,3]; + let x = Test(&slice); + let Test(&_slice) = x; + + + let x = (10, [1,2,3]); + let x : &(i32, [i32]) = &x; + + let & ref _y = x; + + let slice = &[1,2,3]; + let x = (10, &slice); + let (_, &_slice) = x; +} diff --git a/src/test/ui/dynamically-sized-types/dst-raw.rs b/src/test/ui/dynamically-sized-types/dst-raw.rs new file mode 100644 index 000000000..0893b02e7 --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-raw.rs @@ -0,0 +1,138 @@ +// run-pass +// Test DST raw pointers + + +#![feature(unsized_tuple_coercion)] + +trait Trait { + fn foo(&self) -> isize; +} + +struct A { + f: isize +} +impl Trait for A { + fn foo(&self) -> isize { + self.f + } +} + +struct Foo<T: ?Sized> { + f: T +} + +pub fn main() { + // raw trait object + let x = A { f: 42 }; + let z: *const dyn Trait = &x; + let r = unsafe { + (&*z).foo() + }; + assert_eq!(r, 42); + + // raw DST struct + let p = Foo {f: A { f: 42 }}; + let o: *const Foo<dyn Trait> = &p; + let r = unsafe { + (&*o).f.foo() + }; + assert_eq!(r, 42); + + // raw DST tuple + let p = (A { f: 42 },); + let o: *const (dyn Trait,) = &p; + let r = unsafe { + (&*o).0.foo() + }; + assert_eq!(r, 42); + + // raw slice + let a: *const [_] = &[1, 2, 3]; + unsafe { + let b = (*a)[2]; + assert_eq!(b, 3); + let len = (*a).len(); + assert_eq!(len, 3); + } + + // raw slice with explicit cast + let a = &[1, 2, 3] as *const [i32]; + unsafe { + let b = (*a)[2]; + assert_eq!(b, 3); + let len = (*a).len(); + assert_eq!(len, 3); + } + + // raw DST struct with slice + let c: *const Foo<[_]> = &Foo {f: [1, 2, 3]}; + unsafe { + let b = (&*c).f[0]; + assert_eq!(b, 1); + let len = (&*c).f.len(); + assert_eq!(len, 3); + } + + // raw DST tuple with slice + let c: *const ([_],) = &([1, 2, 3],); + unsafe { + let b = (&*c).0[0]; + assert_eq!(b, 1); + let len = (&*c).0.len(); + assert_eq!(len, 3); + } + + // all of the above with *mut + let mut x = A { f: 42 }; + let z: *mut dyn Trait = &mut x; + let r = unsafe { + (&*z).foo() + }; + assert_eq!(r, 42); + + let mut p = Foo {f: A { f: 42 }}; + let o: *mut Foo<dyn Trait> = &mut p; + let r = unsafe { + (&*o).f.foo() + }; + assert_eq!(r, 42); + + let mut p = (A { f: 42 },); + let o: *mut (dyn Trait,) = &mut p; + let r = unsafe { + (&*o).0.foo() + }; + assert_eq!(r, 42); + + let a: *mut [_] = &mut [1, 2, 3]; + unsafe { + let b = (*a)[2]; + assert_eq!(b, 3); + let len = (*a).len(); + assert_eq!(len, 3); + } + + let a = &mut [1, 2, 3] as *mut [i32]; + unsafe { + let b = (*a)[2]; + assert_eq!(b, 3); + let len = (*a).len(); + assert_eq!(len, 3); + } + + let c: *mut Foo<[_]> = &mut Foo {f: [1, 2, 3]}; + unsafe { + let b = (&*c).f[0]; + assert_eq!(b, 1); + let len = (&*c).f.len(); + assert_eq!(len, 3); + } + + let c: *mut ([_],) = &mut ([1, 2, 3],); + unsafe { + let b = (&*c).0[0]; + assert_eq!(b, 1); + let len = (&*c).0.len(); + assert_eq!(len, 3); + } +} diff --git a/src/test/ui/dynamically-sized-types/dst-struct-sole.rs b/src/test/ui/dynamically-sized-types/dst-struct-sole.rs new file mode 100644 index 000000000..6ca07fcf8 --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-struct-sole.rs @@ -0,0 +1,76 @@ +// run-pass +// As dst-struct.rs, but the unsized field is the only field in the struct. + + +struct Fat<T: ?Sized> { + ptr: T +} + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.ptr; + assert_eq!(x.ptr.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.ptr[1], 2); +} + +fn foo2<T:ToBar>(x: &Fat<[T]>) { + let y = &x.ptr; + let bar = Bar; + assert_eq!(x.ptr.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.ptr[1].to_bar(), bar); +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = Fat { ptr: [1, 2, 3] }; + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &Fat { ptr: [1, 2, 3] }; + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = Fat { ptr: [bar, bar, bar] }; + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &Fat { ptr: [bar, bar, bar] }; + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut Fat { ptr: [1, 2, 3] }; + f5.ptr[1] = 34; + assert_eq!(f5.ptr[0], 1); + assert_eq!(f5.ptr[1], 34); + assert_eq!(f5.ptr[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &Fat { ptr: [] }; + assert!(f5.ptr.is_empty()); + let f5: &Fat<[Bar]> = &Fat { ptr: [] }; + assert!(f5.ptr.is_empty()); +} diff --git a/src/test/ui/dynamically-sized-types/dst-struct.rs b/src/test/ui/dynamically-sized-types/dst-struct.rs new file mode 100644 index 000000000..25ec07b88 --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-struct.rs @@ -0,0 +1,122 @@ +// run-pass +#![feature(box_syntax)] + +struct Fat<T: ?Sized> { + f1: isize, + f2: &'static str, + ptr: T +} + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.ptr; + assert_eq!(x.ptr.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.ptr[1], 2); + assert_eq!(x.f1, 5); + assert_eq!(x.f2, "some str"); +} + +fn foo2<T:ToBar>(x: &Fat<[T]>) { + let y = &x.ptr; + let bar = Bar; + assert_eq!(x.ptr.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.ptr[1].to_bar(), bar); + assert_eq!(x.f1, 5); + assert_eq!(x.f2, "some str"); +} + +fn foo3(x: &Fat<Fat<[isize]>>) { + let y = &x.ptr.ptr; + assert_eq!(x.f1, 5); + assert_eq!(x.f2, "some str"); + assert_eq!(x.ptr.f1, 8); + assert_eq!(x.ptr.f2, "deep str"); + assert_eq!(x.ptr.ptr.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.ptr.ptr[1], 2); +} + + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = Fat { f1: 5, f2: "some str", ptr: [bar, bar, bar] }; + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &Fat { f1: 5, f2: "some str", ptr: [bar, bar, bar] }; + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; + f5.ptr[1] = 34; + assert_eq!(f5.ptr[0], 1); + assert_eq!(f5.ptr[1], 34); + assert_eq!(f5.ptr[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &Fat { f1: 5, f2: "some str", ptr: [] }; + assert!(f5.ptr.is_empty()); + let f5: &Fat<[Bar]> = &Fat { f1: 5, f2: "some str", ptr: [] }; + assert!(f5.ptr.is_empty()); + + // Deeply nested. + let f1 = Fat { f1: 5, f2: "some str", ptr: Fat { f1: 8, f2: "deep str", ptr: [1, 2, 3]} }; + foo3(&f1); + let f2 = &f1; + foo3(f2); + let f3: &Fat<Fat<[isize]>> = f2; + foo3(f3); + let f4: &Fat<Fat<[isize]>> = &f1; + foo3(f4); + let f5: &Fat<Fat<[isize]>> = + &Fat { f1: 5, f2: "some str", ptr: Fat { f1: 8, f2: "deep str", ptr: [1, 2, 3]} }; + foo3(f5); + + // Box. + let f1 = Box::new([1, 2, 3]); + assert_eq!((*f1)[1], 2); + let f2: Box<[isize]> = f1; + assert_eq!((*f2)[1], 2); + + // Nested Box. + let f1 : Box<Fat<[isize; 3]>> = box Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; + foo(&*f1); + let f2 : Box<Fat<[isize]>> = f1; + foo(&*f2); + + let f3 : Box<Fat<[isize]>> = + Box::<Fat<[_; 3]>>::new(Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }); + foo(&*f3); +} diff --git a/src/test/ui/dynamically-sized-types/dst-trait-tuple.rs b/src/test/ui/dynamically-sized-types/dst-trait-tuple.rs new file mode 100644 index 000000000..c1e45215a --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-trait-tuple.rs @@ -0,0 +1,102 @@ +// run-pass +#![allow(type_alias_bounds)] + +#![allow(unused_features)] +#![feature(unsized_tuple_coercion)] + +type Fat<T: ?Sized> = (isize, &'static str, T); + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +#[derive(Copy, Clone, PartialEq, Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } + fn to_val(&self) -> isize { + 0 + } +} +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +// x is a fat pointer +fn foo(x: &Fat<dyn ToBar>) { + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!(x.2.to_bar(), Bar); + assert_eq!(x.2.to_val(), 42); + + let y = &x.2; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); +} + +fn bar(x: &dyn ToBar) { + assert_eq!(x.to_bar(), Bar); + assert_eq!(x.to_val(), 42); +} + +fn baz(x: &Fat<Fat<dyn ToBar>>) { + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!((x.2).0, 8); + assert_eq!((x.2).1, "deep str"); + assert_eq!((x.2).2.to_bar(), Bar); + assert_eq!((x.2).2.to_val(), 42); + + let y = &(x.2).2; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); + +} + +pub fn main() { + let f1 = (5, "some str", Bar1 {f :42}); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<dyn ToBar> = f2; + foo(f3); + let f4: &Fat<dyn ToBar> = &f1; + foo(f4); + let f5: &Fat<dyn ToBar> = &(5, "some str", Bar1 {f :42}); + foo(f5); + + // Zero size object. + let f6: &Fat<dyn ToBar> = &(5, "some str", Bar); + assert_eq!(f6.2.to_bar(), Bar); + + // &* + // + let f7: Box<dyn ToBar> = Box::new(Bar1 {f :42}); + bar(&*f7); + + // Deep nesting + let f1 = (5, "some str", (8, "deep str", Bar1 {f :42})); + baz(&f1); + let f2 = &f1; + baz(f2); + let f3: &Fat<Fat<dyn ToBar>> = f2; + baz(f3); + let f4: &Fat<Fat<dyn ToBar>> = &f1; + baz(f4); + let f5: &Fat<Fat<dyn ToBar>> = &(5, "some str", (8, "deep str", Bar1 {f :42})); + baz(f5); +} diff --git a/src/test/ui/dynamically-sized-types/dst-trait.rs b/src/test/ui/dynamically-sized-types/dst-trait.rs new file mode 100644 index 000000000..ec6bc7219 --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-trait.rs @@ -0,0 +1,105 @@ +// run-pass +#![feature(box_syntax)] + +struct Fat<T: ?Sized> { + f1: isize, + f2: &'static str, + ptr: T +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +#[derive(Copy, Clone, PartialEq, Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } + fn to_val(&self) -> isize { + 0 + } +} +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +// x is a fat pointer +fn foo(x: &Fat<dyn ToBar>) { + assert_eq!(x.f1, 5); + assert_eq!(x.f2, "some str"); + assert_eq!(x.ptr.to_bar(), Bar); + assert_eq!(x.ptr.to_val(), 42); + + let y = &x.ptr; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); +} + +fn bar(x: &dyn ToBar) { + assert_eq!(x.to_bar(), Bar); + assert_eq!(x.to_val(), 42); +} + +fn baz(x: &Fat<Fat<dyn ToBar>>) { + assert_eq!(x.f1, 5); + assert_eq!(x.f2, "some str"); + assert_eq!(x.ptr.f1, 8); + assert_eq!(x.ptr.f2, "deep str"); + assert_eq!(x.ptr.ptr.to_bar(), Bar); + assert_eq!(x.ptr.ptr.to_val(), 42); + + let y = &x.ptr.ptr; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); + +} + +pub fn main() { + let f1 = Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} }; + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<dyn ToBar> = f2; + foo(f3); + let f4: &Fat<dyn ToBar> = &f1; + foo(f4); + let f5: &Fat<dyn ToBar> = &Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} }; + foo(f5); + + // Zero size object. + let f6: &Fat<dyn ToBar> = &Fat { f1: 5, f2: "some str", ptr: Bar }; + assert_eq!(f6.ptr.to_bar(), Bar); + + // &* + // + let f7: Box<dyn ToBar> = Box::new(Bar1 {f :42}); + bar(&*f7); + + // Deep nesting + let f1 = + Fat { f1: 5, f2: "some str", ptr: Fat { f1: 8, f2: "deep str", ptr: Bar1 {f :42}} }; + baz(&f1); + let f2 = &f1; + baz(f2); + let f3: &Fat<Fat<dyn ToBar>> = f2; + baz(f3); + let f4: &Fat<Fat<dyn ToBar>> = &f1; + baz(f4); + let f5: &Fat<Fat<dyn ToBar>> = + &Fat { f1: 5, f2: "some str", ptr: Fat { f1: 8, f2: "deep str", ptr: Bar1 {f :42}} }; + baz(f5); +} diff --git a/src/test/ui/dynamically-sized-types/dst-tuple-no-reorder.rs b/src/test/ui/dynamically-sized-types/dst-tuple-no-reorder.rs new file mode 100644 index 000000000..26b923f43 --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-tuple-no-reorder.rs @@ -0,0 +1,26 @@ +// run-pass + +#![feature(unsized_tuple_coercion)] + +// Ensure that unsizable fields that might be accessed don't get reordered + +fn nonzero_size() { + let sized: (u8, [u32; 2]) = (123, [456, 789]); + let unsize: &(u8, [u32]) = &sized; + assert_eq!(unsize.0, 123); + assert_eq!(unsize.1.len(), 2); + assert_eq!(unsize.1[0], 456); + assert_eq!(unsize.1[1], 789); +} + +fn zst() { + let sized: (u8, [u32; 0]) = (123, []); + let unsize: &(u8, [u32]) = &sized; + assert_eq!(unsize.0, 123); + assert_eq!(unsize.1.len(), 0); +} + +pub fn main() { + nonzero_size(); + zst(); +} diff --git a/src/test/ui/dynamically-sized-types/dst-tuple-sole.rs b/src/test/ui/dynamically-sized-types/dst-tuple-sole.rs new file mode 100644 index 000000000..606689da0 --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-tuple-sole.rs @@ -0,0 +1,79 @@ +// run-pass +#![allow(stable_features)] +#![allow(type_alias_bounds)] + +// As dst-tuple.rs, but the unsized field is the only field in the tuple. + + +#![feature(unsized_tuple_coercion)] + +type Fat<T: ?Sized> = (T,); + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.0; + assert_eq!(x.0.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.0[1], 2); +} + +fn foo2<T:ToBar>(x: &Fat<[T]>) { + let y = &x.0; + let bar = Bar; + assert_eq!(x.0.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.0[1].to_bar(), bar); +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = ([1, 2, 3],); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &([1, 2, 3],); + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = ([bar, bar, bar],); + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &([bar, bar, bar],); + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut ([1, 2, 3],); + f5.0[1] = 34; + assert_eq!(f5.0[0], 1); + assert_eq!(f5.0[1], 34); + assert_eq!(f5.0[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &([],); + assert!(f5.0.is_empty()); + let f5: &Fat<[Bar]> = &([],); + assert!(f5.0.is_empty()); +} diff --git a/src/test/ui/dynamically-sized-types/dst-tuple-zst-offsets.rs b/src/test/ui/dynamically-sized-types/dst-tuple-zst-offsets.rs new file mode 100644 index 000000000..b0cefe770 --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-tuple-zst-offsets.rs @@ -0,0 +1,22 @@ +// run-pass + +#![feature(unsized_tuple_coercion)] + +// Check that we do not change the offsets of ZST fields when unsizing + +fn scalar_layout() { + let sized: &(u8, [(); 13]) = &(123, [(); 13]); + let unsize: &(u8, [()]) = sized; + assert_eq!(sized.1.as_ptr(), unsize.1.as_ptr()); +} + +fn scalarpair_layout() { + let sized: &(u8, u16, [(); 13]) = &(123, 456, [(); 13]); + let unsize: &(u8, u16, [()]) = sized; + assert_eq!(sized.2.as_ptr(), unsize.2.as_ptr()); +} + +pub fn main() { + scalar_layout(); + scalarpair_layout(); +} diff --git a/src/test/ui/dynamically-sized-types/dst-tuple.rs b/src/test/ui/dynamically-sized-types/dst-tuple.rs new file mode 100644 index 000000000..604ac5112 --- /dev/null +++ b/src/test/ui/dynamically-sized-types/dst-tuple.rs @@ -0,0 +1,119 @@ +// run-pass +#![allow(type_alias_bounds)] + +#![feature(unsized_tuple_coercion)] + +type Fat<T: ?Sized> = (isize, &'static str, T); + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.2; + assert_eq!(x.2.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.2[1], 2); + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); +} + +fn foo2<T:ToBar>(x: &Fat<[T]>) { + let y = &x.2; + let bar = Bar; + assert_eq!(x.2.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.2[1].to_bar(), bar); + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); +} + +fn foo3(x: &Fat<Fat<[isize]>>) { + let y = &(x.2).2; + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!((x.2).0, 8); + assert_eq!((x.2).1, "deep str"); + assert_eq!((x.2).2.len(), 3); + assert_eq!(y[0], 1); + assert_eq!((x.2).2[1], 2); +} + + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = (5, "some str", [1, 2, 3]); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &(5, "some str", [1, 2, 3]); + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = (5, "some str", [bar, bar, bar]); + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &(5, "some str", [bar, bar, bar]); + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut (5, "some str", [1, 2, 3]); + f5.2[1] = 34; + assert_eq!(f5.2[0], 1); + assert_eq!(f5.2[1], 34); + assert_eq!(f5.2[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &(5, "some str", []); + assert!(f5.2.is_empty()); + let f5: &Fat<[Bar]> = &(5, "some str", []); + assert!(f5.2.is_empty()); + + // Deeply nested. + let f1 = (5, "some str", (8, "deep str", [1, 2, 3])); + foo3(&f1); + let f2 = &f1; + foo3(f2); + let f3: &Fat<Fat<[isize]>> = f2; + foo3(f3); + let f4: &Fat<Fat<[isize]>> = &f1; + foo3(f4); + let f5: &Fat<Fat<[isize]>> = &(5, "some str", (8, "deep str", [1, 2, 3])); + foo3(f5); + + // Box. + let f1 = Box::new([1, 2, 3]); + assert_eq!((*f1)[1], 2); + let f2: Box<[isize]> = f1; + assert_eq!((*f2)[1], 2); + + // Nested Box. + let f1 : Box<Fat<[isize; 3]>> = Box::new((5, "some str", [1, 2, 3])); + foo(&*f1); + let f2 : Box<Fat<[isize]>> = f1; + foo(&*f2); + + let f3 : Box<Fat<[isize]>> = + Box::<Fat<[_; 3]>>::new((5, "some str", [1, 2, 3])); + foo(&*f3); +} |