diff options
Diffstat (limited to 'src/test/ui/array-slice-vec')
91 files changed, 2116 insertions, 0 deletions
diff --git a/src/test/ui/array-slice-vec/array-break-length.rs b/src/test/ui/array-slice-vec/array-break-length.rs new file mode 100644 index 000000000..60589f7c2 --- /dev/null +++ b/src/test/ui/array-slice-vec/array-break-length.rs @@ -0,0 +1,9 @@ +fn main() { + loop { + |_: [_; break]| {} //~ ERROR: `break` outside of a loop + } + + loop { + |_: [_; continue]| {} //~ ERROR: `continue` outside of a loop + } +} diff --git a/src/test/ui/array-slice-vec/array-break-length.stderr b/src/test/ui/array-slice-vec/array-break-length.stderr new file mode 100644 index 000000000..93f1c238b --- /dev/null +++ b/src/test/ui/array-slice-vec/array-break-length.stderr @@ -0,0 +1,15 @@ +error[E0268]: `break` outside of a loop + --> $DIR/array-break-length.rs:3:17 + | +LL | |_: [_; break]| {} + | ^^^^^ cannot `break` outside of a loop + +error[E0268]: `continue` outside of a loop + --> $DIR/array-break-length.rs:7:17 + | +LL | |_: [_; continue]| {} + | ^^^^^^^^ cannot `continue` outside of a loop + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0268`. diff --git a/src/test/ui/array-slice-vec/array-not-vector.rs b/src/test/ui/array-slice-vec/array-not-vector.rs new file mode 100644 index 000000000..5e46f015b --- /dev/null +++ b/src/test/ui/array-slice-vec/array-not-vector.rs @@ -0,0 +1,12 @@ +fn main() { + let _x: i32 = [1, 2, 3]; + //~^ ERROR mismatched types + //~| expected `i32`, found array + + let x: &[i32] = &[1, 2, 3]; + let _y: &i32 = x; + //~^ ERROR mismatched types + //~| expected reference `&i32` + //~| found reference `&[i32]` + //~| expected `i32`, found slice +} diff --git a/src/test/ui/array-slice-vec/array-not-vector.stderr b/src/test/ui/array-slice-vec/array-not-vector.stderr new file mode 100644 index 000000000..0e187d907 --- /dev/null +++ b/src/test/ui/array-slice-vec/array-not-vector.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/array-not-vector.rs:2:19 + | +LL | let _x: i32 = [1, 2, 3]; + | --- ^^^^^^^^^ expected `i32`, found array `[{integer}; 3]` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/array-not-vector.rs:7:20 + | +LL | let _y: &i32 = x; + | ---- ^ expected `i32`, found slice `[i32]` + | | + | expected due to this + | + = note: expected reference `&i32` + found reference `&[i32]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/array-slice-vec/array_const_index-0.rs b/src/test/ui/array-slice-vec/array_const_index-0.rs new file mode 100644 index 000000000..9ff7e2c56 --- /dev/null +++ b/src/test/ui/array-slice-vec/array_const_index-0.rs @@ -0,0 +1,9 @@ +const A: &'static [i32] = &[]; +const B: i32 = (&A)[1]; +//~^ index out of bounds: the length is 0 but the index is 1 +//~| ERROR any use of this value will cause an error +//~| WARN this was previously accepted by the compiler but is being phased out + +fn main() { + let _ = B; +} diff --git a/src/test/ui/array-slice-vec/array_const_index-0.stderr b/src/test/ui/array-slice-vec/array_const_index-0.stderr new file mode 100644 index 000000000..483239871 --- /dev/null +++ b/src/test/ui/array-slice-vec/array_const_index-0.stderr @@ -0,0 +1,23 @@ +error: any use of this value will cause an error + --> $DIR/array_const_index-0.rs:2:16 + | +LL | const B: i32 = (&A)[1]; + | ------------ ^^^^^^^ index out of bounds: the length is 0 but the index is 1 + | + = note: `#[deny(const_err)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> + +error: aborting due to previous error + +Future incompatibility report: Future breakage diagnostic: +error: any use of this value will cause an error + --> $DIR/array_const_index-0.rs:2:16 + | +LL | const B: i32 = (&A)[1]; + | ------------ ^^^^^^^ index out of bounds: the length is 0 but the index is 1 + | + = note: `#[deny(const_err)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> + diff --git a/src/test/ui/array-slice-vec/array_const_index-1.rs b/src/test/ui/array-slice-vec/array_const_index-1.rs new file mode 100644 index 000000000..f4326189c --- /dev/null +++ b/src/test/ui/array-slice-vec/array_const_index-1.rs @@ -0,0 +1,9 @@ +const A: [i32; 0] = []; +const B: i32 = A[1]; +//~^ index out of bounds: the length is 0 but the index is 1 +//~| ERROR any use of this value will cause an error +//~| WARN this was previously accepted by the compiler but is being phased out + +fn main() { + let _ = B; +} diff --git a/src/test/ui/array-slice-vec/array_const_index-1.stderr b/src/test/ui/array-slice-vec/array_const_index-1.stderr new file mode 100644 index 000000000..361f518c0 --- /dev/null +++ b/src/test/ui/array-slice-vec/array_const_index-1.stderr @@ -0,0 +1,23 @@ +error: any use of this value will cause an error + --> $DIR/array_const_index-1.rs:2:16 + | +LL | const B: i32 = A[1]; + | ------------ ^^^^ index out of bounds: the length is 0 but the index is 1 + | + = note: `#[deny(const_err)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> + +error: aborting due to previous error + +Future incompatibility report: Future breakage diagnostic: +error: any use of this value will cause an error + --> $DIR/array_const_index-1.rs:2:16 + | +LL | const B: i32 = A[1]; + | ------------ ^^^^ index out of bounds: the length is 0 but the index is 1 + | + = note: `#[deny(const_err)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800> + diff --git a/src/test/ui/array-slice-vec/array_const_index-2.rs b/src/test/ui/array-slice-vec/array_const_index-2.rs new file mode 100644 index 000000000..8ee225f5c --- /dev/null +++ b/src/test/ui/array-slice-vec/array_const_index-2.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +#![allow(stable_features)] + +#![feature(const_indexing)] + +fn main() { + const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47]; + const IDX: usize = 3; + const VAL: i32 = ARR[IDX]; + const BLUB: [i32; (ARR[0] - 41) as usize] = [5]; +} diff --git a/src/test/ui/array-slice-vec/bounds-check-no-overflow.rs b/src/test/ui/array-slice-vec/bounds-check-no-overflow.rs new file mode 100644 index 000000000..577853a4e --- /dev/null +++ b/src/test/ui/array-slice-vec/bounds-check-no-overflow.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:index out of bounds +// ignore-emscripten no processes + +use std::mem::size_of; + +fn main() { + let xs = [1, 2, 3]; + xs[usize::MAX / size_of::<isize>() + 1]; +} diff --git a/src/test/ui/array-slice-vec/box-of-array-of-drop-1.rs b/src/test/ui/array-slice-vec/box-of-array-of-drop-1.rs new file mode 100644 index 000000000..2b3ece67b --- /dev/null +++ b/src/test/ui/array-slice-vec/box-of-array-of-drop-1.rs @@ -0,0 +1,53 @@ +// run-pass +// needs-unwind +#![allow(overflowing_literals)] + +// Test that we cleanup a fixed size Box<[D; k]> properly when D has a +// destructor. + +// ignore-emscripten no threads support + +use std::thread; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static LOG: AtomicUsize = AtomicUsize::new(0); + +struct D(u8); + +impl Drop for D { + fn drop(&mut self) { + println!("Dropping {}", self.0); + let old = LOG.load(Ordering::SeqCst); + let _ = LOG.compare_exchange( + old, + old << 4 | self.0 as usize, + Ordering::SeqCst, + Ordering::SeqCst + ); + } +} + +fn main() { + fn die() -> D { panic!("Oh no"); } + let g = thread::spawn(|| { + let _b1: Box<[D; 4]> = Box::new([D( 1), D( 2), D( 3), D( 4)]); + let _b2: Box<[D; 4]> = Box::new([D( 5), D( 6), D( 7), D( 8)]); + let _b3: Box<[D; 4]> = Box::new([D( 9), D(10), die(), D(12)]); + let _b4: Box<[D; 4]> = Box::new([D(13), D(14), D(15), D(16)]); + }); + assert!(g.join().is_err()); + + // When the panic occurs, we will be in the midst of constructing + // the input to `_b3`. Therefore, we drop the elements of the + // partially filled array first, before we get around to dropping + // the elements of `_b1` and _b2`. + + // Issue 23222: The order in which the elements actually get + // dropped is a little funky. See similar notes in nested-vec-3; + // in essence, I would not be surprised if we change the ordering + // given in `expect` in the future. + + let expect = 0x__A_9__5_6_7_8__1_2_3_4; + let actual = LOG.load(Ordering::SeqCst); + assert!(actual == expect, "expect: 0x{:x} actual: 0x{:x}", expect, actual); +} diff --git a/src/test/ui/array-slice-vec/box-of-array-of-drop-2.rs b/src/test/ui/array-slice-vec/box-of-array-of-drop-2.rs new file mode 100644 index 000000000..c0ca45875 --- /dev/null +++ b/src/test/ui/array-slice-vec/box-of-array-of-drop-2.rs @@ -0,0 +1,53 @@ +// run-pass +// needs-unwind +#![allow(overflowing_literals)] + +// Test that we cleanup dynamic sized Box<[D]> properly when D has a +// destructor. + +// ignore-emscripten no threads support + +use std::thread; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static LOG: AtomicUsize = AtomicUsize::new(0); + +struct D(u8); + +impl Drop for D { + fn drop(&mut self) { + println!("Dropping {}", self.0); + let old = LOG.load(Ordering::SeqCst); + let _ = LOG.compare_exchange( + old, + old << 4 | self.0 as usize, + Ordering::SeqCst, + Ordering::SeqCst + ); + } +} + +fn main() { + fn die() -> D { panic!("Oh no"); } + let g = thread::spawn(|| { + let _b1: Box<[D; 4]> = Box::new([D( 1), D( 2), D( 3), D( 4)]); + let _b2: Box<[D; 4]> = Box::new([D( 5), D( 6), D( 7), D( 8)]); + let _b3: Box<[D; 4]> = Box::new([D( 9), D(10), die(), D(12)]); + let _b4: Box<[D; 4]> = Box::new([D(13), D(14), D(15), D(16)]); + }); + assert!(g.join().is_err()); + + // When the panic occurs, we will be in the midst of constructing + // the input to `_b3`. Therefore, we drop the elements of the + // partially filled array first, before we get around to dropping + // the elements of `_b1` and _b2`. + + // Issue 23222: The order in which the elements actually get + // dropped is a little funky. See similar notes in nested-vec-3; + // in essence, I would not be surprised if we change the ordering + // given in `expect` in the future. + + let expect = 0x__A_9__5_6_7_8__1_2_3_4; + let actual = LOG.load(Ordering::SeqCst); + assert!(actual == expect, "expect: 0x{:x} actual: 0x{:x}", expect, actual); +} diff --git a/src/test/ui/array-slice-vec/byte-literals.rs b/src/test/ui/array-slice-vec/byte-literals.rs new file mode 100644 index 000000000..2649c2eac --- /dev/null +++ b/src/test/ui/array-slice-vec/byte-literals.rs @@ -0,0 +1,67 @@ +// run-pass +// + + +static FOO: u8 = b'\xF0'; +static BAR: &'static [u8] = b"a\xF0\t"; +static BAR_FIXED: &'static [u8; 3] = b"a\xF0\t"; +static BAZ: &'static [u8] = br"a\n"; + +pub fn main() { + let bar: &'static [u8] = b"a\xF0\t"; + let bar_fixed: &'static [u8; 3] = b"a\xF0\t"; + + assert_eq!(b'a', 97u8); + assert_eq!(b'\n', 10u8); + assert_eq!(b'\r', 13u8); + assert_eq!(b'\t', 9u8); + assert_eq!(b'\\', 92u8); + assert_eq!(b'\'', 39u8); + assert_eq!(b'\"', 34u8); + assert_eq!(b'\0', 0u8); + assert_eq!(b'\xF0', 240u8); + assert_eq!(FOO, 240u8); + + match 42 { + b'*' => {}, + _ => panic!() + } + + match 100 { + b'a' ..= b'z' => {}, + _ => panic!() + } + + let expected: &[_] = &[97u8, 10u8, 13u8, 9u8, 92u8, 39u8, 34u8, 0u8, 240u8]; + assert_eq!(b"a\n\r\t\\\'\"\0\xF0", expected); + let expected: &[_] = &[97u8, 98u8]; + assert_eq!(b"a\ + b", expected); + let expected: &[_] = &[97u8, 240u8, 9u8]; + assert_eq!(BAR, expected); + assert_eq!(BAR_FIXED, expected); + assert_eq!(bar, expected); + assert_eq!(bar_fixed, expected); + + let val = &[97u8, 10u8]; + match val { + b"a\n" => {}, + _ => panic!(), + } + + let buf = vec![97u8, 98, 99, 100]; + assert_eq!(match &buf[0..3] { + b"def" => 1, + b"abc" => 2, + _ => 3 + }, 2); + + let expected: &[_] = &[97u8, 92u8, 110u8]; + assert_eq!(BAZ, expected); + let expected: &[_] = &[97u8, 92u8, 110u8]; + assert_eq!(br"a\n", expected); + assert_eq!(br"a\n", b"a\\n"); + let expected: &[_] = &[97u8, 34u8, 35u8, 35u8, 98u8]; + assert_eq!(br###"a"##b"###, expected); + assert_eq!(br###"a"##b"###, b"a\"##b"); +} diff --git a/src/test/ui/array-slice-vec/cast-in-array-size.rs b/src/test/ui/array-slice-vec/cast-in-array-size.rs new file mode 100644 index 000000000..b112dcaef --- /dev/null +++ b/src/test/ui/array-slice-vec/cast-in-array-size.rs @@ -0,0 +1,14 @@ +// run-pass + + +// issues #10618 and #16382 +// pretty-expanded FIXME #23616 + +const SIZE: isize = 25; + +fn main() { + let _a: [bool; 1 as usize]; + let _b: [isize; SIZE as usize] = [1; SIZE as usize]; + let _c: [bool; '\n' as usize] = [true; '\n' as usize]; + let _d: [bool; true as usize] = [true; true as usize]; +} diff --git a/src/test/ui/array-slice-vec/check-static-mut-slices.rs b/src/test/ui/array-slice-vec/check-static-mut-slices.rs new file mode 100644 index 000000000..b89c63403 --- /dev/null +++ b/src/test/ui/array-slice-vec/check-static-mut-slices.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] + +// Checks that mutable static items can have mutable slices + + +static mut TEST: &'static mut [isize] = &mut [1]; +static mut EMPTY: &'static mut [isize] = &mut []; + +pub fn main() { + unsafe { + TEST[0] += 1; + assert_eq!(TEST[0], 2); + } +} diff --git a/src/test/ui/array-slice-vec/check-static-slice.rs b/src/test/ui/array-slice-vec/check-static-slice.rs new file mode 100644 index 000000000..1c607d134 --- /dev/null +++ b/src/test/ui/array-slice-vec/check-static-slice.rs @@ -0,0 +1,36 @@ +// run-pass + +// Check that the various ways of getting to a reference to a vec (both sized +// and unsized) work properly. + + +const AA: [isize; 3] = [1, 2, 3]; +const AB: &'static [isize; 3] = &AA; +const AC: &'static [isize] = AB; +const AD: &'static [isize] = &AA; +const AE: &'static [isize; 3] = &[1, 2, 3]; +const AF: &'static [isize] = &[1, 2, 3]; + +static CA: isize = AA[0]; +static CB: isize = AB[1]; +static CC: isize = AC[2]; +static CD: isize = AD[0]; +static CE: isize = AE[1]; +static CF: isize = AF[2]; + +static AG: &'static isize = &AA[2]; + +fn main () { + let b: &[isize] = &[1, 2, 3]; + assert_eq!(AC, b); + assert_eq!(AD, b); + assert_eq!(AF, b); + assert_eq!(*AG, 3); + + assert_eq!(CA, 1); + assert_eq!(CB, 2); + assert_eq!(CC, 3); + assert_eq!(CD, 1); + assert_eq!(CE, 2); + assert_eq!(CF, 3); +} diff --git a/src/test/ui/array-slice-vec/copy-out-of-array-1.rs b/src/test/ui/array-slice-vec/copy-out-of-array-1.rs new file mode 100644 index 000000000..c6d311148 --- /dev/null +++ b/src/test/ui/array-slice-vec/copy-out-of-array-1.rs @@ -0,0 +1,19 @@ +// run-pass + +// Ensure that we can copy out of a fixed-size array. +// +// (Compare with ui/moves/move-out-of-array-1.rs) + +#[derive(Copy, Clone)] +struct C { _x: u8 } + +fn main() { + fn d() -> C { C { _x: 0 } } + + let _d1 = foo([d(), d(), d(), d()], 1); + let _d3 = foo([d(), d(), d(), d()], 3); +} + +fn foo(a: [C; 4], i: usize) -> C { + a[i] +} diff --git a/src/test/ui/array-slice-vec/destructure-array-1.rs b/src/test/ui/array-slice-vec/destructure-array-1.rs new file mode 100644 index 000000000..74d893ee5 --- /dev/null +++ b/src/test/ui/array-slice-vec/destructure-array-1.rs @@ -0,0 +1,27 @@ +// run-pass + +// Ensure that we can do a destructuring bind of a fixed-size array, +// even when the element type has a destructor. + +struct D { x: u8 } + +impl Drop for D { fn drop(&mut self) { } } + +fn main() { + fn d(x: u8) -> D { D { x: x } } + + let d1 = foo([d(1), d(2), d(3), d(4)], 1); + let d3 = foo([d(5), d(6), d(7), d(8)], 3); + assert_eq!(d1.x, 2); + assert_eq!(d3.x, 8); +} + +fn foo([a, b, c, d]: [D; 4], i: usize) -> D { + match i { + 0 => a, + 1 => b, + 2 => c, + 3 => d, + _ => panic!("unmatched"), + } +} diff --git a/src/test/ui/array-slice-vec/dst-raw-slice.rs b/src/test/ui/array-slice-vec/dst-raw-slice.rs new file mode 100644 index 000000000..371d16f09 --- /dev/null +++ b/src/test/ui/array-slice-vec/dst-raw-slice.rs @@ -0,0 +1,13 @@ +// Test bounds checking for DST raw slices + +// run-fail +// error-pattern:index out of bounds +// ignore-emscripten no processes + +#[allow(unconditional_panic)] +fn main() { + let a: *const [_] = &[1, 2, 3]; + unsafe { + let _b = (*a)[3]; + } +} diff --git a/src/test/ui/array-slice-vec/empty-mutable-vec.rs b/src/test/ui/array-slice-vec/empty-mutable-vec.rs new file mode 100644 index 000000000..91ab280b9 --- /dev/null +++ b/src/test/ui/array-slice-vec/empty-mutable-vec.rs @@ -0,0 +1,8 @@ +// run-pass + +// pretty-expanded FIXME #23616 + +#![allow(unused_mut)] + + +pub fn main() { let mut _v: Vec<isize> = Vec::new(); } diff --git a/src/test/ui/array-slice-vec/estr-slice.rs b/src/test/ui/array-slice-vec/estr-slice.rs new file mode 100644 index 000000000..cd2c17220 --- /dev/null +++ b/src/test/ui/array-slice-vec/estr-slice.rs @@ -0,0 +1,50 @@ +// run-pass + + +pub fn main() { + let x = "hello"; + let v = "hello"; + let y : &str = "there"; + + println!("{}", x); + println!("{}", y); + + assert_eq!(x.as_bytes()[0], 'h' as u8); + assert_eq!(x.as_bytes()[4], 'o' as u8); + + let z : &str = "thing"; + assert_eq!(v, x); + assert_ne!(x, z); + + let a = "aaaa"; + let b = "bbbb"; + + let c = "cccc"; + let cc = "ccccc"; + + println!("{}", a); + + assert!(a < b); + assert!(a <= b); + assert_ne!(a, b); + assert!(b >= a); + assert!(b > a); + + println!("{}", b); + + assert!(a < c); + assert!(a <= c); + assert_ne!(a, c); + assert!(c >= a); + assert!(c > a); + + println!("{}", c); + + assert!(c < cc); + assert!(c <= cc); + assert_ne!(c, cc); + assert!(cc >= c); + assert!(cc > c); + + println!("{}", cc); +} diff --git a/src/test/ui/array-slice-vec/evec-slice.rs b/src/test/ui/array-slice-vec/evec-slice.rs new file mode 100644 index 000000000..4bdf2dbdd --- /dev/null +++ b/src/test/ui/array-slice-vec/evec-slice.rs @@ -0,0 +1,47 @@ +// run-pass +#![allow(unused_assignments)] + +pub fn main() { + let x : &[isize] = &[1,2,3,4,5]; + let mut z : &[isize] = &[1,2,3,4,5]; + z = x; + assert_eq!(z[0], 1); + assert_eq!(z[4], 5); + + let a : &[isize] = &[1,1,1,1,1]; + let b : &[isize] = &[2,2,2,2,2]; + let c : &[isize] = &[2,2,2,2,3]; + let cc : &[isize] = &[2,2,2,2,2,2]; + + println!("{:?}", a); + + assert!(a < b); + assert!(a <= b); + assert!(a != b); + assert!(b >= a); + assert!(b > a); + + println!("{:?}", b); + + assert!(b < c); + assert!(b <= c); + assert!(b != c); + assert!(c >= b); + assert!(c > b); + + assert!(a < c); + assert!(a <= c); + assert!(a != c); + assert!(c >= a); + assert!(c > a); + + println!("{:?}", c); + + assert!(a < cc); + assert!(a <= cc); + assert!(a != cc); + assert!(cc >= a); + assert!(cc > a); + + println!("{:?}", cc); +} diff --git a/src/test/ui/array-slice-vec/fixed_length_copy.rs b/src/test/ui/array-slice-vec/fixed_length_copy.rs new file mode 100644 index 000000000..f73173e84 --- /dev/null +++ b/src/test/ui/array-slice-vec/fixed_length_copy.rs @@ -0,0 +1,9 @@ +// run-pass + + +pub fn main() { + let arr = [1,2,3]; + let arr2 = arr; + assert_eq!(arr[1], 2); + assert_eq!(arr2[2], 3); +} diff --git a/src/test/ui/array-slice-vec/huge-largest-array.rs b/src/test/ui/array-slice-vec/huge-largest-array.rs new file mode 100644 index 000000000..9e78162c8 --- /dev/null +++ b/src/test/ui/array-slice-vec/huge-largest-array.rs @@ -0,0 +1,14 @@ +// run-pass + + +use std::mem::size_of; + +#[cfg(target_pointer_width = "32")] +pub fn main() { + assert_eq!(size_of::<[u8; (1 << 31) - 1]>(), (1 << 31) - 1); +} + +#[cfg(target_pointer_width = "64")] +pub fn main() { + assert_eq!(size_of::<[u8; (1 << 47) - 1]>(), (1 << 47) - 1); +} diff --git a/src/test/ui/array-slice-vec/infer_array_len.rs b/src/test/ui/array-slice-vec/infer_array_len.rs new file mode 100644 index 000000000..22fe7cb88 --- /dev/null +++ b/src/test/ui/array-slice-vec/infer_array_len.rs @@ -0,0 +1,21 @@ +// see issue #70529 +struct A; + +impl From<A> for [u8; 2] { + fn from(a: A) -> Self { + [0; 2] + } +} + +impl From<A> for [u8; 3] { + fn from(a: A) -> Self { + [0; 3] + } +} + + +fn main() { + let a = A; + let [_, _] = a.into(); + //~^ ERROR type annotations needed +} diff --git a/src/test/ui/array-slice-vec/infer_array_len.stderr b/src/test/ui/array-slice-vec/infer_array_len.stderr new file mode 100644 index 000000000..919550cac --- /dev/null +++ b/src/test/ui/array-slice-vec/infer_array_len.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/infer_array_len.rs:19:9 + | +LL | let [_, _] = a.into(); + | ^^^^^^ + | +help: consider giving this pattern a type + | +LL | let [_, _]: _ = a.into(); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/array-slice-vec/issue-15730.rs b/src/test/ui/array-slice-vec/issue-15730.rs new file mode 100644 index 000000000..dacffd154 --- /dev/null +++ b/src/test/ui/array-slice-vec/issue-15730.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(unused_mut)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +fn main() { + let mut array = [1, 2, 3]; + let pie_slice = &array[1..2]; +} diff --git a/src/test/ui/array-slice-vec/issue-18425.rs b/src/test/ui/array-slice-vec/issue-18425.rs new file mode 100644 index 000000000..354c14a75 --- /dev/null +++ b/src/test/ui/array-slice-vec/issue-18425.rs @@ -0,0 +1,9 @@ +// run-pass +// Check that codegen doesn't ICE when codegenning an array repeat +// expression with a count of 1 and a non-Copy element type. + +// pretty-expanded FIXME #23616 + +fn main() { + let _ = [Box::new(1_usize); 1]; +} diff --git a/src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.rs b/src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.rs new file mode 100644 index 000000000..061b0d675 --- /dev/null +++ b/src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.rs @@ -0,0 +1,18 @@ +// We used to not lower the extra `b @ ..` into `b @ _` which meant that no type +// was registered for the binding `b` although it passed through resolve. +// This resulted in an ICE (#69103). + +fn main() { + let [a @ .., b @ ..] = &mut [1, 2]; + //~^ ERROR `..` can only be used once per slice pattern + b; + + let [.., c @ ..] = [1, 2]; + //~^ ERROR `..` can only be used once per slice pattern + c; + + // This never ICEd, but let's make sure it won't regress either. + let (.., d @ ..) = (1, 2); + //~^ ERROR `..` patterns are not allowed here + d; +} diff --git a/src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.stderr b/src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.stderr new file mode 100644 index 000000000..9432e2f0c --- /dev/null +++ b/src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.stderr @@ -0,0 +1,26 @@ +error: `..` can only be used once per slice pattern + --> $DIR/issue-69103-extra-binding-subslice.rs:6:22 + | +LL | let [a @ .., b @ ..] = &mut [1, 2]; + | -- ^^ can only be used once per slice pattern + | | + | previously used here + +error: `..` can only be used once per slice pattern + --> $DIR/issue-69103-extra-binding-subslice.rs:10:18 + | +LL | let [.., c @ ..] = [1, 2]; + | -- ^^ can only be used once per slice pattern + | | + | previously used here + +error: `..` patterns are not allowed here + --> $DIR/issue-69103-extra-binding-subslice.rs:15:18 + | +LL | let (.., d @ ..) = (1, 2); + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/array-slice-vec/ivec-pass-by-value.rs b/src/test/ui/array-slice-vec/ivec-pass-by-value.rs new file mode 100644 index 000000000..e22aef963 --- /dev/null +++ b/src/test/ui/array-slice-vec/ivec-pass-by-value.rs @@ -0,0 +1,4 @@ +// run-pass + +fn f(_a: Vec<isize> ) { } +pub fn main() { f(vec![1, 2, 3, 4, 5]); } diff --git a/src/test/ui/array-slice-vec/match_arr_unknown_len.rs b/src/test/ui/array-slice-vec/match_arr_unknown_len.rs new file mode 100644 index 000000000..d190d7054 --- /dev/null +++ b/src/test/ui/array-slice-vec/match_arr_unknown_len.rs @@ -0,0 +1,8 @@ +fn is_123<const N: usize>(x: [u32; N]) -> bool { + match x { + [1, 2] => true, //~ ERROR mismatched types + _ => false + } +} + +fn main() {} diff --git a/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr b/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr new file mode 100644 index 000000000..5e531a993 --- /dev/null +++ b/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/match_arr_unknown_len.rs:3:9 + | +LL | [1, 2] => true, + | ^^^^^^ expected `2`, found `N` + | + = note: expected array `[u32; 2]` + found array `[u32; N]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/array-slice-vec/mut-vstore-expr.rs b/src/test/ui/array-slice-vec/mut-vstore-expr.rs new file mode 100644 index 000000000..75b309a48 --- /dev/null +++ b/src/test/ui/array-slice-vec/mut-vstore-expr.rs @@ -0,0 +1,6 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + let _x: &mut [isize] = &mut [ 1, 2, 3 ]; +} diff --git a/src/test/ui/array-slice-vec/mutability-inherits-through-fixed-length-vec.rs b/src/test/ui/array-slice-vec/mutability-inherits-through-fixed-length-vec.rs new file mode 100644 index 000000000..7afb9d846 --- /dev/null +++ b/src/test/ui/array-slice-vec/mutability-inherits-through-fixed-length-vec.rs @@ -0,0 +1,19 @@ +// run-pass + + +fn test1() { + let mut ints = [0; 32]; + ints[0] += 1; + assert_eq!(ints[0], 1); +} + +fn test2() { + let mut ints = [0; 32]; + for i in &mut ints { *i += 22; } + for i in &ints { assert_eq!(*i, 22); } +} + +pub fn main() { + test1(); + test2(); +} diff --git a/src/test/ui/array-slice-vec/mutable-alias-vec.rs b/src/test/ui/array-slice-vec/mutable-alias-vec.rs new file mode 100644 index 000000000..98dd46824 --- /dev/null +++ b/src/test/ui/array-slice-vec/mutable-alias-vec.rs @@ -0,0 +1,15 @@ +// run-pass + +fn grow(v: &mut Vec<isize> ) { + v.push(1); +} + +pub fn main() { + let mut v: Vec<isize> = Vec::new(); + grow(&mut v); + grow(&mut v); + grow(&mut v); + let len = v.len(); + println!("{}", len); + assert_eq!(len, 3 as usize); +} diff --git a/src/test/ui/array-slice-vec/nested-vec-1.rs b/src/test/ui/array-slice-vec/nested-vec-1.rs new file mode 100644 index 000000000..02a3ccf46 --- /dev/null +++ b/src/test/ui/array-slice-vec/nested-vec-1.rs @@ -0,0 +1,8 @@ +// run-pass + +// Test that using the `vec!` macro nested within itself works + +fn main() { + let nested = vec![vec![1u32, 2u32, 3u32]]; + assert_eq!(nested[0][1], 2); +} diff --git a/src/test/ui/array-slice-vec/nested-vec-2.rs b/src/test/ui/array-slice-vec/nested-vec-2.rs new file mode 100644 index 000000000..d4a704d76 --- /dev/null +++ b/src/test/ui/array-slice-vec/nested-vec-2.rs @@ -0,0 +1,15 @@ +// run-pass + +// Test that using the `vec!` macro nested within itself works +// when the contents implement Drop + +struct D(u32); + +impl Drop for D { + fn drop(&mut self) { println!("Dropping {}", self.0); } +} + +fn main() { + let nested = vec![vec![D(1u32), D(2u32), D(3u32)]]; + assert_eq!(nested[0][1].0, 2); +} diff --git a/src/test/ui/array-slice-vec/nested-vec-3.rs b/src/test/ui/array-slice-vec/nested-vec-3.rs new file mode 100644 index 000000000..b3ae683a8 --- /dev/null +++ b/src/test/ui/array-slice-vec/nested-vec-3.rs @@ -0,0 +1,60 @@ +// run-pass +// needs-unwind +#![allow(overflowing_literals)] + +// ignore-emscripten no threads support + +// Test that using the `vec!` macro nested within itself works when +// the contents implement Drop and we hit a panic in the middle of +// construction. + +use std::thread; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static LOG: AtomicUsize = AtomicUsize::new(0); + +struct D(u8); + +impl Drop for D { + fn drop(&mut self) { + println!("Dropping {}", self.0); + let old = LOG.load(Ordering::SeqCst); + let _ = LOG.compare_exchange( + old, + old << 4 | self.0 as usize, + Ordering::SeqCst, + Ordering::SeqCst, + ); + } +} + +fn main() { + fn die() -> D { panic!("Oh no"); } + let g = thread::spawn(|| { + let _nested = vec![vec![D( 1), D( 2), D( 3), D( 4)], + vec![D( 5), D( 6), D( 7), D( 8)], + vec![D( 9), D(10), die(), D(12)], + vec![D(13), D(14), D(15), D(16)]]; + }); + assert!(g.join().is_err()); + + // When the panic occurs, we will be in the midst of constructing the + // second inner vector. Therefore, we drop the elements of the + // partially filled vector first, before we get around to dropping + // the elements of the filled vector. + + // Issue 23222: The order in which the elements actually get + // dropped is a little funky: as noted above, we'll drop the 9+10 + // first, but due to #23222, they get dropped in reverse + // order. Likewise, again due to #23222, we will drop the second + // filled vec before the first filled vec. + // + // If Issue 23222 is "fixed", then presumably the corrected + // expected order of events will be 0x__9_A__1_2_3_4__5_6_7_8; + // that is, we would still drop 9+10 first, since they belong to + // the more deeply nested expression when the panic occurs. + + let expect = 0x__A_9__5_6_7_8__1_2_3_4; + let actual = LOG.load(Ordering::SeqCst); + assert!(actual == expect, "expect: 0x{:x} actual: 0x{:x}", expect, actual); +} diff --git a/src/test/ui/array-slice-vec/new-style-fixed-length-vec.rs b/src/test/ui/array-slice-vec/new-style-fixed-length-vec.rs new file mode 100644 index 000000000..454f94be8 --- /dev/null +++ b/src/test/ui/array-slice-vec/new-style-fixed-length-vec.rs @@ -0,0 +1,7 @@ +// run-pass + +static FOO: [isize; 3] = [1, 2, 3]; + +pub fn main() { + println!("{} {} {}", FOO[0], FOO[1], FOO[2]); +} diff --git a/src/test/ui/array-slice-vec/rcvr-borrowed-to-slice.rs b/src/test/ui/array-slice-vec/rcvr-borrowed-to-slice.rs new file mode 100644 index 000000000..17cf7e335 --- /dev/null +++ b/src/test/ui/array-slice-vec/rcvr-borrowed-to-slice.rs @@ -0,0 +1,33 @@ +// run-pass + +#![allow(non_camel_case_types)] + +trait sum { + fn sum_(self) -> isize; +} + +// Note: impl on a slice +impl<'a> sum for &'a [isize] { + fn sum_(self) -> isize { + self.iter().fold(0, |a, &b| a + b) + } +} + +fn call_sum(x: &[isize]) -> isize { x.sum_() } + +pub fn main() { + let x = vec![1, 2, 3]; + let y = call_sum(&x); + println!("y=={}", y); + assert_eq!(y, 6); + + let x = vec![1, 2, 3]; + let y = x.sum_(); + println!("y=={}", y); + assert_eq!(y, 6); + + let x = vec![1, 2, 3]; + let y = x.sum_(); + println!("y=={}", y); + assert_eq!(y, 6); +} diff --git a/src/test/ui/array-slice-vec/repeat_empty_ok.rs b/src/test/ui/array-slice-vec/repeat_empty_ok.rs new file mode 100644 index 000000000..25463ea5e --- /dev/null +++ b/src/test/ui/array-slice-vec/repeat_empty_ok.rs @@ -0,0 +1,15 @@ +#![crate_type = "lib"] + +pub struct Header<'a> { + pub value: &'a [u8], +} + +pub fn test() { + let headers = [Header{value: &[]}; 128]; + //~^ ERROR the trait bound +} + +pub fn test2() { + let headers = [Header{value: &[0]}; 128]; + //~^ ERROR the trait bound +} diff --git a/src/test/ui/array-slice-vec/repeat_empty_ok.stderr b/src/test/ui/array-slice-vec/repeat_empty_ok.stderr new file mode 100644 index 000000000..724bdcd92 --- /dev/null +++ b/src/test/ui/array-slice-vec/repeat_empty_ok.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `Header<'_>: Copy` is not satisfied + --> $DIR/repeat_empty_ok.rs:8:20 + | +LL | let headers = [Header{value: &[]}; 128]; + | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>` + | + = note: the `Copy` trait is required because this value will be copied for each element of the array +help: consider annotating `Header<'_>` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error[E0277]: the trait bound `Header<'_>: Copy` is not satisfied + --> $DIR/repeat_empty_ok.rs:13:20 + | +LL | let headers = [Header{value: &[0]}; 128]; + | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>` + | + = note: the `Copy` trait is required because this value will be copied for each element of the array +help: consider annotating `Header<'_>` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/array-slice-vec/repeated-vector-syntax.rs b/src/test/ui/array-slice-vec/repeated-vector-syntax.rs new file mode 100644 index 000000000..4458eb06d --- /dev/null +++ b/src/test/ui/array-slice-vec/repeated-vector-syntax.rs @@ -0,0 +1,13 @@ +// run-pass + +pub fn main() { + let x = [ [true]; 512 ]; + let y = [ 0; 1 ]; + + print!("["); + for xi in &x[..] { + print!("{:?}, ", &xi[..]); + } + println!("]"); + println!("{:?}", &y[..]); +} diff --git a/src/test/ui/array-slice-vec/show-boxed-slice.rs b/src/test/ui/array-slice-vec/show-boxed-slice.rs new file mode 100644 index 000000000..c10f779b1 --- /dev/null +++ b/src/test/ui/array-slice-vec/show-boxed-slice.rs @@ -0,0 +1,8 @@ +// run-pass + +#[derive(Debug)] +struct Foo(#[allow(unused_tuple_struct_fields)] Box<[u8]>); + +pub fn main() { + println!("{:?}", Foo(Box::new([0, 1, 2]))); +} diff --git a/src/test/ui/array-slice-vec/slice-2.rs b/src/test/ui/array-slice-vec/slice-2.rs new file mode 100644 index 000000000..5423e295a --- /dev/null +++ b/src/test/ui/array-slice-vec/slice-2.rs @@ -0,0 +1,11 @@ +// Test that slicing syntax gives errors if we have not implemented the trait. + +struct Foo; + +fn main() { + let x = Foo; + &x[..]; //~ ERROR cannot index into a value of type `Foo` + &x[Foo..]; //~ ERROR cannot index into a value of type `Foo` + &x[..Foo]; //~ ERROR cannot index into a value of type `Foo` + &x[Foo..Foo]; //~ ERROR cannot index into a value of type `Foo` +} diff --git a/src/test/ui/array-slice-vec/slice-2.stderr b/src/test/ui/array-slice-vec/slice-2.stderr new file mode 100644 index 000000000..561feb90f --- /dev/null +++ b/src/test/ui/array-slice-vec/slice-2.stderr @@ -0,0 +1,27 @@ +error[E0608]: cannot index into a value of type `Foo` + --> $DIR/slice-2.rs:7:6 + | +LL | &x[..]; + | ^^^^^ + +error[E0608]: cannot index into a value of type `Foo` + --> $DIR/slice-2.rs:8:6 + | +LL | &x[Foo..]; + | ^^^^^^^^ + +error[E0608]: cannot index into a value of type `Foo` + --> $DIR/slice-2.rs:9:6 + | +LL | &x[..Foo]; + | ^^^^^^^^ + +error[E0608]: cannot index into a value of type `Foo` + --> $DIR/slice-2.rs:10:6 + | +LL | &x[Foo..Foo]; + | ^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0608`. diff --git a/src/test/ui/array-slice-vec/slice-mut-2.rs b/src/test/ui/array-slice-vec/slice-mut-2.rs new file mode 100644 index 000000000..216edbb78 --- /dev/null +++ b/src/test/ui/array-slice-vec/slice-mut-2.rs @@ -0,0 +1,8 @@ +// Test mutability and slicing syntax. + +fn main() { + let x: &[isize] = &[1, 2, 3, 4, 5]; + // Can't mutably slice an immutable slice + let slice: &mut [isize] = &mut [0, 1]; + let _ = &mut x[2..4]; //~ERROR cannot borrow `*x` as mutable, as it is behind a `&` reference +} diff --git a/src/test/ui/array-slice-vec/slice-mut-2.stderr b/src/test/ui/array-slice-vec/slice-mut-2.stderr new file mode 100644 index 000000000..bad026877 --- /dev/null +++ b/src/test/ui/array-slice-vec/slice-mut-2.stderr @@ -0,0 +1,12 @@ +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/slice-mut-2.rs:7:18 + | +LL | let x: &[isize] = &[1, 2, 3, 4, 5]; + | ---------------- help: consider changing this to be a mutable reference: `&mut [1, 2, 3, 4, 5]` +... +LL | let _ = &mut x[2..4]; + | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/array-slice-vec/slice-mut.rs b/src/test/ui/array-slice-vec/slice-mut.rs new file mode 100644 index 000000000..e9989f0f4 --- /dev/null +++ b/src/test/ui/array-slice-vec/slice-mut.rs @@ -0,0 +1,12 @@ +// Test mutability and slicing syntax. + +fn main() { + let x: &[isize] = &[1, 2, 3, 4, 5]; + // Immutable slices are not mutable. + + let y: &mut[_] = &x[2..4]; + //~^ ERROR mismatched types + //~| expected mutable reference `&mut [_]` + //~| found reference `&[isize]` + //~| types differ in mutability +} diff --git a/src/test/ui/array-slice-vec/slice-mut.stderr b/src/test/ui/array-slice-vec/slice-mut.stderr new file mode 100644 index 000000000..7d34defc1 --- /dev/null +++ b/src/test/ui/array-slice-vec/slice-mut.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/slice-mut.rs:7:22 + | +LL | let y: &mut[_] = &x[2..4]; + | ------- ^^^^^^^^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut [_]` + found reference `&[isize]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/array-slice-vec/slice-of-zero-size-elements.rs b/src/test/ui/array-slice-vec/slice-of-zero-size-elements.rs new file mode 100644 index 000000000..83b08a3db --- /dev/null +++ b/src/test/ui/array-slice-vec/slice-of-zero-size-elements.rs @@ -0,0 +1,53 @@ +// run-pass +#![allow(stable_features)] + +// compile-flags: -C debug-assertions + +#![feature(iter_to_slice)] + +use std::slice; + +fn foo<T>(v: &[T]) -> Option<&[T]> { + let mut it = v.iter(); + for _ in 0..5 { + let _ = it.next(); + } + Some(it.as_slice()) +} + +fn foo_mut<T>(v: &mut [T]) -> Option<&mut [T]> { + let mut it = v.iter_mut(); + for _ in 0..5 { + let _ = it.next(); + } + Some(it.into_slice()) +} + +pub fn main() { + // In a slice of zero-size elements the pointer is meaningless. + // Ensure iteration still works even if the pointer is at the end of the address space. + let slice: &[()] = unsafe { slice::from_raw_parts(-5isize as *const (), 10) }; + assert_eq!(slice.len(), 10); + assert_eq!(slice.iter().count(), 10); + + // .nth() on the iterator should also behave correctly + let mut it = slice.iter(); + assert!(it.nth(5).is_some()); + assert_eq!(it.count(), 4); + + // Converting Iter to a slice should never have a null pointer + assert!(foo(slice).is_some()); + + // Test mutable iterators as well + let slice: &mut [()] = unsafe { slice::from_raw_parts_mut(-5isize as *mut (), 10) }; + assert_eq!(slice.len(), 10); + assert_eq!(slice.iter_mut().count(), 10); + + { + let mut it = slice.iter_mut(); + assert!(it.nth(5).is_some()); + assert_eq!(it.count(), 4); + } + + assert!(foo_mut(slice).is_some()) +} diff --git a/src/test/ui/array-slice-vec/slice-panic-1.rs b/src/test/ui/array-slice-vec/slice-panic-1.rs new file mode 100644 index 000000000..3829078ab --- /dev/null +++ b/src/test/ui/array-slice-vec/slice-panic-1.rs @@ -0,0 +1,27 @@ +// run-pass +// needs-unwind + +// ignore-emscripten no threads support + +// Test that if a slicing expr[..] fails, the correct cleanups happen. + + +use std::thread; + +struct Foo; + +static mut DTOR_COUNT: isize = 0; + +impl Drop for Foo { + fn drop(&mut self) { unsafe { DTOR_COUNT += 1; } } +} + +fn foo() { + let x: &[_] = &[Foo, Foo]; + let _ = &x[3..4]; +} + +fn main() { + let _ = thread::spawn(move|| foo()).join(); + unsafe { assert_eq!(DTOR_COUNT, 2); } +} diff --git a/src/test/ui/array-slice-vec/slice-panic-2.rs b/src/test/ui/array-slice-vec/slice-panic-2.rs new file mode 100644 index 000000000..d83c611d3 --- /dev/null +++ b/src/test/ui/array-slice-vec/slice-panic-2.rs @@ -0,0 +1,31 @@ +// run-pass +// needs-unwind + +// ignore-emscripten no threads support + +// Test that if a slicing expr[..] fails, the correct cleanups happen. + + +use std::thread; + +struct Foo; + +static mut DTOR_COUNT: isize = 0; + +impl Drop for Foo { + fn drop(&mut self) { unsafe { DTOR_COUNT += 1; } } +} + +fn bar() -> usize { + panic!(); +} + +fn foo() { + let x: &[_] = &[Foo, Foo]; + let _ = &x[3..bar()]; +} + +fn main() { + let _ = thread::spawn(move|| foo()).join(); + unsafe { assert_eq!(DTOR_COUNT, 2); } +} diff --git a/src/test/ui/array-slice-vec/slice-pat-type-mismatches.rs b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.rs new file mode 100644 index 000000000..521b898e7 --- /dev/null +++ b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.rs @@ -0,0 +1,36 @@ +fn main() { + match "foo".to_string() { + ['f', 'o', ..] => {} + //~^ ERROR expected an array or slice, found `String` + _ => { } + }; + + // Note that this one works with default binding modes. + match &[0, 1, 2] { + [..] => {} + }; + + match &[0, 1, 2] { + &[..] => {} // ok + }; + + match [0, 1, 2] { + [0] => {}, //~ ERROR pattern requires + + [0, 1, x @ ..] => { + let a: [_; 1] = x; + } + [0, 1, 2, 3, x @ ..] => {} //~ ERROR pattern requires + }; + + match does_not_exist { //~ ERROR cannot find value `does_not_exist` in this scope + [] => {} + }; +} + +fn another_fn_to_avoid_suppression() { + match Default::default() + { + [] => {} //~ ERROR type annotations needed + }; +} diff --git a/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr new file mode 100644 index 000000000..70a4cbebe --- /dev/null +++ b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr @@ -0,0 +1,34 @@ +error[E0425]: cannot find value `does_not_exist` in this scope + --> $DIR/slice-pat-type-mismatches.rs:26:11 + | +LL | match does_not_exist { + | ^^^^^^^^^^^^^^ not found in this scope + +error[E0529]: expected an array or slice, found `String` + --> $DIR/slice-pat-type-mismatches.rs:3:9 + | +LL | ['f', 'o', ..] => {} + | ^^^^^^^^^^^^^^ pattern cannot match with input type `String` + +error[E0527]: pattern requires 1 element but array has 3 + --> $DIR/slice-pat-type-mismatches.rs:18:9 + | +LL | [0] => {}, + | ^^^ expected 3 elements + +error[E0528]: pattern requires at least 4 elements but array has 3 + --> $DIR/slice-pat-type-mismatches.rs:23:9 + | +LL | [0, 1, 2, 3, x @ ..] => {} + | ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements + +error[E0282]: type annotations needed + --> $DIR/slice-pat-type-mismatches.rs:34:9 + | +LL | [] => {} + | ^^ cannot infer type + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0282, E0425, E0527, E0528, E0529. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/array-slice-vec/slice-to-vec-comparison.rs b/src/test/ui/array-slice-vec/slice-to-vec-comparison.rs new file mode 100644 index 000000000..7026a4900 --- /dev/null +++ b/src/test/ui/array-slice-vec/slice-to-vec-comparison.rs @@ -0,0 +1,6 @@ +fn main() { + let a = &[]; + let b: &Vec<u8> = &vec![]; + a > b; + //~^ ERROR mismatched types +} diff --git a/src/test/ui/array-slice-vec/slice-to-vec-comparison.stderr b/src/test/ui/array-slice-vec/slice-to-vec-comparison.stderr new file mode 100644 index 000000000..e3b3b040f --- /dev/null +++ b/src/test/ui/array-slice-vec/slice-to-vec-comparison.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/slice-to-vec-comparison.rs:4:9 + | +LL | a > b; + | ^ expected array of 0 elements, found struct `Vec` + | + = note: expected reference `&[_; 0]` + found reference `&Vec<u8>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/array-slice-vec/slice.rs b/src/test/ui/array-slice-vec/slice.rs new file mode 100644 index 000000000..a514e2027 --- /dev/null +++ b/src/test/ui/array-slice-vec/slice.rs @@ -0,0 +1,81 @@ +// run-pass +#![allow(unused_variables)] + +// Test slicing sugar. + +extern crate core; +use core::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull}; + +static mut COUNT: usize = 0; + +struct Foo; + +impl Index<Range<Foo>> for Foo { + type Output = Foo; + fn index(&self, index: Range<Foo>) -> &Foo { + unsafe { COUNT += 1; } + self + } +} +impl Index<RangeTo<Foo>> for Foo { + type Output = Foo; + fn index(&self, index: RangeTo<Foo>) -> &Foo { + unsafe { COUNT += 1; } + self + } +} +impl Index<RangeFrom<Foo>> for Foo { + type Output = Foo; + fn index(&self, index: RangeFrom<Foo>) -> &Foo { + unsafe { COUNT += 1; } + self + } +} +impl Index<RangeFull> for Foo { + type Output = Foo; + fn index(&self, _index: RangeFull) -> &Foo { + unsafe { COUNT += 1; } + self + } +} + +impl IndexMut<Range<Foo>> for Foo { + fn index_mut(&mut self, index: Range<Foo>) -> &mut Foo { + unsafe { COUNT += 1; } + self + } +} +impl IndexMut<RangeTo<Foo>> for Foo { + fn index_mut(&mut self, index: RangeTo<Foo>) -> &mut Foo { + unsafe { COUNT += 1; } + self + } +} +impl IndexMut<RangeFrom<Foo>> for Foo { + fn index_mut(&mut self, index: RangeFrom<Foo>) -> &mut Foo { + unsafe { COUNT += 1; } + self + } +} +impl IndexMut<RangeFull> for Foo { + fn index_mut(&mut self, _index: RangeFull) -> &mut Foo { + unsafe { COUNT += 1; } + self + } +} + + +fn main() { + let mut x = Foo; + let _ = &x[..]; + let _ = &x[Foo..]; + let _ = &x[..Foo]; + let _ = &x[Foo..Foo]; + let _ = &mut x[..]; + let _ = &mut x[Foo..]; + let _ = &mut x[..Foo]; + let _ = &mut x[Foo..Foo]; + unsafe { + assert_eq!(COUNT, 8); + } +} diff --git a/src/test/ui/array-slice-vec/slice_binary_search.rs b/src/test/ui/array-slice-vec/slice_binary_search.rs new file mode 100644 index 000000000..4d8022ecb --- /dev/null +++ b/src/test/ui/array-slice-vec/slice_binary_search.rs @@ -0,0 +1,22 @@ +// run-pass + +// Test binary_search_by_key lifetime. Issue #34683 + +#[allow(dead_code)] +#[derive(Debug)] +struct Assignment { + topic: String, + partition: i32, +} + +fn main() { + let xs = vec![ + Assignment { topic: "abc".into(), partition: 1 }, + Assignment { topic: "def".into(), partition: 2 }, + Assignment { topic: "ghi".into(), partition: 3 }, + ]; + + let key: &str = "def"; + let r = xs.binary_search_by_key(&key, |e| &e.topic); + assert_eq!(Ok(1), r.map(|i| i)); +} diff --git a/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs new file mode 100644 index 000000000..97e33624b --- /dev/null +++ b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs @@ -0,0 +1,11 @@ +fn main() { + let a: &[u8] = &[]; + match a { + [1, tail @ .., tail @ ..] => {}, + //~^ ERROR identifier `tail` is bound more than once in the same pattern + //~| ERROR `..` can only be used once per slice pattern + _ => () + } +} + +const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr new file mode 100644 index 000000000..4d6078788 --- /dev/null +++ b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr @@ -0,0 +1,24 @@ +error[E0416]: identifier `tail` is bound more than once in the same pattern + --> $DIR/subslice-only-once-semantic-restriction.rs:4:24 + | +LL | [1, tail @ .., tail @ ..] => {}, + | ^^^^ used in a pattern more than once + +error: `..` can only be used once per slice pattern + --> $DIR/subslice-only-once-semantic-restriction.rs:4:31 + | +LL | [1, tail @ .., tail @ ..] => {}, + | -- ^^ can only be used once per slice pattern + | | + | previously used here + +error[E0308]: mismatched types + --> $DIR/subslice-only-once-semantic-restriction.rs:11:30 + | +LL | const RECOVERY_WITNESS: () = 0; + | ^ expected `()`, found integer + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0416. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs b/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs new file mode 100644 index 000000000..5a6283e9f --- /dev/null +++ b/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs @@ -0,0 +1,96 @@ +// Test that slice subslice patterns are correctly handled in const evaluation. + +// run-pass + +#[derive(PartialEq, Debug, Clone)] +struct N(u8); + +#[derive(PartialEq, Debug, Clone)] +struct Z; + +macro_rules! n { + ($($e:expr),* $(,)?) => { + [$(N($e)),*] + } +} + +// This macro has an unused variable so that it can be repeated base on the +// number of times a repeated variable (`$e` in `z`) occurs. +macro_rules! zed { + ($e:expr) => { Z } +} + +macro_rules! z { + ($($e:expr),* $(,)?) => { + [$(zed!($e)),*] + } +} + +// Compare constant evaluation and runtime evaluation of a given expression. +macro_rules! compare_evaluation_inner { + ($e:expr, $t:ty $(,)?) => {{ + const CONST_EVAL: $t = $e; + const fn const_eval() -> $t { $e } + static CONST_EVAL2: $t = const_eval(); + let runtime_eval = $e; + assert_eq!(CONST_EVAL, runtime_eval); + assert_eq!(CONST_EVAL2, runtime_eval); + }} +} + +// Compare the result of matching `$e` against `$p` using both `if let` and +// `match`. +macro_rules! compare_evaluation { + ($p:pat, $e:expr, $matches:expr, $t:ty $(,)?) => {{ + compare_evaluation_inner!(if let $p = $e as &[_] { $matches } else { None }, $t); + compare_evaluation_inner!(match $e as &[_] { $p => $matches, _ => None }, $t); + }} +} + +// Repeat `$test`, substituting the given macro variables with the given +// identifiers. +// +// For example: +// +// repeat! { +// ($name); X; Y: +// struct $name; +// } +// +// Expands to: +// +// struct X; struct Y; +// +// This is used to repeat the tests using both the `N` and `Z` +// types. +macro_rules! repeat { + (($($dollar:tt $placeholder:ident)*); $($($values:ident),+);*: $($test:tt)*) => { + macro_rules! single { + ($($dollar $placeholder:ident),*) => { $($test)* } + } + $(single!($($values),+);)* + } +} + +fn main() { + repeat! { + ($arr $Ty); n, N; z, Z: + compare_evaluation!([_, x @ .., _], &$arr!(1, 2, 3, 4), Some(x), Option<&'static [$Ty]>); + compare_evaluation!([x, .., _], &$arr!(1, 2, 3, 4), Some(x), Option<&'static $Ty>); + compare_evaluation!([_, .., x], &$arr!(1, 2, 3, 4), Some(x), Option<&'static $Ty>); + + compare_evaluation!([_, x @ .., _], &$arr!(1, 2), Some(x), Option<&'static [$Ty]>); + compare_evaluation!([x, .., _], &$arr!(1, 2), Some(x), Option<&'static $Ty>); + compare_evaluation!([_, .., x], &$arr!(1, 2), Some(x), Option<&'static $Ty>); + + compare_evaluation!([_, x @ .., _], &$arr!(1), Some(x), Option<&'static [$Ty]>); + compare_evaluation!([x, .., _], &$arr!(1), Some(x), Option<&'static $Ty>); + compare_evaluation!([_, .., x], &$arr!(1), Some(x), Option<&'static $Ty>); + } + + compare_evaluation!([N(x), .., _], &n!(1, 2, 3, 4), Some(x), Option<&'static u8>); + compare_evaluation!([_, .., N(x)], &n!(1, 2, 3, 4), Some(x), Option<&'static u8>); + + compare_evaluation!([N(x), .., _], &n!(1, 2), Some(x), Option<&'static u8>); + compare_evaluation!([_, .., N(x)], &n!(1, 2), Some(x), Option<&'static u8>); +} diff --git a/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs b/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs new file mode 100644 index 000000000..0b793fa01 --- /dev/null +++ b/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs @@ -0,0 +1,95 @@ +// Test that array subslice patterns are correctly handled in const evaluation. + +// run-pass + +#[derive(PartialEq, Debug, Clone)] +struct N(u8); + +#[derive(PartialEq, Debug, Clone)] +struct Z; + +macro_rules! n { + ($($e:expr),* $(,)?) => { + [$(N($e)),*] + } +} + +// This macro has an unused variable so that it can be repeated base on the +// number of times a repeated variable (`$e` in `z`) occurs. +macro_rules! zed { + ($e:expr) => { Z } +} + +macro_rules! z { + ($($e:expr),* $(,)?) => { + [$(zed!($e)),*] + } +} + +// Compare constant evaluation and runtime evaluation of a given expression. +macro_rules! compare_evaluation { + ($e:expr, $t:ty $(,)?) => {{ + const CONST_EVAL: $t = $e; + const fn const_eval() -> $t { $e } + static CONST_EVAL2: $t = const_eval(); + let runtime_eval = $e; + assert_eq!(CONST_EVAL, runtime_eval); + assert_eq!(CONST_EVAL2, runtime_eval); + }} +} + +// Repeat `$test`, substituting the given macro variables with the given +// identifiers. +// +// For example: +// +// repeat! { +// ($name); X; Y: +// struct $name; +// } +// +// Expands to: +// +// struct X; struct Y; +// +// This is used to repeat the tests using both the `N` and `Z` +// types. +macro_rules! repeat { + (($($dollar:tt $placeholder:ident)*); $($($values:ident),+);*: $($test:tt)*) => { + macro_rules! single { + ($($dollar $placeholder:ident),*) => { $($test)* } + } + $(single!($($values),+);)* + } +} + +fn main() { + repeat! { + ($arr $Ty); n, N; z, Z: + compare_evaluation!({ let [_, x @ .., _] = $arr!(1, 2, 3, 4); x }, [$Ty; 2]); + compare_evaluation!({ let [_, ref x @ .., _] = $arr!(1, 2, 3, 4); x }, &'static [$Ty; 2]); + compare_evaluation!({ let [_, x @ .., _] = &$arr!(1, 2, 3, 4); x }, &'static [$Ty; 2]); + + compare_evaluation!({ let [_, _, x @ .., _, _] = $arr!(1, 2, 3, 4); x }, [$Ty; 0]); + compare_evaluation!( + { let [_, _, ref x @ .., _, _] = $arr!(1, 2, 3, 4); x }, + &'static [$Ty; 0], + ); + compare_evaluation!( + { let [_, _, x @ .., _, _] = &$arr!(1, 2, 3, 4); x }, + &'static [$Ty; 0], + ); + + compare_evaluation!({ let [_, .., x] = $arr!(1, 2, 3, 4); x }, $Ty); + compare_evaluation!({ let [_, .., ref x] = $arr!(1, 2, 3, 4); x }, &'static $Ty); + compare_evaluation!({ let [_, _y @ .., x] = &$arr!(1, 2, 3, 4); x }, &'static $Ty); + } + + compare_evaluation!({ let [_, .., N(x)] = n!(1, 2, 3, 4); x }, u8); + compare_evaluation!({ let [_, .., N(ref x)] = n!(1, 2, 3, 4); x }, &'static u8); + compare_evaluation!({ let [_, .., N(x)] = &n!(1, 2, 3, 4); x }, &'static u8); + + compare_evaluation!({ let [N(x), .., _] = n!(1, 2, 3, 4); x }, u8); + compare_evaluation!({ let [N(ref x), .., _] = n!(1, 2, 3, 4); x }, &'static u8); + compare_evaluation!({ let [N(x), .., _] = &n!(1, 2, 3, 4); x }, &'static u8); +} diff --git a/src/test/ui/array-slice-vec/variance-vec-covariant.rs b/src/test/ui/array-slice-vec/variance-vec-covariant.rs new file mode 100644 index 000000000..d7e64132f --- /dev/null +++ b/src/test/ui/array-slice-vec/variance-vec-covariant.rs @@ -0,0 +1,20 @@ +// run-pass + +// Test that vec is now covariant in its argument type. + +#![allow(dead_code)] + +fn foo<'a,'b>(v1: Vec<&'a i32>, v2: Vec<&'b i32>) -> i32 { + bar(v1, v2).cloned().unwrap_or(0) // only type checks if we can intersect 'a and 'b +} + +fn bar<'c>(v1: Vec<&'c i32>, v2: Vec<&'c i32>) -> Option<&'c i32> { + v1.get(0).cloned().or_else(|| v2.get(0).cloned()) +} + +fn main() { + let x = 22; + let y = 44; + assert_eq!(foo(vec![&x], vec![&y]), 22); + assert_eq!(foo(vec![&y], vec![&x]), 44); +} diff --git a/src/test/ui/array-slice-vec/vec-dst.rs b/src/test/ui/array-slice-vec/vec-dst.rs new file mode 100644 index 000000000..c58ddbc42 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-dst.rs @@ -0,0 +1,24 @@ +// run-pass + +pub fn main() { + // Tests for indexing into Box<[T; n]>/& [T; n] + let x: [isize; 3] = [1, 2, 3]; + let mut x: Box<[isize; 3]> = x.into(); + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); + x[1] = 45; + assert_eq!(x[0], 1); + assert_eq!(x[1], 45); + assert_eq!(x[2], 3); + + let mut x: [isize; 3] = [1, 2, 3]; + let x: &mut [isize; 3] = &mut x; + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); + x[1] = 45; + assert_eq!(x[0], 1); + assert_eq!(x[1], 45); + assert_eq!(x[2], 3); +} diff --git a/src/test/ui/array-slice-vec/vec-fixed-length.rs b/src/test/ui/array-slice-vec/vec-fixed-length.rs new file mode 100644 index 000000000..908c39c79 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-fixed-length.rs @@ -0,0 +1,24 @@ +// run-pass + + +use std::mem::size_of; + +#[cfg(not(target_pointer_width = "64"))] +fn test_big_vec() {} + +#[cfg(target_pointer_width = "64")] +fn test_big_vec() +{ + assert_eq!(size_of::<[u8; 1 << 32]>(), (1 << 32)); +} + +fn main() { + let x: [isize; 4] = [1, 2, 3, 4]; + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); + assert_eq!(x[3], 4); + + assert_eq!(size_of::<[u8; 4]>(), 4); + test_big_vec(); +} diff --git a/src/test/ui/array-slice-vec/vec-late-init.rs b/src/test/ui/array-slice-vec/vec-late-init.rs new file mode 100644 index 000000000..5dee36082 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-late-init.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(unused_mut)] + + +pub fn main() { + let mut later: Vec<isize> ; + if true { later = vec![1]; } else { later = vec![2]; } + println!("{}", later[0]); +} diff --git a/src/test/ui/array-slice-vec/vec-macro-no-std.rs b/src/test/ui/array-slice-vec/vec-macro-no-std.rs new file mode 100644 index 000000000..443895f7c --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-macro-no-std.rs @@ -0,0 +1,27 @@ +// run-pass + +// ignore-emscripten no no_std executables + +#![feature(lang_items, start, rustc_private)] +#![no_std] + +extern crate std as other; + +extern crate libc; + +#[macro_use] +extern crate alloc; + +use alloc::vec::Vec; + +// Issue #16806 + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + let x: Vec<u8> = vec![0, 1, 2]; + match x.last() { + Some(&2) => (), + _ => panic!(), + } + 0 +} diff --git a/src/test/ui/array-slice-vec/vec-macro-rvalue-scope.rs b/src/test/ui/array-slice-vec/vec-macro-rvalue-scope.rs new file mode 100644 index 000000000..bde010371 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-macro-rvalue-scope.rs @@ -0,0 +1,11 @@ +// run-pass + + +fn one() -> i32 { 1 } + +// Make sure the vec![...] macro doesn't introduce hidden rvalue +// scopes (such as blocks) around the element expressions. +pub fn main() { + assert_eq!(vec![&one(), &one(), &2], vec![&1, &1, &(one()+one())]); + assert_eq!(vec![&one(); 2], vec![&1, &one()]); +} diff --git a/src/test/ui/array-slice-vec/vec-macro-with-brackets.rs b/src/test/ui/array-slice-vec/vec-macro-with-brackets.rs new file mode 100644 index 000000000..6c95bd500 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-macro-with-brackets.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(unused_variables)] + +// pretty-expanded FIXME #23616 + +macro_rules! vec [ + ($($e:expr),*) => ({ + let mut _temp = ::std::vec::Vec::new(); + $(_temp.push($e);)* + _temp + }) +]; + +pub fn main() { + let my_vec = vec![1, 2, 3, 4, 5]; +} diff --git a/src/test/ui/array-slice-vec/vec-macro-with-comma-only.rs b/src/test/ui/array-slice-vec/vec-macro-with-comma-only.rs new file mode 100644 index 000000000..574a53c58 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-macro-with-comma-only.rs @@ -0,0 +1,3 @@ +pub fn main() { + vec![,]; //~ ERROR no rules expected the token `,` +} diff --git a/src/test/ui/array-slice-vec/vec-macro-with-comma-only.stderr b/src/test/ui/array-slice-vec/vec-macro-with-comma-only.stderr new file mode 100644 index 000000000..abbee347c --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-macro-with-comma-only.stderr @@ -0,0 +1,8 @@ +error: no rules expected the token `,` + --> $DIR/vec-macro-with-comma-only.rs:2:10 + | +LL | vec![,]; + | ^ no rules expected this token in macro call + +error: aborting due to previous error + diff --git a/src/test/ui/array-slice-vec/vec-macro-with-trailing-comma.rs b/src/test/ui/array-slice-vec/vec-macro-with-trailing-comma.rs new file mode 100644 index 000000000..f7a51f9c4 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-macro-with-trailing-comma.rs @@ -0,0 +1,8 @@ +// run-pass + + + +pub fn main() { + assert_eq!(vec![1], vec![1,]); + assert_eq!(vec![1, 2, 3], vec![1, 2, 3,]); +} diff --git a/src/test/ui/array-slice-vec/vec-matching-autoslice.rs b/src/test/ui/array-slice-vec/vec-matching-autoslice.rs new file mode 100644 index 000000000..8179edf42 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-matching-autoslice.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620 + +pub fn main() { + let x = [1, 2, 3]; + match x { + [2, _, _] => panic!(), + [1, a, b] => { + assert_eq!([a, b], [2, 3]); + } + [_, _, _] => panic!(), + } + + let y = ([(1, true), (2, false)], 0.5f64); + match y { + ([(1, a), (b, false)], _) => { + assert_eq!(a, true); + assert_eq!(b, 2); + } + ([_, _], 0.5) => panic!(), + ([_, _], _) => panic!(), + } +} diff --git a/src/test/ui/array-slice-vec/vec-matching-fixed.rs b/src/test/ui/array-slice-vec/vec-matching-fixed.rs new file mode 100644 index 000000000..fdeb7e4fd --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-matching-fixed.rs @@ -0,0 +1,30 @@ +// run-pass + +fn a() { + let x = [1, 2, 3]; + match x { + [1, 2, 4] => unreachable!(), + [0, 2, 3, ..] => unreachable!(), + [0, .., 3] => unreachable!(), + [0, ..] => unreachable!(), + [1, 2, 3] => (), + [_, _, _] => unreachable!(), + } + match x { + [..] => (), + } + match x { + [_, _, _, ..] => (), + } + match x { + [a, b, c] => { + assert_eq!(1, a); + assert_eq!(2, b); + assert_eq!(3, c); + } + } +} + +pub fn main() { + a(); +} diff --git a/src/test/ui/array-slice-vec/vec-matching-fold.rs b/src/test/ui/array-slice-vec/vec-matching-fold.rs new file mode 100644 index 000000000..998899271 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-matching-fold.rs @@ -0,0 +1,46 @@ +// run-pass + +use std::fmt::Debug; + +fn foldl<T, U, F>(values: &[T], + initial: U, + mut function: F) + -> U where + U: Clone+Debug, T:Debug, + F: FnMut(U, &T) -> U, +{ match values { + &[ref head, ref tail @ ..] => + foldl(tail, function(initial, head), function), + &[] => { + // FIXME: call guards + let res = initial.clone(); res + } + } +} + +fn foldr<T, U, F>(values: &[T], + initial: U, + mut function: F) + -> U where + U: Clone, + F: FnMut(&T, U) -> U, +{ + match values { + &[ref head @ .., ref tail] => + foldr(head, function(tail, initial), function), + &[] => { + // FIXME: call guards + let res = initial.clone(); res + } + } +} + +pub fn main() { + let x = &[1, 2, 3, 4, 5]; + + let product = foldl(x, 1, |a, b| a * *b); + assert_eq!(product, 120); + + let sum = foldr(x, 0, |a, b| *a + b); + assert_eq!(sum, 15); +} diff --git a/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs b/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs new file mode 100644 index 000000000..ed34f074a --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(unused_variables)] + +pub fn main() { + let x = &[1, 2, 3, 4, 5]; + let x: &[isize] = &[1, 2, 3, 4, 5]; + if !x.is_empty() { + let el = match x { + &[1, ref tail @ ..] => &tail[0], + _ => unreachable!() + }; + println!("{}", *el); + } +} diff --git a/src/test/ui/array-slice-vec/vec-matching.rs b/src/test/ui/array-slice-vec/vec-matching.rs new file mode 100644 index 000000000..7009244aa --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-matching.rs @@ -0,0 +1,142 @@ +// run-pass + +fn a() { + let x = [1]; + match x { + [a] => { + assert_eq!(a, 1); + } + } +} + +fn b() { + let x = [1, 2, 3]; + match x { + [a, b, c @ ..] => { + assert_eq!(a, 1); + assert_eq!(b, 2); + let expected: &[_] = &[3]; + assert_eq!(c, expected); + } + } + match x { + [a @ .., b, c] => { + let expected: &[_] = &[1]; + assert_eq!(a, expected); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + [a, b @ .., c] => { + assert_eq!(a, 1); + let expected: &[_] = &[2]; + assert_eq!(b, expected); + assert_eq!(c, 3); + } + } + match x { + [a, b, c] => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } +} + + +fn b_slice() { + let x : &[_] = &[1, 2, 3]; + match x { + &[a, b, ref c @ ..] => { + assert_eq!(a, 1); + assert_eq!(b, 2); + let expected: &[_] = &[3]; + assert_eq!(c, expected); + } + _ => unreachable!() + } + match x { + &[ref a @ .., b, c] => { + let expected: &[_] = &[1]; + assert_eq!(a, expected); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + _ => unreachable!() + } + match x { + &[a, ref b @ .., c] => { + assert_eq!(a, 1); + let expected: &[_] = &[2]; + assert_eq!(b, expected); + assert_eq!(c, 3); + } + _ => unreachable!() + } + match x { + &[a, b, c] => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + _ => unreachable!() + } +} + +fn c() { + let x = [1]; + match x { + [2, ..] => panic!(), + [..] => () + } +} + +fn d() { + let x = [1, 2, 3]; + let branch = match x { + [1, 1, ..] => 0, + [1, 2, 3, ..] => 1, + [1, 2, ..] => 2, + _ => 3 + }; + assert_eq!(branch, 1); +} + +fn e() { + let x: &[isize] = &[1, 2, 3]; + let a = match *x { + [1, 2] => 0, + [..] => 1, + }; + + assert_eq!(a, 1); + + let b = match *x { + [2, ..] => 0, + [1, 2, ..] => 1, + [_] => 2, + [..] => 3 + }; + + assert_eq!(b, 1); + + + let c = match *x { + [_, _, _, _, ..] => 0, + [1, 2, ..] => 1, + [_] => 2, + [..] => 3 + }; + + assert_eq!(c, 1); +} + +pub fn main() { + a(); + b(); + b_slice(); + c(); + d(); + e(); +} diff --git a/src/test/ui/array-slice-vec/vec-mut-iter-borrow.rs b/src/test/ui/array-slice-vec/vec-mut-iter-borrow.rs new file mode 100644 index 000000000..4aa737446 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-mut-iter-borrow.rs @@ -0,0 +1,7 @@ +fn main() { + let mut xs: Vec<isize> = vec![]; + + for x in &mut xs { + xs.push(1) //~ ERROR cannot borrow `xs` + } +} diff --git a/src/test/ui/array-slice-vec/vec-mut-iter-borrow.stderr b/src/test/ui/array-slice-vec/vec-mut-iter-borrow.stderr new file mode 100644 index 000000000..0ec263c85 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-mut-iter-borrow.stderr @@ -0,0 +1,14 @@ +error[E0499]: cannot borrow `xs` as mutable more than once at a time + --> $DIR/vec-mut-iter-borrow.rs:5:9 + | +LL | for x in &mut xs { + | ------- + | | + | first mutable borrow occurs here + | first borrow later used here +LL | xs.push(1) + | ^^^^^^^^^^ second mutable borrow occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/array-slice-vec/vec-overrun.rs b/src/test/ui/array-slice-vec/vec-overrun.rs new file mode 100644 index 000000000..bdc7d507d --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-overrun.rs @@ -0,0 +1,12 @@ +// run-fail +// error-pattern:index out of bounds: the len is 1 but the index is 2 +// ignore-emscripten no processes + +fn main() { + let v: Vec<isize> = vec![10]; + let x: usize = 0; + assert_eq!(v[x], 10); + // Bounds-check panic. + + assert_eq!(v[x + 2], 20); +} diff --git a/src/test/ui/array-slice-vec/vec-repeat-with-cast.rs b/src/test/ui/array-slice-vec/vec-repeat-with-cast.rs new file mode 100644 index 000000000..3e0e18873 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-repeat-with-cast.rs @@ -0,0 +1,5 @@ +// run-pass + +// pretty-expanded FIXME #23616 + +pub fn main() { let _a = [0; 1 as usize]; } diff --git a/src/test/ui/array-slice-vec/vec-res-add.rs b/src/test/ui/array-slice-vec/vec-res-add.rs new file mode 100644 index 000000000..57b552ee5 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-res-add.rs @@ -0,0 +1,19 @@ +#[derive(Debug)] +struct R { + i:isize +} + +fn r(i:isize) -> R { R { i: i } } + +impl Drop for R { + fn drop(&mut self) {} +} + +fn main() { + // This can't make sense as it would copy the classes + let i = vec![r(0)]; + let j = vec![r(1)]; + let k = i + j; + //~^ ERROR cannot add `Vec<R>` to `Vec<R>` + println!("{:?}", j); +} diff --git a/src/test/ui/array-slice-vec/vec-res-add.stderr b/src/test/ui/array-slice-vec/vec-res-add.stderr new file mode 100644 index 000000000..751127136 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-res-add.stderr @@ -0,0 +1,11 @@ +error[E0369]: cannot add `Vec<R>` to `Vec<R>` + --> $DIR/vec-res-add.rs:16:15 + | +LL | let k = i + j; + | - ^ - Vec<R> + | | + | Vec<R> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/array-slice-vec/vec-tail-matching.rs b/src/test/ui/array-slice-vec/vec-tail-matching.rs new file mode 100644 index 000000000..5f1699227 --- /dev/null +++ b/src/test/ui/array-slice-vec/vec-tail-matching.rs @@ -0,0 +1,34 @@ +// run-pass + +struct Foo { + string: &'static str +} + +pub fn main() { + let x = [ + Foo { string: "foo" }, + Foo { string: "bar" }, + Foo { string: "baz" } + ]; + match x { + [ref first, ref tail @ ..] => { + assert_eq!(first.string, "foo"); + assert_eq!(tail.len(), 2); + assert_eq!(tail[0].string, "bar"); + assert_eq!(tail[1].string, "baz"); + + match *(tail as &[_]) { + [Foo { .. }, _, Foo { .. }, ref _tail @ ..] => { + unreachable!(); + } + [Foo { string: ref a }, Foo { string: ref b }] => { + assert_eq!("bar", &a[0..a.len()]); + assert_eq!("baz", &b[0..b.len()]); + } + _ => { + unreachable!(); + } + } + } + } +} diff --git a/src/test/ui/array-slice-vec/vector-cast-weirdness.rs b/src/test/ui/array-slice-vec/vector-cast-weirdness.rs new file mode 100644 index 000000000..e8f2c7147 --- /dev/null +++ b/src/test/ui/array-slice-vec/vector-cast-weirdness.rs @@ -0,0 +1,34 @@ +// Issue #14893. Tests that casts from vectors don't behave strangely in the +// presence of the `_` type shorthand notation. +// +// Update: after a change to the way casts are done, we have more type information +// around and so the errors here are no longer exactly the same. +// +// Update: With PR #81479 some of the previously rejected cases are now allowed. +// New test cases added. + +struct X { + y: [u8; 2], +} + +fn main() { + let x1 = X { y: [0, 0] }; + + // No longer a type mismatch - the `_` can be fully resolved by type inference. + let p1: *const u8 = &x1.y as *const _; + let p1: *mut u8 = &x1.y as *mut _; + //~^ ERROR: casting `&[u8; 2]` as `*mut u8` is invalid + let t1: *const [u8; 2] = &x1.y as *const _; + let t1: *mut [u8; 2] = &x1.y as *mut _; + //~^ ERROR: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid + let h1: *const [u8; 2] = &x1.y as *const [u8; 2]; + let t1: *mut [u8; 2] = &x1.y as *mut [u8; 2]; + //~^ ERROR: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid + + let mut x1 = X { y: [0, 0] }; + + let p1: *mut u8 = &mut x1.y as *mut _; + let p2: *const u8 = &mut x1.y as *const _; + let t1: *mut [u8; 2] = &mut x1.y as *mut _; + let h1: *mut [u8; 2] = &mut x1.y as *mut [u8; 2]; +} diff --git a/src/test/ui/array-slice-vec/vector-cast-weirdness.stderr b/src/test/ui/array-slice-vec/vector-cast-weirdness.stderr new file mode 100644 index 000000000..6fdb1ac9e --- /dev/null +++ b/src/test/ui/array-slice-vec/vector-cast-weirdness.stderr @@ -0,0 +1,21 @@ +error[E0606]: casting `&[u8; 2]` as `*mut u8` is invalid + --> $DIR/vector-cast-weirdness.rs:19:23 + | +LL | let p1: *mut u8 = &x1.y as *mut _; + | ^^^^^^^^^^^^^^^ + +error[E0606]: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid + --> $DIR/vector-cast-weirdness.rs:22:28 + | +LL | let t1: *mut [u8; 2] = &x1.y as *mut _; + | ^^^^^^^^^^^^^^^ + +error[E0606]: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid + --> $DIR/vector-cast-weirdness.rs:25:28 + | +LL | let t1: *mut [u8; 2] = &x1.y as *mut [u8; 2]; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0606`. diff --git a/src/test/ui/array-slice-vec/vector-no-ann-2.rs b/src/test/ui/array-slice-vec/vector-no-ann-2.rs new file mode 100644 index 000000000..e2055f551 --- /dev/null +++ b/src/test/ui/array-slice-vec/vector-no-ann-2.rs @@ -0,0 +1,7 @@ +// run-pass + +// pretty-expanded FIXME #23616 + +pub fn main() { + let _quux: Box<Vec<usize>> = Box::new(Vec::new()); +} diff --git a/src/test/ui/array-slice-vec/vector-no-ann.rs b/src/test/ui/array-slice-vec/vector-no-ann.rs new file mode 100644 index 000000000..1f11d9c8d --- /dev/null +++ b/src/test/ui/array-slice-vec/vector-no-ann.rs @@ -0,0 +1,4 @@ +fn main() { + let _foo = Vec::new(); + //~^ ERROR type annotations needed +} diff --git a/src/test/ui/array-slice-vec/vector-no-ann.stderr b/src/test/ui/array-slice-vec/vector-no-ann.stderr new file mode 100644 index 000000000..d2ea08aa4 --- /dev/null +++ b/src/test/ui/array-slice-vec/vector-no-ann.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `Vec<T>` + --> $DIR/vector-no-ann.rs:2:9 + | +LL | let _foo = Vec::new(); + | ^^^^ + | +help: consider giving `_foo` an explicit type, where the type for type parameter `T` is specified + | +LL | let _foo: Vec<T> = Vec::new(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. |