diff options
Diffstat (limited to 'src/test/ui/coercion')
47 files changed, 1390 insertions, 0 deletions
diff --git a/src/test/ui/coercion/auxiliary/issue-39823.rs b/src/test/ui/coercion/auxiliary/issue-39823.rs new file mode 100644 index 000000000..3af9c68f2 --- /dev/null +++ b/src/test/ui/coercion/auxiliary/issue-39823.rs @@ -0,0 +1,7 @@ +#![crate_type="rlib"] + +#[derive(Debug, PartialEq)] +pub struct RemoteC(pub u32); + +#[derive(Debug, PartialEq)] +pub struct RemoteG<T>(pub T); diff --git a/src/test/ui/coercion/coerce-expect-unsized-ascribed.rs b/src/test/ui/coercion/coerce-expect-unsized-ascribed.rs new file mode 100644 index 000000000..c139e823c --- /dev/null +++ b/src/test/ui/coercion/coerce-expect-unsized-ascribed.rs @@ -0,0 +1,32 @@ +// A version of coerce-expect-unsized that uses type ascription. +// Doesn't work so far, but supposed to work eventually + +#![feature(box_syntax, type_ascription)] + +use std::fmt::Debug; + +pub fn main() { + let _ = box { [1, 2, 3] }: Box<[i32]>; //~ ERROR mismatched types + let _ = box if true { [1, 2, 3] } else { [1, 3, 4] }: Box<[i32]>; //~ ERROR mismatched types + let _ = box match true { true => [1, 2, 3], false => [1, 3, 4] }: Box<[i32]>; + //~^ ERROR mismatched types + let _ = box { |x| (x as u8) }: Box<dyn Fn(i32) -> _>; //~ ERROR mismatched types + let _ = box if true { false } else { true }: Box<dyn Debug>; //~ ERROR mismatched types + let _ = box match true { true => 'a', false => 'b' }: Box<dyn Debug>; //~ ERROR mismatched types + + let _ = &{ [1, 2, 3] }: &[i32]; //~ ERROR mismatched types + let _ = &if true { [1, 2, 3] } else { [1, 3, 4] }: &[i32]; //~ ERROR mismatched types + let _ = &match true { true => [1, 2, 3], false => [1, 3, 4] }: &[i32]; + //~^ ERROR mismatched types + let _ = &{ |x| (x as u8) }: &dyn Fn(i32) -> _; //~ ERROR mismatched types + let _ = &if true { false } else { true }: &dyn Debug; //~ ERROR mismatched types + let _ = &match true { true => 'a', false => 'b' }: &dyn Debug; //~ ERROR mismatched types + + let _ = Box::new([1, 2, 3]): Box<[i32]>; //~ ERROR mismatched types + let _ = Box::new(|x| (x as u8)): Box<dyn Fn(i32) -> _>; //~ ERROR mismatched types + + let _ = vec![ + Box::new(|x| (x as u8)), + box |x| (x as i16 as u8), + ]: Vec<Box<dyn Fn(i32) -> _>>; +} diff --git a/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr new file mode 100644 index 000000000..9d614e610 --- /dev/null +++ b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr @@ -0,0 +1,129 @@ +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:9:13 + | +LL | let _ = box { [1, 2, 3] }: Box<[i32]>; + | ^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` + | + = note: expected struct `Box<[i32]>` + found struct `Box<[i32; 3]>` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:10:13 + | +LL | let _ = box if true { [1, 2, 3] } else { [1, 3, 4] }: Box<[i32]>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` + | + = note: expected struct `Box<[i32]>` + found struct `Box<[i32; 3]>` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:11:13 + | +LL | let _ = box match true { true => [1, 2, 3], false => [1, 3, 4] }: Box<[i32]>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` + | + = note: expected struct `Box<[i32]>` + found struct `Box<[i32; 3]>` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:13:13 + | +LL | let _ = box { |x| (x as u8) }: Box<dyn Fn(i32) -> _>; + | ^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure + | + = note: expected struct `Box<dyn Fn(i32) -> u8>` + found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:13:19: 13:22]>` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:14:13 + | +LL | let _ = box if true { false } else { true }: Box<dyn Debug>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `bool` + | + = note: expected struct `Box<dyn Debug>` + found struct `Box<bool>` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:15:13 + | +LL | let _ = box match true { true => 'a', false => 'b' }: Box<dyn Debug>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `char` + | + = note: expected struct `Box<dyn Debug>` + found struct `Box<char>` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:17:13 + | +LL | let _ = &{ [1, 2, 3] }: &[i32]; + | ^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` + | + = note: expected reference `&[i32]` + found reference `&[i32; 3]` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:18:13 + | +LL | let _ = &if true { [1, 2, 3] } else { [1, 3, 4] }: &[i32]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` + | + = note: expected reference `&[i32]` + found reference `&[i32; 3]` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:19:13 + | +LL | let _ = &match true { true => [1, 2, 3], false => [1, 3, 4] }: &[i32]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` + | + = note: expected reference `&[i32]` + found reference `&[i32; 3]` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:21:13 + | +LL | let _ = &{ |x| (x as u8) }: &dyn Fn(i32) -> _; + | ^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure + | + = note: expected reference `&dyn Fn(i32) -> u8` + found reference `&[closure@$DIR/coerce-expect-unsized-ascribed.rs:21:16: 21:19]` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:22:13 + | +LL | let _ = &if true { false } else { true }: &dyn Debug; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `bool` + | + = note: expected reference `&dyn Debug` + found reference `&bool` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:23:13 + | +LL | let _ = &match true { true => 'a', false => 'b' }: &dyn Debug; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `char` + | + = note: expected reference `&dyn Debug` + found reference `&char` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:25:13 + | +LL | let _ = Box::new([1, 2, 3]): Box<[i32]>; + | ^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` + | + = note: expected struct `Box<[i32]>` + found struct `Box<[i32; 3]>` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:26:13 + | +LL | let _ = Box::new(|x| (x as u8)): Box<dyn Fn(i32) -> _>; + | ^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure + | + = note: expected struct `Box<dyn Fn(i32) -> u8>` + found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:26:22: 26:25]>` + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0308`. 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 000000000..eeb8fe823 --- /dev/null +++ b/src/test/ui/coercion/coerce-expect-unsized.rs @@ -0,0 +1,43 @@ +// run-pass +#![allow(unused_braces)] + +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)), + ]; +} diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr b/src/test/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr new file mode 100644 index 000000000..980da5360 --- /dev/null +++ b/src/test/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `(): std::error::Error` is not satisfied + --> $DIR/coerce-issue-49593-box-never-windows.rs:18:53 + | +LL | /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` + | + = note: required for the cast from `()` to the object type `dyn std::error::Error` + +error[E0277]: the trait bound `(): std::error::Error` is not satisfied + --> $DIR/coerce-issue-49593-box-never-windows.rs:23:49 + | +LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` + | + = note: required for the cast from `()` to the object type `(dyn std::error::Error + 'static)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never-windows.rs b/src/test/ui/coercion/coerce-issue-49593-box-never-windows.rs new file mode 100644 index 000000000..95d3935ca --- /dev/null +++ b/src/test/ui/coercion/coerce-issue-49593-box-never-windows.rs @@ -0,0 +1,58 @@ +// revisions: nofallback fallback +// only-windows - the number of `Error` impls is platform-dependent +//[fallback] check-pass +//[nofallback] check-fail + +#![feature(never_type)] +#![cfg_attr(fallback, feature(never_type_fallback))] +#![allow(unreachable_code)] + +use std::error::Error; +use std::mem; + +fn raw_ptr_box<T>(t: T) -> *mut T { + panic!() +} + +fn foo(x: !) -> Box<dyn Error> { + /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x) + //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied +} + +fn foo_raw_ptr(x: !) -> *mut dyn Error { + /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) + //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied +} + +fn no_coercion(d: *mut dyn Error) -> *mut dyn Error { + /* an unsize coercion won't compile here, and it is indeed not used + because there is nothing requiring the _ to be Sized */ + d as *mut _ +} + +trait Xyz {} +struct S; +struct T; +impl Xyz for S {} +impl Xyz for T {} + +fn foo_no_never() { + let mut x /* : Option<S> */ = None; + let mut first_iter = false; + loop { + if !first_iter { + let y: Box<dyn Xyz> + = /* Box<$0> is coerced to Box<Xyz> here */ Box::new(x.unwrap()); + } + + x = Some(S); + first_iter = true; + } + + let mut y : Option<S> = None; + // assert types are equal + mem::swap(&mut x, &mut y); +} + +fn main() { +} diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr new file mode 100644 index 000000000..322681b97 --- /dev/null +++ b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `(): std::error::Error` is not satisfied + --> $DIR/coerce-issue-49593-box-never.rs:18:53 + | +LL | /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` + | + = note: required for the cast from `()` to the object type `dyn std::error::Error` + +error[E0277]: the trait bound `(): std::error::Error` is not satisfied + --> $DIR/coerce-issue-49593-box-never.rs:23:49 + | +LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` + | + = note: required for the cast from `()` to the object type `(dyn std::error::Error + 'static)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.rs b/src/test/ui/coercion/coerce-issue-49593-box-never.rs new file mode 100644 index 000000000..16efb65ac --- /dev/null +++ b/src/test/ui/coercion/coerce-issue-49593-box-never.rs @@ -0,0 +1,58 @@ +// revisions: nofallback fallback +// ignore-windows - the number of `Error` impls is platform-dependent +//[fallback] check-pass +//[nofallback] check-fail + +#![feature(never_type)] +#![cfg_attr(fallback, feature(never_type_fallback))] +#![allow(unreachable_code)] + +use std::error::Error; +use std::mem; + +fn raw_ptr_box<T>(t: T) -> *mut T { + panic!() +} + +fn foo(x: !) -> Box<dyn Error> { + /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x) + //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied +} + +fn foo_raw_ptr(x: !) -> *mut dyn Error { + /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) + //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied +} + +fn no_coercion(d: *mut dyn Error) -> *mut dyn Error { + /* an unsize coercion won't compile here, and it is indeed not used + because there is nothing requiring the _ to be Sized */ + d as *mut _ +} + +trait Xyz {} +struct S; +struct T; +impl Xyz for S {} +impl Xyz for T {} + +fn foo_no_never() { + let mut x /* : Option<S> */ = None; + let mut first_iter = false; + loop { + if !first_iter { + let y: Box<dyn Xyz> + = /* Box<$0> is coerced to Box<Xyz> here */ Box::new(x.unwrap()); + } + + x = Some(S); + first_iter = true; + } + + let mut y : Option<S> = None; + // assert types are equal + mem::swap(&mut x, &mut y); +} + +fn main() { +} diff --git a/src/test/ui/coercion/coerce-mut.rs b/src/test/ui/coercion/coerce-mut.rs new file mode 100644 index 000000000..43f0b5585 --- /dev/null +++ b/src/test/ui/coercion/coerce-mut.rs @@ -0,0 +1,10 @@ +fn f(x: &mut i32) {} + +fn main() { + let x = 0; + f(&x); + //~^ ERROR mismatched types + //~| expected mutable reference `&mut i32` + //~| found reference `&{integer}` + //~| types differ in mutability +} diff --git a/src/test/ui/coercion/coerce-mut.stderr b/src/test/ui/coercion/coerce-mut.stderr new file mode 100644 index 000000000..11a4f3101 --- /dev/null +++ b/src/test/ui/coercion/coerce-mut.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/coerce-mut.rs:5:7 + | +LL | f(&x); + | - ^^ types differ in mutability + | | + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut i32` + found reference `&{integer}` +note: function defined here + --> $DIR/coerce-mut.rs:1:4 + | +LL | fn f(x: &mut i32) {} + | ^ ----------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. 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 000000000..01d9c1e48 --- /dev/null +++ b/src/test/ui/coercion/coerce-overloaded-autoderef-fail.rs @@ -0,0 +1,32 @@ +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() {} 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 000000000..d067c3b3a --- /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 new file mode 100644 index 000000000..d5484607c --- /dev/null +++ b/src/test/ui/coercion/coerce-overloaded-autoderef.rs @@ -0,0 +1,68 @@ +// 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() {} 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 000000000..f033e1b5d --- /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 000000000..64a365229 --- /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 000000000..c2aaae1c7 --- /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 000000000..9a5652acf --- /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<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)); +} diff --git a/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.rs b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.rs new file mode 100644 index 000000000..48be2d314 --- /dev/null +++ b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.rs @@ -0,0 +1,6 @@ +fn test<T>(_a: T, _b: T) {} + +fn main() { + test(&mut 7, &7); + //~^ mismatched types +} diff --git a/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr new file mode 100644 index 000000000..36551e5af --- /dev/null +++ b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/coerce-reborrow-multi-arg-fail.rs:4:18 + | +LL | test(&mut 7, &7); + | ---- ^^ types differ in mutability + | | + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut {integer}` + found reference `&{integer}` +note: function defined here + --> $DIR/coerce-reborrow-multi-arg-fail.rs:1:4 + | +LL | fn test<T>(_a: T, _b: T) {} + | ^^^^ ----- ----- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/coercion/coerce-reborrow-multi-arg.rs b/src/test/ui/coercion/coerce-reborrow-multi-arg.rs new file mode 100644 index 000000000..93cd0bb3e --- /dev/null +++ b/src/test/ui/coercion/coerce-reborrow-multi-arg.rs @@ -0,0 +1,9 @@ +// build-pass +fn test<T>(_a: T, _b: T) {} + +fn main() { + test(&7, &7); + test(&7, &mut 7); + test::<&i32>(&mut 7, &7); + test::<&i32>(&mut 7, &mut 7); +} 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 000000000..76cd6793b --- /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 000000000..e6e7c3a51 --- /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 000000000..2635754f1 --- /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 000000000..c03336ea3 --- /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 new file mode 100644 index 000000000..85598a42e --- /dev/null +++ b/src/test/ui/coercion/coerce-to-bang-cast.rs @@ -0,0 +1,12 @@ +#![feature(never_type)] + +fn cast_a() { + let y = {return; 22} as !; + //~^ ERROR non-primitive cast +} + +fn cast_b() { + let y = 22 as !; //~ ERROR non-primitive cast +} + +fn main() { } diff --git a/src/test/ui/coercion/coerce-to-bang-cast.stderr b/src/test/ui/coercion/coerce-to-bang-cast.stderr new file mode 100644 index 000000000..50e009aa2 --- /dev/null +++ b/src/test/ui/coercion/coerce-to-bang-cast.stderr @@ -0,0 +1,15 @@ +error[E0605]: non-primitive cast: `i32` as `!` + --> $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: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 + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0605`. diff --git a/src/test/ui/coercion/coerce-to-bang.rs b/src/test/ui/coercion/coerce-to-bang.rs new file mode 100644 index 000000000..1e06934d0 --- /dev/null +++ b/src/test/ui/coercion/coerce-to-bang.rs @@ -0,0 +1,79 @@ +#![feature(never_type)] + +fn foo(x: usize, y: !, z: usize) { } + +fn call_foo_a() { + foo(return, 22, 44); + //~^ ERROR mismatched types +} + +fn call_foo_b() { + // Divergence happens in the argument itself, definitely ok. + foo(22, return, 44); +} + +fn call_foo_c() { + // This test fails because the divergence happens **after** the + // coercion to `!`: + foo(22, 44, return); //~ ERROR mismatched types +} + +fn call_foo_d() { + // This test passes because `a` has type `!`: + let a: ! = return; + let b = 22; + let c = 44; + foo(a, b, c); // ... and hence a reference to `a` is expected to diverge. + //~^ ERROR mismatched types +} + +fn call_foo_e() { + // This test probably could pass but we don't *know* that `a` + // has type `!` so we don't let it work. + let a = return; + let b = 22; + let c = 44; + foo(a, b, c); //~ ERROR mismatched types +} + +fn call_foo_f() { + // This fn fails because `a` has type `usize`, and hence a + // reference to is it **not** considered to diverge. + let a: usize = return; + let b = 22; + let c = 44; + foo(a, b, c); //~ ERROR mismatched types +} + +fn array_a() { + // Return is coerced to `!` just fine, but `22` cannot be. + let x: [!; 2] = [return, 22]; //~ ERROR mismatched types +} + +fn array_b() { + // Error: divergence has not yet occurred. + let x: [!; 2] = [22, return]; //~ ERROR mismatched types +} + +fn tuple_a() { + // No divergence at all. + let x: (usize, !, usize) = (22, 44, 66); //~ ERROR mismatched types +} + +fn tuple_b() { + // Divergence happens before coercion: OK + let x: (usize, !, usize) = (return, 44, 66); + //~^ ERROR mismatched types +} + +fn tuple_c() { + // Divergence happens before coercion: OK + let x: (usize, !, usize) = (22, return, 66); +} + +fn tuple_d() { + // Error: divergence happens too late + let x: (usize, !, usize) = (22, 44, return); //~ ERROR mismatched types +} + +fn main() { } diff --git a/src/test/ui/coercion/coerce-to-bang.stderr b/src/test/ui/coercion/coerce-to-bang.stderr new file mode 100644 index 000000000..add8f14cf --- /dev/null +++ b/src/test/ui/coercion/coerce-to-bang.stderr @@ -0,0 +1,130 @@ +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:6:17 + | +LL | foo(return, 22, 44); + | --- ^^ expected `!`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type `!` + found type `{integer}` +note: function defined here + --> $DIR/coerce-to-bang.rs:3:4 + | +LL | fn foo(x: usize, y: !, z: usize) { } + | ^^^ -------- ---- -------- + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:18:13 + | +LL | foo(22, 44, return); + | --- ^^ expected `!`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type `!` + found type `{integer}` +note: function defined here + --> $DIR/coerce-to-bang.rs:3:4 + | +LL | fn foo(x: usize, y: !, z: usize) { } + | ^^^ -------- ---- -------- + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:26:12 + | +LL | foo(a, b, c); // ... and hence a reference to `a` is expected to diverge. + | --- ^ expected `!`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type `!` + found type `{integer}` +note: function defined here + --> $DIR/coerce-to-bang.rs:3:4 + | +LL | fn foo(x: usize, y: !, z: usize) { } + | ^^^ -------- ---- -------- + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:36:12 + | +LL | foo(a, b, c); + | --- ^ expected `!`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type `!` + found type `{integer}` +note: function defined here + --> $DIR/coerce-to-bang.rs:3:4 + | +LL | fn foo(x: usize, y: !, z: usize) { } + | ^^^ -------- ---- -------- + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:45:12 + | +LL | foo(a, b, c); + | --- ^ expected `!`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type `!` + found type `{integer}` +note: function defined here + --> $DIR/coerce-to-bang.rs:3:4 + | +LL | fn foo(x: usize, y: !, z: usize) { } + | ^^^ -------- ---- -------- + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:50:21 + | +LL | let x: [!; 2] = [return, 22]; + | ------ ^^^^^^^^^^^^ expected `!`, found integer + | | + | expected due to this + | + = note: expected array `[!; 2]` + found array `[{integer}; 2]` + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:55:22 + | +LL | let x: [!; 2] = [22, return]; + | ^^ expected `!`, found integer + | + = note: expected type `!` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:60:37 + | +LL | let x: (usize, !, usize) = (22, 44, 66); + | ^^ expected `!`, found integer + | + = note: expected type `!` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:65:41 + | +LL | let x: (usize, !, usize) = (return, 44, 66); + | ^^ expected `!`, found integer + | + = note: expected type `!` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:76:37 + | +LL | let x: (usize, !, usize) = (22, 44, return); + | ^^ expected `!`, found integer + | + = note: expected type `!` + found type `{integer}` + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0308`. 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 000000000..95a7ee8fe --- /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<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); +} diff --git a/src/test/ui/coercion/coerce-unify.rs b/src/test/ui/coercion/coerce-unify.rs new file mode 100644 index 000000000..f1818f9bb --- /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::<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)]; +} 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 000000000..45b53300c --- /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<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() {} diff --git a/src/test/ui/coercion/coercion-missing-tail-expected-type.fixed b/src/test/ui/coercion/coercion-missing-tail-expected-type.fixed new file mode 100644 index 000000000..713e04774 --- /dev/null +++ b/src/test/ui/coercion/coercion-missing-tail-expected-type.fixed @@ -0,0 +1,16 @@ +// #41425 -- error message "mismatched types" has wrong types +// run-rustfix + +fn plus_one(x: i32) -> i32 { //~ ERROR mismatched types + x + 1 +} + +fn foo() -> Result<u8, u64> { //~ ERROR mismatched types + Ok(1) +} + +fn main() { + let x = plus_one(5); + let _ = foo(); + println!("X = {}", x); +} diff --git a/src/test/ui/coercion/coercion-missing-tail-expected-type.rs b/src/test/ui/coercion/coercion-missing-tail-expected-type.rs new file mode 100644 index 000000000..e14d79d8a --- /dev/null +++ b/src/test/ui/coercion/coercion-missing-tail-expected-type.rs @@ -0,0 +1,16 @@ +// #41425 -- error message "mismatched types" has wrong types +// run-rustfix + +fn plus_one(x: i32) -> i32 { //~ ERROR mismatched types + x + 1; +} + +fn foo() -> Result<u8, u64> { //~ ERROR mismatched types + Ok(1); +} + +fn main() { + let x = plus_one(5); + let _ = foo(); + println!("X = {}", x); +} diff --git a/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr new file mode 100644 index 000000000..a4843bca5 --- /dev/null +++ b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/coercion-missing-tail-expected-type.rs:4:24 + | +LL | fn plus_one(x: i32) -> i32 { + | -------- ^^^ expected `i32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +LL | x + 1; + | - help: remove this semicolon + +error[E0308]: mismatched types + --> $DIR/coercion-missing-tail-expected-type.rs:8:13 + | +LL | fn foo() -> Result<u8, u64> { + | --- ^^^^^^^^^^^^^^^ expected enum `Result`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +LL | Ok(1); + | - help: remove this semicolon + | + = note: expected enum `Result<u8, u64>` + found unit type `()` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/coercion/coercion-slice.rs b/src/test/ui/coercion/coercion-slice.rs new file mode 100644 index 000000000..b756c8f82 --- /dev/null +++ b/src/test/ui/coercion/coercion-slice.rs @@ -0,0 +1,7 @@ +// Tests that we forbid coercion from `[T; n]` to `&[T]` + +fn main() { + let _: &[i32] = [0]; + //~^ ERROR mismatched types + //~| expected `&[i32]`, found array `[{integer}; 1]` +} diff --git a/src/test/ui/coercion/coercion-slice.stderr b/src/test/ui/coercion/coercion-slice.stderr new file mode 100644 index 000000000..42dc954ff --- /dev/null +++ b/src/test/ui/coercion/coercion-slice.stderr @@ -0,0 +1,13 @@ +error[E0308]: mismatched types + --> $DIR/coercion-slice.rs:4:21 + | +LL | let _: &[i32] = [0]; + | ------ ^^^ + | | | + | | expected `&[i32]`, found array `[{integer}; 1]` + | | help: consider borrowing here: `&[0]` + | expected due to this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/coercion/issue-14589.rs b/src/test/ui/coercion/issue-14589.rs new file mode 100644 index 000000000..d35ee5c73 --- /dev/null +++ b/src/test/ui/coercion/issue-14589.rs @@ -0,0 +1,24 @@ +// run-pass +// All 3 expressions should work in that the argument gets +// coerced to a trait object + +// pretty-expanded FIXME #23616 + +fn main() { + send::<Box<dyn Foo>>(Box::new(Output(0))); + Test::<Box<dyn Foo>>::foo(Box::new(Output(0))); + Test::<Box<dyn Foo>>::new().send(Box::new(Output(0))); +} + +fn send<T>(_: T) {} + +struct Test<T> { marker: std::marker::PhantomData<T> } +impl<T> Test<T> { + fn new() -> Test<T> { Test { marker: ::std::marker::PhantomData } } + fn foo(_: T) {} + fn send(&self, _: T) {} +} + +trait Foo { fn dummy(&self) { }} +struct Output(#[allow(unused_tuple_struct_fields)] isize); +impl Foo for Output {} diff --git a/src/test/ui/coercion/issue-37655.rs b/src/test/ui/coercion/issue-37655.rs new file mode 100644 index 000000000..416854d66 --- /dev/null +++ b/src/test/ui/coercion/issue-37655.rs @@ -0,0 +1,37 @@ +// check-pass +// Regression test for #37655. The problem was a false edge created by +// coercion that wound up requiring that `'a` (in `split()`) outlive +// `'b`, which shouldn't be necessary. + +#![allow(warnings)] + +trait SliceExt<T> { + type Item; + + fn get_me<I>(&self, index: I) -> &I::Output + where I: SliceIndex<Self::Item>; +} + +impl<T> SliceExt<T> for [T] { + type Item = T; + + fn get_me<I>(&self, index: I) -> &I::Output + where I: SliceIndex<T> + { + panic!() + } +} + +pub trait SliceIndex<T> { + type Output: ?Sized; +} + +impl<T> SliceIndex<T> for usize { + type Output = T; +} + +fn foo<'a, 'b>(split: &'b [&'a [u8]]) -> &'a [u8] { + split.get_me(0) +} + +fn main() { } diff --git a/src/test/ui/coercion/issue-39823.rs b/src/test/ui/coercion/issue-39823.rs new file mode 100644 index 000000000..148cf527e --- /dev/null +++ b/src/test/ui/coercion/issue-39823.rs @@ -0,0 +1,25 @@ +// run-pass +// aux-build:issue-39823.rs + +extern crate issue_39823; +use issue_39823::{RemoteC, RemoteG}; + +#[derive(Debug, PartialEq)] +struct LocalC(u32); + +#[derive(Debug, PartialEq)] +struct LocalG<T>(T); + +fn main() { + let virtual_localc : &dyn Fn(_) -> LocalC = &LocalC; + assert_eq!(virtual_localc(1), LocalC(1)); + + let virtual_localg : &dyn Fn(_) -> LocalG<u32> = &LocalG; + assert_eq!(virtual_localg(1), LocalG(1)); + + let virtual_remotec : &dyn Fn(_) -> RemoteC = &RemoteC; + assert_eq!(virtual_remotec(1), RemoteC(1)); + + let virtual_remoteg : &dyn Fn(_) -> RemoteG<u32> = &RemoteG; + assert_eq!(virtual_remoteg(1), RemoteG(1)); +} diff --git a/src/test/ui/coercion/issue-53475.rs b/src/test/ui/coercion/issue-53475.rs new file mode 100644 index 000000000..3770c024f --- /dev/null +++ b/src/test/ui/coercion/issue-53475.rs @@ -0,0 +1,13 @@ +#![feature(coerce_unsized)] + +use std::any::Any; +use std::ops::CoerceUnsized; + +struct Foo<T> { + data: Box<T>, +} + +impl<T> CoerceUnsized<Foo<dyn Any>> for Foo<T> {} +//~^ ERROR the parameter type `T` may not live long enough + +fn main() {} diff --git a/src/test/ui/coercion/issue-53475.stderr b/src/test/ui/coercion/issue-53475.stderr new file mode 100644 index 000000000..522c50dca --- /dev/null +++ b/src/test/ui/coercion/issue-53475.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue-53475.rs:10:1 + | +LL | impl<T> CoerceUnsized<Foo<dyn Any>> for Foo<T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | impl<T: 'static> CoerceUnsized<Foo<dyn Any>> for Foo<T> {} + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/coercion/issue-73886.rs b/src/test/ui/coercion/issue-73886.rs new file mode 100644 index 000000000..9c0c87a5c --- /dev/null +++ b/src/test/ui/coercion/issue-73886.rs @@ -0,0 +1,6 @@ +fn main() { + let _ = &&[0] as &[_]; + //~^ ERROR non-primitive cast: `&&[i32; 1]` as `&[_]` + let _ = 7u32 as Option<_>; + //~^ ERROR non-primitive cast: `u32` as `Option<_>` +} diff --git a/src/test/ui/coercion/issue-73886.stderr b/src/test/ui/coercion/issue-73886.stderr new file mode 100644 index 000000000..a6f8ba65a --- /dev/null +++ b/src/test/ui/coercion/issue-73886.stderr @@ -0,0 +1,17 @@ +error[E0605]: non-primitive cast: `&&[i32; 1]` as `&[_]` + --> $DIR/issue-73886.rs:2:13 + | +LL | let _ = &&[0] 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: `u32` as `Option<_>` + --> $DIR/issue-73886.rs:4:13 + | +LL | let _ = 7u32 as Option<_>; + | ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)` + | + = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0605`. diff --git a/src/test/ui/coercion/issue-88097.rs b/src/test/ui/coercion/issue-88097.rs new file mode 100644 index 000000000..e543e1bae --- /dev/null +++ b/src/test/ui/coercion/issue-88097.rs @@ -0,0 +1,31 @@ +// In #88097, the compiler attempted to coerce a closure type to itself via +// a function pointer, which caused an unnecessary error. Check that this +// behavior has been fixed. + +// check-pass + +fn peculiar() -> impl Fn(u8) -> u8 { + return |x| x + 1 +} + +fn peculiar2() -> impl Fn(u8) -> u8 { + return |x| x + 1; +} + +fn peculiar3() -> impl Fn(u8) -> u8 { + let f = |x| x + 1; + return f +} + +fn peculiar4() -> impl Fn(u8) -> u8 { + let f = |x| x + 1; + f +} + +fn peculiar5() -> impl Fn(u8) -> u8 { + let f = |x| x + 1; + let g = |x| x + 2; + return if true { f } else { g } +} + +fn main() {} diff --git a/src/test/ui/coercion/retslot-cast.rs b/src/test/ui/coercion/retslot-cast.rs new file mode 100644 index 000000000..ae500cb15 --- /dev/null +++ b/src/test/ui/coercion/retslot-cast.rs @@ -0,0 +1,22 @@ +#![allow(warnings)] + +pub fn fail(x: Option<&(Iterator<Item=()>+Send)>) + -> Option<&Iterator<Item=()>> { + // This call used to trigger an LLVM assertion because the return + // slot had type "Option<&Iterator>"* instead of + // "Option<&(Iterator+Send)>"* -- but this now yields a + // compilation error and I'm not sure how to create a comparable + // test. To ensure that this PARTICULAR failure doesn't occur + // again, though, I've left this test here, so if this ever starts + // to compile again, we can adjust the test appropriately (clearly + // it should never ICE...). -nmatsakis + inner(x) //~ ERROR mismatched types +} + +pub fn inner(x: Option<&(Iterator<Item=()>+Send)>) + -> Option<&(Iterator<Item=()>+Send)> { + x +} + + +fn main() {} diff --git a/src/test/ui/coercion/retslot-cast.stderr b/src/test/ui/coercion/retslot-cast.stderr new file mode 100644 index 000000000..798ce1199 --- /dev/null +++ b/src/test/ui/coercion/retslot-cast.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/retslot-cast.rs:13:5 + | +LL | -> Option<&Iterator<Item=()>> { + | -------------------------- expected `Option<&dyn Iterator<Item = ()>>` because of return type +... +LL | inner(x) + | ^^^^^^^^ expected trait `Iterator<Item = ()>`, found trait `Iterator<Item = ()> + Send` + | + = note: expected enum `Option<&dyn Iterator<Item = ()>>` + found enum `Option<&dyn Iterator<Item = ()> + Send>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/coercion/unsafe-coercion.rs b/src/test/ui/coercion/unsafe-coercion.rs new file mode 100644 index 000000000..2478deeab --- /dev/null +++ b/src/test/ui/coercion/unsafe-coercion.rs @@ -0,0 +1,17 @@ +// run-pass +// Check that safe fns are not a subtype of unsafe fns. + + +fn foo(x: i32) -> i32 { + x * 22 +} + +fn bar(x: fn(i32) -> i32) -> unsafe fn(i32) -> i32 { + x // OK, coercion! +} + +fn main() { + let f = bar(foo); + let x = unsafe { f(2) }; + assert_eq!(x, 44); +} |