+++ /dev/null
-// 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<dyn Fn(isize) -> _> = Box::new({ |x| (x as u8) });
- let _: Box<dyn Debug> = Box::new(if true { false } else { true });
- let _: Box<dyn Debug> = 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<dyn Fn(isize) -> _> = Box::new(|x| (x as u8));
-
- let _: Rc<RefCell<[isize]>> = Rc::new(RefCell::new([1, 2, 3]));
- let _: Rc<RefCell<dyn FnMut(isize) -> _>> = Rc::new(RefCell::new(|x| (x as u8)));
-
- let _: Vec<Box<dyn Fn(isize) -> _>> = vec![
- Box::new(|x| (x as u8)),
- Box::new(|x| (x as i16 as u8)),
- ];
-}
+++ /dev/null
-// 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>(_: &T) {}
-fn use_mut<T>(_: &mut T) {}
-
-fn use_rc<T>(t: Rc<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_mut_box<T>(mut t: &mut Box<T>) {
- 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>(t: &Box<T>) {
- 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<u8>) {
- 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<u8>) {
- 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() {}
+++ /dev/null
-// 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() {}
+++ /dev/null
-// 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);
-}
+++ /dev/null
-// 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() {}
+++ /dev/null
-// run-pass
-
-
-fn bar(v: &mut [usize]) -> Vec<usize> {
- v.to_vec()
-}
-
-fn bip(v: &[usize]) -> Vec<usize> {
- 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));
-}
+++ /dev/null
-// 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);
-}
+++ /dev/null
-// 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);
-}
+++ /dev/null
-// 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]);
-}
+++ /dev/null
-// 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]);
-}
+++ /dev/null
-// 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<T>(self, x: T) -> Option<T> { Some(x) }
-}
-
-pub fn main() {
- let _: Option<fn()> = Some(main);
- let _: Option<fn()> = Foo.foo(main);
-
- // The same two cases, with implicit type variables made explicit.
- let _: Option<fn()> = Some::<_>(main);
- let _: Option<fn()> = Foo.foo::<_>(main);
-}
+++ /dev/null
-// 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::<u8>, size_of::<u16>, size_of::<usize> 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)];
-}
+++ /dev/null
-// 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<T> 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() {}
--- /dev/null
+// 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<dyn Fn(isize) -> _> = Box::new({ |x| (x as u8) });
+ let _: Box<dyn Debug> = Box::new(if true { false } else { true });
+ let _: Box<dyn Debug> = 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<dyn Fn(isize) -> _> = Box::new(|x| (x as u8));
+
+ let _: Rc<RefCell<[isize]>> = Rc::new(RefCell::new([1, 2, 3]));
+ let _: Rc<RefCell<dyn FnMut(isize) -> _>> = Rc::new(RefCell::new(|x| (x as u8)));
+
+ let _: Vec<Box<dyn Fn(isize) -> _>> = vec![
+ Box::new(|x| (x as u8)),
+ Box::new(|x| (x as i16 as u8)),
+ ];
+}
--- /dev/null
+fn borrow_mut<T>(x: &mut T) -> &mut T { x }
+fn borrow<T>(x: &T) -> &T { x }
+
+fn borrow_mut2<T>(_: &mut T, _: &mut T) {}
+fn borrow2<T>(_: &mut T, _: &T) {}
+
+fn double_mut_borrow<T>(x: &mut Box<T>) {
+ 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<i32>) {
+ 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<T>(x: &mut Box<T>) {
+ borrow_mut2(x, x);
+ //~^ ERROR cannot borrow `*x` as mutable more than once at a time
+}
+
+fn double_borrow2<T>(x: &mut Box<T>) {
+ borrow2(x, x);
+ //~^ ERROR cannot borrow `*x` as mutable because it is also borrowed as immutable
+}
+
+pub fn main() {}
--- /dev/null
+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`.
-fn borrow_mut<T>(x: &mut T) -> &mut T { x }
-fn borrow<T>(x: &T) -> &T { x }
+// run-pass
+#![allow(unused_braces)]
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
-fn borrow_mut2<T>(_: &mut T, _: &mut T) {}
-fn borrow2<T>(_: &mut T, _: &T) {}
+use std::rc::Rc;
-fn double_mut_borrow<T>(x: &mut Box<T>) {
- 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>(_: &T) {}
+fn use_mut<T>(_: &mut T) {}
+
+fn use_rc<T>(t: Rc<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_mut_box<T>(mut t: &mut Box<T>) {
+ 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<i32>) {
- 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>(t: &Box<T>) {
+ 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<u8>) {
+ 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<T>(x: &mut Box<T>) {
- borrow_mut2(x, x);
- //~^ ERROR cannot borrow `*x` as mutable more than once at a time
+fn use_vec_ref(v: &Vec<u8>) {
+ 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<T>(x: &mut Box<T>) {
- 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() {}
+++ /dev/null
-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`.
--- /dev/null
+// 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() {}
--- /dev/null
+// 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);
+}
--- /dev/null
+// 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() {}
--- /dev/null
+// run-pass
+
+
+fn bar(v: &mut [usize]) -> Vec<usize> {
+ v.to_vec()
+}
+
+fn bip(v: &[usize]) -> Vec<usize> {
+ 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));
+}
--- /dev/null
+// 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);
+}
--- /dev/null
+// 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);
+}
--- /dev/null
+// 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]);
+}
--- /dev/null
+// 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]);
+}
#![feature(never_type)]
-fn foo(x: usize, y: !, z: usize) { }
-
fn cast_a() {
let y = {return; 22} as !;
//~^ ERROR non-primitive cast
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
--- /dev/null
+// 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<T>(self, x: T) -> Option<T> { Some(x) }
+}
+
+pub fn main() {
+ let _: Option<fn()> = Some(main);
+ let _: Option<fn()> = Foo.foo(main);
+
+ // The same two cases, with implicit type variables made explicit.
+ let _: Option<fn()> = Some::<_>(main);
+ let _: Option<fn()> = Foo.foo::<_>(main);
+}
--- /dev/null
+// 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::<u8>, size_of::<u16>, size_of::<usize> 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)];
+}
--- /dev/null
+// 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<T> 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() {}