From: Bastian Kauschke Date: Sat, 30 May 2020 17:42:22 +0000 (+0200) Subject: merge coercion test folders X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=0b5007e4b7c4ee9a3d0356e54f91ef3def094a0a;p=rust.git merge coercion test folders --- diff --git a/src/test/ui/coerce/coerce-expect-unsized.rs b/src/test/ui/coerce/coerce-expect-unsized.rs deleted file mode 100644 index d486fdf73ab..00000000000 --- a/src/test/ui/coerce/coerce-expect-unsized.rs +++ /dev/null @@ -1,44 +0,0 @@ -// run-pass -#![allow(unused_braces)] -#![feature(box_syntax)] - -use std::cell::RefCell; -use std::fmt::Debug; -use std::rc::Rc; - -// Check that coercions apply at the pointer level and don't cause -// rvalue expressions to be unsized. See #20169 for more information. - -pub fn main() { - let _: Box<[isize]> = Box::new({ [1, 2, 3] }); - let _: Box<[isize]> = Box::new(if true { [1, 2, 3] } else { [1, 3, 4] }); - let _: Box<[isize]> = Box::new(match true { true => [1, 2, 3], false => [1, 3, 4] }); - let _: Box _> = Box::new({ |x| (x as u8) }); - let _: Box = Box::new(if true { false } else { true }); - let _: Box = Box::new(match true { true => 'a', false => 'b' }); - - let _: &[isize] = &{ [1, 2, 3] }; - let _: &[isize] = &if true { [1, 2, 3] } else { [1, 3, 4] }; - let _: &[isize] = &match true { true => [1, 2, 3], false => [1, 3, 4] }; - let _: &dyn Fn(isize) -> _ = &{ |x| (x as u8) }; - let _: &dyn Debug = &if true { false } else { true }; - let _: &dyn Debug = &match true { true => 'a', false => 'b' }; - - let _: &str = &{ String::new() }; - let _: &str = &if true { String::from("...") } else { 5.to_string() }; - let _: &str = &match true { - true => format!("{}", false), - false => ["x", "y"].join("+") - }; - - let _: Box<[isize]> = Box::new([1, 2, 3]); - let _: Box _> = Box::new(|x| (x as u8)); - - let _: Rc> = Rc::new(RefCell::new([1, 2, 3])); - let _: Rc _>> = Rc::new(RefCell::new(|x| (x as u8))); - - let _: Vec _>> = vec![ - Box::new(|x| (x as u8)), - Box::new(|x| (x as i16 as u8)), - ]; -} diff --git a/src/test/ui/coerce/coerce-overloaded-autoderef.rs b/src/test/ui/coerce/coerce-overloaded-autoderef.rs deleted file mode 100644 index d5484607c8b..00000000000 --- a/src/test/ui/coerce/coerce-overloaded-autoderef.rs +++ /dev/null @@ -1,68 +0,0 @@ -// run-pass -#![allow(unused_braces)] -#![allow(dead_code)] -// pretty-expanded FIXME #23616 - -use std::rc::Rc; - -// Examples from the "deref coercions" RFC, at rust-lang/rfcs#241. - -fn use_ref(_: &T) {} -fn use_mut(_: &mut T) {} - -fn use_rc(t: Rc) { - use_ref(&*t); // what you have to write today - use_ref(&t); // what you'd be able to write - use_ref(&&&&&&t); - use_ref(&mut &&&&&t); - use_ref(&&&mut &&&t); -} - -fn use_mut_box(mut t: &mut Box) { - use_mut(&mut *t); // what you have to write today - use_mut(t); // what you'd be able to write - use_mut(&mut &mut &mut t); - - use_ref(&*t); // what you have to write today - use_ref(t); // what you'd be able to write - use_ref(&&&&&&t); - use_ref(&mut &&&&&t); - use_ref(&&&mut &&&t); -} - -fn use_nested(t: &Box) { - use_ref(&**t); // what you have to write today - use_ref(t); // what you'd be able to write (note: recursive deref) - use_ref(&&&&&&t); - use_ref(&mut &&&&&t); - use_ref(&&&mut &&&t); -} - -fn use_slice(_: &[u8]) {} -fn use_slice_mut(_: &mut [u8]) {} - -fn use_vec(mut v: Vec) { - use_slice_mut(&mut v[..]); // what you have to write today - use_slice_mut(&mut v); // what you'd be able to write - use_slice_mut(&mut &mut &mut v); - - use_slice(&v[..]); // what you have to write today - use_slice(&v); // what you'd be able to write - use_slice(&&&&&&v); - use_slice(&mut &&&&&v); - use_slice(&&&mut &&&v); -} - -fn use_vec_ref(v: &Vec) { - use_slice(&v[..]); // what you have to write today - use_slice(v); // what you'd be able to write - use_slice(&&&&&&v); - use_slice(&mut &&&&&v); - use_slice(&&&mut &&&v); -} - -fn use_op_rhs(s: &mut String) { - *s += {&String::from(" ")}; -} - -pub fn main() {} diff --git a/src/test/ui/coerce/coerce-reborrow-imm-ptr-arg.rs b/src/test/ui/coerce/coerce-reborrow-imm-ptr-arg.rs deleted file mode 100644 index f033e1b5d2b..00000000000 --- a/src/test/ui/coerce/coerce-reborrow-imm-ptr-arg.rs +++ /dev/null @@ -1,17 +0,0 @@ -// run-pass -#![allow(dead_code)] -// pretty-expanded FIXME #23616 - -fn negate(x: &isize) -> isize { - -*x -} - -fn negate_mut(y: &mut isize) -> isize { - negate(y) -} - -fn negate_imm(y: &isize) -> isize { - negate(y) -} - -pub fn main() {} diff --git a/src/test/ui/coerce/coerce-reborrow-imm-ptr-rcvr.rs b/src/test/ui/coerce/coerce-reborrow-imm-ptr-rcvr.rs deleted file mode 100644 index 64a365229cb..00000000000 --- a/src/test/ui/coerce/coerce-reborrow-imm-ptr-rcvr.rs +++ /dev/null @@ -1,18 +0,0 @@ -// run-pass - -struct SpeechMaker { - speeches: usize -} - -impl SpeechMaker { - pub fn how_many(&self) -> usize { self.speeches } -} - -fn foo(speaker: &SpeechMaker) -> usize { - speaker.how_many() + 33 -} - -pub fn main() { - let lincoln = SpeechMaker {speeches: 22}; - assert_eq!(foo(&lincoln), 55); -} diff --git a/src/test/ui/coerce/coerce-reborrow-imm-vec-arg.rs b/src/test/ui/coerce/coerce-reborrow-imm-vec-arg.rs deleted file mode 100644 index c2aaae1c73e..00000000000 --- a/src/test/ui/coerce/coerce-reborrow-imm-vec-arg.rs +++ /dev/null @@ -1,19 +0,0 @@ -// run-pass -#![allow(dead_code)] -// pretty-expanded FIXME #23616 - -fn sum(x: &[isize]) -> isize { - let mut sum = 0; - for y in x { sum += *y; } - return sum; -} - -fn sum_mut(y: &mut [isize]) -> isize { - sum(y) -} - -fn sum_imm(y: &[isize]) -> isize { - sum(y) -} - -pub fn main() {} diff --git a/src/test/ui/coerce/coerce-reborrow-imm-vec-rcvr.rs b/src/test/ui/coerce/coerce-reborrow-imm-vec-rcvr.rs deleted file mode 100644 index 9a5652acf87..00000000000 --- a/src/test/ui/coerce/coerce-reborrow-imm-vec-rcvr.rs +++ /dev/null @@ -1,16 +0,0 @@ -// run-pass - - -fn bar(v: &mut [usize]) -> Vec { - v.to_vec() -} - -fn bip(v: &[usize]) -> Vec { - v.to_vec() -} - -pub fn main() { - let mut the_vec = vec![1, 2, 3, 100]; - assert_eq!(the_vec.clone(), bar(&mut the_vec)); - assert_eq!(the_vec.clone(), bip(&the_vec)); -} diff --git a/src/test/ui/coerce/coerce-reborrow-mut-ptr-arg.rs b/src/test/ui/coerce/coerce-reborrow-mut-ptr-arg.rs deleted file mode 100644 index 76cd6793b3c..00000000000 --- a/src/test/ui/coerce/coerce-reborrow-mut-ptr-arg.rs +++ /dev/null @@ -1,25 +0,0 @@ -// run-pass -// pretty-expanded FIXME #23616 - -struct SpeechMaker { - speeches: usize -} - -fn talk(x: &mut SpeechMaker) { - x.speeches += 1; -} - -fn give_a_few_speeches(speaker: &mut SpeechMaker) { - - // Here speaker is reborrowed for each call, so we don't get errors - // about speaker being moved. - - talk(speaker); - talk(speaker); - talk(speaker); -} - -pub fn main() { - let mut lincoln = SpeechMaker {speeches: 22}; - give_a_few_speeches(&mut lincoln); -} diff --git a/src/test/ui/coerce/coerce-reborrow-mut-ptr-rcvr.rs b/src/test/ui/coerce/coerce-reborrow-mut-ptr-rcvr.rs deleted file mode 100644 index e6e7c3a51aa..00000000000 --- a/src/test/ui/coerce/coerce-reborrow-mut-ptr-rcvr.rs +++ /dev/null @@ -1,27 +0,0 @@ -// run-pass -// pretty-expanded FIXME #23616 - -struct SpeechMaker { - speeches: usize -} - -impl SpeechMaker { - pub fn talk(&mut self) { - self.speeches += 1; - } -} - -fn give_a_few_speeches(speaker: &mut SpeechMaker) { - - // Here speaker is reborrowed for each call, so we don't get errors - // about speaker being moved. - - speaker.talk(); - speaker.talk(); - speaker.talk(); -} - -pub fn main() { - let mut lincoln = SpeechMaker {speeches: 22}; - give_a_few_speeches(&mut lincoln); -} diff --git a/src/test/ui/coerce/coerce-reborrow-mut-vec-arg.rs b/src/test/ui/coerce/coerce-reborrow-mut-vec-arg.rs deleted file mode 100644 index 2635754f14d..00000000000 --- a/src/test/ui/coerce/coerce-reborrow-mut-vec-arg.rs +++ /dev/null @@ -1,18 +0,0 @@ -// run-pass - - -fn reverse(v: &mut [usize]) { - v.reverse(); -} - -fn bar(v: &mut [usize]) { - reverse(v); - reverse(v); - reverse(v); -} - -pub fn main() { - let mut the_vec = vec![1, 2, 3, 100]; - bar(&mut the_vec); - assert_eq!(the_vec, [100, 3, 2, 1]); -} diff --git a/src/test/ui/coerce/coerce-reborrow-mut-vec-rcvr.rs b/src/test/ui/coerce/coerce-reborrow-mut-vec-rcvr.rs deleted file mode 100644 index c03336ea37a..00000000000 --- a/src/test/ui/coerce/coerce-reborrow-mut-vec-rcvr.rs +++ /dev/null @@ -1,14 +0,0 @@ -// run-pass - - -fn bar(v: &mut [usize]) { - v.reverse(); - v.reverse(); - v.reverse(); -} - -pub fn main() { - let mut the_vec = vec![1, 2, 3, 100]; - bar(&mut the_vec); - assert_eq!(the_vec, [100, 3, 2, 1]); -} diff --git a/src/test/ui/coerce/coerce-unify-return.rs b/src/test/ui/coerce/coerce-unify-return.rs deleted file mode 100644 index 95a7ee8fe0f..00000000000 --- a/src/test/ui/coerce/coerce-unify-return.rs +++ /dev/null @@ -1,19 +0,0 @@ -// run-pass -// Check that coercions unify the expected return type of a polymorphic -// function call, instead of leaving the type variables as they were. - -// pretty-expanded FIXME #23616 - -struct Foo; -impl Foo { - fn foo(self, x: T) -> Option { Some(x) } -} - -pub fn main() { - let _: Option = Some(main); - let _: Option = Foo.foo(main); - - // The same two cases, with implicit type variables made explicit. - let _: Option = Some::<_>(main); - let _: Option = Foo.foo::<_>(main); -} diff --git a/src/test/ui/coerce/coerce-unify.rs b/src/test/ui/coerce/coerce-unify.rs deleted file mode 100644 index f1818f9bb5a..00000000000 --- a/src/test/ui/coerce/coerce-unify.rs +++ /dev/null @@ -1,68 +0,0 @@ -// run-pass -// Check that coercions can unify if-else, match arms and array elements. - -// Try to construct if-else chains, matches and arrays out of given expressions. -macro_rules! check { - ($last:expr $(, $rest:expr)+) => { - // Last expression comes first because of whacky ifs and matches. - let _ = $(if false { $rest })else+ else { $last }; - - let _ = match 0 { $(_ if false => $rest,)+ _ => $last }; - - let _ = [$($rest,)+ $last]; - } -} - -// Check all non-uniform cases of 2 and 3 expressions of 2 types. -macro_rules! check2 { - ($a:expr, $b:expr) => { - check!($a, $b); - check!($b, $a); - - check!($a, $a, $b); - check!($a, $b, $a); - check!($a, $b, $b); - - check!($b, $a, $a); - check!($b, $a, $b); - check!($b, $b, $a); - } -} - -// Check all non-uniform cases of 2 and 3 expressions of 3 types. -macro_rules! check3 { - ($a:expr, $b:expr, $c:expr) => { - // Delegate to check2 for cases where a type repeats. - check2!($a, $b); - check2!($b, $c); - check2!($a, $c); - - // Check the remaining cases, i.e., permutations of ($a, $b, $c). - check!($a, $b, $c); - check!($a, $c, $b); - check!($b, $a, $c); - check!($b, $c, $a); - check!($c, $a, $b); - check!($c, $b, $a); - } -} - -use std::mem::size_of; - -fn foo() {} -fn bar() {} - -pub fn main() { - check3!(foo, bar, foo as fn()); - check3!(size_of::, size_of::, size_of:: as fn() -> usize); - - let s = String::from("bar"); - check2!("foo", &s); - - let a = [1, 2, 3]; - let v = vec![1, 2, 3]; - check2!(&a[..], &v); - - // Make sure in-array coercion still works. - let _ = [("a", Default::default()), (Default::default(), "b"), (&s, &s)]; -} diff --git a/src/test/ui/coerce/coerce-unsize-subtype.rs b/src/test/ui/coerce/coerce-unsize-subtype.rs deleted file mode 100644 index 45b53300c5b..00000000000 --- a/src/test/ui/coerce/coerce-unsize-subtype.rs +++ /dev/null @@ -1,40 +0,0 @@ -// run-pass -#![allow(dead_code)] -// pretty-expanded FIXME #23616 - -use std::rc::Rc; - -fn lub_short<'a, T>(_: &[&'a T], _: &[&'a T]) {} - -// The two arguments are a subtype of their LUB, after coercion. -fn long_and_short<'a, T>(xs: &[&'static T; 1], ys: &[&'a T; 1]) { - lub_short(xs, ys); -} - -// The argument coerces to a subtype of the return type. -fn long_to_short<'a, 'b, T>(xs: &'b [&'static T; 1]) -> &'b [&'a T] { - xs -} - -// Rc is covariant over T just like &T. -fn long_to_short_rc<'a, T>(xs: Rc<[&'static T; 1]>) -> Rc<[&'a T]> { - xs -} - -// LUB-coercion (if-else/match/array) coerces `xs: &'b [&'static T: N]` -// to a subtype of the LUB of `xs` and `ys` (i.e., `&'b [&'a T]`), -// regardless of the order they appear (in if-else/match/array). -fn long_and_short_lub1<'a, 'b, T>(xs: &'b [&'static T; 1], ys: &'b [&'a T]) { - let _order1 = [xs, ys]; - let _order2 = [ys, xs]; -} - -// LUB-coercion should also have the exact same effect when `&'b [&'a T; N]` -// needs to be coerced, i.e., the resulting type is not &'b [&'static T], but -// rather the `&'b [&'a T]` LUB. -fn long_and_short_lub2<'a, 'b, T>(xs: &'b [&'static T], ys: &'b [&'a T; 1]) { - let _order1 = [xs, ys]; - let _order2 = [ys, xs]; -} - -fn main() {} diff --git a/src/test/ui/coercion/coerce-expect-unsized.rs b/src/test/ui/coercion/coerce-expect-unsized.rs new file mode 100644 index 00000000000..d486fdf73ab --- /dev/null +++ b/src/test/ui/coercion/coerce-expect-unsized.rs @@ -0,0 +1,44 @@ +// run-pass +#![allow(unused_braces)] +#![feature(box_syntax)] + +use std::cell::RefCell; +use std::fmt::Debug; +use std::rc::Rc; + +// Check that coercions apply at the pointer level and don't cause +// rvalue expressions to be unsized. See #20169 for more information. + +pub fn main() { + let _: Box<[isize]> = Box::new({ [1, 2, 3] }); + let _: Box<[isize]> = Box::new(if true { [1, 2, 3] } else { [1, 3, 4] }); + let _: Box<[isize]> = Box::new(match true { true => [1, 2, 3], false => [1, 3, 4] }); + let _: Box _> = Box::new({ |x| (x as u8) }); + let _: Box = Box::new(if true { false } else { true }); + let _: Box = Box::new(match true { true => 'a', false => 'b' }); + + let _: &[isize] = &{ [1, 2, 3] }; + let _: &[isize] = &if true { [1, 2, 3] } else { [1, 3, 4] }; + let _: &[isize] = &match true { true => [1, 2, 3], false => [1, 3, 4] }; + let _: &dyn Fn(isize) -> _ = &{ |x| (x as u8) }; + let _: &dyn Debug = &if true { false } else { true }; + let _: &dyn Debug = &match true { true => 'a', false => 'b' }; + + let _: &str = &{ String::new() }; + let _: &str = &if true { String::from("...") } else { 5.to_string() }; + let _: &str = &match true { + true => format!("{}", false), + false => ["x", "y"].join("+") + }; + + let _: Box<[isize]> = Box::new([1, 2, 3]); + let _: Box _> = Box::new(|x| (x as u8)); + + let _: Rc> = Rc::new(RefCell::new([1, 2, 3])); + let _: Rc _>> = Rc::new(RefCell::new(|x| (x as u8))); + + let _: Vec _>> = vec![ + Box::new(|x| (x as u8)), + Box::new(|x| (x as i16 as u8)), + ]; +} diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef-fail.rs b/src/test/ui/coercion/coerce-overloaded-autoderef-fail.rs new file mode 100644 index 00000000000..01d9c1e486a --- /dev/null +++ b/src/test/ui/coercion/coerce-overloaded-autoderef-fail.rs @@ -0,0 +1,32 @@ +fn borrow_mut(x: &mut T) -> &mut T { x } +fn borrow(x: &T) -> &T { x } + +fn borrow_mut2(_: &mut T, _: &mut T) {} +fn borrow2(_: &mut T, _: &T) {} + +fn double_mut_borrow(x: &mut Box) { + let y = borrow_mut(x); + let z = borrow_mut(x); + //~^ ERROR cannot borrow `*x` as mutable more than once at a time + drop((y, z)); +} + +fn double_imm_borrow(x: &mut Box) { + let y = borrow(x); + let z = borrow(x); + **x += 1; + //~^ ERROR cannot assign to `**x` because it is borrowed + drop((y, z)); +} + +fn double_mut_borrow2(x: &mut Box) { + borrow_mut2(x, x); + //~^ ERROR cannot borrow `*x` as mutable more than once at a time +} + +fn double_borrow2(x: &mut Box) { + borrow2(x, x); + //~^ ERROR cannot borrow `*x` as mutable because it is also borrowed as immutable +} + +pub fn main() {} diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef-fail.stderr b/src/test/ui/coercion/coerce-overloaded-autoderef-fail.stderr new file mode 100644 index 00000000000..d067c3b3a18 --- /dev/null +++ b/src/test/ui/coercion/coerce-overloaded-autoderef-fail.stderr @@ -0,0 +1,46 @@ +error[E0499]: cannot borrow `*x` as mutable more than once at a time + --> $DIR/coerce-overloaded-autoderef-fail.rs:9:24 + | +LL | let y = borrow_mut(x); + | - first mutable borrow occurs here +LL | let z = borrow_mut(x); + | ^ second mutable borrow occurs here +LL | +LL | drop((y, z)); + | - first borrow later used here + +error[E0506]: cannot assign to `**x` because it is borrowed + --> $DIR/coerce-overloaded-autoderef-fail.rs:17:5 + | +LL | let y = borrow(x); + | - borrow of `**x` occurs here +LL | let z = borrow(x); +LL | **x += 1; + | ^^^^^^^^ assignment to borrowed `**x` occurs here +LL | +LL | drop((y, z)); + | - borrow later used here + +error[E0499]: cannot borrow `*x` as mutable more than once at a time + --> $DIR/coerce-overloaded-autoderef-fail.rs:23:20 + | +LL | borrow_mut2(x, x); + | ----------- - ^ second mutable borrow occurs here + | | | + | | first mutable borrow occurs here + | first borrow later used by call + +error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable + --> $DIR/coerce-overloaded-autoderef-fail.rs:28:5 + | +LL | borrow2(x, x); + | -------^^^^-^ + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | immutable borrow later used by call + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0499, E0502, E0506. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef.rs b/src/test/ui/coercion/coerce-overloaded-autoderef.rs index 01d9c1e486a..d5484607c8b 100644 --- a/src/test/ui/coercion/coerce-overloaded-autoderef.rs +++ b/src/test/ui/coercion/coerce-overloaded-autoderef.rs @@ -1,32 +1,68 @@ -fn borrow_mut(x: &mut T) -> &mut T { x } -fn borrow(x: &T) -> &T { x } +// run-pass +#![allow(unused_braces)] +#![allow(dead_code)] +// pretty-expanded FIXME #23616 -fn borrow_mut2(_: &mut T, _: &mut T) {} -fn borrow2(_: &mut T, _: &T) {} +use std::rc::Rc; -fn double_mut_borrow(x: &mut Box) { - let y = borrow_mut(x); - let z = borrow_mut(x); - //~^ ERROR cannot borrow `*x` as mutable more than once at a time - drop((y, z)); +// Examples from the "deref coercions" RFC, at rust-lang/rfcs#241. + +fn use_ref(_: &T) {} +fn use_mut(_: &mut T) {} + +fn use_rc(t: Rc) { + use_ref(&*t); // what you have to write today + use_ref(&t); // what you'd be able to write + use_ref(&&&&&&t); + use_ref(&mut &&&&&t); + use_ref(&&&mut &&&t); +} + +fn use_mut_box(mut t: &mut Box) { + use_mut(&mut *t); // what you have to write today + use_mut(t); // what you'd be able to write + use_mut(&mut &mut &mut t); + + use_ref(&*t); // what you have to write today + use_ref(t); // what you'd be able to write + use_ref(&&&&&&t); + use_ref(&mut &&&&&t); + use_ref(&&&mut &&&t); } -fn double_imm_borrow(x: &mut Box) { - let y = borrow(x); - let z = borrow(x); - **x += 1; - //~^ ERROR cannot assign to `**x` because it is borrowed - drop((y, z)); +fn use_nested(t: &Box) { + use_ref(&**t); // what you have to write today + use_ref(t); // what you'd be able to write (note: recursive deref) + use_ref(&&&&&&t); + use_ref(&mut &&&&&t); + use_ref(&&&mut &&&t); +} + +fn use_slice(_: &[u8]) {} +fn use_slice_mut(_: &mut [u8]) {} + +fn use_vec(mut v: Vec) { + use_slice_mut(&mut v[..]); // what you have to write today + use_slice_mut(&mut v); // what you'd be able to write + use_slice_mut(&mut &mut &mut v); + + use_slice(&v[..]); // what you have to write today + use_slice(&v); // what you'd be able to write + use_slice(&&&&&&v); + use_slice(&mut &&&&&v); + use_slice(&&&mut &&&v); } -fn double_mut_borrow2(x: &mut Box) { - borrow_mut2(x, x); - //~^ ERROR cannot borrow `*x` as mutable more than once at a time +fn use_vec_ref(v: &Vec) { + use_slice(&v[..]); // what you have to write today + use_slice(v); // what you'd be able to write + use_slice(&&&&&&v); + use_slice(&mut &&&&&v); + use_slice(&&&mut &&&v); } -fn double_borrow2(x: &mut Box) { - borrow2(x, x); - //~^ ERROR cannot borrow `*x` as mutable because it is also borrowed as immutable +fn use_op_rhs(s: &mut String) { + *s += {&String::from(" ")}; } pub fn main() {} diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef.stderr b/src/test/ui/coercion/coerce-overloaded-autoderef.stderr deleted file mode 100644 index 7cdfcb5f4fc..00000000000 --- a/src/test/ui/coercion/coerce-overloaded-autoderef.stderr +++ /dev/null @@ -1,46 +0,0 @@ -error[E0499]: cannot borrow `*x` as mutable more than once at a time - --> $DIR/coerce-overloaded-autoderef.rs:9:24 - | -LL | let y = borrow_mut(x); - | - first mutable borrow occurs here -LL | let z = borrow_mut(x); - | ^ second mutable borrow occurs here -LL | -LL | drop((y, z)); - | - first borrow later used here - -error[E0506]: cannot assign to `**x` because it is borrowed - --> $DIR/coerce-overloaded-autoderef.rs:17:5 - | -LL | let y = borrow(x); - | - borrow of `**x` occurs here -LL | let z = borrow(x); -LL | **x += 1; - | ^^^^^^^^ assignment to borrowed `**x` occurs here -LL | -LL | drop((y, z)); - | - borrow later used here - -error[E0499]: cannot borrow `*x` as mutable more than once at a time - --> $DIR/coerce-overloaded-autoderef.rs:23:20 - | -LL | borrow_mut2(x, x); - | ----------- - ^ second mutable borrow occurs here - | | | - | | first mutable borrow occurs here - | first borrow later used by call - -error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable - --> $DIR/coerce-overloaded-autoderef.rs:28:5 - | -LL | borrow2(x, x); - | -------^^^^-^ - | | | - | | immutable borrow occurs here - | mutable borrow occurs here - | immutable borrow later used by call - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0499, E0502, E0506. -For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/coercion/coerce-reborrow-imm-ptr-arg.rs b/src/test/ui/coercion/coerce-reborrow-imm-ptr-arg.rs new file mode 100644 index 00000000000..f033e1b5d2b --- /dev/null +++ b/src/test/ui/coercion/coerce-reborrow-imm-ptr-arg.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn negate(x: &isize) -> isize { + -*x +} + +fn negate_mut(y: &mut isize) -> isize { + negate(y) +} + +fn negate_imm(y: &isize) -> isize { + negate(y) +} + +pub fn main() {} diff --git a/src/test/ui/coercion/coerce-reborrow-imm-ptr-rcvr.rs b/src/test/ui/coercion/coerce-reborrow-imm-ptr-rcvr.rs new file mode 100644 index 00000000000..64a365229cb --- /dev/null +++ b/src/test/ui/coercion/coerce-reborrow-imm-ptr-rcvr.rs @@ -0,0 +1,18 @@ +// run-pass + +struct SpeechMaker { + speeches: usize +} + +impl SpeechMaker { + pub fn how_many(&self) -> usize { self.speeches } +} + +fn foo(speaker: &SpeechMaker) -> usize { + speaker.how_many() + 33 +} + +pub fn main() { + let lincoln = SpeechMaker {speeches: 22}; + assert_eq!(foo(&lincoln), 55); +} diff --git a/src/test/ui/coercion/coerce-reborrow-imm-vec-arg.rs b/src/test/ui/coercion/coerce-reborrow-imm-vec-arg.rs new file mode 100644 index 00000000000..c2aaae1c73e --- /dev/null +++ b/src/test/ui/coercion/coerce-reborrow-imm-vec-arg.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn sum(x: &[isize]) -> isize { + let mut sum = 0; + for y in x { sum += *y; } + return sum; +} + +fn sum_mut(y: &mut [isize]) -> isize { + sum(y) +} + +fn sum_imm(y: &[isize]) -> isize { + sum(y) +} + +pub fn main() {} diff --git a/src/test/ui/coercion/coerce-reborrow-imm-vec-rcvr.rs b/src/test/ui/coercion/coerce-reborrow-imm-vec-rcvr.rs new file mode 100644 index 00000000000..9a5652acf87 --- /dev/null +++ b/src/test/ui/coercion/coerce-reborrow-imm-vec-rcvr.rs @@ -0,0 +1,16 @@ +// run-pass + + +fn bar(v: &mut [usize]) -> Vec { + v.to_vec() +} + +fn bip(v: &[usize]) -> Vec { + v.to_vec() +} + +pub fn main() { + let mut the_vec = vec![1, 2, 3, 100]; + assert_eq!(the_vec.clone(), bar(&mut the_vec)); + assert_eq!(the_vec.clone(), bip(&the_vec)); +} diff --git a/src/test/ui/coercion/coerce-reborrow-mut-ptr-arg.rs b/src/test/ui/coercion/coerce-reborrow-mut-ptr-arg.rs new file mode 100644 index 00000000000..76cd6793b3c --- /dev/null +++ b/src/test/ui/coercion/coerce-reborrow-mut-ptr-arg.rs @@ -0,0 +1,25 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct SpeechMaker { + speeches: usize +} + +fn talk(x: &mut SpeechMaker) { + x.speeches += 1; +} + +fn give_a_few_speeches(speaker: &mut SpeechMaker) { + + // Here speaker is reborrowed for each call, so we don't get errors + // about speaker being moved. + + talk(speaker); + talk(speaker); + talk(speaker); +} + +pub fn main() { + let mut lincoln = SpeechMaker {speeches: 22}; + give_a_few_speeches(&mut lincoln); +} diff --git a/src/test/ui/coercion/coerce-reborrow-mut-ptr-rcvr.rs b/src/test/ui/coercion/coerce-reborrow-mut-ptr-rcvr.rs new file mode 100644 index 00000000000..e6e7c3a51aa --- /dev/null +++ b/src/test/ui/coercion/coerce-reborrow-mut-ptr-rcvr.rs @@ -0,0 +1,27 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct SpeechMaker { + speeches: usize +} + +impl SpeechMaker { + pub fn talk(&mut self) { + self.speeches += 1; + } +} + +fn give_a_few_speeches(speaker: &mut SpeechMaker) { + + // Here speaker is reborrowed for each call, so we don't get errors + // about speaker being moved. + + speaker.talk(); + speaker.talk(); + speaker.talk(); +} + +pub fn main() { + let mut lincoln = SpeechMaker {speeches: 22}; + give_a_few_speeches(&mut lincoln); +} diff --git a/src/test/ui/coercion/coerce-reborrow-mut-vec-arg.rs b/src/test/ui/coercion/coerce-reborrow-mut-vec-arg.rs new file mode 100644 index 00000000000..2635754f14d --- /dev/null +++ b/src/test/ui/coercion/coerce-reborrow-mut-vec-arg.rs @@ -0,0 +1,18 @@ +// run-pass + + +fn reverse(v: &mut [usize]) { + v.reverse(); +} + +fn bar(v: &mut [usize]) { + reverse(v); + reverse(v); + reverse(v); +} + +pub fn main() { + let mut the_vec = vec![1, 2, 3, 100]; + bar(&mut the_vec); + assert_eq!(the_vec, [100, 3, 2, 1]); +} diff --git a/src/test/ui/coercion/coerce-reborrow-mut-vec-rcvr.rs b/src/test/ui/coercion/coerce-reborrow-mut-vec-rcvr.rs new file mode 100644 index 00000000000..c03336ea37a --- /dev/null +++ b/src/test/ui/coercion/coerce-reborrow-mut-vec-rcvr.rs @@ -0,0 +1,14 @@ +// run-pass + + +fn bar(v: &mut [usize]) { + v.reverse(); + v.reverse(); + v.reverse(); +} + +pub fn main() { + let mut the_vec = vec![1, 2, 3, 100]; + bar(&mut the_vec); + assert_eq!(the_vec, [100, 3, 2, 1]); +} diff --git a/src/test/ui/coercion/coerce-to-bang-cast.rs b/src/test/ui/coercion/coerce-to-bang-cast.rs index 8ef19480846..85598a42ecc 100644 --- a/src/test/ui/coercion/coerce-to-bang-cast.rs +++ b/src/test/ui/coercion/coerce-to-bang-cast.rs @@ -1,7 +1,5 @@ #![feature(never_type)] -fn foo(x: usize, y: !, z: usize) { } - fn cast_a() { let y = {return; 22} as !; //~^ ERROR non-primitive cast diff --git a/src/test/ui/coercion/coerce-to-bang-cast.stderr b/src/test/ui/coercion/coerce-to-bang-cast.stderr index d3adbd5158d..50e009aa25b 100644 --- a/src/test/ui/coercion/coerce-to-bang-cast.stderr +++ b/src/test/ui/coercion/coerce-to-bang-cast.stderr @@ -1,11 +1,11 @@ error[E0605]: non-primitive cast: `i32` as `!` - --> $DIR/coerce-to-bang-cast.rs:6:13 + --> $DIR/coerce-to-bang-cast.rs:4:13 | LL | let y = {return; 22} as !; | ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object error[E0605]: non-primitive cast: `i32` as `!` - --> $DIR/coerce-to-bang-cast.rs:11:13 + --> $DIR/coerce-to-bang-cast.rs:9:13 | LL | let y = 22 as !; | ^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object diff --git a/src/test/ui/coercion/coerce-unify-return.rs b/src/test/ui/coercion/coerce-unify-return.rs new file mode 100644 index 00000000000..95a7ee8fe0f --- /dev/null +++ b/src/test/ui/coercion/coerce-unify-return.rs @@ -0,0 +1,19 @@ +// run-pass +// Check that coercions unify the expected return type of a polymorphic +// function call, instead of leaving the type variables as they were. + +// pretty-expanded FIXME #23616 + +struct Foo; +impl Foo { + fn foo(self, x: T) -> Option { Some(x) } +} + +pub fn main() { + let _: Option = Some(main); + let _: Option = Foo.foo(main); + + // The same two cases, with implicit type variables made explicit. + let _: Option = Some::<_>(main); + let _: Option = Foo.foo::<_>(main); +} diff --git a/src/test/ui/coercion/coerce-unify.rs b/src/test/ui/coercion/coerce-unify.rs new file mode 100644 index 00000000000..f1818f9bb5a --- /dev/null +++ b/src/test/ui/coercion/coerce-unify.rs @@ -0,0 +1,68 @@ +// run-pass +// Check that coercions can unify if-else, match arms and array elements. + +// Try to construct if-else chains, matches and arrays out of given expressions. +macro_rules! check { + ($last:expr $(, $rest:expr)+) => { + // Last expression comes first because of whacky ifs and matches. + let _ = $(if false { $rest })else+ else { $last }; + + let _ = match 0 { $(_ if false => $rest,)+ _ => $last }; + + let _ = [$($rest,)+ $last]; + } +} + +// Check all non-uniform cases of 2 and 3 expressions of 2 types. +macro_rules! check2 { + ($a:expr, $b:expr) => { + check!($a, $b); + check!($b, $a); + + check!($a, $a, $b); + check!($a, $b, $a); + check!($a, $b, $b); + + check!($b, $a, $a); + check!($b, $a, $b); + check!($b, $b, $a); + } +} + +// Check all non-uniform cases of 2 and 3 expressions of 3 types. +macro_rules! check3 { + ($a:expr, $b:expr, $c:expr) => { + // Delegate to check2 for cases where a type repeats. + check2!($a, $b); + check2!($b, $c); + check2!($a, $c); + + // Check the remaining cases, i.e., permutations of ($a, $b, $c). + check!($a, $b, $c); + check!($a, $c, $b); + check!($b, $a, $c); + check!($b, $c, $a); + check!($c, $a, $b); + check!($c, $b, $a); + } +} + +use std::mem::size_of; + +fn foo() {} +fn bar() {} + +pub fn main() { + check3!(foo, bar, foo as fn()); + check3!(size_of::, size_of::, size_of:: as fn() -> usize); + + let s = String::from("bar"); + check2!("foo", &s); + + let a = [1, 2, 3]; + let v = vec![1, 2, 3]; + check2!(&a[..], &v); + + // Make sure in-array coercion still works. + let _ = [("a", Default::default()), (Default::default(), "b"), (&s, &s)]; +} diff --git a/src/test/ui/coercion/coerce-unsize-subtype.rs b/src/test/ui/coercion/coerce-unsize-subtype.rs new file mode 100644 index 00000000000..45b53300c5b --- /dev/null +++ b/src/test/ui/coercion/coerce-unsize-subtype.rs @@ -0,0 +1,40 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +use std::rc::Rc; + +fn lub_short<'a, T>(_: &[&'a T], _: &[&'a T]) {} + +// The two arguments are a subtype of their LUB, after coercion. +fn long_and_short<'a, T>(xs: &[&'static T; 1], ys: &[&'a T; 1]) { + lub_short(xs, ys); +} + +// The argument coerces to a subtype of the return type. +fn long_to_short<'a, 'b, T>(xs: &'b [&'static T; 1]) -> &'b [&'a T] { + xs +} + +// Rc is covariant over T just like &T. +fn long_to_short_rc<'a, T>(xs: Rc<[&'static T; 1]>) -> Rc<[&'a T]> { + xs +} + +// LUB-coercion (if-else/match/array) coerces `xs: &'b [&'static T: N]` +// to a subtype of the LUB of `xs` and `ys` (i.e., `&'b [&'a T]`), +// regardless of the order they appear (in if-else/match/array). +fn long_and_short_lub1<'a, 'b, T>(xs: &'b [&'static T; 1], ys: &'b [&'a T]) { + let _order1 = [xs, ys]; + let _order2 = [ys, xs]; +} + +// LUB-coercion should also have the exact same effect when `&'b [&'a T; N]` +// needs to be coerced, i.e., the resulting type is not &'b [&'static T], but +// rather the `&'b [&'a T]` LUB. +fn long_and_short_lub2<'a, 'b, T>(xs: &'b [&'static T], ys: &'b [&'a T; 1]) { + let _order1 = [xs, ys]; + let _order2 = [ys, xs]; +} + +fn main() {}