diff options
Diffstat (limited to '')
516 files changed, 17106 insertions, 0 deletions
diff --git a/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.rs b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.rs new file mode 100644 index 000000000..ef64d799b --- /dev/null +++ b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.rs @@ -0,0 +1,28 @@ +trait Trait { + fn func1() -> Struct1<Self>; //~ ERROR E0277 + fn func2<'a>() -> Struct2<'a, Self>; //~ ERROR E0277 + fn func3() -> Struct3<Self>; //~ ERROR E0277 + fn func4() -> Struct4<Self>; //~ ERROR E0277 +} + +struct Struct1<T>{ + _t: std::marker::PhantomData<*const T>, +} +struct Struct2<'a, T>{ + _t: &'a T, +} +struct Struct3<T>{ + _t: T, +} + +struct X<T>(T); + +struct Struct4<T>{ + _t: X<T>, +} + +struct Struct5<T: ?Sized>{ + _t: X<T>, //~ ERROR E0277 +} + +fn main() {} diff --git a/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr new file mode 100644 index 000000000..b77c8c7fd --- /dev/null +++ b/src/test/ui/suggestions/adt-param-with-implicit-sized-bound.stderr @@ -0,0 +1,112 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:25:9 + | +LL | struct Struct5<T: ?Sized>{ + | - this type parameter needs to be `std::marker::Sized` +LL | _t: X<T>, + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `X` + --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 + | +LL | struct X<T>(T); + | ^ required by this bound in `X` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>` + --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 + | +LL | struct X<T>(T); + | ^ - ...if indirection were used here: `Box<T>` + | | + | this could be changed to `T: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - struct Struct5<T: ?Sized>{ +LL + struct Struct5<T>{ + | + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:2:19 + | +LL | fn func1() -> Struct1<Self>; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Struct1` + --> $DIR/adt-param-with-implicit-sized-bound.rs:8:16 + | +LL | struct Struct1<T>{ + | ^ required by this bound in `Struct1` +help: consider further restricting `Self` + | +LL | fn func1() -> Struct1<Self> where Self: Sized; + | +++++++++++++++++ +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Struct1<T: ?Sized>{ + | ++++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:3:23 + | +LL | fn func2<'a>() -> Struct2<'a, Self>; + | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Struct2` + --> $DIR/adt-param-with-implicit-sized-bound.rs:11:20 + | +LL | struct Struct2<'a, T>{ + | ^ required by this bound in `Struct2` +help: consider further restricting `Self` + | +LL | fn func2<'a>() -> Struct2<'a, Self> where Self: Sized; + | +++++++++++++++++ +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Struct2<'a, T: ?Sized>{ + | ++++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:4:19 + | +LL | fn func3() -> Struct3<Self>; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Struct3` + --> $DIR/adt-param-with-implicit-sized-bound.rs:14:16 + | +LL | struct Struct3<T>{ + | ^ required by this bound in `Struct3` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>` + --> $DIR/adt-param-with-implicit-sized-bound.rs:14:16 + | +LL | struct Struct3<T>{ + | ^ this could be changed to `T: ?Sized`... +LL | _t: T, + | - ...if indirection were used here: `Box<T>` +help: consider further restricting `Self` + | +LL | fn func3() -> Struct3<Self> where Self: Sized; + | +++++++++++++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:5:19 + | +LL | fn func4() -> Struct4<Self>; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Struct4` + --> $DIR/adt-param-with-implicit-sized-bound.rs:20:16 + | +LL | struct Struct4<T>{ + | ^ required by this bound in `Struct4` +help: consider further restricting `Self` + | +LL | fn func4() -> Struct4<Self> where Self: Sized; + | +++++++++++++++++ +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Struct4<T: ?Sized>{ + | ++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/args-instead-of-tuple-errors.rs b/src/test/ui/suggestions/args-instead-of-tuple-errors.rs new file mode 100644 index 000000000..5403b8d6d --- /dev/null +++ b/src/test/ui/suggestions/args-instead-of-tuple-errors.rs @@ -0,0 +1,22 @@ +// Ensure we don't suggest tuple-wrapping when we'd end up with a type error + +fn main() { + // we shouldn't suggest to fix these - `2` isn't a `bool` + + let _: Option<(i32, bool)> = Some(1, 2); + //~^ ERROR this enum variant takes 1 argument but 2 arguments were supplied + int_bool(1, 2); + //~^ ERROR this function takes 1 argument but 2 arguments were supplied + + let _: Option<(i8,)> = Some(); + //~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied + + let _: Option<(i32,)> = Some(5_usize); + //~^ ERROR mismatched types + + let _: Option<(i32,)> = Some((5_usize)); + //~^ ERROR mismatched types +} + +fn int_bool(_: (i32, bool)) { +} diff --git a/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr b/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr new file mode 100644 index 000000000..805c75f46 --- /dev/null +++ b/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr @@ -0,0 +1,92 @@ +error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied + --> $DIR/args-instead-of-tuple-errors.rs:6:34 + | +LL | let _: Option<(i32, bool)> = Some(1, 2); + | ^^^^ - - argument of type `{integer}` unexpected + | | + | expected tuple, found integer + | + = note: expected tuple `(i32, bool)` + found type `{integer}` +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^^^ +help: remove the extra argument + | +LL | let _: Option<(i32, bool)> = Some(/* (i32, bool) */); + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/args-instead-of-tuple-errors.rs:8:5 + | +LL | int_bool(1, 2); + | ^^^^^^^^ - - argument of type `{integer}` unexpected + | | + | expected tuple, found integer + | + = note: expected tuple `(i32, bool)` + found type `{integer}` +note: function defined here + --> $DIR/args-instead-of-tuple-errors.rs:21:4 + | +LL | fn int_bool(_: (i32, bool)) { + | ^^^^^^^^ -------------- +help: remove the extra argument + | +LL | int_bool(/* (i32, bool) */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied + --> $DIR/args-instead-of-tuple-errors.rs:11:28 + | +LL | let _: Option<(i8,)> = Some(); + | ^^^^-- an argument of type `(i8,)` is missing + | +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^^^ +help: provide the argument + | +LL | let _: Option<(i8,)> = Some(/* (i8,) */); + | ~~~~~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/args-instead-of-tuple-errors.rs:14:34 + | +LL | let _: Option<(i32,)> = Some(5_usize); + | ---- ^^^^^^^ expected tuple, found `usize` + | | + | arguments to this enum variant are incorrect + | + = note: expected tuple `(i32,)` + found type `usize` +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^^^ + +error[E0308]: mismatched types + --> $DIR/args-instead-of-tuple-errors.rs:17:34 + | +LL | let _: Option<(i32,)> = Some((5_usize)); + | ---- ^^^^^^^^^ expected tuple, found `usize` + | | + | arguments to this enum variant are incorrect + | + = note: expected tuple `(i32,)` + found type `usize` +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0061, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/src/test/ui/suggestions/args-instead-of-tuple.fixed b/src/test/ui/suggestions/args-instead-of-tuple.fixed new file mode 100644 index 000000000..66e53f9ce --- /dev/null +++ b/src/test/ui/suggestions/args-instead-of-tuple.fixed @@ -0,0 +1,33 @@ +// Test suggesting tuples where bare arguments may have been passed +// See issue #86481 for details. + +// run-rustfix + +fn main() { + let _: Result<(i32, i8), ()> = Ok((1, 2)); + //~^ ERROR this enum variant takes 1 argument but 2 arguments were supplied + let _: Option<(i32, i8, &'static str)> = Some((1, 2, "hi")); + //~^ ERROR this enum variant takes 1 argument but 3 arguments were supplied + let _: Option<()> = Some(()); + //~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied + + let _: Option<(i32,)> = Some((3,)); + //~^ ERROR mismatched types + + let _: Option<(i32,)> = Some((3,)); + //~^ ERROR mismatched types + + two_ints((1, 2)); //~ ERROR this function takes 1 argument + + with_generic((3, 4)); //~ ERROR this function takes 1 argument +} + +fn two_ints(_: (i32, i32)) { +} + +fn with_generic<T: Copy + Send>((a, b): (i32, T)) { + if false { + // test generics/bound handling + with_generic((a, b)); //~ ERROR this function takes 1 argument + } +} diff --git a/src/test/ui/suggestions/args-instead-of-tuple.rs b/src/test/ui/suggestions/args-instead-of-tuple.rs new file mode 100644 index 000000000..a15bff07e --- /dev/null +++ b/src/test/ui/suggestions/args-instead-of-tuple.rs @@ -0,0 +1,33 @@ +// Test suggesting tuples where bare arguments may have been passed +// See issue #86481 for details. + +// run-rustfix + +fn main() { + let _: Result<(i32, i8), ()> = Ok(1, 2); + //~^ ERROR this enum variant takes 1 argument but 2 arguments were supplied + let _: Option<(i32, i8, &'static str)> = Some(1, 2, "hi"); + //~^ ERROR this enum variant takes 1 argument but 3 arguments were supplied + let _: Option<()> = Some(); + //~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied + + let _: Option<(i32,)> = Some(3); + //~^ ERROR mismatched types + + let _: Option<(i32,)> = Some((3)); + //~^ ERROR mismatched types + + two_ints(1, 2); //~ ERROR this function takes 1 argument + + with_generic(3, 4); //~ ERROR this function takes 1 argument +} + +fn two_ints(_: (i32, i32)) { +} + +fn with_generic<T: Copy + Send>((a, b): (i32, T)) { + if false { + // test generics/bound handling + with_generic(a, b); //~ ERROR this function takes 1 argument + } +} diff --git a/src/test/ui/suggestions/args-instead-of-tuple.stderr b/src/test/ui/suggestions/args-instead-of-tuple.stderr new file mode 100644 index 000000000..2448a5149 --- /dev/null +++ b/src/test/ui/suggestions/args-instead-of-tuple.stderr @@ -0,0 +1,140 @@ +error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied + --> $DIR/args-instead-of-tuple.rs:7:36 + | +LL | let _: Result<(i32, i8), ()> = Ok(1, 2); + | ^^ + | +note: tuple variant defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + | +LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^ +help: wrap these arguments in parentheses to construct a tuple + | +LL | let _: Result<(i32, i8), ()> = Ok((1, 2)); + | + + + +error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied + --> $DIR/args-instead-of-tuple.rs:9:46 + | +LL | let _: Option<(i32, i8, &'static str)> = Some(1, 2, "hi"); + | ^^^^ + | +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^^^ +help: wrap these arguments in parentheses to construct a tuple + | +LL | let _: Option<(i32, i8, &'static str)> = Some((1, 2, "hi")); + | + + + +error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied + --> $DIR/args-instead-of-tuple.rs:11:25 + | +LL | let _: Option<()> = Some(); + | ^^^^-- an argument of type `()` is missing + | +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^^^ +help: provide the argument + | +LL | let _: Option<()> = Some(()); + | ~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/args-instead-of-tuple.rs:14:34 + | +LL | let _: Option<(i32,)> = Some(3); + | ---- ^ expected tuple, found integer + | | + | arguments to this enum variant are incorrect + | + = note: expected tuple `(i32,)` + found type `{integer}` +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^^^ +help: use a trailing comma to create a tuple with one element + | +LL | let _: Option<(i32,)> = Some((3,)); + | + ++ + +error[E0308]: mismatched types + --> $DIR/args-instead-of-tuple.rs:17:34 + | +LL | let _: Option<(i32,)> = Some((3)); + | ---- ^^^ expected tuple, found integer + | | + | arguments to this enum variant are incorrect + | + = note: expected tuple `(i32,)` + found type `{integer}` +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^^^ +help: use a trailing comma to create a tuple with one element + | +LL | let _: Option<(i32,)> = Some((3,)); + | + + +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/args-instead-of-tuple.rs:20:5 + | +LL | two_ints(1, 2); + | ^^^^^^^^ + | +note: function defined here + --> $DIR/args-instead-of-tuple.rs:25:4 + | +LL | fn two_ints(_: (i32, i32)) { + | ^^^^^^^^ ------------- +help: wrap these arguments in parentheses to construct a tuple + | +LL | two_ints((1, 2)); + | + + + +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/args-instead-of-tuple.rs:22:5 + | +LL | with_generic(3, 4); + | ^^^^^^^^^^^^ + | +note: function defined here + --> $DIR/args-instead-of-tuple.rs:28:4 + | +LL | fn with_generic<T: Copy + Send>((a, b): (i32, T)) { + | ^^^^^^^^^^^^ ---------------- +help: wrap these arguments in parentheses to construct a tuple + | +LL | with_generic((3, 4)); + | + + + +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/args-instead-of-tuple.rs:31:9 + | +LL | with_generic(a, b); + | ^^^^^^^^^^^^ + | +note: function defined here + --> $DIR/args-instead-of-tuple.rs:28:4 + | +LL | fn with_generic<T: Copy + Send>((a, b): (i32, T)) { + | ^^^^^^^^^^^^ ---------------- +help: wrap these arguments in parentheses to construct a tuple + | +LL | with_generic((a, b)); + | + + + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0061, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/src/test/ui/suggestions/as-ref-2.fixed b/src/test/ui/suggestions/as-ref-2.fixed new file mode 100644 index 000000000..13bbb233f --- /dev/null +++ b/src/test/ui/suggestions/as-ref-2.fixed @@ -0,0 +1,13 @@ +// run-rustfix + +struct Struct; + +fn bar(_: &Struct) -> Struct { + Struct +} + +fn main() { + let foo = Some(Struct); + let _x: Option<Struct> = foo.as_ref().map(|s| bar(&s)); + let _y = foo; //~ERROR use of moved value: `foo` +} diff --git a/src/test/ui/suggestions/as-ref-2.rs b/src/test/ui/suggestions/as-ref-2.rs new file mode 100644 index 000000000..74d61cdd9 --- /dev/null +++ b/src/test/ui/suggestions/as-ref-2.rs @@ -0,0 +1,13 @@ +// run-rustfix + +struct Struct; + +fn bar(_: &Struct) -> Struct { + Struct +} + +fn main() { + let foo = Some(Struct); + let _x: Option<Struct> = foo.map(|s| bar(&s)); + let _y = foo; //~ERROR use of moved value: `foo` +} diff --git a/src/test/ui/suggestions/as-ref-2.stderr b/src/test/ui/suggestions/as-ref-2.stderr new file mode 100644 index 000000000..3c9d0f72a --- /dev/null +++ b/src/test/ui/suggestions/as-ref-2.stderr @@ -0,0 +1,23 @@ +error[E0382]: use of moved value: `foo` + --> $DIR/as-ref-2.rs:12:14 + | +LL | let foo = Some(Struct); + | --- move occurs because `foo` has type `Option<Struct>`, which does not implement the `Copy` trait +LL | let _x: Option<Struct> = foo.map(|s| bar(&s)); + | ---------------- `foo` moved due to this method call +LL | let _y = foo; + | ^^^ value used here after move + | +note: this function takes ownership of the receiver `self`, which moves `foo` + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | pub const fn map<U, F>(self, f: F) -> Option<U> + | ^^^^ +help: consider calling `.as_ref()` to borrow the type's contents + | +LL | let _x: Option<Struct> = foo.as_ref().map(|s| bar(&s)); + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/suggestions/as-ref.rs b/src/test/ui/suggestions/as-ref.rs new file mode 100644 index 000000000..46d946153 --- /dev/null +++ b/src/test/ui/suggestions/as-ref.rs @@ -0,0 +1,20 @@ +struct Foo; + +fn takes_ref(_: &Foo) {} + +fn main() { + let ref opt = Some(Foo); + opt.map(|arg| takes_ref(arg)); //~ ERROR mismatched types [E0308] + opt.and_then(|arg| Some(takes_ref(arg))); //~ ERROR mismatched types [E0308] + let ref opt: Result<_, ()> = Ok(Foo); + opt.map(|arg| takes_ref(arg)); //~ ERROR mismatched types [E0308] + opt.and_then(|arg| Ok(takes_ref(arg))); //~ ERROR mismatched types [E0308] + let x: &Option<usize> = &Some(3); + let y: Option<&usize> = x; //~ ERROR mismatched types [E0308] + let x: &Result<usize, usize> = &Ok(3); + let y: Result<&usize, &usize> = x; + //~^ ERROR mismatched types [E0308] + // note: do not suggest because of `E: usize` + let x: &Result<usize, usize> = &Ok(3); + let y: Result<&usize, usize> = x; //~ ERROR mismatched types [E0308] +} diff --git a/src/test/ui/suggestions/as-ref.stderr b/src/test/ui/suggestions/as-ref.stderr new file mode 100644 index 000000000..1efd1b317 --- /dev/null +++ b/src/test/ui/suggestions/as-ref.stderr @@ -0,0 +1,102 @@ +error[E0308]: mismatched types + --> $DIR/as-ref.rs:7:29 + | +LL | opt.map(|arg| takes_ref(arg)); + | --- --------- ^^^ expected `&Foo`, found struct `Foo` + | | | + | | arguments to this function are incorrect + | help: consider using `as_ref` instead: `as_ref().map` + | +note: function defined here + --> $DIR/as-ref.rs:3:4 + | +LL | fn takes_ref(_: &Foo) {} + | ^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:8:39 + | +LL | opt.and_then(|arg| Some(takes_ref(arg))); + | -------- --------- ^^^ expected `&Foo`, found struct `Foo` + | | | + | | arguments to this function are incorrect + | help: consider using `as_ref` instead: `as_ref().and_then` + | +note: function defined here + --> $DIR/as-ref.rs:3:4 + | +LL | fn takes_ref(_: &Foo) {} + | ^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:10:29 + | +LL | opt.map(|arg| takes_ref(arg)); + | --- --------- ^^^ expected `&Foo`, found struct `Foo` + | | | + | | arguments to this function are incorrect + | help: consider using `as_ref` instead: `as_ref().map` + | +note: function defined here + --> $DIR/as-ref.rs:3:4 + | +LL | fn takes_ref(_: &Foo) {} + | ^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:11:37 + | +LL | opt.and_then(|arg| Ok(takes_ref(arg))); + | -------- --------- ^^^ expected `&Foo`, found struct `Foo` + | | | + | | arguments to this function are incorrect + | help: consider using `as_ref` instead: `as_ref().and_then` + | +note: function defined here + --> $DIR/as-ref.rs:3:4 + | +LL | fn takes_ref(_: &Foo) {} + | ^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:13:29 + | +LL | let y: Option<&usize> = x; + | -------------- ^ + | | | + | | expected enum `Option`, found `&Option<usize>` + | | help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`: `x.as_ref()` + | expected due to this + | + = note: expected enum `Option<&usize>` + found reference `&Option<usize>` + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:15:37 + | +LL | let y: Result<&usize, &usize> = x; + | ---------------------- ^ expected enum `Result`, found reference + | | + | expected due to this + | + = note: expected enum `Result<&usize, &usize>` + found reference `&Result<usize, usize>` +help: you can convert from `&Result<T, E>` to `Result<&T, &E>` using `.as_ref()` + | +LL | let y: Result<&usize, &usize> = x.as_ref(); + | ~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:19:36 + | +LL | let y: Result<&usize, usize> = x; + | --------------------- ^ expected enum `Result`, found reference + | | + | expected due to this + | + = note: expected enum `Result<&usize, usize>` + found reference `&Result<usize, usize>` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/assoc-const-as-field.rs b/src/test/ui/suggestions/assoc-const-as-field.rs new file mode 100644 index 000000000..678b58936 --- /dev/null +++ b/src/test/ui/suggestions/assoc-const-as-field.rs @@ -0,0 +1,13 @@ +pub mod Mod { + pub struct Foo {} + impl Foo { + pub const BAR: usize = 42; + } +} + +fn foo(_: usize) {} + +fn main() { + foo(Mod::Foo.Bar); + //~^ ERROR expected value, found +} diff --git a/src/test/ui/suggestions/assoc-const-as-field.stderr b/src/test/ui/suggestions/assoc-const-as-field.stderr new file mode 100644 index 000000000..5e746ecb2 --- /dev/null +++ b/src/test/ui/suggestions/assoc-const-as-field.stderr @@ -0,0 +1,11 @@ +error[E0423]: expected value, found struct `Mod::Foo` + --> $DIR/assoc-const-as-field.rs:11:9 + | +LL | foo(Mod::Foo.Bar); + | ^^^^^^^^---- + | | + | help: use the path separator to refer to an item: `Mod::Foo::Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/suggestions/assoc-type-in-method-return.rs b/src/test/ui/suggestions/assoc-type-in-method-return.rs new file mode 100644 index 000000000..9bde65998 --- /dev/null +++ b/src/test/ui/suggestions/assoc-type-in-method-return.rs @@ -0,0 +1,7 @@ +trait A { + type Bla; + fn to_bla(&self) -> Bla; + //~^ ERROR cannot find type `Bla` in this scope +} + +fn main() {} diff --git a/src/test/ui/suggestions/assoc-type-in-method-return.stderr b/src/test/ui/suggestions/assoc-type-in-method-return.stderr new file mode 100644 index 000000000..202e4a16e --- /dev/null +++ b/src/test/ui/suggestions/assoc-type-in-method-return.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Bla` in this scope + --> $DIR/assoc-type-in-method-return.rs:3:25 + | +LL | fn to_bla(&self) -> Bla; + | ^^^ help: you might have meant to use the associated type: `Self::Bla` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/suggestions/assoc_fn_without_self.rs b/src/test/ui/suggestions/assoc_fn_without_self.rs new file mode 100644 index 000000000..778d98477 --- /dev/null +++ b/src/test/ui/suggestions/assoc_fn_without_self.rs @@ -0,0 +1,20 @@ +fn main() {} + +struct S; + +impl S { + fn foo() {} + + fn bar(&self) {} + + fn baz(a: u8, b: u8) {} + + fn b() { + fn c() { + foo(); //~ ERROR cannot find function `foo` in this scope + } + foo(); //~ ERROR cannot find function `foo` in this scope + bar(); //~ ERROR cannot find function `bar` in this scope + baz(2, 3); //~ ERROR cannot find function `baz` in this scope + } +} diff --git a/src/test/ui/suggestions/assoc_fn_without_self.stderr b/src/test/ui/suggestions/assoc_fn_without_self.stderr new file mode 100644 index 000000000..4a0e62e73 --- /dev/null +++ b/src/test/ui/suggestions/assoc_fn_without_self.stderr @@ -0,0 +1,37 @@ +error[E0425]: cannot find function `foo` in this scope + --> $DIR/assoc_fn_without_self.rs:14:13 + | +LL | foo(); + | ^^^ not found in this scope + +error[E0425]: cannot find function `foo` in this scope + --> $DIR/assoc_fn_without_self.rs:16:9 + | +LL | foo(); + | ^^^ not found in this scope + | +help: consider using the associated function + | +LL | Self::foo(); + | ~~~~~~~~~ + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/assoc_fn_without_self.rs:17:9 + | +LL | bar(); + | ^^^ not found in this scope + +error[E0425]: cannot find function `baz` in this scope + --> $DIR/assoc_fn_without_self.rs:18:9 + | +LL | baz(2, 3); + | ^^^ not found in this scope + | +help: consider using the associated function + | +LL | Self::baz(2, 3); + | ~~~~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs new file mode 100644 index 000000000..156162c90 --- /dev/null +++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs @@ -0,0 +1,13 @@ +// edition:2018 +#![feature(async_closure)] +use std::future::Future; + +async fn foo() {} + +fn bar(f: impl Future<Output=()>) {} + +fn main() { + bar(foo); //~ERROR E0277 + let async_closure = async || (); + bar(async_closure); //~ERROR E0277 +} diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr new file mode 100644 index 000000000..c7d420e0a --- /dev/null +++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -0,0 +1,48 @@ +error[E0277]: `fn() -> impl Future<Output = ()> {foo}` is not a future + --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:10:9 + | +LL | async fn foo() {} + | --- consider calling this function +... +LL | bar(foo); + | --- ^^^ `fn() -> impl Future<Output = ()> {foo}` is not a future + | | + | required by a bound introduced by this call + | + = help: the trait `Future` is not implemented for `fn() -> impl Future<Output = ()> {foo}` + = note: fn() -> impl Future<Output = ()> {foo} must be a future or must implement `IntoFuture` to be awaited +note: required by a bound in `bar` + --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 + | +LL | fn bar(f: impl Future<Output=()>) {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `bar` +help: use parentheses to call the function + | +LL | bar(foo()); + | ++ + +error[E0277]: `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future + --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9 + | +LL | let async_closure = async || (); + | -------- consider calling this closure +LL | bar(async_closure); + | --- ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future + | | + | required by a bound introduced by this call + | + = help: the trait `Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` + = note: [closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33] must be a future or must implement `IntoFuture` to be awaited +note: required by a bound in `bar` + --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 + | +LL | fn bar(f: impl Future<Output=()>) {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `bar` +help: use parentheses to call the closure + | +LL | bar(async_closure()); + | ++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/attribute-typos.rs b/src/test/ui/suggestions/attribute-typos.rs new file mode 100644 index 000000000..7c8231bbb --- /dev/null +++ b/src/test/ui/suggestions/attribute-typos.rs @@ -0,0 +1,11 @@ +#[deprcated] //~ ERROR cannot find attribute `deprcated` in this scope +fn foo() {} + +#[tests] //~ ERROR cannot find attribute `tests` in this scope +fn bar() {} + +#[rustc_err] +//~^ ERROR cannot find attribute `rustc_err` in this scope +//~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler + +fn main() {} diff --git a/src/test/ui/suggestions/attribute-typos.stderr b/src/test/ui/suggestions/attribute-typos.stderr new file mode 100644 index 000000000..54122cb73 --- /dev/null +++ b/src/test/ui/suggestions/attribute-typos.stderr @@ -0,0 +1,31 @@ +error: attributes starting with `rustc` are reserved for use by the `rustc` compiler + --> $DIR/attribute-typos.rs:7:3 + | +LL | #[rustc_err] + | ^^^^^^^^^ + +error: cannot find attribute `rustc_err` in this scope + --> $DIR/attribute-typos.rs:7:3 + | +LL | #[rustc_err] + | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_error` + +error: cannot find attribute `tests` in this scope + --> $DIR/attribute-typos.rs:4:3 + | +LL | #[tests] + | ^^^^^ help: an attribute macro with a similar name exists: `test` + | + ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL + | +LL | pub macro test($item:item) { + | -------------- similarly named attribute macro `test` defined here + +error: cannot find attribute `deprcated` in this scope + --> $DIR/attribute-typos.rs:1:3 + | +LL | #[deprcated] + | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `deprecated` + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/suggestions/auxiliary/foo.rs b/src/test/ui/suggestions/auxiliary/foo.rs new file mode 100644 index 000000000..e90bbef6d --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/foo.rs @@ -0,0 +1,3 @@ +//! Contains a struct with almost the same name as itself, to trigger Levenshtein suggestions. + +pub struct Foo; diff --git a/src/test/ui/suggestions/auxiliary/issue-61963-1.rs b/src/test/ui/suggestions/auxiliary/issue-61963-1.rs new file mode 100644 index 000000000..6c2df7e84 --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/issue-61963-1.rs @@ -0,0 +1,40 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Group, TokenStream, TokenTree}; + +// This macro exists as part of a reproduction of #61963 but without using quote/syn/proc_macro2. + +#[proc_macro_derive(DomObject)] +pub fn expand_token_stream(input: TokenStream) -> TokenStream { + // Construct a dummy span - `#0 bytes(0..0)` - which is present in the input because + // of the specially crafted generated tokens in the `attribute-crate` proc-macro. + let dummy_span = input.clone().into_iter().nth(0).unwrap().span(); + + // Define what the macro would output if constructed properly from the source using syn/quote. + let output: TokenStream = "impl Bar for ((), Qux<Qux<Baz> >) { } + impl Bar for ((), Box<Bar>) { }".parse().unwrap(); + + let mut tokens: Vec<_> = output.into_iter().collect(); + // Adjust token spans to match the original crate (which would use `quote`). Some of the + // generated tokens point to the dummy span. + for token in tokens.iter_mut() { + if let TokenTree::Group(group) = token { + let mut tokens: Vec<_> = group.stream().into_iter().collect(); + for token in tokens.iter_mut().skip(2) { + token.set_span(dummy_span); + } + + let mut stream = TokenStream::new(); + stream.extend(tokens); + *group = Group::new(group.delimiter(), stream); + } + } + + let mut output = TokenStream::new(); + output.extend(tokens); + output +} diff --git a/src/test/ui/suggestions/auxiliary/issue-61963.rs b/src/test/ui/suggestions/auxiliary/issue-61963.rs new file mode 100644 index 000000000..e86f1610a --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/issue-61963.rs @@ -0,0 +1,41 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Group, Spacing, Punct, TokenTree, TokenStream}; + +// This macro exists as part of a reproduction of #61963 but without using quote/syn/proc_macro2. + +#[proc_macro_attribute] +pub fn dom_struct(_: TokenStream, input: TokenStream) -> TokenStream { + // Construct the expected output tokens - the input but with a `#[derive(DomObject)]` applied. + let attributes: TokenStream = + "#[derive(DomObject)]".to_string().parse().unwrap(); + let output: TokenStream = attributes.into_iter() + .chain(input.into_iter()).collect(); + + let mut tokens: Vec<_> = output.into_iter().collect(); + // Adjust the spacing of `>` tokens to match what `quote` would produce. + for token in tokens.iter_mut() { + if let TokenTree::Group(group) = token { + let mut tokens: Vec<_> = group.stream().into_iter().collect(); + for token in tokens.iter_mut() { + if let TokenTree::Punct(p) = token { + if p.as_char() == '>' { + *p = Punct::new('>', Spacing::Alone); + } + } + } + + let mut stream = TokenStream::new(); + stream.extend(tokens); + *group = Group::new(group.delimiter(), stream); + } + } + + let mut output = TokenStream::new(); + output.extend(tokens); + output +} diff --git a/src/test/ui/suggestions/auxiliary/issue-81839.rs b/src/test/ui/suggestions/auxiliary/issue-81839.rs new file mode 100644 index 000000000..5683c45ad --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/issue-81839.rs @@ -0,0 +1,9 @@ +// edition:2018 + +pub struct Test {} + +impl Test { + pub async fn answer_str(&self, _s: &str) -> Test { + Test {} + } +} diff --git a/src/test/ui/suggestions/auxiliary/meow.rs b/src/test/ui/suggestions/auxiliary/meow.rs new file mode 100644 index 000000000..115df70a6 --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/meow.rs @@ -0,0 +1,11 @@ +pub trait Meow { + fn meow(&self) {} +} + +pub struct GlobalMeow; + +impl Meow for GlobalMeow {} + +pub(crate) struct PrivateMeow; + +impl Meow for PrivateMeow {} diff --git a/src/test/ui/suggestions/auxiliary/not-object-safe.rs b/src/test/ui/suggestions/auxiliary/not-object-safe.rs new file mode 100644 index 000000000..7c9829b82 --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/not-object-safe.rs @@ -0,0 +1,6 @@ +use std::sync::Arc; + +pub trait A { + fn f(); + fn f2(self: &Arc<Self>); +} diff --git a/src/test/ui/suggestions/auxiliary/proc-macro-type-error.rs b/src/test/ui/suggestions/auxiliary/proc-macro-type-error.rs new file mode 100644 index 000000000..d71747f96 --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/proc-macro-type-error.rs @@ -0,0 +1,18 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] +#![feature(proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::{quote, TokenStream}; + +#[proc_macro_attribute] +pub fn hello(_: TokenStream, _: TokenStream) -> TokenStream { + quote!( + fn f(_: &mut i32) {} + fn g() { + f(123); + } + ) +} diff --git a/src/test/ui/suggestions/borrow-for-loop-head.rs b/src/test/ui/suggestions/borrow-for-loop-head.rs new file mode 100644 index 000000000..c2bda55e5 --- /dev/null +++ b/src/test/ui/suggestions/borrow-for-loop-head.rs @@ -0,0 +1,10 @@ +fn main() { + let a = vec![1, 2, 3]; + for i in &a { + for j in a { + //~^ ERROR cannot move out of `a` because it is borrowed + //~| ERROR use of moved value: `a` + println!("{} * {} = {}", i, j, i * j); + } + } +} diff --git a/src/test/ui/suggestions/borrow-for-loop-head.stderr b/src/test/ui/suggestions/borrow-for-loop-head.stderr new file mode 100644 index 000000000..1059e3d15 --- /dev/null +++ b/src/test/ui/suggestions/borrow-for-loop-head.stderr @@ -0,0 +1,31 @@ +error[E0505]: cannot move out of `a` because it is borrowed + --> $DIR/borrow-for-loop-head.rs:4:18 + | +LL | for i in &a { + | -- borrow of `a` occurs here +LL | for j in a { + | ^ move out of `a` occurs here + +error[E0382]: use of moved value: `a` + --> $DIR/borrow-for-loop-head.rs:4:18 + | +LL | let a = vec![1, 2, 3]; + | - move occurs because `a` has type `Vec<i32>`, which does not implement the `Copy` trait +LL | for i in &a { +LL | for j in a { + | ^ `a` moved due to this implicit call to `.into_iter()`, in previous iteration of loop + | +note: this function takes ownership of the receiver `self`, which moves `a` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^ +help: consider iterating over a slice of the `Vec<i32>`'s content to avoid moving into the `for` loop + | +LL | for j in &a { + | + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0382, E0505. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/suggestions/bound-suggestions.fixed b/src/test/ui/suggestions/bound-suggestions.fixed new file mode 100644 index 000000000..17a019c69 --- /dev/null +++ b/src/test/ui/suggestions/bound-suggestions.fixed @@ -0,0 +1,68 @@ +// run-rustfix + +#[allow(unused)] +use std::fmt::Debug; +// Rustfix should add this, or use `std::fmt::Debug` instead. + +#[allow(dead_code)] +fn test_impl(t: impl Sized + std::fmt::Debug) { + println!("{:?}", t); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_no_bounds<T: std::fmt::Debug>(t: T) { + println!("{:?}", t); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_one_bound<T: Sized + std::fmt::Debug>(t: T) { + println!("{:?}", t); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_no_bounds_where<X, Y>(x: X, y: Y) where X: std::fmt::Debug, Y: std::fmt::Debug { + println!("{:?} {:?}", x, y); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_one_bound_where<X>(x: X) where X: Sized + std::fmt::Debug { + println!("{:?}", x); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_many_bounds_where<X>(x: X) where X: Sized + std::fmt::Debug, X: Sized { + println!("{:?}", x); + //~^ ERROR doesn't implement +} + +trait Foo<T>: Sized { + const SIZE: usize = core::mem::size_of::<Self>(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Bar: std::fmt::Display + Sized { + const SIZE: usize = core::mem::size_of::<Self>(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Baz: Sized where Self: std::fmt::Display { + const SIZE: usize = core::mem::size_of::<Self>(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Qux<T>: Sized where Self: std::fmt::Display { + const SIZE: usize = core::mem::size_of::<Self>(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Bat<T>: std::fmt::Display + Sized { + const SIZE: usize = core::mem::size_of::<Self>(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +fn main() { } diff --git a/src/test/ui/suggestions/bound-suggestions.rs b/src/test/ui/suggestions/bound-suggestions.rs new file mode 100644 index 000000000..86f708d42 --- /dev/null +++ b/src/test/ui/suggestions/bound-suggestions.rs @@ -0,0 +1,68 @@ +// run-rustfix + +#[allow(unused)] +use std::fmt::Debug; +// Rustfix should add this, or use `std::fmt::Debug` instead. + +#[allow(dead_code)] +fn test_impl(t: impl Sized) { + println!("{:?}", t); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_no_bounds<T>(t: T) { + println!("{:?}", t); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_one_bound<T: Sized>(t: T) { + println!("{:?}", t); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_no_bounds_where<X, Y>(x: X, y: Y) where X: std::fmt::Debug, { + println!("{:?} {:?}", x, y); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_one_bound_where<X>(x: X) where X: Sized { + println!("{:?}", x); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_many_bounds_where<X>(x: X) where X: Sized, X: Sized { + println!("{:?}", x); + //~^ ERROR doesn't implement +} + +trait Foo<T> { + const SIZE: usize = core::mem::size_of::<Self>(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Bar: std::fmt::Display { + const SIZE: usize = core::mem::size_of::<Self>(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Baz where Self: std::fmt::Display { + const SIZE: usize = core::mem::size_of::<Self>(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Qux<T> where Self: std::fmt::Display { + const SIZE: usize = core::mem::size_of::<Self>(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Bat<T>: std::fmt::Display { + const SIZE: usize = core::mem::size_of::<Self>(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +fn main() { } diff --git a/src/test/ui/suggestions/bound-suggestions.stderr b/src/test/ui/suggestions/bound-suggestions.stderr new file mode 100644 index 000000000..d53715937 --- /dev/null +++ b/src/test/ui/suggestions/bound-suggestions.stderr @@ -0,0 +1,155 @@ +error[E0277]: `impl Sized` doesn't implement `Debug` + --> $DIR/bound-suggestions.rs:9:22 + | +LL | println!("{:?}", t); + | ^ `impl Sized` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | fn test_impl(t: impl Sized + std::fmt::Debug) { + | +++++++++++++++++ + +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/bound-suggestions.rs:15:22 + | +LL | println!("{:?}", t); + | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | fn test_no_bounds<T: std::fmt::Debug>(t: T) { + | +++++++++++++++++ + +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/bound-suggestions.rs:21:22 + | +LL | println!("{:?}", t); + | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | fn test_one_bound<T: Sized + std::fmt::Debug>(t: T) { + | +++++++++++++++++ + +error[E0277]: `Y` doesn't implement `Debug` + --> $DIR/bound-suggestions.rs:27:30 + | +LL | println!("{:?} {:?}", x, y); + | ^ `Y` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting type parameter `Y` + | +LL | fn test_no_bounds_where<X, Y>(x: X, y: Y) where X: std::fmt::Debug, Y: std::fmt::Debug { + | ~~~~~~~~~~~~~~~~~~~~ + +error[E0277]: `X` doesn't implement `Debug` + --> $DIR/bound-suggestions.rs:33:22 + | +LL | println!("{:?}", x); + | ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | fn test_one_bound_where<X>(x: X) where X: Sized + std::fmt::Debug { + | +++++++++++++++++ + +error[E0277]: `X` doesn't implement `Debug` + --> $DIR/bound-suggestions.rs:39:22 + | +LL | println!("{:?}", x); + | ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | fn test_many_bounds_where<X>(x: X) where X: Sized + std::fmt::Debug, X: Sized { + | +++++++++++++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:44:46 + | +LL | const SIZE: usize = core::mem::size_of::<Self>(); + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub const fn size_of<T>() -> usize { + | ^ required by this bound in `std::mem::size_of` +help: consider further restricting `Self` + | +LL | trait Foo<T>: Sized { + | +++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:49:46 + | +LL | const SIZE: usize = core::mem::size_of::<Self>(); + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub const fn size_of<T>() -> usize { + | ^ required by this bound in `std::mem::size_of` +help: consider further restricting `Self` + | +LL | trait Bar: std::fmt::Display + Sized { + | +++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:54:46 + | +LL | const SIZE: usize = core::mem::size_of::<Self>(); + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub const fn size_of<T>() -> usize { + | ^ required by this bound in `std::mem::size_of` +help: consider further restricting `Self` + | +LL | trait Baz: Sized where Self: std::fmt::Display { + | +++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:59:46 + | +LL | const SIZE: usize = core::mem::size_of::<Self>(); + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub const fn size_of<T>() -> usize { + | ^ required by this bound in `std::mem::size_of` +help: consider further restricting `Self` + | +LL | trait Qux<T>: Sized where Self: std::fmt::Display { + | +++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:64:46 + | +LL | const SIZE: usize = core::mem::size_of::<Self>(); + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub const fn size_of<T>() -> usize { + | ^ required by this bound in `std::mem::size_of` +help: consider further restricting `Self` + | +LL | trait Bat<T>: std::fmt::Display + Sized { + | +++++++ + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/box-future-wrong-output.rs b/src/test/ui/suggestions/box-future-wrong-output.rs new file mode 100644 index 000000000..d49819fcb --- /dev/null +++ b/src/test/ui/suggestions/box-future-wrong-output.rs @@ -0,0 +1,22 @@ +// Issue #72117 +// edition:2018 + +use core::future::Future; +use core::pin::Pin; + +pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>; + +impl<T: ?Sized> FutureExt for T where T: Future {} +trait FutureExt: Future { + fn boxed<'a>(self) -> BoxFuture<'a, Self::Output> + where + Self: Sized + Send + 'a, + { + Box::pin(self) + } +} + +fn main() { + let _: BoxFuture<'static, bool> = async {}.boxed(); + //~^ ERROR: mismatched types +} diff --git a/src/test/ui/suggestions/box-future-wrong-output.stderr b/src/test/ui/suggestions/box-future-wrong-output.stderr new file mode 100644 index 000000000..e0c57af25 --- /dev/null +++ b/src/test/ui/suggestions/box-future-wrong-output.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/box-future-wrong-output.rs:20:39 + | +LL | let _: BoxFuture<'static, bool> = async {}.boxed(); + | ------------------------ ^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | | + | expected due to this + | + = note: expected struct `Pin<Box<(dyn Future<Output = bool> + Send + 'static)>>` + found struct `Pin<Box<dyn Future<Output = ()> + Send>>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/boxed-variant-field.rs b/src/test/ui/suggestions/boxed-variant-field.rs new file mode 100644 index 000000000..e79be2f61 --- /dev/null +++ b/src/test/ui/suggestions/boxed-variant-field.rs @@ -0,0 +1,16 @@ +enum Ty { + Unit, + List(Box<Ty>), +} + +fn foo(x: Ty) -> Ty { + match x { + Ty::Unit => Ty::Unit, + Ty::List(elem) => foo(elem), + //~^ ERROR mismatched types + //~| HELP consider unboxing the value + //~| HELP try wrapping + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/boxed-variant-field.stderr b/src/test/ui/suggestions/boxed-variant-field.stderr new file mode 100644 index 000000000..6dfb73480 --- /dev/null +++ b/src/test/ui/suggestions/boxed-variant-field.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/boxed-variant-field.rs:9:31 + | +LL | Ty::List(elem) => foo(elem), + | --- ^^^^ expected enum `Ty`, found struct `Box` + | | + | arguments to this function are incorrect + | + = note: expected enum `Ty` + found struct `Box<Ty>` +note: function defined here + --> $DIR/boxed-variant-field.rs:6:4 + | +LL | fn foo(x: Ty) -> Ty { + | ^^^ ----- +help: consider unboxing the value + | +LL | Ty::List(elem) => foo(*elem), + | + +help: try wrapping the expression in `Ty::List` + | +LL | Ty::List(elem) => foo(Ty::List(elem)), + | +++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/chain-method-call-mutation-in-place.rs b/src/test/ui/suggestions/chain-method-call-mutation-in-place.rs new file mode 100644 index 000000000..cb92ab87a --- /dev/null +++ b/src/test/ui/suggestions/chain-method-call-mutation-in-place.rs @@ -0,0 +1,4 @@ +fn main() {} +fn foo(mut s: String) -> String { + s.push_str("asdf") //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/chain-method-call-mutation-in-place.stderr b/src/test/ui/suggestions/chain-method-call-mutation-in-place.stderr new file mode 100644 index 000000000..965dbb967 --- /dev/null +++ b/src/test/ui/suggestions/chain-method-call-mutation-in-place.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/chain-method-call-mutation-in-place.rs:3:5 + | +LL | fn foo(mut s: String) -> String { + | ------ expected `String` because of return type +LL | s.push_str("asdf") + | ^^^^^^^^^^^^^^^^^^ expected struct `String`, found `()` + | +note: method `push_str` modifies its receiver in-place + --> $DIR/chain-method-call-mutation-in-place.rs:3:7 + | +LL | s.push_str("asdf") + | - ^^^^^^^^ this call modifies `s` in-place + | | + | you probably want to use this value after calling the method... + = note: ...instead of the `()` output of method `push_str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/const-in-struct-pat.rs b/src/test/ui/suggestions/const-in-struct-pat.rs new file mode 100644 index 000000000..1cbba9354 --- /dev/null +++ b/src/test/ui/suggestions/const-in-struct-pat.rs @@ -0,0 +1,11 @@ +#[allow(non_camel_case_types)] +struct foo; +struct Thing { + foo: String, +} + +fn example(t: Thing) { + let Thing { foo } = t; //~ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/suggestions/const-in-struct-pat.stderr b/src/test/ui/suggestions/const-in-struct-pat.stderr new file mode 100644 index 000000000..c8b93f3dc --- /dev/null +++ b/src/test/ui/suggestions/const-in-struct-pat.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/const-in-struct-pat.rs:8:17 + | +LL | struct foo; + | ---------- unit struct defined here +... +LL | let Thing { foo } = t; + | ^^^ - this expression has type `Thing` + | | + | expected struct `String`, found struct `foo` + | `foo` is interpreted as a unit struct, not a new binding + | +help: bind the struct field to a different name instead + | +LL | let Thing { foo: other_foo } = t; + | +++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/const-no-type.rs b/src/test/ui/suggestions/const-no-type.rs new file mode 100644 index 000000000..6f46cfdf0 --- /dev/null +++ b/src/test/ui/suggestions/const-no-type.rs @@ -0,0 +1,51 @@ +// In the cases below, the type is missing from the `const` and `static` items. +// +// Here, we test that we: +// +// a) Perform parser recovery. +// +// b) Emit a diagnostic with the actual inferred type to RHS of `=` as the suggestion. + +fn main() {} + +// These will not reach typeck: + +#[cfg(FALSE)] +const C2 = 42; +//~^ ERROR missing type for `const` item +//~| HELP provide a type for the item +//~| SUGGESTION C2: <type> + +#[cfg(FALSE)] +static S2 = "abc"; +//~^ ERROR missing type for `static` item +//~| HELP provide a type for the item +//~| SUGGESTION S2: <type> + +#[cfg(FALSE)] +static mut SM2 = "abc"; +//~^ ERROR missing type for `static mut` item +//~| HELP provide a type for the item +//~| SUGGESTION SM2: <type> + +// These will, so the diagnostics should be stolen by typeck: + +const C = 42; +//~^ ERROR missing type for `const` item +//~| HELP provide a type for the constant +//~| SUGGESTION C: i32 + +const D = &&42; +//~^ ERROR missing type for `const` item +//~| HELP provide a type for the constant +//~| SUGGESTION D: &&i32 + +static S = Vec::<String>::new(); +//~^ ERROR missing type for `static` item +//~| HELP provide a type for the static variable +//~| SUGGESTION S: Vec<String> + +static mut SM = "abc"; +//~^ ERROR missing type for `static mut` item +//~| HELP provide a type for the static variable +//~| SUGGESTION &str diff --git a/src/test/ui/suggestions/const-no-type.stderr b/src/test/ui/suggestions/const-no-type.stderr new file mode 100644 index 000000000..3b0fd6337 --- /dev/null +++ b/src/test/ui/suggestions/const-no-type.stderr @@ -0,0 +1,44 @@ +error: missing type for `const` item + --> $DIR/const-no-type.rs:33:7 + | +LL | const C = 42; + | ^ help: provide a type for the constant: `C: i32` + +error: missing type for `const` item + --> $DIR/const-no-type.rs:38:7 + | +LL | const D = &&42; + | ^ help: provide a type for the constant: `D: &&i32` + +error: missing type for `static` item + --> $DIR/const-no-type.rs:43:8 + | +LL | static S = Vec::<String>::new(); + | ^ help: provide a type for the static variable: `S: Vec<String>` + +error: missing type for `static mut` item + --> $DIR/const-no-type.rs:48:12 + | +LL | static mut SM = "abc"; + | ^^ help: provide a type for the static variable: `SM: &str` + +error: missing type for `const` item + --> $DIR/const-no-type.rs:14:7 + | +LL | const C2 = 42; + | ^^ help: provide a type for the item: `C2: <type>` + +error: missing type for `static` item + --> $DIR/const-no-type.rs:20:8 + | +LL | static S2 = "abc"; + | ^^ help: provide a type for the item: `S2: <type>` + +error: missing type for `static mut` item + --> $DIR/const-no-type.rs:26:12 + | +LL | static mut SM2 = "abc"; + | ^^^ help: provide a type for the item: `SM2: <type>` + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.rs b/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.rs new file mode 100644 index 000000000..ac819dce6 --- /dev/null +++ b/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.rs @@ -0,0 +1,10 @@ +fn main() { + let A = 3; + //~^ ERROR refutable pattern in local binding: `i32::MIN..=1_i32` and + //~| interpreted as a constant pattern, not a new variable + //~| HELP introduce a variable instead + //~| SUGGESTION a_var + + const A: i32 = 2; + //~^ constant defined here +} diff --git a/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr b/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr new file mode 100644 index 000000000..618bcaca1 --- /dev/null +++ b/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr @@ -0,0 +1,17 @@ +error[E0005]: refutable pattern in local binding: `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered + --> $DIR/const-pat-non-exaustive-let-new-var.rs:2:9 + | +LL | let A = 3; + | ^ + | | + | interpreted as a constant pattern, not a new variable + | help: introduce a variable instead: `a_var` +... +LL | const A: i32 = 2; + | ------------ constant defined here + | + = note: the matched value is of type `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/src/test/ui/suggestions/constrain-suggest-ice.rs b/src/test/ui/suggestions/constrain-suggest-ice.rs new file mode 100644 index 000000000..69b874bed --- /dev/null +++ b/src/test/ui/suggestions/constrain-suggest-ice.rs @@ -0,0 +1,11 @@ +struct Bug<S>{ //~ ERROR parameter `S` is never used [E0392] + A: [(); { + let x: [u8; Self::W] = [0; Self::W]; //~ ERROR generic `Self` types are currently not permitted in anonymous constants + //~^ ERROR generic `Self` types are currently not permitted in anonymous constants + //~^^ ERROR the size for values of type `S` cannot be known at compilation time [E0277] + F //~ ERROR cannot find value `F` in this scope [E0425] + } +} //~ ERROR mismatched closing delimiter: `}` +//~^ ERROR mismatched closing delimiter: `}` + +fn main() {} diff --git a/src/test/ui/suggestions/constrain-suggest-ice.stderr b/src/test/ui/suggestions/constrain-suggest-ice.stderr new file mode 100644 index 000000000..477eb2786 --- /dev/null +++ b/src/test/ui/suggestions/constrain-suggest-ice.stderr @@ -0,0 +1,81 @@ +error: mismatched closing delimiter: `}` + --> $DIR/constrain-suggest-ice.rs:2:8 + | +LL | struct Bug<S>{ + | - closing delimiter possibly meant for this +LL | A: [(); { + | ^ unclosed delimiter +... +LL | } + | ^ mismatched closing delimiter + +error: mismatched closing delimiter: `}` + --> $DIR/constrain-suggest-ice.rs:2:8 + | +LL | struct Bug<S>{ + | - closing delimiter possibly meant for this +LL | A: [(); { + | ^ unclosed delimiter +... +LL | } + | ^ mismatched closing delimiter + +error[E0425]: cannot find value `F` in this scope + --> $DIR/constrain-suggest-ice.rs:6:9 + | +LL | F + | ^ + | +help: a local variable with a similar name exists + | +LL | x + | ~ +help: you might be missing a type parameter + | +LL | struct Bug<S, F>{ + | +++ + +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/constrain-suggest-ice.rs:3:21 + | +LL | let x: [u8; Self::W] = [0; Self::W]; + | ^^^^ + +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/constrain-suggest-ice.rs:3:36 + | +LL | let x: [u8; Self::W] = [0; Self::W]; + | ^^^^ + +error[E0277]: the size for values of type `S` cannot be known at compilation time + --> $DIR/constrain-suggest-ice.rs:3:36 + | +LL | struct Bug<S>{ + | - this type parameter needs to be `std::marker::Sized` +LL | A: [(); { +LL | let x: [u8; Self::W] = [0; Self::W]; + | ^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Bug` + --> $DIR/constrain-suggest-ice.rs:1:12 + | +LL | struct Bug<S>{ + | ^ required by this bound in `Bug` +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Bug<S: ?Sized>{ + | ++++++++ + +error[E0392]: parameter `S` is never used + --> $DIR/constrain-suggest-ice.rs:1:12 + | +LL | struct Bug<S>{ + | ^ unused parameter + | + = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `S` to be a const parameter, use `const S: usize` instead + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0277, E0392, E0425. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/constrain-trait.fixed b/src/test/ui/suggestions/constrain-trait.fixed new file mode 100644 index 000000000..f292f27f0 --- /dev/null +++ b/src/test/ui/suggestions/constrain-trait.fixed @@ -0,0 +1,47 @@ +// run-rustfix +// check-only + +#[derive(Debug)] +struct Demo { + a: String +} + +trait GetString { + fn get_a(&self) -> &String; +} + +trait UseString: std::fmt::Debug + GetString { + fn use_string(&self) { + println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found + } +} + +trait UseString2: GetString { + fn use_string(&self) { + println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found + } +} + +impl GetString for Demo { + fn get_a(&self) -> &String { + &self.a + } +} + +impl UseString for Demo {} +impl UseString2 for Demo {} + + +#[cfg(test)] +mod tests { + use crate::{Demo, UseString}; + + #[test] + fn it_works() { + let d = Demo { a: "test".to_string() }; + d.use_string(); + } +} + + +fn main() {} diff --git a/src/test/ui/suggestions/constrain-trait.rs b/src/test/ui/suggestions/constrain-trait.rs new file mode 100644 index 000000000..99ccf7a7f --- /dev/null +++ b/src/test/ui/suggestions/constrain-trait.rs @@ -0,0 +1,47 @@ +// run-rustfix +// check-only + +#[derive(Debug)] +struct Demo { + a: String +} + +trait GetString { + fn get_a(&self) -> &String; +} + +trait UseString: std::fmt::Debug { + fn use_string(&self) { + println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found + } +} + +trait UseString2 { + fn use_string(&self) { + println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found + } +} + +impl GetString for Demo { + fn get_a(&self) -> &String { + &self.a + } +} + +impl UseString for Demo {} +impl UseString2 for Demo {} + + +#[cfg(test)] +mod tests { + use crate::{Demo, UseString}; + + #[test] + fn it_works() { + let d = Demo { a: "test".to_string() }; + d.use_string(); + } +} + + +fn main() {} diff --git a/src/test/ui/suggestions/constrain-trait.stderr b/src/test/ui/suggestions/constrain-trait.stderr new file mode 100644 index 000000000..a26f86917 --- /dev/null +++ b/src/test/ui/suggestions/constrain-trait.stderr @@ -0,0 +1,27 @@ +error[E0599]: no method named `get_a` found for reference `&Self` in the current scope + --> $DIR/constrain-trait.rs:15:31 + | +LL | println!("{:?}", self.get_a()); + | ^^^^^ method not found in `&Self` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `get_a`, perhaps you need to add another supertrait for it: + | +LL | trait UseString: std::fmt::Debug + GetString { + | +++++++++++ + +error[E0599]: no method named `get_a` found for reference `&Self` in the current scope + --> $DIR/constrain-trait.rs:21:31 + | +LL | println!("{:?}", self.get_a()); + | ^^^^^ method not found in `&Self` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `get_a`, perhaps you need to add a supertrait for it: + | +LL | trait UseString2: GetString { + | +++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/core-std-import-order-issue-83564.rs b/src/test/ui/suggestions/core-std-import-order-issue-83564.rs new file mode 100644 index 000000000..b7fe5af7b --- /dev/null +++ b/src/test/ui/suggestions/core-std-import-order-issue-83564.rs @@ -0,0 +1,10 @@ +// edition:2018 + +// This is a regression test for #83564. +// For some reason, Rust 2018 or higher is required to reproduce the bug. + +fn main() { + //~^ HELP consider importing one of these items + let _x = NonZeroU32::new(5).unwrap(); + //~^ ERROR failed to resolve: use of undeclared type `NonZeroU32` +} diff --git a/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr b/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr new file mode 100644 index 000000000..ce85d93b9 --- /dev/null +++ b/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr @@ -0,0 +1,16 @@ +error[E0433]: failed to resolve: use of undeclared type `NonZeroU32` + --> $DIR/core-std-import-order-issue-83564.rs:8:14 + | +LL | let _x = NonZeroU32::new(5).unwrap(); + | ^^^^^^^^^^ not found in this scope + | +help: consider importing one of these items + | +LL | use core::num::NonZeroU32; + | +LL | use std::num::NonZeroU32; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/suggestions/count2len.rs b/src/test/ui/suggestions/count2len.rs new file mode 100644 index 000000000..f11a789ef --- /dev/null +++ b/src/test/ui/suggestions/count2len.rs @@ -0,0 +1,8 @@ +fn main() { + let slice = [1,2,3,4]; + let vec = vec![1,2,3,4]; + + slice.count(); //~ERROR: E0599 + vec.count(); //~ERROR: E0599 + vec.as_slice().count(); //~ERROR: E0599 +} diff --git a/src/test/ui/suggestions/count2len.stderr b/src/test/ui/suggestions/count2len.stderr new file mode 100644 index 000000000..6394a84dd --- /dev/null +++ b/src/test/ui/suggestions/count2len.stderr @@ -0,0 +1,36 @@ +error[E0599]: no method named `count` found for array `[{integer}; 4]` in the current scope + --> $DIR/count2len.rs:5:11 + | +LL | slice.count(); + | ^^^^^ + | | + | method cannot be called on `[{integer}; 4]` due to unsatisfied trait bounds + | help: consider using `len` instead + | + = note: `count` is defined on `Iterator`, which `[{integer}; 4]` does not implement + +error[E0599]: no method named `count` found for struct `Vec<{integer}>` in the current scope + --> $DIR/count2len.rs:6:9 + | +LL | vec.count(); + | ^^^^^ + | | + | method cannot be called on `Vec<{integer}>` due to unsatisfied trait bounds + | help: consider using `len` instead + | + = note: `count` is defined on `Iterator`, which `Vec<{integer}>` does not implement + +error[E0599]: no method named `count` found for reference `&[{integer}]` in the current scope + --> $DIR/count2len.rs:7:20 + | +LL | vec.as_slice().count(); + | ^^^^^ + | | + | method cannot be called on `&[{integer}]` due to unsatisfied trait bounds + | help: consider using `len` instead + | + = note: `count` is defined on `Iterator`, which `&[{integer}]` does not implement + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/crate-or-module-typo.rs b/src/test/ui/suggestions/crate-or-module-typo.rs new file mode 100644 index 000000000..2471b11c6 --- /dev/null +++ b/src/test/ui/suggestions/crate-or-module-typo.rs @@ -0,0 +1,17 @@ +// edition:2018 + +use st::cell::Cell; //~ ERROR failed to resolve: use of undeclared crate or module `st` + +mod bar { + pub fn bar() { bar::baz(); } //~ ERROR failed to resolve: use of undeclared crate or module `bar` + + fn baz() {} +} + +use bas::bar; //~ ERROR unresolved import `bas` + +struct Foo { + bar: st::cell::Cell<bool> //~ ERROR failed to resolve: use of undeclared crate or module `st` +} + +fn main() {} diff --git a/src/test/ui/suggestions/crate-or-module-typo.stderr b/src/test/ui/suggestions/crate-or-module-typo.stderr new file mode 100644 index 000000000..e8250c9fa --- /dev/null +++ b/src/test/ui/suggestions/crate-or-module-typo.stderr @@ -0,0 +1,43 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `st` + --> $DIR/crate-or-module-typo.rs:3:5 + | +LL | use st::cell::Cell; + | ^^ use of undeclared crate or module `st` + | +help: there is a crate or module with a similar name + | +LL | use std::cell::Cell; + | ~~~ + +error[E0432]: unresolved import `bas` + --> $DIR/crate-or-module-typo.rs:11:5 + | +LL | use bas::bar; + | ^^^ use of undeclared crate or module `bas` + | +help: there is a crate or module with a similar name + | +LL | use bar::bar; + | ~~~ + +error[E0433]: failed to resolve: use of undeclared crate or module `bar` + --> $DIR/crate-or-module-typo.rs:6:20 + | +LL | pub fn bar() { bar::baz(); } + | ^^^ use of undeclared crate or module `bar` + +error[E0433]: failed to resolve: use of undeclared crate or module `st` + --> $DIR/crate-or-module-typo.rs:14:10 + | +LL | bar: st::cell::Cell<bool> + | ^^ use of undeclared crate or module `st` + | +help: there is a crate or module with a similar name + | +LL | bar: std::cell::Cell<bool> + | ~~~ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/suggestions/derive-clone-for-eq.fixed b/src/test/ui/suggestions/derive-clone-for-eq.fixed new file mode 100644 index 000000000..f07784d53 --- /dev/null +++ b/src/test/ui/suggestions/derive-clone-for-eq.fixed @@ -0,0 +1,18 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/79076 + +use std::cmp::PartialEq; + +#[derive(Clone, Eq)] //~ ERROR [E0277] +pub struct Struct<T: std::clone::Clone>(T); + +impl<T: Clone, U> PartialEq<U> for Struct<T> +where + U: Into<Struct<T>> + Clone +{ + fn eq(&self, _other: &U) -> bool { + todo!() + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/derive-clone-for-eq.rs b/src/test/ui/suggestions/derive-clone-for-eq.rs new file mode 100644 index 000000000..15c0d4659 --- /dev/null +++ b/src/test/ui/suggestions/derive-clone-for-eq.rs @@ -0,0 +1,18 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/79076 + +use std::cmp::PartialEq; + +#[derive(Clone, Eq)] //~ ERROR [E0277] +pub struct Struct<T>(T); + +impl<T: Clone, U> PartialEq<U> for Struct<T> +where + U: Into<Struct<T>> + Clone +{ + fn eq(&self, _other: &U) -> bool { + todo!() + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/derive-clone-for-eq.stderr b/src/test/ui/suggestions/derive-clone-for-eq.stderr new file mode 100644 index 000000000..55a23c031 --- /dev/null +++ b/src/test/ui/suggestions/derive-clone-for-eq.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/derive-clone-for-eq.rs:6:17 + | +LL | #[derive(Clone, Eq)] + | ^^ the trait `Clone` is not implemented for `T` + | +note: required because of the requirements on the impl of `PartialEq` for `Struct<T>` + --> $DIR/derive-clone-for-eq.rs:9:19 + | +LL | impl<T: Clone, U> PartialEq<U> for Struct<T> + | ^^^^^^^^^^^^ ^^^^^^^^^ +note: required by a bound in `Eq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | pub trait Eq: PartialEq<Self> { + | ^^^^^^^^^^^^^^^ required by this bound in `Eq` + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | pub struct Struct<T: std::clone::Clone>(T); + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/derive-macro-missing-bounds.rs b/src/test/ui/suggestions/derive-macro-missing-bounds.rs new file mode 100644 index 000000000..56c218f97 --- /dev/null +++ b/src/test/ui/suggestions/derive-macro-missing-bounds.rs @@ -0,0 +1,89 @@ +mod a { + use std::fmt::{Debug, Formatter, Result}; + struct Inner<T>(T); + + impl Debug for Inner<()> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer<T>(Inner<T>); //~ ERROR `a::Inner<T>` doesn't implement `Debug` +} + +mod b { + use std::fmt::{Debug, Formatter, Result}; + struct Inner<T>(T); + + impl<T: Debug> Debug for Inner<T> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer<T>(Inner<T>); +} + +mod c { + use std::fmt::{Debug, Formatter, Result}; + struct Inner<T>(T); + trait Trait {} + + impl<T: Debug + Trait> Debug for Inner<T> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: c::Trait` is not satisfied +} + +mod d { + use std::fmt::{Debug, Formatter, Result}; + struct Inner<T>(T); + trait Trait {} + + impl<T> Debug for Inner<T> where T: Debug, T: Trait { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: d::Trait` is not satisfied +} + +mod e { + use std::fmt::{Debug, Formatter, Result}; + struct Inner<T>(T); + trait Trait {} + + impl<T> Debug for Inner<T> where T: Debug + Trait { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: e::Trait` is not satisfied +} + +mod f { + use std::fmt::{Debug, Formatter, Result}; + struct Inner<T>(T); + trait Trait {} + + impl<T: Debug> Debug for Inner<T> where T: Trait { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer<T>(Inner<T>); //~ ERROR the trait bound `T: f::Trait` is not satisfied +} + +fn main() {} diff --git a/src/test/ui/suggestions/derive-macro-missing-bounds.stderr b/src/test/ui/suggestions/derive-macro-missing-bounds.stderr new file mode 100644 index 000000000..4186dc7cb --- /dev/null +++ b/src/test/ui/suggestions/derive-macro-missing-bounds.stderr @@ -0,0 +1,111 @@ +error[E0277]: `a::Inner<T>` doesn't implement `Debug` + --> $DIR/derive-macro-missing-bounds.rs:12:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer<T>(Inner<T>); + | ^^^^^^^^ `a::Inner<T>` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `a::Inner<T>` + = note: add `#[derive(Debug)]` to `a::Inner<T>` or manually `impl Debug for a::Inner<T>` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `a::Inner<T>` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | struct Outer<T>(Inner<T>) where a::Inner<T>: Debug; + | ++++++++++++++++++++++++ + +error[E0277]: the trait bound `T: c::Trait` is not satisfied + --> $DIR/derive-macro-missing-bounds.rs:41:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer<T>(Inner<T>); + | ^^^^^^^^ the trait `c::Trait` is not implemented for `T` + | +note: required because of the requirements on the impl of `Debug` for `c::Inner<T>` + --> $DIR/derive-macro-missing-bounds.rs:34:28 + | +LL | impl<T: Debug + Trait> Debug for Inner<T> { + | ^^^^^ ^^^^^^^^ + = note: 1 redundant requirement hidden + = note: required because of the requirements on the impl of `Debug` for `&c::Inner<T>` + = note: required for the cast from `&c::Inner<T>` to the object type `dyn Debug` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | struct Outer<T: c::Trait>(Inner<T>); + | ++++++++++ + +error[E0277]: the trait bound `T: d::Trait` is not satisfied + --> $DIR/derive-macro-missing-bounds.rs:56:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer<T>(Inner<T>); + | ^^^^^^^^ the trait `d::Trait` is not implemented for `T` + | +note: required because of the requirements on the impl of `Debug` for `d::Inner<T>` + --> $DIR/derive-macro-missing-bounds.rs:49:13 + | +LL | impl<T> Debug for Inner<T> where T: Debug, T: Trait { + | ^^^^^ ^^^^^^^^ + = note: 1 redundant requirement hidden + = note: required because of the requirements on the impl of `Debug` for `&d::Inner<T>` + = note: required for the cast from `&d::Inner<T>` to the object type `dyn Debug` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | struct Outer<T: d::Trait>(Inner<T>); + | ++++++++++ + +error[E0277]: the trait bound `T: e::Trait` is not satisfied + --> $DIR/derive-macro-missing-bounds.rs:71:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer<T>(Inner<T>); + | ^^^^^^^^ the trait `e::Trait` is not implemented for `T` + | +note: required because of the requirements on the impl of `Debug` for `e::Inner<T>` + --> $DIR/derive-macro-missing-bounds.rs:64:13 + | +LL | impl<T> Debug for Inner<T> where T: Debug + Trait { + | ^^^^^ ^^^^^^^^ + = note: 1 redundant requirement hidden + = note: required because of the requirements on the impl of `Debug` for `&e::Inner<T>` + = note: required for the cast from `&e::Inner<T>` to the object type `dyn Debug` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | struct Outer<T: e::Trait>(Inner<T>); + | ++++++++++ + +error[E0277]: the trait bound `T: f::Trait` is not satisfied + --> $DIR/derive-macro-missing-bounds.rs:86:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer<T>(Inner<T>); + | ^^^^^^^^ the trait `f::Trait` is not implemented for `T` + | +note: required because of the requirements on the impl of `Debug` for `f::Inner<T>` + --> $DIR/derive-macro-missing-bounds.rs:79:20 + | +LL | impl<T: Debug> Debug for Inner<T> where T: Trait { + | ^^^^^ ^^^^^^^^ + = note: 1 redundant requirement hidden + = note: required because of the requirements on the impl of `Debug` for `&f::Inner<T>` + = note: required for the cast from `&f::Inner<T>` to the object type `dyn Debug` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | struct Outer<T: f::Trait>(Inner<T>); + | ++++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/derive-trait-for-method-call.rs b/src/test/ui/suggestions/derive-trait-for-method-call.rs new file mode 100644 index 000000000..25043da52 --- /dev/null +++ b/src/test/ui/suggestions/derive-trait-for-method-call.rs @@ -0,0 +1,44 @@ +use std::time::Instant; + +enum Enum { + First +} + +#[derive(Clone)] +enum CloneEnum { + First +} + +struct Struct { +} + +#[derive(Clone)] +struct CloneStruct { +} + +struct Foo<X, Y> (X, Y); +impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> { + fn test(&self) -> (X, Y) { + (self.0, self.1) + } +} + +fn test1() { + let x = Foo(Enum::First, CloneEnum::First); + let y = x.test(); + //~^the method `test` exists for struct `Foo<Enum, CloneEnum>`, but its trait bounds were not satisfied [E0599] +} + +fn test2() { + let x = Foo(Struct{}, CloneStruct{}); + let y = x.test(); + //~^the method `test` exists for struct `Foo<Struct, CloneStruct>`, but its trait bounds were not satisfied [E0599] +} + +fn test3() { + let x = Foo(Vec::<Enum>::new(), Instant::now()); + let y = x.test(); + //~^the method `test` exists for struct `Foo<Vec<Enum>, Instant>`, but its trait bounds were not satisfied [E0599] +} + +fn main() {} diff --git a/src/test/ui/suggestions/derive-trait-for-method-call.stderr b/src/test/ui/suggestions/derive-trait-for-method-call.stderr new file mode 100644 index 000000000..7cc372f24 --- /dev/null +++ b/src/test/ui/suggestions/derive-trait-for-method-call.stderr @@ -0,0 +1,89 @@ +error[E0599]: the method `test` exists for struct `Foo<Enum, CloneEnum>`, but its trait bounds were not satisfied + --> $DIR/derive-trait-for-method-call.rs:28:15 + | +LL | enum Enum { + | --------- + | | + | doesn't satisfy `Enum: Clone` + | doesn't satisfy `Enum: Default` +... +LL | enum CloneEnum { + | -------------- doesn't satisfy `CloneEnum: Default` +... +LL | struct Foo<X, Y> (X, Y); + | ---------------- method `test` not found for this struct +... +LL | let y = x.test(); + | ^^^^ method cannot be called on `Foo<Enum, CloneEnum>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `Enum: Clone` + `Enum: Default` + `CloneEnum: Default` +note: the following trait must be implemented + --> $SRC_DIR/core/src/default.rs:LL:COL + | +LL | pub trait Default: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider annotating `Enum` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error[E0599]: the method `test` exists for struct `Foo<Struct, CloneStruct>`, but its trait bounds were not satisfied + --> $DIR/derive-trait-for-method-call.rs:34:15 + | +LL | struct Struct { + | ------------- + | | + | doesn't satisfy `Struct: Clone` + | doesn't satisfy `Struct: Default` +... +LL | struct CloneStruct { + | ------------------ doesn't satisfy `CloneStruct: Default` +... +LL | struct Foo<X, Y> (X, Y); + | ---------------- method `test` not found for this struct +... +LL | let y = x.test(); + | ^^^^ method cannot be called on `Foo<Struct, CloneStruct>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `Struct: Clone` + `Struct: Default` + `CloneStruct: Default` +help: consider annotating `CloneStruct` with `#[derive(Default)]` + | +LL | #[derive(Default)] + | +help: consider annotating `Struct` with `#[derive(Clone, Default)]` + | +LL | #[derive(Clone, Default)] + | + +error[E0599]: the method `test` exists for struct `Foo<Vec<Enum>, Instant>`, but its trait bounds were not satisfied + --> $DIR/derive-trait-for-method-call.rs:40:15 + | +LL | struct Foo<X, Y> (X, Y); + | ---------------- method `test` not found for this struct +... +LL | let y = x.test(); + | ^^^^ method cannot be called on `Foo<Vec<Enum>, Instant>` due to unsatisfied trait bounds + | + ::: $SRC_DIR/std/src/time.rs:LL:COL + | +LL | pub struct Instant(time::Instant); + | ------------------ doesn't satisfy `Instant: Default` + | + ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + | +LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> { + | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<Enum>: Clone` + | + = note: the following trait bounds were not satisfied: + `Vec<Enum>: Clone` + `Instant: Default` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.rs b/src/test/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.rs new file mode 100644 index 000000000..a25be862a --- /dev/null +++ b/src/test/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.rs @@ -0,0 +1,5 @@ +use std::result; +impl result { //~ ERROR expected type, found module `result` + fn into_future() -> Err {} //~ ERROR expected type, found variant `Err` +} +fn main() {} diff --git a/src/test/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr b/src/test/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr new file mode 100644 index 000000000..7bdc8e00f --- /dev/null +++ b/src/test/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr @@ -0,0 +1,20 @@ +error[E0573]: expected type, found module `result` + --> $DIR/do-not-attempt-to-add-suggestions-with-no-changes.rs:2:6 + | +LL | impl result { + | ^^^^^^ help: an enum with a similar name exists: `Result` + | + ::: $SRC_DIR/core/src/result.rs:LL:COL + | +LL | pub enum Result<T, E> { + | --------------------- similarly named enum `Result` defined here + +error[E0573]: expected type, found variant `Err` + --> $DIR/do-not-attempt-to-add-suggestions-with-no-changes.rs:3:25 + | +LL | fn into_future() -> Err {} + | ^^^ not a type + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs new file mode 100644 index 000000000..ef1c09d21 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs @@ -0,0 +1,14 @@ +fn warn(_: &str) {} + +macro_rules! intrinsic_match { + ($intrinsic:expr) => { + warn(format!("unsupported intrinsic {}", $intrinsic)); + //~^ ERROR mismatched types + }; +} + +fn main() { + intrinsic_match! { + "abc" + }; +} diff --git a/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr new file mode 100644 index 000000000..5dc4e6444 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr @@ -0,0 +1,13 @@ +error[E0308]: mismatched types + --> $DIR/dont-suggest-deref-inside-macro-issue-58298.rs:11:5 + | +LL | / intrinsic_match! { +LL | | "abc" +LL | | }; + | |_____^ expected `&str`, found struct `String` + | + = note: this error originates in the macro `format` which comes from the expansion of the macro `intrinsic_match` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs new file mode 100644 index 000000000..15e0af1de --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs @@ -0,0 +1,8 @@ +#![crate_type = "lib"] + +extern crate core; + +pub mod __private { + #[doc(hidden)] + pub use core::option::Option::{self, None, Some}; +} diff --git a/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs new file mode 100644 index 000000000..5a5079d82 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs @@ -0,0 +1,8 @@ +#![crate_type = "lib"] + +extern crate core; + +#[doc(hidden)] +pub mod __private { + pub use core::option::Option::{self, None, Some}; +} diff --git a/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs new file mode 100644 index 000000000..38dabc9d7 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs @@ -0,0 +1,10 @@ +// aux-build:hidden-child.rs + +// FIXME(compiler-errors): This currently suggests the wrong thing. +// UI test exists to track the problem. + +extern crate hidden_child; + +fn main() { + let x: Option<i32> = 1i32; //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr new file mode 100644 index 000000000..67f4ac08d --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/hidden-child.rs:9:26 + | +LL | let x: Option<i32> = 1i32; + | ----------- ^^^^ expected enum `Option`, found `i32` + | | + | expected due to this + | + = note: expected enum `Option<i32>` + found type `i32` +help: try wrapping the expression in `hidden_child::__private::Some` + | +LL | let x: Option<i32> = hidden_child::__private::Some(1i32); + | ++++++++++++++++++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs new file mode 100644 index 000000000..4d96d6c16 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs @@ -0,0 +1,7 @@ +// aux-build:hidden-parent.rs + +extern crate hidden_parent; + +fn main() { + let x: Option<i32> = 1i32; //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr new file mode 100644 index 000000000..d92b81279 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/hidden-parent.rs:6:26 + | +LL | let x: Option<i32> = 1i32; + | ----------- ^^^^ expected enum `Option`, found `i32` + | | + | expected due to this + | + = note: expected enum `Option<i32>` + found type `i32` +help: try wrapping the expression in `Some` + | +LL | let x: Option<i32> = Some(1i32); + | +++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.rs b/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.rs new file mode 100644 index 000000000..acb897571 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.rs @@ -0,0 +1,15 @@ +// https://github.com/rust-lang/rust/issues/96834 +// +// This test case verifies that rustc does not make an unhelpful suggestion: +// +// help: consider wrapping the receiver expression with the appropriate type +// | +// 14 | Pin::new(&mut a).set(0, 3); +// | +++++++++++++ + +// +// We can tell that it isn't helpful, because `Pin::set` takes two parameters (including +// the receiver), but the function call on line 14 supplies three. +fn main() { + let mut a = [0u8; 1]; + a.set(0, 3); //~ERROR +} diff --git a/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.stderr b/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.stderr new file mode 100644 index 000000000..677aa031b --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `set` found for array `[u8; 1]` in the current scope + --> $DIR/dont-suggest-pin-array-dot-set.rs:14:7 + | +LL | a.set(0, 3); + | ^^^ help: there is an associated function with a similar name: `get` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs new file mode 100644 index 000000000..bf0c1dc27 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs @@ -0,0 +1,150 @@ +#[derive(Clone)] +enum Either { + One(X), + Two(X), +} + +#[derive(Clone)] +struct X(Y); + +#[derive(Clone)] +struct Y; + + +pub fn main() { + let e = Either::One(X(Y)); + let mut em = Either::One(X(Y)); + + let r = &e; + let rm = &mut Either::One(X(Y)); + + let x = X(Y); + let mut xm = X(Y); + + let s = &x; + let sm = &mut X(Y); + + let ve = vec![Either::One(X(Y))]; + + let vr = &ve; + let vrm = &mut vec![Either::One(X(Y))]; + + let vx = vec![X(Y)]; + + let vs = &vx; + let vsm = &mut vec![X(Y)]; + + // test for duplicate suggestions + + let &(X(_t), X(_u)) = &(x.clone(), x.clone()); + //~^ ERROR cannot move + //~| HELP consider removing the `&` + //~| SUGGESTION (X(_t), X(_u)) + if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { } + //~^ ERROR cannot move + //~| HELP consider removing the `&` + //~| SUGGESTION (Either::One(_t), Either::Two(_u)) + while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { } + //~^ ERROR cannot move + //~| HELP consider removing the `&` + //~| SUGGESTION (Either::One(_t), Either::Two(_u)) + match &(e.clone(), e.clone()) { + //~^ ERROR cannot move + &(Either::One(_t), Either::Two(_u)) => (), + //~^ HELP consider removing the `&` + //~| SUGGESTION (Either::One(_t), Either::Two(_u)) + &(Either::Two(_t), Either::One(_u)) => (), + //~^ HELP consider removing the `&` + //~| SUGGESTION (Either::Two(_t), Either::One(_u)) + _ => (), + } + match &(e.clone(), e.clone()) { + //~^ ERROR cannot move + &(Either::One(_t), Either::Two(_u)) + //~^ HELP consider removing the `&` + //~| SUGGESTION (Either::One(_t), Either::Two(_u)) + | &(Either::Two(_t), Either::One(_u)) => (), + // FIXME: would really like a suggestion here too + _ => (), + } + match &(e.clone(), e.clone()) { + //~^ ERROR cannot move + &(Either::One(_t), Either::Two(_u)) => (), + //~^ HELP consider removing the `&` + //~| SUGGESTION (Either::One(_t), Either::Two(_u)) + &(Either::Two(ref _t), Either::One(ref _u)) => (), + _ => (), + } + match &(e.clone(), e.clone()) { + //~^ ERROR cannot move + &(Either::One(_t), Either::Two(_u)) => (), + //~^ HELP consider removing the `&` + //~| SUGGESTION (Either::One(_t), Either::Two(_u)) + (Either::Two(_t), Either::One(_u)) => (), + _ => (), + } + fn f5(&(X(_t), X(_u)): &(X, X)) { } + //~^ ERROR cannot move + //~| HELP consider removing the `&` + //~| SUGGESTION (X(_t), X(_u)) + + let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone()); + //~^ ERROR cannot move + //~| HELP consider removing the `&mut` + //~| SUGGESTION (X(_t), X(_u)) + if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { } + //~^ ERROR cannot move + //~| HELP consider removing the `&mut` + //~| SUGGESTION (Either::One(_t), Either::Two(_u)) + while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { } + //~^ ERROR cannot move + //~| HELP consider removing the `&mut` + //~| SUGGESTION (Either::One(_t), Either::Two(_u)) + match &mut (em.clone(), em.clone()) { + //~^ ERROR cannot move + &mut (Either::One(_t), Either::Two(_u)) => (), + //~^ HELP consider removing the `&mut` + //~| SUGGESTION (Either::One(_t), Either::Two(_u)) + &mut (Either::Two(_t), Either::One(_u)) => (), + //~^ HELP consider removing the `&mut` + //~| SUGGESTION (Either::Two(_t), Either::One(_u)) + _ => (), + } + match &mut (em.clone(), em.clone()) { + //~^ ERROR cannot move + &mut (Either::One(_t), Either::Two(_u)) + //~^ HELP consider removing the `&mut` + //~| SUGGESTION (Either::One(_t), Either::Two(_u)) + | &mut (Either::Two(_t), Either::One(_u)) => (), + // FIXME: would really like a suggestion here too + _ => (), + } + match &mut (em.clone(), em.clone()) { + //~^ ERROR cannot move + &mut (Either::One(_t), Either::Two(_u)) => (), + //~^ HELP consider removing the `&mut` + //~| SUGGESTION (Either::One(_t), Either::Two(_u)) + &mut (Either::Two(ref _t), Either::One(ref _u)) => (), + _ => (), + } + match &mut (em.clone(), em.clone()) { + //~^ ERROR cannot move + &mut (Either::One(_t), Either::Two(_u)) => (), + //~^ HELP consider removing the `&mut` + //~| SUGGESTION (Either::One(_t), Either::Two(_u)) + &mut (Either::Two(ref mut _t), Either::One(ref mut _u)) => (), + _ => (), + } + match &mut (em.clone(), em.clone()) { + //~^ ERROR cannot move + &mut (Either::One(_t), Either::Two(_u)) => (), + //~^ HELP consider removing the `&mut` + //~| SUGGESTION (Either::One(_t), Either::Two(_u)) + (Either::Two(_t), Either::One(_u)) => (), + _ => (), + } + fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { } + //~^ ERROR cannot move + //~| HELP consider removing the `&mut` + //~| SUGGESTION (X(_t), X(_u)) +} diff --git a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr new file mode 100644 index 000000000..40ad671f9 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr @@ -0,0 +1,262 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:39:27 + | +LL | let &(X(_t), X(_u)) = &(x.clone(), x.clone()); + | --------------- ^^^^^^^^^^^^^^^^^^^^^^^ + | | | | + | | | ...and here + | | data moved here + | help: consider removing the `&`: `(X(_t), X(_u))` + | + = note: move occurs because these variables have types that don't implement the `Copy` trait + +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:43:50 + | +LL | if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { } + | ----------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^ + | | | | + | | | ...and here + | | data moved here + | help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))` + | + = note: move occurs because these variables have types that don't implement the `Copy` trait + +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:47:53 + | +LL | while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { } + | ----------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^ + | | | | + | | | ...and here + | | data moved here + | help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))` + | + = note: move occurs because these variables have types that don't implement the `Copy` trait + +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:51:11 + | +LL | match &(e.clone(), e.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &(Either::One(_t), Either::Two(_u)) => (), + | -- -- ...and here + | | + | data moved here +... +LL | &(Either::Two(_t), Either::One(_u)) => (), + | -- ...and here -- ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the `&` + | +LL | (Either::One(_t), Either::Two(_u)) => (), + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: consider removing the `&` + | +LL | (Either::Two(_t), Either::One(_u)) => (), + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:61:11 + | +LL | match &(e.clone(), e.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &(Either::One(_t), Either::Two(_u)) + | -- -- ...and here + | | + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the `&` + | +LL ~ (Either::One(_t), Either::Two(_u)) +LL + +LL + +LL ~ | &(Either::Two(_t), Either::One(_u)) => (), + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:70:11 + | +LL | match &(e.clone(), e.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &(Either::One(_t), Either::Two(_u)) => (), + | ----------------------------------- + | | | | + | | | ...and here + | | data moved here + | help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))` + | + = note: move occurs because these variables have types that don't implement the `Copy` trait + +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:78:11 + | +LL | match &(e.clone(), e.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &(Either::One(_t), Either::Two(_u)) => (), + | ----------------------------------- + | | | | + | | | ...and here + | | data moved here + | help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))` + | + = note: move occurs because these variables have types that don't implement the `Copy` trait + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:91:31 + | +LL | let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone()); + | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | | + | | | ...and here + | | data moved here + | help: consider removing the `&mut`: `(X(_t), X(_u))` + | + = note: move occurs because these variables have types that don't implement the `Copy` trait + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:95:54 + | +LL | if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { } + | --------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | | + | | | ...and here + | | data moved here + | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))` + | + = note: move occurs because these variables have types that don't implement the `Copy` trait + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:99:57 + | +LL | while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { } + | --------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | | + | | | ...and here + | | data moved here + | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))` + | + = note: move occurs because these variables have types that don't implement the `Copy` trait + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:103:11 + | +LL | match &mut (em.clone(), em.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &mut (Either::One(_t), Either::Two(_u)) => (), + | -- -- ...and here + | | + | data moved here +... +LL | &mut (Either::Two(_t), Either::One(_u)) => (), + | -- ...and here -- ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the `&mut` + | +LL | (Either::One(_t), Either::Two(_u)) => (), + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: consider removing the `&mut` + | +LL | (Either::Two(_t), Either::One(_u)) => (), + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:113:11 + | +LL | match &mut (em.clone(), em.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &mut (Either::One(_t), Either::Two(_u)) + | -- -- ...and here + | | + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the `&mut` + | +LL ~ (Either::One(_t), Either::Two(_u)) +LL + +LL + +LL ~ | &mut (Either::Two(_t), Either::One(_u)) => (), + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:122:11 + | +LL | match &mut (em.clone(), em.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &mut (Either::One(_t), Either::Two(_u)) => (), + | --------------------------------------- + | | | | + | | | ...and here + | | data moved here + | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))` + | + = note: move occurs because these variables have types that don't implement the `Copy` trait + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:130:11 + | +LL | match &mut (em.clone(), em.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &mut (Either::One(_t), Either::Two(_u)) => (), + | --------------------------------------- + | | | | + | | | ...and here + | | data moved here + | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))` + | + = note: move occurs because these variables have types that don't implement the `Copy` trait + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:138:11 + | +LL | match &mut (em.clone(), em.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &mut (Either::One(_t), Either::Two(_u)) => (), + | --------------------------------------- + | | | | + | | | ...and here + | | data moved here + | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))` + | + = note: move occurs because these variables have types that don't implement the `Copy` trait + +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:86:11 + | +LL | fn f5(&(X(_t), X(_u)): &(X, X)) { } + | ^^^^--^^^^^--^^ + | | | | + | | | ...and here + | | data moved here + | help: consider removing the `&`: `(X(_t), X(_u))` + | + = note: move occurs because these variables have types that don't implement the `Copy` trait + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:146:11 + | +LL | fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { } + | ^^^^^^^^--^^^^^--^^ + | | | | + | | | ...and here + | | data moved here + | help: consider removing the `&mut`: `(X(_t), X(_u))` + | + = note: move occurs because these variables have types that don't implement the `Copy` trait + +error: aborting due to 17 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs new file mode 100644 index 000000000..f1e043c30 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs @@ -0,0 +1,159 @@ +#[derive(Clone)] +enum Either { + One(X), + Two(X), +} + +#[derive(Clone)] +struct X(Y); + +#[derive(Clone)] +struct Y; + +fn consume_fn<F: Fn()>(_f: F) { } + +fn consume_fnmut<F: FnMut()>(_f: F) { } + +pub fn main() { } + +fn move_into_fn() { + let e = Either::One(X(Y)); + let mut em = Either::One(X(Y)); + + let x = X(Y); + + // move into Fn + + consume_fn(|| { + let X(_t) = x; + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &x + if let Either::One(_t) = e { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &e + while let Either::One(_t) = e { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &e + match e { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &e + Either::One(_t) + | Either::Two(_t) => (), + } + match e { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &e + Either::One(_t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + + let X(mut _t) = x; + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &x + if let Either::One(mut _t) = em { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &em + while let Either::One(mut _t) = em { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &em + match em { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &em + Either::One(mut _t) + | Either::Two(mut _t) => (), + } + match em { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &em + Either::One(mut _t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + }); +} + +fn move_into_fnmut() { + let e = Either::One(X(Y)); + let mut em = Either::One(X(Y)); + + let x = X(Y); + + // move into FnMut + + consume_fnmut(|| { + let X(_t) = x; + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &x + if let Either::One(_t) = e { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &e + while let Either::One(_t) = e { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &e + match e { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &e + Either::One(_t) + | Either::Two(_t) => (), + } + match e { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &e + Either::One(_t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + + let X(mut _t) = x; + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &x + if let Either::One(mut _t) = em { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &em + while let Either::One(mut _t) = em { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &em + match em { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &em + Either::One(mut _t) + | Either::Two(mut _t) => (), + } + match em { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &em + Either::One(mut _t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + match em { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &em + Either::One(mut _t) => (), + Either::Two(ref mut _t) => (), + // FIXME: should suggest removing `ref` too + } + }); +} diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr new file mode 100644 index 000000000..e06ee4290 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr @@ -0,0 +1,343 @@ +error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:28:21 + | +LL | let x = X(Y); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +LL | let X(_t) = x; + | -- ^ help: consider borrowing here: `&x` + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:32:34 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | if let Either::One(_t) = e { } + | -- ^ help: consider borrowing here: `&e` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:36:37 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | while let Either::One(_t) = e { } + | -- ^ help: consider borrowing here: `&e` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:40:15 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | match e { + | ^ help: consider borrowing here: `&e` +... +LL | Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:47:15 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | match e { + | ^ help: consider borrowing here: `&e` +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:56:25 + | +LL | let x = X(Y); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | let X(mut _t) = x; + | ------ ^ help: consider borrowing here: `&x` + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:60:38 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | if let Either::One(mut _t) = em { } + | ------ ^^ help: consider borrowing here: `&em` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:64:41 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | while let Either::One(mut _t) = em { } + | ------ ^^ help: consider borrowing here: `&em` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:68:15 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | match em { + | ^^ help: consider borrowing here: `&em` +... +LL | Either::One(mut _t) + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:75:15 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | match em { + | ^^ help: consider borrowing here: `&em` +... +LL | Either::One(mut _t) => (), + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:95:21 + | +LL | let x = X(Y); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +LL | let X(_t) = x; + | -- ^ help: consider borrowing here: `&x` + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:99:34 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | if let Either::One(_t) = e { } + | -- ^ help: consider borrowing here: `&e` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:103:37 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | while let Either::One(_t) = e { } + | -- ^ help: consider borrowing here: `&e` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:107:15 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match e { + | ^ help: consider borrowing here: `&e` +... +LL | Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:114:15 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match e { + | ^ help: consider borrowing here: `&e` +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:123:25 + | +LL | let x = X(Y); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | let X(mut _t) = x; + | ------ ^ help: consider borrowing here: `&x` + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:127:38 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | if let Either::One(mut _t) = em { } + | ------ ^^ help: consider borrowing here: `&em` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:131:41 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | while let Either::One(mut _t) = em { } + | ------ ^^ help: consider borrowing here: `&em` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:135:15 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match em { + | ^^ help: consider borrowing here: `&em` +... +LL | Either::One(mut _t) + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:142:15 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match em { + | ^^ help: consider borrowing here: `&em` +... +LL | Either::One(mut _t) => (), + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:150:15 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match em { + | ^^ help: consider borrowing here: `&em` +... +LL | Either::One(mut _t) => (), + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error: aborting due to 21 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.rs b/src/test/ui/suggestions/dont-suggest-ref/simple.rs new file mode 100644 index 000000000..c53ac3d2c --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-ref/simple.rs @@ -0,0 +1,364 @@ +#[derive(Clone)] +enum Either { + One(X), + Two(X), +} + +#[derive(Clone)] +struct X(Y); + +#[derive(Clone)] +struct Y; + +pub fn main() { + let e = Either::One(X(Y)); + let mut em = Either::One(X(Y)); + + let r = &e; + let rm = &mut Either::One(X(Y)); + + let x = X(Y); + let mut xm = X(Y); + + let s = &x; + let sm = &mut X(Y); + + let ve = vec![Either::One(X(Y))]; + + let vr = &ve; + let vrm = &mut vec![Either::One(X(Y))]; + + let vx = vec![X(Y)]; + + let vs = &vx; + let vsm = &mut vec![X(Y)]; + + // move from Either/X place + + let X(_t) = *s; + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION s + if let Either::One(_t) = *r { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION r + while let Either::One(_t) = *r { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION r + match *r { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION r + Either::One(_t) + | Either::Two(_t) => (), + } + match *r { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION r + Either::One(_t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + + let X(_t) = *sm; + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION sm + if let Either::One(_t) = *rm { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION rm + while let Either::One(_t) = *rm { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION rm + match *rm { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION rm + Either::One(_t) + | Either::Two(_t) => (), + } + match *rm { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION rm + Either::One(_t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + match *rm { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION rm + Either::One(_t) => (), + Either::Two(ref mut _t) => (), + // FIXME: should suggest removing `ref` too + } + + let X(_t) = vs[0]; + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &vs[0] + if let Either::One(_t) = vr[0] { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &vr[0] + while let Either::One(_t) = vr[0] { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &vr[0] + match vr[0] { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &vr[0] + Either::One(_t) + | Either::Two(_t) => (), + } + match vr[0] { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &vr[0] + Either::One(_t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + + let X(_t) = vsm[0]; + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &vsm[0] + if let Either::One(_t) = vrm[0] { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &vrm[0] + while let Either::One(_t) = vrm[0] { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &vrm[0] + match vrm[0] { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &vrm[0] + Either::One(_t) + | Either::Two(_t) => (), + } + match vrm[0] { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &vrm[0] + Either::One(_t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + match vrm[0] { + //~^ ERROR cannot move + //~| HELP consider borrowing here + //~| SUGGESTION &vrm[0] + Either::One(_t) => (), + Either::Two(ref mut _t) => (), + // FIXME: should suggest removing `ref` too + } + + // move from &Either/&X place + + let &X(_t) = s; + //~^ ERROR cannot move + //~| HELP consider removing the `&` + //~| SUGGESTION X(_t) + if let &Either::One(_t) = r { } + //~^ ERROR cannot move + //~| HELP consider removing the `&` + //~| SUGGESTION Either::One(_t) + while let &Either::One(_t) = r { } + //~^ ERROR cannot move + //~| HELP consider removing the `&` + //~| SUGGESTION Either::One(_t) + match r { + //~^ ERROR cannot move + &Either::One(_t) + //~^ HELP consider removing the `&` + //~| SUGGESTION Either::One(_t) + | &Either::Two(_t) => (), + // FIXME: would really like a suggestion here too + } + match r { + //~^ ERROR cannot move + &Either::One(_t) => (), + //~^ HELP consider removing the `&` + //~| SUGGESTION Either::One(_t) + &Either::Two(ref _t) => (), + } + match r { + //~^ ERROR cannot move + &Either::One(_t) => (), + //~^ HELP consider removing the `&` + //~| SUGGESTION Either::One(_t) + Either::Two(_t) => (), + } + fn f1(&X(_t): &X) { } + //~^ ERROR cannot move + //~| HELP consider removing the `&` + //~| SUGGESTION X(_t) + + let &mut X(_t) = sm; + //~^ ERROR cannot move + //~| HELP consider removing the `&mut` + //~| SUGGESTION X(_t) + if let &mut Either::One(_t) = rm { } + //~^ ERROR cannot move + //~| HELP consider removing the `&mut` + //~| SUGGESTION Either::One(_t) + while let &mut Either::One(_t) = rm { } + //~^ ERROR cannot move + //~| HELP consider removing the `&mut` + //~| SUGGESTION Either::One(_t) + match rm { + //~^ ERROR cannot move + &mut Either::One(_t) => (), + //~^ HELP consider removing the `&mut` + //~| SUGGESTION Either::One(_t) + &mut Either::Two(_t) => (), + //~^ HELP consider removing the `&mut` + //~| SUGGESTION Either::Two(_t) + } + match rm { + //~^ ERROR cannot move + &mut Either::One(_t) => (), + //~^ HELP consider removing the `&mut` + //~| SUGGESTION Either::One(_t) + &mut Either::Two(ref _t) => (), + } + match rm { + //~^ ERROR cannot move + &mut Either::One(_t) => (), + //~^ HELP consider removing the `&mut` + //~| SUGGESTION Either::One(_t) + &mut Either::Two(ref mut _t) => (), + } + match rm { + //~^ ERROR cannot move + &mut Either::One(_t) => (), + //~^ HELP consider removing the `&mut` + //~| SUGGESTION Either::One(_t) + Either::Two(_t) => (), + } + fn f2(&mut X(_t): &mut X) { } + //~^ ERROR cannot move + //~| HELP consider removing the `&mut` + //~| SUGGESTION X(_t) + + // move from tuple of &Either/&X + + // FIXME: These should have suggestions. + + let (&X(_t),) = (&x.clone(),); + //~^ ERROR cannot move + if let (&Either::One(_t),) = (&e.clone(),) { } + //~^ ERROR cannot move + while let (&Either::One(_t),) = (&e.clone(),) { } + //~^ ERROR cannot move + match (&e.clone(),) { + //~^ ERROR cannot move + (&Either::One(_t),) + | (&Either::Two(_t),) => (), + } + fn f3((&X(_t),): (&X,)) { } + //~^ ERROR cannot move + + let (&mut X(_t),) = (&mut xm.clone(),); + //~^ ERROR cannot move + if let (&mut Either::One(_t),) = (&mut em.clone(),) { } + //~^ ERROR cannot move + while let (&mut Either::One(_t),) = (&mut em.clone(),) { } + //~^ ERROR cannot move + match (&mut em.clone(),) { + //~^ ERROR cannot move + (&mut Either::One(_t),) => (), + (&mut Either::Two(_t),) => (), + } + fn f4((&mut X(_t),): (&mut X,)) { } + //~^ ERROR cannot move + + // move from &Either/&X value + + let &X(_t) = &x; + //~^ ERROR cannot move + //~| HELP consider removing the `&` + //~| SUGGESTION X(_t) + if let &Either::One(_t) = &e { } + //~^ ERROR cannot move + //~| HELP consider removing the `&` + //~| SUGGESTION Either::One(_t) + while let &Either::One(_t) = &e { } + //~^ ERROR cannot move + //~| HELP consider removing the `&` + //~| SUGGESTION Either::One(_t) + match &e { + //~^ ERROR cannot move + &Either::One(_t) + //~^ HELP consider removing the `&` + //~| SUGGESTION Either::One(_t) + | &Either::Two(_t) => (), + // FIXME: would really like a suggestion here too + } + match &e { + //~^ ERROR cannot move + &Either::One(_t) => (), + //~^ HELP consider removing the `&` + //~| SUGGESTION Either::One(_t) + &Either::Two(ref _t) => (), + } + match &e { + //~^ ERROR cannot move + &Either::One(_t) => (), + //~^ HELP consider removing the `&` + //~| SUGGESTION Either::One(_t) + Either::Two(_t) => (), + } + + let &mut X(_t) = &mut xm; + //~^ ERROR cannot move + //~| HELP consider removing the `&mut` + //~| SUGGESTION X(_t) + if let &mut Either::One(_t) = &mut em { } + //~^ ERROR cannot move + //~| HELP consider removing the `&mut` + //~| SUGGESTION Either::One(_t) + while let &mut Either::One(_t) = &mut em { } + //~^ ERROR cannot move + //~| HELP consider removing the `&mut` + //~| SUGGESTION Either::One(_t) + match &mut em { + //~^ ERROR cannot move + &mut Either::One(_t) + //~^ HELP consider removing the `&mut` + //~| SUGGESTION Either::One(_t) + | &mut Either::Two(_t) => (), + // FIXME: would really like a suggestion here too + } + match &mut em { + //~^ ERROR cannot move + &mut Either::One(_t) => (), + //~^ HELP consider removing the `&mut` + //~| SUGGESTION Either::One(_t) + &mut Either::Two(ref _t) => (), + } + match &mut em { + //~^ ERROR cannot move + &mut Either::One(_t) => (), + //~^ HELP consider removing the `&mut` + //~| SUGGESTION Either::One(_t) + &mut Either::Two(ref mut _t) => (), + } + match &mut em { + //~^ ERROR cannot move + &mut Either::One(_t) => (), + //~^ HELP consider removing the `&mut` + //~| SUGGESTION Either::One(_t) + Either::Two(_t) => (), + } +} diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.stderr b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr new file mode 100644 index 000000000..e5443290f --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr @@ -0,0 +1,680 @@ +error[E0507]: cannot move out of `s` which is behind a shared reference + --> $DIR/simple.rs:38:17 + | +LL | let X(_t) = *s; + | -- ^^ help: consider borrowing here: `&*s` + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference + --> $DIR/simple.rs:42:30 + | +LL | if let Either::One(_t) = *r { } + | -- ^^ help: consider borrowing here: `&*r` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference + --> $DIR/simple.rs:46:33 + | +LL | while let Either::One(_t) = *r { } + | -- ^^ help: consider borrowing here: `&*r` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference + --> $DIR/simple.rs:50:11 + | +LL | match *r { + | ^^ help: consider borrowing here: `&*r` +... +LL | Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference + --> $DIR/simple.rs:57:11 + | +LL | match *r { + | ^^ help: consider borrowing here: `&*r` +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `sm` which is behind a mutable reference + --> $DIR/simple.rs:66:17 + | +LL | let X(_t) = *sm; + | -- ^^^ help: consider borrowing here: `&*sm` + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:70:30 + | +LL | if let Either::One(_t) = *rm { } + | -- ^^^ help: consider borrowing here: `&*rm` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:74:33 + | +LL | while let Either::One(_t) = *rm { } + | -- ^^^ help: consider borrowing here: `&*rm` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference + --> $DIR/simple.rs:78:11 + | +LL | match *rm { + | ^^^ help: consider borrowing here: `&*rm` +... +LL | Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:85:11 + | +LL | match *rm { + | ^^^ help: consider borrowing here: `&*rm` +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:93:11 + | +LL | match *rm { + | ^^^ help: consider borrowing here: `&*rm` +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of index of `Vec<X>` + --> $DIR/simple.rs:102:17 + | +LL | let X(_t) = vs[0]; + | -- ^^^^^ help: consider borrowing here: `&vs[0]` + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of index of `Vec<Either>` + --> $DIR/simple.rs:106:30 + | +LL | if let Either::One(_t) = vr[0] { } + | -- ^^^^^ help: consider borrowing here: `&vr[0]` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of index of `Vec<Either>` + --> $DIR/simple.rs:110:33 + | +LL | while let Either::One(_t) = vr[0] { } + | -- ^^^^^ help: consider borrowing here: `&vr[0]` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of index of `Vec<Either>` + --> $DIR/simple.rs:114:11 + | +LL | match vr[0] { + | ^^^^^ help: consider borrowing here: `&vr[0]` +... +LL | Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of index of `Vec<Either>` + --> $DIR/simple.rs:121:11 + | +LL | match vr[0] { + | ^^^^^ help: consider borrowing here: `&vr[0]` +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of index of `Vec<X>` + --> $DIR/simple.rs:130:17 + | +LL | let X(_t) = vsm[0]; + | -- ^^^^^^ help: consider borrowing here: `&vsm[0]` + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of index of `Vec<Either>` + --> $DIR/simple.rs:134:30 + | +LL | if let Either::One(_t) = vrm[0] { } + | -- ^^^^^^ help: consider borrowing here: `&vrm[0]` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of index of `Vec<Either>` + --> $DIR/simple.rs:138:33 + | +LL | while let Either::One(_t) = vrm[0] { } + | -- ^^^^^^ help: consider borrowing here: `&vrm[0]` + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of index of `Vec<Either>` + --> $DIR/simple.rs:142:11 + | +LL | match vrm[0] { + | ^^^^^^ help: consider borrowing here: `&vrm[0]` +... +LL | Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of index of `Vec<Either>` + --> $DIR/simple.rs:149:11 + | +LL | match vrm[0] { + | ^^^^^^ help: consider borrowing here: `&vrm[0]` +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of index of `Vec<Either>` + --> $DIR/simple.rs:157:11 + | +LL | match vrm[0] { + | ^^^^^^ help: consider borrowing here: `&vrm[0]` +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `s` which is behind a shared reference + --> $DIR/simple.rs:168:18 + | +LL | let &X(_t) = s; + | ------ ^ + | | | + | | data moved here + | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | help: consider removing the `&`: `X(_t)` + +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference + --> $DIR/simple.rs:172:31 + | +LL | if let &Either::One(_t) = r { } + | ---------------- ^ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&`: `Either::One(_t)` + +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference + --> $DIR/simple.rs:176:34 + | +LL | while let &Either::One(_t) = r { } + | ---------------- ^ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&`: `Either::One(_t)` + +error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference + --> $DIR/simple.rs:180:11 + | +LL | match r { + | ^ +LL | +LL | &Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the `&` + | +LL ~ Either::One(_t) +LL + +LL + +LL ~ | &Either::Two(_t) => (), + | + +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference + --> $DIR/simple.rs:188:11 + | +LL | match r { + | ^ +LL | +LL | &Either::One(_t) => (), + | ---------------- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&`: `Either::One(_t)` + +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference + --> $DIR/simple.rs:195:11 + | +LL | match r { + | ^ +LL | +LL | &Either::One(_t) => (), + | ---------------- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&`: `Either::One(_t)` + +error[E0507]: cannot move out of `sm` which is behind a mutable reference + --> $DIR/simple.rs:207:22 + | +LL | let &mut X(_t) = sm; + | ---------- ^^ + | | | + | | data moved here + | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | help: consider removing the `&mut`: `X(_t)` + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:211:35 + | +LL | if let &mut Either::One(_t) = rm { } + | -------------------- ^^ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&mut`: `Either::One(_t)` + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:215:38 + | +LL | while let &mut Either::One(_t) = rm { } + | -------------------- ^^ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&mut`: `Either::One(_t)` + +error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference + --> $DIR/simple.rs:219:11 + | +LL | match rm { + | ^^ +LL | +LL | &mut Either::One(_t) => (), + | -- data moved here +... +LL | &mut Either::Two(_t) => (), + | -- ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the `&mut` + | +LL | Either::One(_t) => (), + | ~~~~~~~~~~~~~~~ +help: consider removing the `&mut` + | +LL | Either::Two(_t) => (), + | ~~~~~~~~~~~~~~~ + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:228:11 + | +LL | match rm { + | ^^ +LL | +LL | &mut Either::One(_t) => (), + | -------------------- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&mut`: `Either::One(_t)` + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:235:11 + | +LL | match rm { + | ^^ +LL | +LL | &mut Either::One(_t) => (), + | -------------------- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&mut`: `Either::One(_t)` + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:242:11 + | +LL | match rm { + | ^^ +LL | +LL | &mut Either::One(_t) => (), + | -------------------- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&mut`: `Either::One(_t)` + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:258:21 + | +LL | let (&X(_t),) = (&x.clone(),); + | -- ^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:260:34 + | +LL | if let (&Either::One(_t),) = (&e.clone(),) { } + | -- ^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:262:37 + | +LL | while let (&Either::One(_t),) = (&e.clone(),) { } + | -- ^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:264:11 + | +LL | match (&e.clone(),) { + | ^^^^^^^^^^^^^ +LL | +LL | (&Either::One(_t),) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:272:25 + | +LL | let (&mut X(_t),) = (&mut xm.clone(),); + | -- ^^^^^^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:274:38 + | +LL | if let (&mut Either::One(_t),) = (&mut em.clone(),) { } + | -- ^^^^^^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:276:41 + | +LL | while let (&mut Either::One(_t),) = (&mut em.clone(),) { } + | -- ^^^^^^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:278:11 + | +LL | match (&mut em.clone(),) { + | ^^^^^^^^^^^^^^^^^^ +LL | +LL | (&mut Either::One(_t),) => (), + | -- data moved here +LL | (&mut Either::Two(_t),) => (), + | -- ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:288:18 + | +LL | let &X(_t) = &x; + | ------ ^^ + | | | + | | data moved here + | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | help: consider removing the `&`: `X(_t)` + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:292:31 + | +LL | if let &Either::One(_t) = &e { } + | ---------------- ^^ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&`: `Either::One(_t)` + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:296:34 + | +LL | while let &Either::One(_t) = &e { } + | ---------------- ^^ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&`: `Either::One(_t)` + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:300:11 + | +LL | match &e { + | ^^ +LL | +LL | &Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the `&` + | +LL ~ Either::One(_t) +LL + +LL + +LL ~ | &Either::Two(_t) => (), + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:308:11 + | +LL | match &e { + | ^^ +LL | +LL | &Either::One(_t) => (), + | ---------------- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&`: `Either::One(_t)` + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:315:11 + | +LL | match &e { + | ^^ +LL | +LL | &Either::One(_t) => (), + | ---------------- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&`: `Either::One(_t)` + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:323:22 + | +LL | let &mut X(_t) = &mut xm; + | ---------- ^^^^^^^ + | | | + | | data moved here + | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | help: consider removing the `&mut`: `X(_t)` + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:327:35 + | +LL | if let &mut Either::One(_t) = &mut em { } + | -------------------- ^^^^^^^ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&mut`: `Either::One(_t)` + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:331:38 + | +LL | while let &mut Either::One(_t) = &mut em { } + | -------------------- ^^^^^^^ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&mut`: `Either::One(_t)` + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:335:11 + | +LL | match &mut em { + | ^^^^^^^ +LL | +LL | &mut Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the `&mut` + | +LL ~ Either::One(_t) +LL + +LL + +LL ~ | &mut Either::Two(_t) => (), + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:343:11 + | +LL | match &mut em { + | ^^^^^^^ +LL | +LL | &mut Either::One(_t) => (), + | -------------------- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&mut`: `Either::One(_t)` + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:350:11 + | +LL | match &mut em { + | ^^^^^^^ +LL | +LL | &mut Either::One(_t) => (), + | -------------------- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&mut`: `Either::One(_t)` + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:357:11 + | +LL | match &mut em { + | ^^^^^^^ +LL | +LL | &mut Either::One(_t) => (), + | -------------------- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | help: consider removing the `&mut`: `Either::One(_t)` + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:202:11 + | +LL | fn f1(&X(_t): &X) { } + | ^^^--^ + | | | + | | data moved here + | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | help: consider removing the `&`: `X(_t)` + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:249:11 + | +LL | fn f2(&mut X(_t): &mut X) { } + | ^^^^^^^--^ + | | | + | | data moved here + | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | help: consider removing the `&mut`: `X(_t)` + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:269:11 + | +LL | fn f3((&X(_t),): (&X,)) { } + | ^^^^--^^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:283:11 + | +LL | fn f4((&mut X(_t),): (&mut X,)) { } + | ^^^^^^^^--^^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + +error: aborting due to 60 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/suggestions/dont-suggest-try_into-in-macros.rs b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.rs new file mode 100644 index 000000000..d625199c9 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.rs @@ -0,0 +1,3 @@ +fn main() { + assert_eq!(10u64, 10usize); //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr new file mode 100644 index 000000000..4e21d3601 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/dont-suggest-try_into-in-macros.rs:2:5 + | +LL | assert_eq!(10u64, 10usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `usize` + | + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.rs b/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.rs new file mode 100644 index 000000000..baa2128eb --- /dev/null +++ b/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.rs @@ -0,0 +1,21 @@ +mod banana { + //~^ HELP the following traits are implemented but not in scope + pub struct Chaenomeles; + + pub trait Apple { + fn pick(&self) {} + } + impl Apple for Chaenomeles {} + + pub trait Peach { + fn pick(&self, a: &mut ()) {} + } + impl<Mango: Peach> Peach for Box<Mango> {} + impl Peach for Chaenomeles {} +} + +fn main() { + banana::Chaenomeles.pick() + //~^ ERROR no method named + //~| HELP items from traits can only be used if the trait is in scope +} diff --git a/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr b/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr new file mode 100644 index 000000000..4658ecb3a --- /dev/null +++ b/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr @@ -0,0 +1,20 @@ +error[E0599]: no method named `pick` found for struct `Chaenomeles` in the current scope + --> $DIR/dont-wrap-ambiguous-receivers.rs:18:25 + | +LL | pub struct Chaenomeles; + | ---------------------- method `pick` not found for this struct +... +LL | banana::Chaenomeles.pick() + | ^^^^ method not found in `Chaenomeles` + | + = help: items from traits can only be used if the trait is in scope +help: the following traits are implemented but not in scope; perhaps add a `use` for one of them: + | +LL | use banana::Apple; + | +LL | use banana::Peach; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/enum-method-probe.fixed b/src/test/ui/suggestions/enum-method-probe.fixed new file mode 100644 index 000000000..6499c92bc --- /dev/null +++ b/src/test/ui/suggestions/enum-method-probe.fixed @@ -0,0 +1,59 @@ +// compile-flags: --edition=2021 +// run-rustfix + +#![allow(unused)] + +struct Foo; + +impl Foo { + fn get(&self) -> u8 { + 42 + } +} + +fn test_result_in_result() -> Result<(), ()> { + let res: Result<_, ()> = Ok(Foo); + res?.get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP use the `?` operator + Ok(()) +} + +async fn async_test_result_in_result() -> Result<(), ()> { + let res: Result<_, ()> = Ok(Foo); + res?.get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP use the `?` operator + Ok(()) +} + +fn test_result_in_unit_return() { + let res: Result<_, ()> = Ok(Foo); + res.expect("REASON").get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err` +} + +async fn async_test_result_in_unit_return() { + let res: Result<_, ()> = Ok(Foo); + res.expect("REASON").get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err` +} + +fn test_option_in_option() -> Option<()> { + let res: Option<_> = Some(Foo); + res?.get(); + //~^ ERROR no method named `get` found for enum `Option` in the current scope + //~| HELP use the `?` operator + Some(()) +} + +fn test_option_in_unit_return() { + let res: Option<_> = Some(Foo); + res.expect("REASON").get(); + //~^ ERROR no method named `get` found for enum `Option` in the current scope + //~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None` +} + +fn main() {} diff --git a/src/test/ui/suggestions/enum-method-probe.rs b/src/test/ui/suggestions/enum-method-probe.rs new file mode 100644 index 000000000..18ea8ed8a --- /dev/null +++ b/src/test/ui/suggestions/enum-method-probe.rs @@ -0,0 +1,59 @@ +// compile-flags: --edition=2021 +// run-rustfix + +#![allow(unused)] + +struct Foo; + +impl Foo { + fn get(&self) -> u8 { + 42 + } +} + +fn test_result_in_result() -> Result<(), ()> { + let res: Result<_, ()> = Ok(Foo); + res.get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP use the `?` operator + Ok(()) +} + +async fn async_test_result_in_result() -> Result<(), ()> { + let res: Result<_, ()> = Ok(Foo); + res.get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP use the `?` operator + Ok(()) +} + +fn test_result_in_unit_return() { + let res: Result<_, ()> = Ok(Foo); + res.get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err` +} + +async fn async_test_result_in_unit_return() { + let res: Result<_, ()> = Ok(Foo); + res.get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err` +} + +fn test_option_in_option() -> Option<()> { + let res: Option<_> = Some(Foo); + res.get(); + //~^ ERROR no method named `get` found for enum `Option` in the current scope + //~| HELP use the `?` operator + Some(()) +} + +fn test_option_in_unit_return() { + let res: Option<_> = Some(Foo); + res.get(); + //~^ ERROR no method named `get` found for enum `Option` in the current scope + //~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None` +} + +fn main() {} diff --git a/src/test/ui/suggestions/enum-method-probe.stderr b/src/test/ui/suggestions/enum-method-probe.stderr new file mode 100644 index 000000000..6ed14984f --- /dev/null +++ b/src/test/ui/suggestions/enum-method-probe.stderr @@ -0,0 +1,99 @@ +error[E0599]: no method named `get` found for enum `Result` in the current scope + --> $DIR/enum-method-probe.rs:24:9 + | +LL | res.get(); + | ^^^ method not found in `Result<Foo, ()>` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:9:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: use the `?` operator to extract the `Foo` value, propagating a `Result::Err` value to the caller + | +LL | res?.get(); + | + + +error[E0599]: no method named `get` found for enum `Result` in the current scope + --> $DIR/enum-method-probe.rs:39:9 + | +LL | res.get(); + | ^^^ method not found in `Result<Foo, ()>` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:9:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err` + | +LL | res.expect("REASON").get(); + | +++++++++++++++++ + +error[E0599]: no method named `get` found for enum `Result` in the current scope + --> $DIR/enum-method-probe.rs:16:9 + | +LL | res.get(); + | ^^^ method not found in `Result<Foo, ()>` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:9:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: use the `?` operator to extract the `Foo` value, propagating a `Result::Err` value to the caller + | +LL | res?.get(); + | + + +error[E0599]: no method named `get` found for enum `Result` in the current scope + --> $DIR/enum-method-probe.rs:32:9 + | +LL | res.get(); + | ^^^ method not found in `Result<Foo, ()>` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:9:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err` + | +LL | res.expect("REASON").get(); + | +++++++++++++++++ + +error[E0599]: no method named `get` found for enum `Option` in the current scope + --> $DIR/enum-method-probe.rs:46:9 + | +LL | res.get(); + | ^^^ method not found in `Option<Foo>` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:9:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: use the `?` operator to extract the `Foo` value, propagating an `Option::None` value to the caller + | +LL | res?.get(); + | + + +error[E0599]: no method named `get` found for enum `Option` in the current scope + --> $DIR/enum-method-probe.rs:54:9 + | +LL | res.get(); + | ^^^ method not found in `Option<Foo>` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:9:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None` + | +LL | res.expect("REASON").get(); + | +++++++++++++++++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs new file mode 100644 index 000000000..7e9c5492d --- /dev/null +++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs @@ -0,0 +1,33 @@ +// edition:2018 +#![allow(dead_code)] +use std::future::Future; +use std::pin::Pin; + +type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>; +// ^^^^^^^^^ This would come from the `futures` crate in real code. + +fn foo<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> { + // We could instead use an `async` block, but this way we have no std spans. + x //~ ERROR mismatched types +} + +fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> { + Box::new(x) //~ ERROR mismatched types +} + +fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> { + Pin::new(x) //~ ERROR mismatched types + //~^ ERROR E0277 +} + +fn qux<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> { + Pin::new(Box::new(x)) //~ ERROR E0277 +} + +fn zap() -> BoxFuture<'static, i32> { + async { //~ ERROR mismatched types + 42 + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr new file mode 100644 index 000000000..71facf57e --- /dev/null +++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -0,0 +1,101 @@ +error[E0308]: mismatched types + --> $DIR/expected-boxed-future-isnt-pinned.rs:11:5 + | +LL | fn foo<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> { + | - this type parameter ----------------------- expected `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` because of return type +LL | // We could instead use an `async` block, but this way we have no std spans. +LL | x + | ^ expected struct `Pin`, found type parameter `F` + | + = note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` + found type parameter `F` +help: you need to pin and box this expression + | +LL | Box::pin(x) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/expected-boxed-future-isnt-pinned.rs:15:5 + | +LL | fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> { + | ----------------------- expected `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` because of return type +LL | Box::new(x) + | ^^^^^^^^^^^ expected struct `Pin`, found struct `Box` + | + = note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` + found struct `Box<F>` + = help: use `Box::pin` + +error[E0308]: mismatched types + --> $DIR/expected-boxed-future-isnt-pinned.rs:19:14 + | +LL | fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> { + | - this type parameter +LL | Pin::new(x) + | -------- ^ expected struct `Box`, found type parameter `F` + | | + | arguments to this function are incorrect + | help: use `Box::pin` to pin and box this expression: `Box::pin` + | + = note: expected struct `Box<dyn Future<Output = i32> + Send>` + found type parameter `F` +note: associated function defined here + --> $SRC_DIR/core/src/pin.rs:LL:COL + | +LL | pub const fn new(pointer: P) -> Pin<P> { + | ^^^ + +error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned + --> $DIR/expected-boxed-future-isnt-pinned.rs:19:5 + | +LL | Pin::new(x) + | ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send` + | + = note: consider using `Box::pin` +note: required by a bound in `Pin::<P>::new` + --> $SRC_DIR/core/src/pin.rs:LL:COL + | +LL | impl<P: Deref<Target: Unpin>> Pin<P> { + | ^^^^^ required by this bound in `Pin::<P>::new` + +error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned + --> $DIR/expected-boxed-future-isnt-pinned.rs:24:5 + | +LL | Pin::new(Box::new(x)) + | ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send` + | + = note: consider using `Box::pin` +note: required by a bound in `Pin::<P>::new` + --> $SRC_DIR/core/src/pin.rs:LL:COL + | +LL | impl<P: Deref<Target: Unpin>> Pin<P> { + | ^^^^^ required by this bound in `Pin::<P>::new` + +error[E0308]: mismatched types + --> $DIR/expected-boxed-future-isnt-pinned.rs:28:5 + | +LL | fn zap() -> BoxFuture<'static, i32> { + | ----------------------- expected `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` because of return type +LL | / async { +LL | | 42 +LL | | } + | |_____^ expected struct `Pin`, found opaque type + | + ::: $SRC_DIR/core/src/future/mod.rs:LL:COL + | +LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return> + | ------------------------------- the found opaque type + | + = note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` + found opaque type `impl Future` +help: you need to pin and box this expression + | +LL ~ Box::pin(async { +LL | 42 +LL ~ }) + | + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/field-access.fixed b/src/test/ui/suggestions/field-access.fixed new file mode 100644 index 000000000..ed9aef6e3 --- /dev/null +++ b/src/test/ui/suggestions/field-access.fixed @@ -0,0 +1,35 @@ +// run-rustfix +#![allow(dead_code)] + +struct A { + b: B, +} + +enum B { + Fst, + Snd, +} + +union Foo { + bar: u32, + qux: f32, +} + +fn main() { + let a = A { b: B::Fst }; + if let B::Fst = a.b {}; //~ ERROR mismatched types [E0308] + //~^ HELP you might have meant to use field `b` whose type is `B` + match a.b { + //~^ HELP you might have meant to use field `b` whose type is `B` + //~| HELP you might have meant to use field `b` whose type is `B` + B::Fst => (), //~ ERROR mismatched types [E0308] + B::Snd => (), //~ ERROR mismatched types [E0308] + } + + let foo = Foo { bar: 42 }; + match unsafe { foo.bar } { + //~^ HELP you might have meant to use field `bar` whose type is `u32` + 1u32 => (), //~ ERROR mismatched types [E0308] + _ => (), + } +} diff --git a/src/test/ui/suggestions/field-access.rs b/src/test/ui/suggestions/field-access.rs new file mode 100644 index 000000000..d80488e8a --- /dev/null +++ b/src/test/ui/suggestions/field-access.rs @@ -0,0 +1,35 @@ +// run-rustfix +#![allow(dead_code)] + +struct A { + b: B, +} + +enum B { + Fst, + Snd, +} + +union Foo { + bar: u32, + qux: f32, +} + +fn main() { + let a = A { b: B::Fst }; + if let B::Fst = a {}; //~ ERROR mismatched types [E0308] + //~^ HELP you might have meant to use field `b` whose type is `B` + match a { + //~^ HELP you might have meant to use field `b` whose type is `B` + //~| HELP you might have meant to use field `b` whose type is `B` + B::Fst => (), //~ ERROR mismatched types [E0308] + B::Snd => (), //~ ERROR mismatched types [E0308] + } + + let foo = Foo { bar: 42 }; + match foo { + //~^ HELP you might have meant to use field `bar` whose type is `u32` + 1u32 => (), //~ ERROR mismatched types [E0308] + _ => (), + } +} diff --git a/src/test/ui/suggestions/field-access.stderr b/src/test/ui/suggestions/field-access.stderr new file mode 100644 index 000000000..b9f0f788b --- /dev/null +++ b/src/test/ui/suggestions/field-access.stderr @@ -0,0 +1,67 @@ +error[E0308]: mismatched types + --> $DIR/field-access.rs:20:12 + | +LL | Fst, + | --- unit variant defined here +... +LL | if let B::Fst = a {}; + | ^^^^^^ - this expression has type `A` + | | + | expected struct `A`, found enum `B` + | +help: you might have meant to use field `b` whose type is `B` + | +LL | if let B::Fst = a.b {}; + | ~~~ + +error[E0308]: mismatched types + --> $DIR/field-access.rs:25:9 + | +LL | Fst, + | --- unit variant defined here +... +LL | match a { + | - this expression has type `A` +... +LL | B::Fst => (), + | ^^^^^^ expected struct `A`, found enum `B` + | +help: you might have meant to use field `b` whose type is `B` + | +LL | match a.b { + | ~~~ + +error[E0308]: mismatched types + --> $DIR/field-access.rs:26:9 + | +LL | Snd, + | --- unit variant defined here +... +LL | match a { + | - this expression has type `A` +... +LL | B::Snd => (), + | ^^^^^^ expected struct `A`, found enum `B` + | +help: you might have meant to use field `b` whose type is `B` + | +LL | match a.b { + | ~~~ + +error[E0308]: mismatched types + --> $DIR/field-access.rs:32:9 + | +LL | match foo { + | --- this expression has type `Foo` +LL | +LL | 1u32 => (), + | ^^^^ expected union `Foo`, found `u32` + | +help: you might have meant to use field `bar` whose type is `u32` + | +LL | match unsafe { foo.bar } { + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/field-has-method.rs b/src/test/ui/suggestions/field-has-method.rs new file mode 100644 index 000000000..980000151 --- /dev/null +++ b/src/test/ui/suggestions/field-has-method.rs @@ -0,0 +1,23 @@ +struct Kind; + +struct Ty { + kind: Kind, +} + +impl Ty { + fn kind(&self) -> Kind { + todo!() + } +} + +struct InferOk<T> { + value: T, + predicates: Vec<()>, +} + +fn foo(i: InferOk<Ty>) { + let k = i.kind(); + //~^ no method named `kind` found for struct `InferOk` in the current scope +} + +fn main() {} diff --git a/src/test/ui/suggestions/field-has-method.stderr b/src/test/ui/suggestions/field-has-method.stderr new file mode 100644 index 000000000..def164017 --- /dev/null +++ b/src/test/ui/suggestions/field-has-method.stderr @@ -0,0 +1,17 @@ +error[E0599]: no method named `kind` found for struct `InferOk` in the current scope + --> $DIR/field-has-method.rs:19:15 + | +LL | struct InferOk<T> { + | ----------------- method `kind` not found for this struct +... +LL | let k = i.kind(); + | ^^^^ method not found in `InferOk<Ty>` + | +help: one of the expressions' fields has a method of the same name + | +LL | let k = i.value.kind(); + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs new file mode 100644 index 000000000..4303e5c54 --- /dev/null +++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs @@ -0,0 +1,20 @@ +// edition:2018 +trait T { + type O; +} + +struct S; + +impl T for S { + type O = (); +} + +fn foo() -> impl T<O=()> { S } + +fn bar(f: impl T<O=()>) {} + +fn main() { + bar(foo); //~ERROR E0277 + let closure = || S; + bar(closure); //~ERROR E0277 +} diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr new file mode 100644 index 000000000..fb0a6f70b --- /dev/null +++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -0,0 +1,44 @@ +error[E0277]: the trait bound `fn() -> impl T<O = ()> {foo}: T` is not satisfied + --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:17:9 + | +LL | fn foo() -> impl T<O=()> { S } + | --- consider calling this function +... +LL | bar(foo); + | --- ^^^ the trait `T` is not implemented for `fn() -> impl T<O = ()> {foo}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `bar` + --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16 + | +LL | fn bar(f: impl T<O=()>) {} + | ^^^^^^^ required by this bound in `bar` +help: use parentheses to call the function + | +LL | bar(foo()); + | ++ + +error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]: T` is not satisfied + --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:19:9 + | +LL | let closure = || S; + | -- consider calling this closure +LL | bar(closure); + | --- ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]` + | | + | required by a bound introduced by this call + | +note: required by a bound in `bar` + --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16 + | +LL | fn bar(f: impl T<O=()>) {} + | ^^^^^^^ required by this bound in `bar` +help: use parentheses to call the closure + | +LL | bar(closure()); + | ++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/fn-missing-lifetime-in-item.rs b/src/test/ui/suggestions/fn-missing-lifetime-in-item.rs new file mode 100644 index 000000000..dac6610b3 --- /dev/null +++ b/src/test/ui/suggestions/fn-missing-lifetime-in-item.rs @@ -0,0 +1,8 @@ +struct S1<F: Fn(&i32, &i32) -> &'a i32>(F); //~ ERROR use of undeclared lifetime name `'a` +struct S2<F: Fn(&i32, &i32) -> &i32>(F); //~ ERROR missing lifetime specifier +struct S3<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F); +//~^ ERROR binding for associated type `Output` references lifetime `'a`, which does not appear +struct S4<F: for<'x> Fn(&'x i32, &'x i32) -> &'x i32>(F); +const C: Option<Box<dyn for<'a> Fn(&usize, &usize) -> &'a usize>> = None; +//~^ ERROR binding for associated type `Output` references lifetime `'a`, which does not appear +fn main() {} diff --git a/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr b/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr new file mode 100644 index 000000000..6d7c3d730 --- /dev/null +++ b/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr @@ -0,0 +1,48 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/fn-missing-lifetime-in-item.rs:1:33 + | +LL | struct S1<F: Fn(&i32, &i32) -> &'a i32>(F); + | ^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F); + | +++++++ +help: consider introducing lifetime `'a` here + | +LL | struct S1<'a, F: Fn(&i32, &i32) -> &'a i32>(F); + | +++ + +error[E0106]: missing lifetime specifier + --> $DIR/fn-missing-lifetime-in-item.rs:2:32 + | +LL | struct S2<F: Fn(&i32, &i32) -> &i32>(F); + | ---- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | struct S2<F: for<'a> Fn(&'a i32, &'a i32) -> &'a i32>(F); + | +++++++ ++ ++ ++ +help: consider introducing a named lifetime parameter + | +LL | struct S2<'a, F: Fn(&'a i32, &'a i32) -> &'a i32>(F); + | +++ ++ ++ ++ + +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/fn-missing-lifetime-in-item.rs:3:40 + | +LL | struct S3<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F); + | ^^^^^^^ + +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/fn-missing-lifetime-in-item.rs:6:55 + | +LL | const C: Option<Box<dyn for<'a> Fn(&usize, &usize) -> &'a usize>> = None; + | ^^^^^^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0106, E0261, E0582. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/fn-needing-specified-return-type-param.rs b/src/test/ui/suggestions/fn-needing-specified-return-type-param.rs new file mode 100644 index 000000000..bcc91b5cb --- /dev/null +++ b/src/test/ui/suggestions/fn-needing-specified-return-type-param.rs @@ -0,0 +1,7 @@ +fn f<A>() -> A { unimplemented!() } +fn foo() { + let _ = f; + //~^ ERROR type annotations needed + //~| HELP consider specifying the generic argument +} +fn main() {} diff --git a/src/test/ui/suggestions/fn-needing-specified-return-type-param.stderr b/src/test/ui/suggestions/fn-needing-specified-return-type-param.stderr new file mode 100644 index 000000000..9dea667fb --- /dev/null +++ b/src/test/ui/suggestions/fn-needing-specified-return-type-param.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/fn-needing-specified-return-type-param.rs:3:13 + | +LL | let _ = f; + | ^ cannot infer type of the type parameter `A` declared on the function `f` + | +help: consider specifying the generic argument + | +LL | let _ = f::<A>; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs b/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs new file mode 100644 index 000000000..ae1dbfeea --- /dev/null +++ b/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs @@ -0,0 +1,19 @@ +fn foo(a: usize, b: usize) -> usize { a } + +struct S(usize, usize); + +trait T { + fn baz(x: usize, y: usize) -> usize { x } +} + +fn main() { + let _: usize = foo(_, _); + //~^ ERROR `_` can only be used on the left-hand side of an assignment + //~| ERROR `_` can only be used on the left-hand side of an assignment + let _: S = S(_, _); + //~^ ERROR `_` can only be used on the left-hand side of an assignment + //~| ERROR `_` can only be used on the left-hand side of an assignment + let _: usize = T::baz(_, _); + //~^ ERROR `_` can only be used on the left-hand side of an assignment + //~| ERROR `_` can only be used on the left-hand side of an assignment +} diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr new file mode 100644 index 000000000..aa5620306 --- /dev/null +++ b/src/test/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr @@ -0,0 +1,38 @@ +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:24 + | +LL | let _: usize = foo(_, _); + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:27 + | +LL | let _: usize = foo(_, _); + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:13:18 + | +LL | let _: S = S(_, _); + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:13:21 + | +LL | let _: S = S(_, _); + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:16:27 + | +LL | let _: usize = T::baz(_, _); + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:16:30 + | +LL | let _: usize = T::baz(_, _); + | ^ `_` not allowed here + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs new file mode 100644 index 000000000..dd5af3e34 --- /dev/null +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs @@ -0,0 +1,47 @@ +fn foo(a: usize, b: usize) -> usize { a } + +fn bar() -> usize { 42 } + +struct S(usize, usize); +enum E { + A(usize), + B { a: usize }, +} +struct V(); + +trait T { + fn baz(x: usize, y: usize) -> usize { x } + fn bat(x: usize) -> usize { 42 } + fn bax(x: usize) -> usize { 42 } + fn bach(x: usize) -> usize; + fn ban(&self) -> usize { 42 } + fn bal(&self) -> usize; +} + +struct X; + +impl T for X { + fn bach(x: usize) -> usize { 42 } + fn bal(&self) -> usize { 42 } +} + +fn main() { + let _: usize = foo; //~ ERROR mismatched types + let _: S = S; //~ ERROR mismatched types + let _: usize = bar; //~ ERROR mismatched types + let _: V = V; //~ ERROR mismatched types + let _: usize = T::baz; //~ ERROR mismatched types + let _: usize = T::bat; //~ ERROR mismatched types + let _: E = E::A; //~ ERROR mismatched types + let _: E = E::B; //~ ERROR expected value, found struct variant `E::B` + let _: usize = X::baz; //~ ERROR mismatched types + let _: usize = X::bat; //~ ERROR mismatched types + let _: usize = X::bax; //~ ERROR mismatched types + let _: usize = X::bach; //~ ERROR mismatched types + let _: usize = X::ban; //~ ERROR mismatched types + let _: usize = X::bal; //~ ERROR mismatched types + let _: usize = X.ban; //~ ERROR attempted to take value of method + let _: usize = X.bal; //~ ERROR attempted to take value of method + let closure = || 42; + let _: usize = closure; //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr new file mode 100644 index 000000000..e75ce0da8 --- /dev/null +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -0,0 +1,297 @@ +error[E0423]: expected value, found struct variant `E::B` + --> $DIR/fn-or-tuple-struct-without-args.rs:36:16 + | +LL | A(usize), + | -------- similarly named tuple variant `A` defined here +LL | B { a: usize }, + | -------------- `E::B` defined here +... +LL | let _: E = E::B; + | ^^^^ + | +help: use struct literal syntax instead + | +LL | let _: E = E::B { a: val }; + | ~~~~~~~~~~~~~~~ +help: a tuple variant with a similar name exists + | +LL | let _: E = E::A; + | ~ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:29:20 + | +LL | fn foo(a: usize, b: usize) -> usize { a } + | ----------------------------------- fn(usize, usize) -> usize {foo} defined here +... +LL | let _: usize = foo; + | ----- ^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn(usize, usize) -> usize {foo}` +help: use parentheses to call this function + | +LL | let _: usize = foo(_, _); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:30:16 + | +LL | struct S(usize, usize); + | -------- fn(usize, usize) -> S {S} defined here +... +LL | let _: S = S; + | - ^ expected struct `S`, found fn item + | | + | expected due to this + | + = note: expected struct `S` + found fn item `fn(usize, usize) -> S {S}` +help: use parentheses to instantiate this tuple struct + | +LL | let _: S = S(_, _); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:31:20 + | +LL | fn bar() -> usize { 42 } + | ----------------- fn() -> usize {bar} defined here +... +LL | let _: usize = bar; + | ----- ^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn() -> usize {bar}` +help: use parentheses to call this function + | +LL | let _: usize = bar(); + | ++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:32:16 + | +LL | struct V(); + | -------- fn() -> V {V} defined here +... +LL | let _: V = V; + | - ^ expected struct `V`, found fn item + | | + | expected due to this + | + = note: expected struct `V` + found fn item `fn() -> V {V}` +help: use parentheses to instantiate this tuple struct + | +LL | let _: V = V(); + | ++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:33:20 + | +LL | fn baz(x: usize, y: usize) -> usize { x } + | ----------------------------------- fn(usize, usize) -> usize {<_ as T>::baz} defined here +... +LL | let _: usize = T::baz; + | ----- ^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn(usize, usize) -> usize {<_ as T>::baz}` +help: use parentheses to call this function + | +LL | let _: usize = T::baz(_, _); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:34:20 + | +LL | fn bat(x: usize) -> usize { 42 } + | ------------------------- fn(usize) -> usize {<_ as T>::bat} defined here +... +LL | let _: usize = T::bat; + | ----- ^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn(usize) -> usize {<_ as T>::bat}` +help: use parentheses to call this function + | +LL | let _: usize = T::bat(_); + | +++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:35:16 + | +LL | A(usize), + | - fn(usize) -> E {E::A} defined here +... +LL | let _: E = E::A; + | - ^^^^ expected enum `E`, found fn item + | | + | expected due to this + | + = note: expected enum `E` + found fn item `fn(usize) -> E {E::A}` +help: use parentheses to instantiate this tuple variant + | +LL | let _: E = E::A(_); + | +++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:37:20 + | +LL | fn baz(x: usize, y: usize) -> usize { x } + | ----------------------------------- fn(usize, usize) -> usize {<X as T>::baz} defined here +... +LL | let _: usize = X::baz; + | ----- ^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn(usize, usize) -> usize {<X as T>::baz}` +help: use parentheses to call this function + | +LL | let _: usize = X::baz(_, _); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:38:20 + | +LL | fn bat(x: usize) -> usize { 42 } + | ------------------------- fn(usize) -> usize {<X as T>::bat} defined here +... +LL | let _: usize = X::bat; + | ----- ^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn(usize) -> usize {<X as T>::bat}` +help: use parentheses to call this function + | +LL | let _: usize = X::bat(_); + | +++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:39:20 + | +LL | fn bax(x: usize) -> usize { 42 } + | ------------------------- fn(usize) -> usize {<X as T>::bax} defined here +... +LL | let _: usize = X::bax; + | ----- ^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn(usize) -> usize {<X as T>::bax}` +help: use parentheses to call this function + | +LL | let _: usize = X::bax(_); + | +++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:40:20 + | +LL | fn bach(x: usize) -> usize; + | --------------------------- fn(usize) -> usize {<X as T>::bach} defined here +... +LL | let _: usize = X::bach; + | ----- ^^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn(usize) -> usize {<X as T>::bach}` +help: use parentheses to call this function + | +LL | let _: usize = X::bach(_); + | +++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:41:20 + | +LL | fn ban(&self) -> usize { 42 } + | ---------------------- for<'r> fn(&'r X) -> usize {<X as T>::ban} defined here +... +LL | let _: usize = X::ban; + | ----- ^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `for<'r> fn(&'r X) -> usize {<X as T>::ban}` +help: use parentheses to call this function + | +LL | let _: usize = X::ban(_); + | +++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:42:20 + | +LL | fn bal(&self) -> usize; + | ----------------------- for<'r> fn(&'r X) -> usize {<X as T>::bal} defined here +... +LL | let _: usize = X::bal; + | ----- ^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `for<'r> fn(&'r X) -> usize {<X as T>::bal}` +help: use parentheses to call this function + | +LL | let _: usize = X::bal(_); + | +++ + +error[E0615]: attempted to take value of method `ban` on type `X` + --> $DIR/fn-or-tuple-struct-without-args.rs:43:22 + | +LL | let _: usize = X.ban; + | ^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let _: usize = X.ban(); + | ++ + +error[E0615]: attempted to take value of method `bal` on type `X` + --> $DIR/fn-or-tuple-struct-without-args.rs:44:22 + | +LL | let _: usize = X.bal; + | ^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let _: usize = X.bal(); + | ++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:46:20 + | +LL | let closure = || 42; + | -- the found closure +LL | let _: usize = closure; + | ----- ^^^^^^^ expected `usize`, found closure + | | + | expected due to this + | + = note: expected type `usize` + found closure `[closure@$DIR/fn-or-tuple-struct-without-args.rs:45:19: 45:21]` +help: use parentheses to call this closure + | +LL | let _: usize = closure(); + | ++ + +error: aborting due to 17 previous errors + +Some errors have detailed explanations: E0308, E0423, E0615. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/fn-trait-notation.fixed b/src/test/ui/suggestions/fn-trait-notation.fixed new file mode 100644 index 000000000..cf940f4e9 --- /dev/null +++ b/src/test/ui/suggestions/fn-trait-notation.fixed @@ -0,0 +1,19 @@ +// run-rustfix +fn e0658<F, G, H>(f: F, g: G, h: H) -> i32 +where + F: Fn(i32) -> i32, //~ ERROR E0658 + G: Fn(i32, i32) -> (i32, i32), //~ ERROR E0658 + H: Fn(i32) -> i32, //~ ERROR E0658 +{ + f(3); + g(3, 4); + h(3) +} + +fn main() { + e0658( + |a| a, + |a, b| (b, a), + |a| a, + ); +} diff --git a/src/test/ui/suggestions/fn-trait-notation.rs b/src/test/ui/suggestions/fn-trait-notation.rs new file mode 100644 index 000000000..f0bb03315 --- /dev/null +++ b/src/test/ui/suggestions/fn-trait-notation.rs @@ -0,0 +1,19 @@ +// run-rustfix +fn e0658<F, G, H>(f: F, g: G, h: H) -> i32 +where + F: Fn<i32, Output = i32>, //~ ERROR E0658 + G: Fn<(i32, i32, ), Output = (i32, i32)>, //~ ERROR E0658 + H: Fn<(i32,), Output = i32>, //~ ERROR E0658 +{ + f(3); + g(3, 4); + h(3) +} + +fn main() { + e0658( + |a| a, + |a, b| (b, a), + |a| a, + ); +} diff --git a/src/test/ui/suggestions/fn-trait-notation.stderr b/src/test/ui/suggestions/fn-trait-notation.stderr new file mode 100644 index 000000000..3e3b54174 --- /dev/null +++ b/src/test/ui/suggestions/fn-trait-notation.stderr @@ -0,0 +1,30 @@ +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/fn-trait-notation.rs:4:8 + | +LL | F: Fn<i32, Output = i32>, + | ^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32) -> i32` + | + = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/fn-trait-notation.rs:5:8 + | +LL | G: Fn<(i32, i32, ), Output = (i32, i32)>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32, i32) -> (i32, i32)` + | + = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/fn-trait-notation.rs:6:8 + | +LL | H: Fn<(i32,), Output = i32>, + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32) -> i32` + | + = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/suggestions/for-i-in-vec.fixed b/src/test/ui/suggestions/for-i-in-vec.fixed new file mode 100644 index 000000000..4f2007bef --- /dev/null +++ b/src/test/ui/suggestions/for-i-in-vec.fixed @@ -0,0 +1,27 @@ +// run-rustfix +#![allow(dead_code)] + +struct Foo { + v: Vec<u32>, + h: std::collections::HashMap<i32, i32>, +} + +impl Foo { + fn bar(&self) { + for _ in &self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference + } + for _ in &self.h { //~ ERROR cannot move out of `self.h` which is behind a shared reference + } + } +} + +const LOADERS: &Vec<&'static u8> = &Vec::new(); + +pub fn break_code() -> Option<&'static u8> { + for loader in &*LOADERS { //~ ERROR cannot move out of a shared reference + return Some(loader); + } + None +} + +fn main() {} diff --git a/src/test/ui/suggestions/for-i-in-vec.rs b/src/test/ui/suggestions/for-i-in-vec.rs new file mode 100644 index 000000000..55fc7ad4e --- /dev/null +++ b/src/test/ui/suggestions/for-i-in-vec.rs @@ -0,0 +1,27 @@ +// run-rustfix +#![allow(dead_code)] + +struct Foo { + v: Vec<u32>, + h: std::collections::HashMap<i32, i32>, +} + +impl Foo { + fn bar(&self) { + for _ in self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference + } + for _ in self.h { //~ ERROR cannot move out of `self.h` which is behind a shared reference + } + } +} + +const LOADERS: &Vec<&'static u8> = &Vec::new(); + +pub fn break_code() -> Option<&'static u8> { + for loader in *LOADERS { //~ ERROR cannot move out of a shared reference + return Some(loader); + } + None +} + +fn main() {} diff --git a/src/test/ui/suggestions/for-i-in-vec.stderr b/src/test/ui/suggestions/for-i-in-vec.stderr new file mode 100644 index 000000000..88be9e30a --- /dev/null +++ b/src/test/ui/suggestions/for-i-in-vec.stderr @@ -0,0 +1,55 @@ +error[E0507]: cannot move out of `self.v` which is behind a shared reference + --> $DIR/for-i-in-vec.rs:11:18 + | +LL | for _ in self.v { + | ^^^^^^ + | | + | `self.v` moved due to this implicit call to `.into_iter()` + | move occurs because `self.v` has type `Vec<u32>`, which does not implement the `Copy` trait + | +note: this function takes ownership of the receiver `self`, which moves `self.v` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^ +help: consider iterating over a slice of the `Vec<u32>`'s content to avoid moving into the `for` loop + | +LL | for _ in &self.v { + | + + +error[E0507]: cannot move out of `self.h` which is behind a shared reference + --> $DIR/for-i-in-vec.rs:13:18 + | +LL | for _ in self.h { + | ^^^^^^ + | | + | `self.h` moved due to this implicit call to `.into_iter()` + | move occurs because `self.h` has type `HashMap<i32, i32>`, which does not implement the `Copy` trait + | +help: consider iterating over a slice of the `HashMap<i32, i32>`'s content to avoid moving into the `for` loop + | +LL | for _ in &self.h { + | + + +error[E0507]: cannot move out of a shared reference + --> $DIR/for-i-in-vec.rs:21:19 + | +LL | for loader in *LOADERS { + | ^^^^^^^^ + | | + | value moved due to this implicit call to `.into_iter()` + | move occurs because value has type `Vec<&u8>`, which does not implement the `Copy` trait + | +note: this function takes ownership of the receiver `self`, which moves value + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^ +help: consider iterating over a slice of the `Vec<&u8>`'s content to avoid moving into the `for` loop + | +LL | for loader in &*LOADERS { + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/suggestions/format-borrow.rs b/src/test/ui/suggestions/format-borrow.rs new file mode 100644 index 000000000..599a79fc0 --- /dev/null +++ b/src/test/ui/suggestions/format-borrow.rs @@ -0,0 +1,10 @@ +fn main() { + let a: String = &String::from("a"); + //~^ ERROR mismatched types + let b: String = &format!("b"); + //~^ ERROR mismatched types + let c: String = &mut format!("c"); + //~^ ERROR mismatched types + let d: String = &mut (format!("d")); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/format-borrow.stderr b/src/test/ui/suggestions/format-borrow.stderr new file mode 100644 index 000000000..fac6a5a5f --- /dev/null +++ b/src/test/ui/suggestions/format-borrow.stderr @@ -0,0 +1,59 @@ +error[E0308]: mismatched types + --> $DIR/format-borrow.rs:2:21 + | +LL | let a: String = &String::from("a"); + | ------ ^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&String` + | | + | expected due to this + | +help: consider removing the borrow + | +LL - let a: String = &String::from("a"); +LL + let a: String = String::from("a"); + | + +error[E0308]: mismatched types + --> $DIR/format-borrow.rs:4:21 + | +LL | let b: String = &format!("b"); + | ------ ^^^^^^^^^^^^^ expected struct `String`, found `&String` + | | + | expected due to this + | +help: consider removing the borrow + | +LL - let b: String = &format!("b"); +LL + let b: String = format!("b"); + | + +error[E0308]: mismatched types + --> $DIR/format-borrow.rs:6:21 + | +LL | let c: String = &mut format!("c"); + | ------ ^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String` + | | + | expected due to this + | +help: consider removing the borrow + | +LL - let c: String = &mut format!("c"); +LL + let c: String = format!("c"); + | + +error[E0308]: mismatched types + --> $DIR/format-borrow.rs:8:21 + | +LL | let d: String = &mut (format!("d")); + | ------ ^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String` + | | + | expected due to this + | +help: consider removing the borrow + | +LL - let d: String = &mut (format!("d")); +LL + let d: String = format!("d")); + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/if-let-typo.rs b/src/test/ui/suggestions/if-let-typo.rs new file mode 100644 index 000000000..375bd3f03 --- /dev/null +++ b/src/test/ui/suggestions/if-let-typo.rs @@ -0,0 +1,11 @@ +fn main() { + let foo = Some(0); + let bar = None; + if Some(x) = foo {} //~ ERROR cannot find value `x` in this scope + //~^ ERROR mismatched types + if Some(foo) = bar {} //~ ERROR mismatched types + if 3 = foo {} //~ ERROR mismatched types + if Some(3) = foo {} //~ ERROR mismatched types + //~^ ERROR invalid left-hand side of assignment + if x = 5 {} //~ ERROR cannot find value `x` in this scope +} diff --git a/src/test/ui/suggestions/if-let-typo.stderr b/src/test/ui/suggestions/if-let-typo.stderr new file mode 100644 index 000000000..3d9ac40ec --- /dev/null +++ b/src/test/ui/suggestions/if-let-typo.stderr @@ -0,0 +1,58 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/if-let-typo.rs:4:13 + | +LL | if Some(x) = foo {} + | ^ not found in this scope + | +help: you might have meant to use pattern matching + | +LL | if let Some(x) = foo {} + | +++ + +error[E0425]: cannot find value `x` in this scope + --> $DIR/if-let-typo.rs:10:8 + | +LL | if x = 5 {} + | ^ not found in this scope + | +help: you might have meant to use pattern matching + | +LL | if let x = 5 {} + | +++ + +error[E0308]: mismatched types + --> $DIR/if-let-typo.rs:4:8 + | +LL | if Some(x) = foo {} + | ^^^^^^^^^^^^^ expected `bool`, found `()` + +error[E0308]: mismatched types + --> $DIR/if-let-typo.rs:6:8 + | +LL | if Some(foo) = bar {} + | ^^^^^^^^^^^^^^^ expected `bool`, found `()` + +error[E0308]: mismatched types + --> $DIR/if-let-typo.rs:7:8 + | +LL | if 3 = foo {} + | ^^^^^^^ expected `bool`, found `()` + +error[E0070]: invalid left-hand side of assignment + --> $DIR/if-let-typo.rs:8:16 + | +LL | if Some(3) = foo {} + | - ^ + | | + | cannot assign to this expression + +error[E0308]: mismatched types + --> $DIR/if-let-typo.rs:8:8 + | +LL | if Some(3) = foo {} + | ^^^^^^^^^^^^^ expected `bool`, found `()` + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0070, E0308, E0425. +For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/suggestions/if-then-neeing-semi.rs b/src/test/ui/suggestions/if-then-neeing-semi.rs new file mode 100644 index 000000000..b487f013d --- /dev/null +++ b/src/test/ui/suggestions/if-then-neeing-semi.rs @@ -0,0 +1,70 @@ +// edition:2018 + +fn dummy() -> i32 { + 42 +} + +fn extra_semicolon() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + dummy(); //~ NOTE expected because of this + //~^ HELP consider removing this semicolon + } else { + dummy() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected `()`, found `i32` + }; +} + +async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE checked the `Output` of this `async fn`, expected opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function + +async fn async_extra_semicolon_same() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + async_dummy(); //~ NOTE expected because of this + //~^ HELP consider removing this semicolon + } else { + async_dummy() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected `()`, found opaque type + //~| NOTE expected unit type `()` + //~| HELP consider `await`ing on the `Future` + }; +} + +async fn async_extra_semicolon_different() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + async_dummy(); //~ NOTE expected because of this + //~^ HELP consider removing this semicolon + } else { + async_dummy2() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected `()`, found opaque type + //~| NOTE expected unit type `()` + //~| HELP consider `await`ing on the `Future` + }; +} + +async fn async_different_futures() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + async_dummy() //~ NOTE expected because of this + //~| HELP consider `await`ing on both `Future`s + } else { + async_dummy2() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected opaque type, found a different opaque type + //~| NOTE expected opaque type `impl Future<Output = ()>` + //~| NOTE distinct uses of `impl Trait` result in different opaque types + }; +} + +fn main() {} diff --git a/src/test/ui/suggestions/if-then-neeing-semi.stderr b/src/test/ui/suggestions/if-then-neeing-semi.stderr new file mode 100644 index 000000000..d7c5818ab --- /dev/null +++ b/src/test/ui/suggestions/if-then-neeing-semi.stderr @@ -0,0 +1,130 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:37:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | async_dummy(); + | | -------------- expected because of this +LL | | +LL | | } else { +LL | | async_dummy() + | | ^^^^^^^^^^^^^ expected `()`, found opaque type +... | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:18:24 + | +LL | async fn async_dummy() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future<Output = ()>` +help: consider `await`ing on the `Future` + | +LL | async_dummy().await + | ++++++ +help: consider removing this semicolon + | +LL - async_dummy(); +LL + async_dummy() + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:50:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | async_dummy(); + | | -------------- expected because of this +LL | | +LL | | } else { +LL | | async_dummy2() + | | ^^^^^^^^^^^^^^ expected `()`, found opaque type +... | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:24:25 + | +LL | async fn async_dummy2() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future<Output = ()>` +help: consider `await`ing on the `Future` + | +LL | async_dummy2().await + | ++++++ +help: consider removing this semicolon and boxing the expressions + | +LL ~ Box::new(async_dummy()) +LL | +LL | } else { +LL ~ Box::new(async_dummy2()) + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:63:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | async_dummy() + | | ------------- expected because of this +LL | | +LL | | } else { +LL | | async_dummy2() + | | ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type +... | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:18:24 + | +LL | async fn async_dummy() {} + | ^ checked the `Output` of this `async fn`, expected opaque type +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:24:25 + | +LL | async fn async_dummy2() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:18:24>) + found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:24:25>) + = note: distinct uses of `impl Trait` result in different opaque types +help: consider `await`ing on both `Future`s + | +LL ~ async_dummy().await +LL | +LL | } else { +LL ~ async_dummy2().await + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:13:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | dummy(); + | | -------- + | | | | + | | | help: consider removing this semicolon + | | expected because of this +LL | | +LL | | } else { +LL | | dummy() + | | ^^^^^^^ expected `()`, found `i32` +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/ignore-nested-field-binding.fixed b/src/test/ui/suggestions/ignore-nested-field-binding.fixed new file mode 100644 index 000000000..1dc44838e --- /dev/null +++ b/src/test/ui/suggestions/ignore-nested-field-binding.fixed @@ -0,0 +1,20 @@ +// Regression test for #88403, where prefixing with an underscore was +// erroneously suggested for a nested shorthand struct field binding. + +// run-rustfix +#![allow(unused)] +#![forbid(unused_variables)] + +struct Inner { i: i32 } +struct Outer { o: Inner } + +fn foo(Outer { o: Inner { i: _ } }: Outer) {} +//~^ ERROR: unused variable: `i` +//~| HELP: try ignoring the field + +fn main() { + let s = Outer { o: Inner { i: 42 } }; + let Outer { o: Inner { i: _ } } = s; + //~^ ERROR: unused variable: `i` + //~| HELP: try ignoring the field +} diff --git a/src/test/ui/suggestions/ignore-nested-field-binding.rs b/src/test/ui/suggestions/ignore-nested-field-binding.rs new file mode 100644 index 000000000..6dc0263ec --- /dev/null +++ b/src/test/ui/suggestions/ignore-nested-field-binding.rs @@ -0,0 +1,20 @@ +// Regression test for #88403, where prefixing with an underscore was +// erroneously suggested for a nested shorthand struct field binding. + +// run-rustfix +#![allow(unused)] +#![forbid(unused_variables)] + +struct Inner { i: i32 } +struct Outer { o: Inner } + +fn foo(Outer { o: Inner { i } }: Outer) {} +//~^ ERROR: unused variable: `i` +//~| HELP: try ignoring the field + +fn main() { + let s = Outer { o: Inner { i: 42 } }; + let Outer { o: Inner { i } } = s; + //~^ ERROR: unused variable: `i` + //~| HELP: try ignoring the field +} diff --git a/src/test/ui/suggestions/ignore-nested-field-binding.stderr b/src/test/ui/suggestions/ignore-nested-field-binding.stderr new file mode 100644 index 000000000..b2936a22a --- /dev/null +++ b/src/test/ui/suggestions/ignore-nested-field-binding.stderr @@ -0,0 +1,20 @@ +error: unused variable: `i` + --> $DIR/ignore-nested-field-binding.rs:11:27 + | +LL | fn foo(Outer { o: Inner { i } }: Outer) {} + | ^ help: try ignoring the field: `i: _` + | +note: the lint level is defined here + --> $DIR/ignore-nested-field-binding.rs:6:11 + | +LL | #![forbid(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: unused variable: `i` + --> $DIR/ignore-nested-field-binding.rs:17:28 + | +LL | let Outer { o: Inner { i } } = s; + | ^ help: try ignoring the field: `i: _` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs new file mode 100644 index 000000000..319789c4e --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs @@ -0,0 +1,18 @@ +// Regression test for #70813 (this used to trigger a debug assertion) + +trait Trait {} + +struct S; + +impl<'a> Trait for &'a mut S {} + +fn foo<X>(_: X) +where + for<'b> &'b X: Trait, +{ +} + +fn main() { + let s = S; + foo::<S>(s); //~ ERROR the trait bound `for<'b> &'b S: Trait` is not satisfied +} diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr new file mode 100644 index 000000000..ba6af8f15 --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `for<'b> &'b S: Trait` is not satisfied + --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:17:5 + | +LL | foo::<S>(s); + | ^^^^^^^^ the trait `for<'b> Trait` is not implemented for `&'b S` + | + = help: the trait `Trait` is implemented for `&'a mut S` + = note: `for<'b> Trait` is implemented for `&'b mut S`, but not for `&'b S` +note: required by a bound in `foo` + --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:11:20 + | +LL | fn foo<X>(_: X) + | --- required by a bound in this +LL | where +LL | for<'b> &'b X: Trait, + | ^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.rs b/src/test/ui/suggestions/imm-ref-trait-object-literal.rs new file mode 100644 index 000000000..22ca6dde4 --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal.rs @@ -0,0 +1,14 @@ +trait Trait {} + +struct S; + +impl<'a> Trait for &'a mut S {} + +fn foo<X: Trait>(_: X) {} + + +fn main() { + let s = S; + foo(&s); //~ ERROR the trait bound `&S: Trait` is not satisfied + foo(s); //~ ERROR the trait bound `S: Trait` is not satisfied +} diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr new file mode 100644 index 000000000..5f3f62a7b --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr @@ -0,0 +1,40 @@ +error[E0277]: the trait bound `&S: Trait` is not satisfied + --> $DIR/imm-ref-trait-object-literal.rs:12:7 + | +LL | foo(&s); + | --- ^^ the trait `Trait` is not implemented for `&S` + | | + | required by a bound introduced by this call + | + = help: the trait `Trait` is implemented for `&'a mut S` +note: required by a bound in `foo` + --> $DIR/imm-ref-trait-object-literal.rs:7:11 + | +LL | fn foo<X: Trait>(_: X) {} + | ^^^^^ required by this bound in `foo` +help: consider changing this borrow's mutability + | +LL | foo(&mut s); + | ~~~~ + +error[E0277]: the trait bound `S: Trait` is not satisfied + --> $DIR/imm-ref-trait-object-literal.rs:13:7 + | +LL | foo(s); + | --- ^ expected an implementor of trait `Trait` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/imm-ref-trait-object-literal.rs:7:11 + | +LL | fn foo<X: Trait>(_: X) {} + | ^^^^^ required by this bound in `foo` +help: consider mutably borrowing here + | +LL | foo(&mut s); + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/imm-ref-trait-object.rs b/src/test/ui/suggestions/imm-ref-trait-object.rs new file mode 100644 index 000000000..288d6c699 --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object.rs @@ -0,0 +1,8 @@ +fn test(t: &dyn Iterator<Item=&u64>) -> u64 { + t.min().unwrap() //~ ERROR the `min` method cannot be invoked on a trait object +} + +fn main() { + let array = [0u64]; + test(&mut array.iter()); +} diff --git a/src/test/ui/suggestions/imm-ref-trait-object.stderr b/src/test/ui/suggestions/imm-ref-trait-object.stderr new file mode 100644 index 000000000..42ca3a78d --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object.stderr @@ -0,0 +1,15 @@ +error: the `min` method cannot be invoked on a trait object + --> $DIR/imm-ref-trait-object.rs:2:8 + | +LL | t.min().unwrap() + | ^^^ + | + ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | Self: Sized, + | ----- this has a `Sized` requirement + | + = note: you need `&mut dyn Iterator<Item = &u64>` instead of `&dyn Iterator<Item = &u64>` + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs new file mode 100644 index 000000000..711cbbd38 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs @@ -0,0 +1,113 @@ +// FIXME: the following cases need to suggest more things to make users reach a working end state. + +mod bav { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> { + fn use_self(&self) -> &() { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> { + val.use_self() //~ ERROR cannot return reference to function parameter + } +} + +mod bap { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> { + fn use_self(&self) -> &() { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR E0515 + } +} + +// This case in particular requires the user to write all of the bounds we have in `mod bax`. +mod bay { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> { + fn use_self(&self) -> &() { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () { + val.use_self() + } +} + +mod bax { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait<'a> { + fn use_self(&'a self) -> &'a () { panic!() } + } + trait Bar {} + + impl<'a> MyTrait<'a> for Box<dyn ObjectTrait<Assoc = i32> + 'a> { + fn use_self(&'a self) -> &'a () { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () { + val.use_self() + } +} + +mod baw { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl<'a> MyTrait for Box<dyn ObjectTrait<Assoc = Box<dyn Bar>>> { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = Box<dyn Bar>>>) -> impl OtherTrait<'a> + 'a{ + val.use_self() //~ ERROR E0515 + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr new file mode 100644 index 000000000..2dc300ac7 --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr @@ -0,0 +1,21 @@ +error[E0515]: cannot return reference to function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9 + | +LL | val.use_self() + | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function + +error[E0515]: cannot return reference to function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9 + | +LL | val.use_self() + | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function + +error[E0515]: cannot return reference to function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:109:9 + | +LL | val.use_self() + | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0515`. diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs new file mode 100644 index 000000000..ae3cd315c --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs @@ -0,0 +1,114 @@ +// FIXME(#96332): We should be able to suggest a fix and automatically fix. + +#![allow(dead_code)] + +mod foo { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait<T> {} + trait MyTrait<T> { + fn use_self<K>(&self) -> &(); + } + trait Irrelevant {} + + impl<T> MyTrait<T> for dyn ObjectTrait<T> { + fn use_self<K>(&self) -> &() { panic!() } + } + impl<T> Irrelevant for dyn ObjectTrait<T> {} + + fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a { + val.use_self::<T>() //~ ERROR borrowed data escapes + } +} + +mod bar { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { + val.use_self() + } +} + +mod baz { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for Box<dyn ObjectTrait> { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for Box<dyn ObjectTrait> {} + + fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () { + val.use_self() + } +} + +mod bat { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + + impl dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() + //~^ ERROR borrowed data escapes + } +} + +mod ban { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { + val.use_self() //~ ERROR borrowed data escapes + } +} + +mod bal { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait {} + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + MyTrait::use_self(val) //~ ERROR borrowed data escapes + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr new file mode 100644 index 000000000..679ebd61e --- /dev/null +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -0,0 +1,105 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:21:9 + | +LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self::<T>() + | ^^^^^^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:15:32 + | +LL | impl<T> MyTrait<T> for dyn ObjectTrait<T> { + | ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self<K>(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl<T> MyTrait<T> for dyn ObjectTrait<T> + '_ { + | ++++ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:70:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:65:14 + | +LL | impl dyn ObjectTrait { + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl dyn ObjectTrait + '_ { + | ++++ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:90:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:26 + | +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +... +LL | impl MyTrait for dyn ObjectTrait {} + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ++++ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:110:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | MyTrait::use_self(val) + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:106:26 + | +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +... +LL | impl MyTrait for dyn ObjectTrait {} + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs new file mode 100644 index 000000000..fe291e021 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs @@ -0,0 +1,21 @@ +// edition:2021 +// gate-test-anonymous_lifetime_in_impl_trait +// Verify the behaviour of `feature(anonymous_lifetime_in_impl_trait)`. + +fn f(_: impl Iterator<Item = &'_ ()>) {} +//~^ ERROR anonymous lifetimes in `impl Trait` are unstable + +fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } +//~^ ERROR anonymous lifetimes in `impl Trait` are unstable +//~| ERROR missing lifetime specifier + +// Anonymous lifetimes in async fn are already allowed. +// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`. +async fn h(_: impl Iterator<Item = &'_ ()>) {} + +// Anonymous lifetimes in async fn are already allowed. +// But that lifetime does not participate in resolution. +async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } +//~^ ERROR missing lifetime specifier + +fn main() {} diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr new file mode 100644 index 000000000..e82a6f769 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -0,0 +1,44 @@ +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime-gated.rs:8:50 + | +LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() } + | ~~~~~~~ + +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime-gated.rs:18:56 + | +LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() } + | ~~~~~~~ + +error[E0658]: anonymous lifetimes in `impl Trait` are unstable + --> $DIR/impl-trait-missing-lifetime-gated.rs:5:31 + | +LL | fn f(_: impl Iterator<Item = &'_ ()>) {} + | ^^ + | + = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable + +error[E0658]: anonymous lifetimes in `impl Trait` are unstable + --> $DIR/impl-trait-missing-lifetime-gated.rs:8:31 + | +LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } + | ^^ + | + = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0106, E0658. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime.rs b/src/test/ui/suggestions/impl-trait-missing-lifetime.rs new file mode 100644 index 000000000..6f7c912d7 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-missing-lifetime.rs @@ -0,0 +1,20 @@ +// edition:2021 + +#![feature(anonymous_lifetime_in_impl_trait)] + +// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`. +fn f(_: impl Iterator<Item = &'_ ()>) {} + +// But that lifetime does not participate in resolution. +fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } +//~^ ERROR missing lifetime specifier + +// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`. +async fn h(_: impl Iterator<Item = &'_ ()>) {} + +// But that lifetime does not participate in resolution. +async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } +//~^ ERROR missing lifetime specifier +//~| ERROR lifetime may not live long enough + +fn main() {} diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime.stderr b/src/test/ui/suggestions/impl-trait-missing-lifetime.stderr new file mode 100644 index 000000000..b476d6101 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-missing-lifetime.stderr @@ -0,0 +1,35 @@ +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime.rs:9:54 + | +LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() } + | ~~~~~~~ + +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime.rs:16:60 + | +LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() } + | ~~~~~~~ + +error: lifetime may not live long enough + --> $DIR/impl-trait-missing-lifetime.rs:16:69 + | +LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } + | -------------- ^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | | + | return type `impl Future<Output = Option<&'static ()>>` contains a lifetime `'1` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs new file mode 100644 index 000000000..cd3741356 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.rs @@ -0,0 +1,21 @@ +trait Bar {} + +impl Bar for i32 {} + +struct Qux; + +impl Bar for Qux {} + +fn foo() -> impl Bar { + //~^ ERROR the trait bound `(): Bar` is not satisfied + 5; + //~^ HELP remove this semicolon +} + +fn bar() -> impl Bar { + //~^ ERROR the trait bound `(): Bar` is not satisfied + //~| HELP the following other types implement trait `Bar`: + ""; +} + +fn main() {} diff --git a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr new file mode 100644 index 000000000..e74c2c421 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/impl-trait-return-trailing-semicolon.rs:9:13 + | +LL | fn foo() -> impl Bar { + | ^^^^^^^^ the trait `Bar` is not implemented for `()` +LL | +LL | 5; + | -- help: remove this semicolon + | | + | this expression has type `{integer}`, which implements `Bar` + +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/impl-trait-return-trailing-semicolon.rs:15:13 + | +LL | fn bar() -> impl Bar { + | ^^^^^^^^ the trait `Bar` is not implemented for `()` + | + = help: the following other types implement trait `Bar`: + Qux + i32 + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/impl-trait-with-missing-bounds.rs b/src/test/ui/suggestions/impl-trait-with-missing-bounds.rs new file mode 100644 index 000000000..949b23600 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-bounds.rs @@ -0,0 +1,52 @@ +// The double space in `impl Iterator` is load bearing! We want to make sure we don't regress by +// accident if the internal string representation changes. +#[rustfmt::skip] +fn foo(constraints: impl Iterator) { + for constraint in constraints { + qux(constraint); +//~^ ERROR `<impl Iterator as Iterator>::Item` doesn't implement `Debug` + } +} + +fn bar<T>(t: T, constraints: impl Iterator) where T: std::fmt::Debug { + for constraint in constraints { + qux(t); + qux(constraint); +//~^ ERROR `<impl Iterator as Iterator>::Item` doesn't implement `Debug` + } +} + +fn baz(t: impl std::fmt::Debug, constraints: impl Iterator) { + for constraint in constraints { + qux(t); + qux(constraint); +//~^ ERROR `<impl Iterator as Iterator>::Item` doesn't implement `Debug` + } +} + +fn bat<I, T: std::fmt::Debug>(t: T, constraints: impl Iterator, _: I) { + for constraint in constraints { + qux(t); + qux(constraint); +//~^ ERROR `<impl Iterator as Iterator>::Item` doesn't implement `Debug` + } +} + +fn bak(constraints: impl Iterator + std::fmt::Debug) { + for constraint in constraints { + qux(constraint); +//~^ ERROR `<impl Iterator + std::fmt::Debug as Iterator>::Item` doesn't implement + } +} + +#[rustfmt::skip] +fn baw<>(constraints: impl Iterator) { + for constraint in constraints { + qux(constraint); +//~^ ERROR `<impl Iterator as Iterator>::Item` doesn't implement `Debug` + } +} + +fn qux(_: impl std::fmt::Debug) {} + +fn main() {} diff --git a/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr b/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr new file mode 100644 index 000000000..a763eb6f2 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr @@ -0,0 +1,117 @@ +error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug` + --> $DIR/impl-trait-with-missing-bounds.rs:6:13 + | +LL | qux(constraint); + | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call + | + = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item` +note: required by a bound in `qux` + --> $DIR/impl-trait-with-missing-bounds.rs:50:16 + | +LL | fn qux(_: impl std::fmt::Debug) {} + | ^^^^^^^^^^^^^^^ required by this bound in `qux` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | fn foo<I: Iterator>(constraints: I) where <I as Iterator>::Item: Debug { + | +++++++++++++ ~ ++++++++++++++++++++++++++++++++++ + +error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug` + --> $DIR/impl-trait-with-missing-bounds.rs:14:13 + | +LL | qux(constraint); + | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call + | + = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item` +note: required by a bound in `qux` + --> $DIR/impl-trait-with-missing-bounds.rs:50:16 + | +LL | fn qux(_: impl std::fmt::Debug) {} + | ^^^^^^^^^^^^^^^ required by this bound in `qux` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | fn bar<T, I: Iterator>(t: T, constraints: I) where T: std::fmt::Debug, <I as Iterator>::Item: Debug { + | +++++++++++++ ~ ++++++++++++++++++++++++++++++ + +error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug` + --> $DIR/impl-trait-with-missing-bounds.rs:22:13 + | +LL | qux(constraint); + | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call + | + = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item` +note: required by a bound in `qux` + --> $DIR/impl-trait-with-missing-bounds.rs:50:16 + | +LL | fn qux(_: impl std::fmt::Debug) {} + | ^^^^^^^^^^^^^^^ required by this bound in `qux` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | fn baz<I: Iterator>(t: impl std::fmt::Debug, constraints: I) where <I as Iterator>::Item: Debug { + | +++++++++++++ ~ ++++++++++++++++++++++++++++++++++ + +error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug` + --> $DIR/impl-trait-with-missing-bounds.rs:30:13 + | +LL | qux(constraint); + | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call + | + = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item` +note: required by a bound in `qux` + --> $DIR/impl-trait-with-missing-bounds.rs:50:16 + | +LL | fn qux(_: impl std::fmt::Debug) {} + | ^^^^^^^^^^^^^^^ required by this bound in `qux` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | fn bat<I, T: std::fmt::Debug, U: Iterator>(t: T, constraints: U, _: I) where <U as Iterator>::Item: Debug { + | +++++++++++++ ~ ++++++++++++++++++++++++++++++++++ + +error[E0277]: `<impl Iterator + std::fmt::Debug as Iterator>::Item` doesn't implement `Debug` + --> $DIR/impl-trait-with-missing-bounds.rs:37:13 + | +LL | qux(constraint); + | --- ^^^^^^^^^^ `<impl Iterator + std::fmt::Debug as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call + | + = help: the trait `Debug` is not implemented for `<impl Iterator + std::fmt::Debug as Iterator>::Item` +note: required by a bound in `qux` + --> $DIR/impl-trait-with-missing-bounds.rs:50:16 + | +LL | fn qux(_: impl std::fmt::Debug) {} + | ^^^^^^^^^^^^^^^ required by this bound in `qux` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | fn bak<I: Iterator + std::fmt::Debug>(constraints: I) where <I as Iterator>::Item: Debug { + | +++++++++++++++++++++++++++++++ ~ ++++++++++++++++++++++++++++++++++ + +error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug` + --> $DIR/impl-trait-with-missing-bounds.rs:45:13 + | +LL | qux(constraint); + | --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call + | + = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item` +note: required by a bound in `qux` + --> $DIR/impl-trait-with-missing-bounds.rs:50:16 + | +LL | fn qux(_: impl std::fmt::Debug) {} + | ^^^^^^^^^^^^^^^ required by this bound in `qux` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | fn baw<I: Iterator>(constraints: I) where <I as Iterator>::Item: Debug { + | ~~~~~~~~~~~~~ ~ ++++++++++++++++++++++++++++++++++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed new file mode 100644 index 000000000..5109511f9 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +trait Foo {} + +trait Bar { + fn hello(&self) {} +} + +struct S; + +impl Foo for S {} +impl Bar for S {} + +fn test(foo: impl Foo + Bar) { + foo.hello(); //~ ERROR E0599 +} + +fn main() { + test(S); +} diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs new file mode 100644 index 000000000..cd05b7738 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs @@ -0,0 +1,20 @@ +// run-rustfix + +trait Foo {} + +trait Bar { + fn hello(&self) {} +} + +struct S; + +impl Foo for S {} +impl Bar for S {} + +fn test(foo: impl Foo) { + foo.hello(); //~ ERROR E0599 +} + +fn main() { + test(S); +} diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr new file mode 100644 index 000000000..20f8e65f7 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr @@ -0,0 +1,17 @@ +error[E0599]: no method named `hello` found for type parameter `impl Foo` in the current scope + --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:15:9 + | +LL | fn test(foo: impl Foo) { + | -------- method `hello` not found for this type parameter +LL | foo.hello(); + | ^^^^^ method not found in `impl Foo` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `hello`, perhaps you need to restrict type parameter `impl Foo` with it: + | +LL | fn test(foo: impl Foo + Bar) { + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/import-trait-for-method-call.rs b/src/test/ui/suggestions/import-trait-for-method-call.rs new file mode 100644 index 000000000..4dbadbdf9 --- /dev/null +++ b/src/test/ui/suggestions/import-trait-for-method-call.rs @@ -0,0 +1,16 @@ +use std::hash::BuildHasher; + +fn next_u64() -> u64 { + let bh = std::collections::hash_map::RandomState::new(); + let h = bh.build_hasher(); + h.finish() //~ ERROR no method named `finish` found for struct `DefaultHasher` +} + +trait Bar {} +impl Bar for String {} + +fn main() { + let s = String::from("hey"); + let x: &dyn Bar = &s; + x.as_ref(); //~ ERROR the method `as_ref` exists for reference `&dyn Bar`, but its trait bounds +} diff --git a/src/test/ui/suggestions/import-trait-for-method-call.stderr b/src/test/ui/suggestions/import-trait-for-method-call.stderr new file mode 100644 index 000000000..bac8de798 --- /dev/null +++ b/src/test/ui/suggestions/import-trait-for-method-call.stderr @@ -0,0 +1,36 @@ +error[E0599]: no method named `finish` found for struct `DefaultHasher` in the current scope + --> $DIR/import-trait-for-method-call.rs:6:7 + | +LL | h.finish() + | ^^^^^^ method not found in `DefaultHasher` + | + ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL + | +LL | fn finish(&self) -> u64; + | ------ the method is available for `DefaultHasher` here + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::hash::Hasher; + | + +error[E0599]: the method `as_ref` exists for reference `&dyn Bar`, but its trait bounds were not satisfied + --> $DIR/import-trait-for-method-call.rs:15:7 + | +LL | trait Bar {} + | --------- doesn't satisfy `dyn Bar: AsRef<_>` +... +LL | x.as_ref(); + | ^^^^^^ method cannot be called on `&dyn Bar` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `dyn Bar: AsRef<_>` + which is required by `&dyn Bar: AsRef<_>` + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `as_ref`, perhaps you need to implement it: + candidate #1: `AsRef` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/into-str.rs b/src/test/ui/suggestions/into-str.rs new file mode 100644 index 000000000..606e44b2e --- /dev/null +++ b/src/test/ui/suggestions/into-str.rs @@ -0,0 +1,6 @@ +fn foo<'a, T>(_t: T) where T: Into<&'a str> {} + +fn main() { + foo(String::new()); + //~^ ERROR the trait bound `&str: From<String>` is not satisfied +} diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr new file mode 100644 index 000000000..8ae5c8479 --- /dev/null +++ b/src/test/ui/suggestions/into-str.stderr @@ -0,0 +1,26 @@ +error[E0277]: the trait bound `&str: From<String>` is not satisfied + --> $DIR/into-str.rs:4:9 + | +LL | foo(String::new()); + | --- ^^^^^^^^^^^^^ the trait `From<String>` is not implemented for `&str` + | | + | required by a bound introduced by this call + | + = note: to coerce a `String` into a `&str`, use `&*` as a prefix + = help: the following other types implement trait `From<T>`: + <String as From<&String>> + <String as From<&mut str>> + <String as From<&str>> + <String as From<Box<str>>> + <String as From<Cow<'a, str>>> + <String as From<char>> + = note: required because of the requirements on the impl of `Into<&str>` for `String` +note: required by a bound in `foo` + --> $DIR/into-str.rs:1:31 + | +LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {} + | ^^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/invalid-bin-op.rs b/src/test/ui/suggestions/invalid-bin-op.rs new file mode 100644 index 000000000..bea1b9155 --- /dev/null +++ b/src/test/ui/suggestions/invalid-bin-op.rs @@ -0,0 +1,7 @@ +pub fn foo<T>(s: S<T>, t: S<T>) { + let _ = s == t; //~ ERROR binary operation `==` cannot be applied to type `S<T>` +} + +struct S<T>(T); + +fn main() {} diff --git a/src/test/ui/suggestions/invalid-bin-op.stderr b/src/test/ui/suggestions/invalid-bin-op.stderr new file mode 100644 index 000000000..08502dfeb --- /dev/null +++ b/src/test/ui/suggestions/invalid-bin-op.stderr @@ -0,0 +1,25 @@ +error[E0369]: binary operation `==` cannot be applied to type `S<T>` + --> $DIR/invalid-bin-op.rs:2:15 + | +LL | let _ = s == t; + | - ^^ - S<T> + | | + | S<T> + | +note: an implementation of `PartialEq<_>` might be missing for `S<T>` + --> $DIR/invalid-bin-op.rs:5:1 + | +LL | struct S<T>(T); + | ^^^^^^^^^^^ must implement `PartialEq<_>` +help: consider annotating `S<T>` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | pub fn foo<T>(s: S<T>, t: S<T>) where S<T>: PartialEq { + | +++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/suggestions/issue-21673.rs b/src/test/ui/suggestions/issue-21673.rs new file mode 100644 index 000000000..9d66cae05 --- /dev/null +++ b/src/test/ui/suggestions/issue-21673.rs @@ -0,0 +1,13 @@ +trait Foo { + fn method(&self) {} +} + +fn call_method<T: std::fmt::Debug>(x: &T) { + x.method() //~ ERROR E0599 +} + +fn call_method_2<T>(x: T) { + x.method() //~ ERROR E0599 +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-21673.stderr b/src/test/ui/suggestions/issue-21673.stderr new file mode 100644 index 000000000..523d7a7cc --- /dev/null +++ b/src/test/ui/suggestions/issue-21673.stderr @@ -0,0 +1,29 @@ +error[E0599]: no method named `method` found for reference `&T` in the current scope + --> $DIR/issue-21673.rs:6:7 + | +LL | x.method() + | ^^^^^^ method not found in `&T` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it: + | +LL | fn call_method<T: std::fmt::Debug + Foo>(x: &T) { + | +++++ + +error[E0599]: no method named `method` found for type parameter `T` in the current scope + --> $DIR/issue-21673.rs:10:7 + | +LL | fn call_method_2<T>(x: T) { + | - method `method` not found for this type parameter +LL | x.method() + | ^^^^^^ method not found in `T` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it: + | +LL | fn call_method_2<T: Foo>(x: T) { + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs new file mode 100644 index 000000000..37f078285 --- /dev/null +++ b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs @@ -0,0 +1,8 @@ +fn vindictive() -> bool { true } + +fn perfidy() -> (i32, i32) { + vindictive() //~ ERROR expected function, found `bool` + (1, 2) +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr new file mode 100644 index 000000000..438075083 --- /dev/null +++ b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr @@ -0,0 +1,16 @@ +error[E0618]: expected function, found `bool` + --> $DIR/issue-51055-missing-semicolon-between-call-and-tuple.rs:4:5 + | +LL | fn vindictive() -> bool { true } + | ----------------------- `vindictive` defined here returns `bool` +... +LL | vindictive() + | -^^^^^^^^^^^- help: consider using a semicolon here: `;` + | _____| + | | +LL | | (1, 2) + | |__________- call expression requires function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/src/test/ui/suggestions/issue-52820.fixed b/src/test/ui/suggestions/issue-52820.fixed new file mode 100644 index 000000000..514690de4 --- /dev/null +++ b/src/test/ui/suggestions/issue-52820.fixed @@ -0,0 +1,15 @@ +// run-rustfix +#![allow(dead_code)] + +struct Bravery { + guts: String, + brains: String, +} + +fn main() { + let guts = "mettle"; + let _ = Bravery { + guts: guts.to_string(), //~ ERROR mismatched types + brains: guts.to_string(), //~ ERROR mismatched types + }; +} diff --git a/src/test/ui/suggestions/issue-52820.rs b/src/test/ui/suggestions/issue-52820.rs new file mode 100644 index 000000000..17cd9224c --- /dev/null +++ b/src/test/ui/suggestions/issue-52820.rs @@ -0,0 +1,15 @@ +// run-rustfix +#![allow(dead_code)] + +struct Bravery { + guts: String, + brains: String, +} + +fn main() { + let guts = "mettle"; + let _ = Bravery { + guts, //~ ERROR mismatched types + brains: guts.clone(), //~ ERROR mismatched types + }; +} diff --git a/src/test/ui/suggestions/issue-52820.stderr b/src/test/ui/suggestions/issue-52820.stderr new file mode 100644 index 000000000..09269ed4e --- /dev/null +++ b/src/test/ui/suggestions/issue-52820.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/issue-52820.rs:12:9 + | +LL | guts, + | ^^^^ expected struct `String`, found `&str` + | +help: try using a conversion method + | +LL | guts: guts.to_string(), + | +++++ ++++++++++++ + +error[E0308]: mismatched types + --> $DIR/issue-52820.rs:13:17 + | +LL | brains: guts.clone(), + | ^^^^^-----^^ + | | | + | | help: try using a conversion method: `to_string` + | expected struct `String`, found `&str` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-53692.fixed b/src/test/ui/suggestions/issue-53692.fixed new file mode 100644 index 000000000..35a677b47 --- /dev/null +++ b/src/test/ui/suggestions/issue-53692.fixed @@ -0,0 +1,20 @@ +// run-rustfix +#![allow(unused_variables)] + +fn main() { + let items = vec![1, 2, 3]; + let ref_items: &[i32] = &items; + let items_clone: Vec<i32> = ref_items.to_vec(); + //~^ ERROR mismatched types + + // in that case no suggestion will be triggered + let items_clone_2: Vec<i32> = items.clone(); + + let s = "hi"; + let string: String = s.to_string(); + //~^ ERROR mismatched types + + // in that case no suggestion will be triggered + let s2 = "hi"; + let string_2: String = s2.to_string(); +} diff --git a/src/test/ui/suggestions/issue-53692.rs b/src/test/ui/suggestions/issue-53692.rs new file mode 100644 index 000000000..6f6707be5 --- /dev/null +++ b/src/test/ui/suggestions/issue-53692.rs @@ -0,0 +1,20 @@ +// run-rustfix +#![allow(unused_variables)] + +fn main() { + let items = vec![1, 2, 3]; + let ref_items: &[i32] = &items; + let items_clone: Vec<i32> = ref_items.clone(); + //~^ ERROR mismatched types + + // in that case no suggestion will be triggered + let items_clone_2: Vec<i32> = items.clone(); + + let s = "hi"; + let string: String = s.clone(); + //~^ ERROR mismatched types + + // in that case no suggestion will be triggered + let s2 = "hi"; + let string_2: String = s2.to_string(); +} diff --git a/src/test/ui/suggestions/issue-53692.stderr b/src/test/ui/suggestions/issue-53692.stderr new file mode 100644 index 000000000..3a1b624f4 --- /dev/null +++ b/src/test/ui/suggestions/issue-53692.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/issue-53692.rs:7:33 + | +LL | let items_clone: Vec<i32> = ref_items.clone(); + | -------- ^^^^^^^^^^-----^^ + | | | | + | | | help: try using a conversion method: `to_vec` + | | expected struct `Vec`, found `&[i32]` + | expected due to this + | + = note: expected struct `Vec<i32>` + found reference `&[i32]` + +error[E0308]: mismatched types + --> $DIR/issue-53692.rs:14:26 + | +LL | let string: String = s.clone(); + | ------ ^^-----^^ + | | | | + | | | help: try using a conversion method: `to_string` + | | expected struct `String`, found `&str` + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-57672.rs b/src/test/ui/suggestions/issue-57672.rs new file mode 100644 index 000000000..ee999d83e --- /dev/null +++ b/src/test/ui/suggestions/issue-57672.rs @@ -0,0 +1,14 @@ +// aux-build:foo.rs +// compile-flags:--extern foo +// check-pass +// edition:2018 + +#![deny(unused_extern_crates)] + +extern crate foo as foo_renamed; + +pub mod m { + pub use foo_renamed::Foo; +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-59819.fixed b/src/test/ui/suggestions/issue-59819.fixed new file mode 100644 index 000000000..644d2a4e4 --- /dev/null +++ b/src/test/ui/suggestions/issue-59819.fixed @@ -0,0 +1,35 @@ +// run-rustfix + +#![allow(warnings)] + +// Test that suggestion to add `*` characters applies to implementations of `Deref` as well as +// references. + +struct Foo(i32); + +struct Bar(String); + +impl std::ops::Deref for Foo { + type Target = i32; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::ops::Deref for Bar { + type Target = String; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn main() { + let x = Foo(42); + let y: i32 = *x; //~ ERROR mismatched types + let a = &42; + let b: i32 = *a; //~ ERROR mismatched types + + // Do not make a suggestion when adding a `*` wouldn't actually fix the issue: + let f = Bar("bar".to_string()); + let g: String = f.to_string(); //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/issue-59819.rs b/src/test/ui/suggestions/issue-59819.rs new file mode 100644 index 000000000..8e8ff8372 --- /dev/null +++ b/src/test/ui/suggestions/issue-59819.rs @@ -0,0 +1,35 @@ +// run-rustfix + +#![allow(warnings)] + +// Test that suggestion to add `*` characters applies to implementations of `Deref` as well as +// references. + +struct Foo(i32); + +struct Bar(String); + +impl std::ops::Deref for Foo { + type Target = i32; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::ops::Deref for Bar { + type Target = String; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn main() { + let x = Foo(42); + let y: i32 = x; //~ ERROR mismatched types + let a = &42; + let b: i32 = a; //~ ERROR mismatched types + + // Do not make a suggestion when adding a `*` wouldn't actually fix the issue: + let f = Bar("bar".to_string()); + let g: String = f; //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/issue-59819.stderr b/src/test/ui/suggestions/issue-59819.stderr new file mode 100644 index 000000000..40e4c7b78 --- /dev/null +++ b/src/test/ui/suggestions/issue-59819.stderr @@ -0,0 +1,38 @@ +error[E0308]: mismatched types + --> $DIR/issue-59819.rs:28:18 + | +LL | let y: i32 = x; + | --- ^ expected `i32`, found struct `Foo` + | | + | expected due to this + | +help: consider dereferencing the type + | +LL | let y: i32 = *x; + | + + +error[E0308]: mismatched types + --> $DIR/issue-59819.rs:30:18 + | +LL | let b: i32 = a; + | --- ^ expected `i32`, found `&{integer}` + | | + | expected due to this + | +help: consider dereferencing the borrow + | +LL | let b: i32 = *a; + | + + +error[E0308]: mismatched types + --> $DIR/issue-59819.rs:34:21 + | +LL | let g: String = f; + | ------ ^- help: try using a conversion method: `.to_string()` + | | | + | | expected struct `String`, found struct `Bar` + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-61226.fixed b/src/test/ui/suggestions/issue-61226.fixed new file mode 100644 index 000000000..6e9d74344 --- /dev/null +++ b/src/test/ui/suggestions/issue-61226.fixed @@ -0,0 +1,6 @@ +// run-rustfix +struct X {} +fn main() { + let _ = vec![X {}]; //… + //~^ ERROR expected value, found struct `X` +} diff --git a/src/test/ui/suggestions/issue-61226.rs b/src/test/ui/suggestions/issue-61226.rs new file mode 100644 index 000000000..695fe7341 --- /dev/null +++ b/src/test/ui/suggestions/issue-61226.rs @@ -0,0 +1,6 @@ +// run-rustfix +struct X {} +fn main() { + let _ = vec![X]; //… + //~^ ERROR expected value, found struct `X` +} diff --git a/src/test/ui/suggestions/issue-61226.stderr b/src/test/ui/suggestions/issue-61226.stderr new file mode 100644 index 000000000..cda962a90 --- /dev/null +++ b/src/test/ui/suggestions/issue-61226.stderr @@ -0,0 +1,12 @@ +error[E0423]: expected value, found struct `X` + --> $DIR/issue-61226.rs:4:18 + | +LL | struct X {} + | ----------- `X` defined here +LL | fn main() { +LL | let _ = vec![X]; //… + | ^ help: use struct literal syntax instead: `X {}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/suggestions/issue-61963.rs b/src/test/ui/suggestions/issue-61963.rs new file mode 100644 index 000000000..a27c38452 --- /dev/null +++ b/src/test/ui/suggestions/issue-61963.rs @@ -0,0 +1,37 @@ +// aux-build:issue-61963.rs +// aux-build:issue-61963-1.rs +#![deny(bare_trait_objects)] + +#[macro_use] +extern crate issue_61963; +#[macro_use] +extern crate issue_61963_1; + +// This test checks that the bare trait object lint does not trigger on macro attributes that +// generate code which would trigger the lint. + +pub struct Baz; +pub trait Bar {} +pub struct Qux<T>(T); + +#[dom_struct] +pub struct Foo { + //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition + qux: Qux<Qux<Baz>>, + bar: Box<Bar>, + //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-61963.stderr b/src/test/ui/suggestions/issue-61963.stderr new file mode 100644 index 000000000..c0d776e59 --- /dev/null +++ b/src/test/ui/suggestions/issue-61963.stderr @@ -0,0 +1,105 @@ +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:28:14 + | +LL | bar: Box<Bar>, + | ^^^ + | +note: the lint level is defined here + --> $DIR/issue-61963.rs:3:9 + | +LL | #![deny(bare_trait_objects)] + | ^^^^^^^^^^^^^^^^^^ + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL - bar: Box<Bar>, +LL + bar: Box<dyn Bar>, + | + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:18:1 + | +LL | pub struct Foo { + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL - pub struct Foo { +LL + dyn pub struct Foo { + | + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:28:14 + | +LL | bar: Box<Bar>, + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL - bar: Box<Bar>, +LL + bar: Box<dyn Bar>, + | + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:28:14 + | +LL | bar: Box<Bar>, + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL - bar: Box<Bar>, +LL + bar: Box<dyn Bar>, + | + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:18:1 + | +LL | pub struct Foo { + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL - pub struct Foo { +LL + dyn pub struct Foo { + | + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:18:1 + | +LL | pub struct Foo { + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL - pub struct Foo { +LL + dyn pub struct Foo { + | + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:18:1 + | +LL | pub struct Foo { + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL - pub struct Foo { +LL + dyn pub struct Foo { + | + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/suggestions/issue-62843.rs b/src/test/ui/suggestions/issue-62843.rs new file mode 100644 index 000000000..d96b12fd1 --- /dev/null +++ b/src/test/ui/suggestions/issue-62843.rs @@ -0,0 +1,5 @@ +fn main() { + let line = String::from("abc"); + let pattern = String::from("bc"); + println!("{:?}", line.find(pattern)); //~ ERROR E0277 +} diff --git a/src/test/ui/suggestions/issue-62843.stderr b/src/test/ui/suggestions/issue-62843.stderr new file mode 100644 index 000000000..bc1c69406 --- /dev/null +++ b/src/test/ui/suggestions/issue-62843.stderr @@ -0,0 +1,23 @@ +error[E0277]: expected a `FnMut<(char,)>` closure, found `String` + --> $DIR/issue-62843.rs:4:32 + | +LL | println!("{:?}", line.find(pattern)); + | ---- ^^^^^^^ expected an implementor of trait `Pattern<'_>` + | | + | required by a bound introduced by this call + | + = note: the trait bound `String: Pattern<'_>` is not satisfied + = note: required because of the requirements on the impl of `Pattern<'_>` for `String` +note: required by a bound in `core::str::<impl str>::find` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL + | +LL | pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> { + | ^^^^^^^^^^^ required by this bound in `core::str::<impl str>::find` +help: consider borrowing here + | +LL | println!("{:?}", line.find(&pattern)); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-64252-self-type.rs b/src/test/ui/suggestions/issue-64252-self-type.rs new file mode 100644 index 000000000..128d5e85c --- /dev/null +++ b/src/test/ui/suggestions/issue-64252-self-type.rs @@ -0,0 +1,14 @@ +// This test checks that a suggestion to add a `self: ` parameter name is provided +// to functions where this is applicable. + +pub fn foo(Box<Self>) { } +//~^ ERROR expected one of `:`, `@`, or `|`, found `<` + +struct Bar; + +impl Bar { + fn bar(Box<Self>) { } + //~^ ERROR expected one of `:`, `@`, or `|`, found `<` +} + +fn main() { } diff --git a/src/test/ui/suggestions/issue-64252-self-type.stderr b/src/test/ui/suggestions/issue-64252-self-type.stderr new file mode 100644 index 000000000..c3418dab0 --- /dev/null +++ b/src/test/ui/suggestions/issue-64252-self-type.stderr @@ -0,0 +1,34 @@ +error: expected one of `:`, `@`, or `|`, found `<` + --> $DIR/issue-64252-self-type.rs:4:15 + | +LL | pub fn foo(Box<Self>) { } + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | pub fn foo(self: Box<Self>) { } + | +++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | pub fn foo(_: Box<Self>) { } + | ++ + +error: expected one of `:`, `@`, or `|`, found `<` + --> $DIR/issue-64252-self-type.rs:10:15 + | +LL | fn bar(Box<Self>) { } + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn bar(self: Box<Self>) { } + | +++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn bar(_: Box<Self>) { } + | ++ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/suggestions/issue-66968-suggest-sorted-words.rs b/src/test/ui/suggestions/issue-66968-suggest-sorted-words.rs new file mode 100644 index 000000000..440bb653a --- /dev/null +++ b/src/test/ui/suggestions/issue-66968-suggest-sorted-words.rs @@ -0,0 +1,4 @@ +fn main() { + let a_longer_variable_name = 1; + println!("{}", a_variable_longer_name); //~ ERROR E0425 +} diff --git a/src/test/ui/suggestions/issue-66968-suggest-sorted-words.stderr b/src/test/ui/suggestions/issue-66968-suggest-sorted-words.stderr new file mode 100644 index 000000000..d7b33ea41 --- /dev/null +++ b/src/test/ui/suggestions/issue-66968-suggest-sorted-words.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `a_variable_longer_name` in this scope + --> $DIR/issue-66968-suggest-sorted-words.rs:3:20 + | +LL | println!("{}", a_variable_longer_name); + | ^^^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `a_longer_variable_name` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/suggestions/issue-68049-1.rs b/src/test/ui/suggestions/issue-68049-1.rs new file mode 100644 index 000000000..0acb7b1bf --- /dev/null +++ b/src/test/ui/suggestions/issue-68049-1.rs @@ -0,0 +1,16 @@ +use std::alloc::{GlobalAlloc, Layout}; + +struct Test(u32); + +unsafe impl GlobalAlloc for Test { + unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { + self.0 += 1; //~ ERROR cannot assign + 0 as *mut u8 + } + + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) { + unimplemented!(); + } +} + +fn main() { } diff --git a/src/test/ui/suggestions/issue-68049-1.stderr b/src/test/ui/suggestions/issue-68049-1.stderr new file mode 100644 index 000000000..7f931f0cd --- /dev/null +++ b/src/test/ui/suggestions/issue-68049-1.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to `self.0`, which is behind a `&` reference + --> $DIR/issue-68049-1.rs:7:9 + | +LL | self.0 += 1; + | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/suggestions/issue-68049-2.rs b/src/test/ui/suggestions/issue-68049-2.rs new file mode 100644 index 000000000..1c3430c14 --- /dev/null +++ b/src/test/ui/suggestions/issue-68049-2.rs @@ -0,0 +1,21 @@ +trait Hello { + fn example(&self, input: &i32); // should suggest here +} + +struct Test1(i32); + +impl Hello for Test1 { + fn example(&self, input: &i32) { // should not suggest here + *input = self.0; //~ ERROR cannot assign + } +} + +struct Test2(i32); + +impl Hello for Test2 { + fn example(&self, input: &i32) { // should not suggest here + self.0 += *input; //~ ERROR cannot assign + } +} + +fn main() { } diff --git a/src/test/ui/suggestions/issue-68049-2.stderr b/src/test/ui/suggestions/issue-68049-2.stderr new file mode 100644 index 000000000..2f31193e4 --- /dev/null +++ b/src/test/ui/suggestions/issue-68049-2.stderr @@ -0,0 +1,21 @@ +error[E0594]: cannot assign to `*input`, which is behind a `&` reference + --> $DIR/issue-68049-2.rs:9:7 + | +LL | fn example(&self, input: &i32); // should suggest here + | ---- help: consider changing that to be a mutable reference: `&mut i32` +... +LL | *input = self.0; + | ^^^^^^^^^^^^^^^ `input` is a `&` reference, so the data it refers to cannot be written + +error[E0594]: cannot assign to `self.0`, which is behind a `&` reference + --> $DIR/issue-68049-2.rs:17:5 + | +LL | fn example(&self, input: &i32); // should suggest here + | ----- help: consider changing that to be a mutable reference: `&mut self` +... +LL | self.0 += *input; + | ^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/suggestions/issue-71394-no-from-impl.rs b/src/test/ui/suggestions/issue-71394-no-from-impl.rs new file mode 100644 index 000000000..0c35deb51 --- /dev/null +++ b/src/test/ui/suggestions/issue-71394-no-from-impl.rs @@ -0,0 +1,5 @@ +fn main() { + let data: &[u8] = &[0; 10]; + let _: &[i8] = data.into(); + //~^ ERROR the trait bound `&[i8]: From<&[u8]>` is not satisfied +} diff --git a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr new file mode 100644 index 000000000..383f40d47 --- /dev/null +++ b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied + --> $DIR/issue-71394-no-from-impl.rs:3:25 + | +LL | let _: &[i8] = data.into(); + | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]` + | + = help: the following other types implement trait `From<T>`: + <[T; LANES] as From<Simd<T, LANES>>> + <[bool; LANES] as From<Mask<T, LANES>>> + = note: required because of the requirements on the impl of `Into<&[i8]>` for `&[u8]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-72766.rs b/src/test/ui/suggestions/issue-72766.rs new file mode 100644 index 000000000..c54be7f5d --- /dev/null +++ b/src/test/ui/suggestions/issue-72766.rs @@ -0,0 +1,20 @@ +// edition:2018 +// incremental + +pub struct SadGirl; + +impl SadGirl { + pub async fn call(&self) -> Result<(), ()> { + Ok(()) + } +} + +async fn async_main() -> Result<(), ()> { + // should be `.call().await?` + SadGirl {}.call()?; //~ ERROR: the `?` operator can only be applied to values + Ok(()) +} + +fn main() { + let _ = async_main(); +} diff --git a/src/test/ui/suggestions/issue-72766.stderr b/src/test/ui/suggestions/issue-72766.stderr new file mode 100644 index 000000000..f257bb9b0 --- /dev/null +++ b/src/test/ui/suggestions/issue-72766.stderr @@ -0,0 +1,15 @@ +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/issue-72766.rs:14:5 + | +LL | SadGirl {}.call()?; + | ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future<Output = Result<(), ()>>` + | + = help: the trait `Try` is not implemented for `impl Future<Output = Result<(), ()>>` +help: consider `await`ing on the `Future` + | +LL | SadGirl {}.call().await?; + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs b/src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs new file mode 100644 index 000000000..3cd6d336e --- /dev/null +++ b/src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs @@ -0,0 +1,32 @@ +// Regression test: if we suggest replacing an `impl Trait` argument to an async +// fn with a named type parameter in order to add bounds, the suggested function +// signature should be well-formed. +// +// edition:2018 + +trait Foo { + type Bar; + fn bar(&self) -> Self::Bar; +} + +async fn run(_: &(), foo: impl Foo) -> std::io::Result<()> { + let bar = foo.bar(); + assert_is_send(&bar); +//~^ ERROR: `<impl Foo as Foo>::Bar` cannot be sent between threads safely + + Ok(()) +} + +// Test our handling of cases where there is a generic parameter list in the +// source, but only synthetic generic parameters +async fn run2< >(_: &(), foo: impl Foo) -> std::io::Result<()> { + let bar = foo.bar(); + assert_is_send(&bar); +//~^ ERROR: `<impl Foo as Foo>::Bar` cannot be sent between threads safely + + Ok(()) +} + +fn assert_is_send<T: Send>(_: &T) {} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr b/src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr new file mode 100644 index 000000000..a3ab0b8ef --- /dev/null +++ b/src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr @@ -0,0 +1,41 @@ +error[E0277]: `<impl Foo as Foo>::Bar` cannot be sent between threads safely + --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:14:20 + | +LL | assert_is_send(&bar); + | -------------- ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `<impl Foo as Foo>::Bar` +note: required by a bound in `assert_is_send` + --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:30:22 + | +LL | fn assert_is_send<T: Send>(_: &T) {} + | ^^^^ required by this bound in `assert_is_send` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | async fn run<F: Foo>(_: &(), foo: F) -> std::io::Result<()> where <F as Foo>::Bar: Send { + | ++++++++ ~ +++++++++++++++++++++++++++ + +error[E0277]: `<impl Foo as Foo>::Bar` cannot be sent between threads safely + --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:24:20 + | +LL | assert_is_send(&bar); + | -------------- ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `<impl Foo as Foo>::Bar` +note: required by a bound in `assert_is_send` + --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:30:22 + | +LL | fn assert_is_send<T: Send>(_: &T) {} + | ^^^^ required by this bound in `assert_is_send` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | async fn run2<F: Foo>(_: &(), foo: F) -> std::io::Result<()> where <F as Foo>::Bar: Send { + | ~~~~~~~~ ~ +++++++++++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-81098.rs b/src/test/ui/suggestions/issue-81098.rs new file mode 100644 index 000000000..a601b5866 --- /dev/null +++ b/src/test/ui/suggestions/issue-81098.rs @@ -0,0 +1,13 @@ +// Don't suggest removing a semicolon if the last statement isn't an expression with semicolon +// (#81098) +fn wat() -> impl core::fmt::Display { //~ ERROR: `()` doesn't implement `std::fmt::Display` + fn why() {} +} + +// Do it if the last statement is an expression with semicolon +// (#54771) +fn ok() -> impl core::fmt::Display { //~ ERROR: `()` doesn't implement `std::fmt::Display` + 1; +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-81098.stderr b/src/test/ui/suggestions/issue-81098.stderr new file mode 100644 index 000000000..4dc47a202 --- /dev/null +++ b/src/test/ui/suggestions/issue-81098.stderr @@ -0,0 +1,25 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/issue-81098.rs:3:13 + | +LL | fn wat() -> impl core::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/issue-81098.rs:9:12 + | +LL | fn ok() -> impl core::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter +LL | 1; + | -- help: remove this semicolon + | | + | this expression has type `{integer}`, which implements `std::fmt::Display` + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-81839.rs b/src/test/ui/suggestions/issue-81839.rs new file mode 100644 index 000000000..0b9b7aefe --- /dev/null +++ b/src/test/ui/suggestions/issue-81839.rs @@ -0,0 +1,17 @@ +// aux-build:issue-81839.rs +// edition:2018 + +extern crate issue_81839; + +async fn test(ans: &str, num: i32, cx: &issue_81839::Test) -> u32 { + match num { + 1 => { + cx.answer_str("hi"); + } + _ => cx.answer_str("hi"), //~ `match` arms have incompatible types + } + + 1 +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-81839.stderr b/src/test/ui/suggestions/issue-81839.stderr new file mode 100644 index 000000000..fae474ced --- /dev/null +++ b/src/test/ui/suggestions/issue-81839.stderr @@ -0,0 +1,27 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/issue-81839.rs:11:14 + | +LL | / match num { +LL | | 1 => { +LL | | cx.answer_str("hi"); + | | -------------------- + | | | | + | | | help: consider removing this semicolon + | | this is found to be of type `()` +LL | | } +LL | | _ => cx.answer_str("hi"), + | | ^^^^^^^^^^^^^^^^^^^ expected `()`, found opaque type +LL | | } + | |_____- `match` arms have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/auxiliary/issue-81839.rs:6:49 + | +LL | pub async fn answer_str(&self, _s: &str) -> Test { + | ^^^^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future<Output = Test>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-82361.fixed b/src/test/ui/suggestions/issue-82361.fixed new file mode 100644 index 000000000..d72de982b --- /dev/null +++ b/src/test/ui/suggestions/issue-82361.fixed @@ -0,0 +1,24 @@ +// run-rustfix + +fn main() { + let a: usize = 123; + let b: &usize = &a; + + if true { + a + } else { + *b //~ ERROR `if` and `else` have incompatible types [E0308] + }; + + if true { + 1 + } else { + 1 //~ ERROR `if` and `else` have incompatible types [E0308] + }; + + if true { + 1 + } else { + 1 //~ ERROR `if` and `else` have incompatible types [E0308] + }; +} diff --git a/src/test/ui/suggestions/issue-82361.rs b/src/test/ui/suggestions/issue-82361.rs new file mode 100644 index 000000000..c068f6d22 --- /dev/null +++ b/src/test/ui/suggestions/issue-82361.rs @@ -0,0 +1,24 @@ +// run-rustfix + +fn main() { + let a: usize = 123; + let b: &usize = &a; + + if true { + a + } else { + b //~ ERROR `if` and `else` have incompatible types [E0308] + }; + + if true { + 1 + } else { + &1 //~ ERROR `if` and `else` have incompatible types [E0308] + }; + + if true { + 1 + } else { + &mut 1 //~ ERROR `if` and `else` have incompatible types [E0308] + }; +} diff --git a/src/test/ui/suggestions/issue-82361.stderr b/src/test/ui/suggestions/issue-82361.stderr new file mode 100644 index 000000000..e4e8ad15d --- /dev/null +++ b/src/test/ui/suggestions/issue-82361.stderr @@ -0,0 +1,56 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-82361.rs:10:9 + | +LL | / if true { +LL | | a + | | - expected because of this +LL | | } else { +LL | | b + | | ^ expected `usize`, found `&usize` +LL | | }; + | |_____- `if` and `else` have incompatible types + | +help: consider dereferencing the borrow + | +LL | *b + | + + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-82361.rs:16:9 + | +LL | / if true { +LL | | 1 + | | - expected because of this +LL | | } else { +LL | | &1 + | | ^^ expected integer, found `&{integer}` +LL | | }; + | |_____- `if` and `else` have incompatible types + | +help: consider removing the borrow + | +LL - &1 +LL + 1 + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-82361.rs:22:9 + | +LL | / if true { +LL | | 1 + | | - expected because of this +LL | | } else { +LL | | &mut 1 + | | ^^^^^^ expected integer, found `&mut {integer}` +LL | | }; + | |_____- `if` and `else` have incompatible types + | +help: consider removing the borrow + | +LL - &mut 1 +LL + 1 + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-82566-1.rs b/src/test/ui/suggestions/issue-82566-1.rs new file mode 100644 index 000000000..95c31fbaa --- /dev/null +++ b/src/test/ui/suggestions/issue-82566-1.rs @@ -0,0 +1,21 @@ +struct T1<const X1: usize>; +struct T2<const X1: usize, const X2: usize>; +struct T3<const X1: usize, const X2: usize, const X3: usize>; + +impl T1<1> { + const C: () = (); +} + +impl T2<1, 2> { + const C: () = (); +} + +impl T3<1, 2, 3> { + const C: () = (); +} + +fn main() { + T1<1>::C; //~ ERROR: comparison operators cannot be chained + T2<1, 2>::C; //~ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + T3<1, 2, 3>::C; //~ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` +} diff --git a/src/test/ui/suggestions/issue-82566-1.stderr b/src/test/ui/suggestions/issue-82566-1.stderr new file mode 100644 index 000000000..72f0f45fb --- /dev/null +++ b/src/test/ui/suggestions/issue-82566-1.stderr @@ -0,0 +1,35 @@ +error: comparison operators cannot be chained + --> $DIR/issue-82566-1.rs:18:7 + | +LL | T1<1>::C; + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | T1::<1>::C; + | ++ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + --> $DIR/issue-82566-1.rs:19:9 + | +LL | T2<1, 2>::C; + | ^ expected one of `.`, `;`, `?`, `}`, or an operator + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | T2::<1, 2>::C; + | ++ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + --> $DIR/issue-82566-1.rs:20:9 + | +LL | T3<1, 2, 3>::C; + | ^ expected one of `.`, `;`, `?`, `}`, or an operator + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | T3::<1, 2, 3>::C; + | ++ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/suggestions/issue-82566-2.rs b/src/test/ui/suggestions/issue-82566-2.rs new file mode 100644 index 000000000..80c8034bd --- /dev/null +++ b/src/test/ui/suggestions/issue-82566-2.rs @@ -0,0 +1,31 @@ +struct Foo1<const N1: usize>; +struct Foo2<const N1: usize, const N2: usize>; +struct Foo3<const N1: usize, const N2: usize, const N3: usize>; + +impl<const N1: usize> Foo1<N1> { + const SUM: usize = N1; +} + +impl<const N1: usize, const N2: usize> Foo2<N1, N2> { + const SUM: usize = N1 + N2; +} + +impl<const N1: usize, const N2: usize, const N3: usize> Foo3<N1, N2, N3> { + const SUM: usize = N1 + N2 + N3; +} + +fn foo1() -> [(); Foo1<10>::SUM] { //~ ERROR: comparison operators cannot be chained + todo!() +} + +fn foo2() -> [(); Foo2<10, 20>::SUM] { + //~^ ERROR: expected one of `.`, `?`, `]`, or an operator, found `,` + todo!() +} + +fn foo3() -> [(); Foo3<10, 20, 30>::SUM] { + //~^ ERROR: expected one of `.`, `?`, `]`, or an operator, found `,` + todo!() +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-82566-2.stderr b/src/test/ui/suggestions/issue-82566-2.stderr new file mode 100644 index 000000000..ef9a41430 --- /dev/null +++ b/src/test/ui/suggestions/issue-82566-2.stderr @@ -0,0 +1,35 @@ +error: comparison operators cannot be chained + --> $DIR/issue-82566-2.rs:17:23 + | +LL | fn foo1() -> [(); Foo1<10>::SUM] { + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | fn foo1() -> [(); Foo1::<10>::SUM] { + | ++ + +error: expected one of `.`, `?`, `]`, or an operator, found `,` + --> $DIR/issue-82566-2.rs:21:26 + | +LL | fn foo2() -> [(); Foo2<10, 20>::SUM] { + | ^ expected one of `.`, `?`, `]`, or an operator + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | fn foo2() -> [(); Foo2::<10, 20>::SUM] { + | ++ + +error: expected one of `.`, `?`, `]`, or an operator, found `,` + --> $DIR/issue-82566-2.rs:26:26 + | +LL | fn foo3() -> [(); Foo3<10, 20, 30>::SUM] { + | ^ expected one of `.`, `?`, `]`, or an operator + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | fn foo3() -> [(); Foo3::<10, 20, 30>::SUM] { + | ++ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/suggestions/issue-83892.fixed b/src/test/ui/suggestions/issue-83892.fixed new file mode 100644 index 000000000..dd093a7a0 --- /dev/null +++ b/src/test/ui/suggestions/issue-83892.fixed @@ -0,0 +1,11 @@ +// run-rustfix + +fn func() -> u8 { + 0 +} + +fn main() { + match () { + () => func() //~ ERROR mismatched types + }; +} diff --git a/src/test/ui/suggestions/issue-83892.rs b/src/test/ui/suggestions/issue-83892.rs new file mode 100644 index 000000000..1d56ecee8 --- /dev/null +++ b/src/test/ui/suggestions/issue-83892.rs @@ -0,0 +1,11 @@ +// run-rustfix + +fn func() -> u8 { + 0 +} + +fn main() { + match () { + () => func() //~ ERROR mismatched types + } +} diff --git a/src/test/ui/suggestions/issue-83892.stderr b/src/test/ui/suggestions/issue-83892.stderr new file mode 100644 index 000000000..baf6b1447 --- /dev/null +++ b/src/test/ui/suggestions/issue-83892.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-83892.rs:9:15 + | +LL | fn main() { + | - expected `()` because of default return type +LL | match () { +LL | () => func() + | ^^^^^^ expected `()`, found `u8` +LL | } + | - help: consider using a semicolon here: `;` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-83943.fixed b/src/test/ui/suggestions/issue-83943.fixed new file mode 100644 index 000000000..e0d4ee29e --- /dev/null +++ b/src/test/ui/suggestions/issue-83943.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + if true { + "A".to_string() + } else { + "B".to_string() //~ ERROR `if` and `else` have incompatible types + }; +} diff --git a/src/test/ui/suggestions/issue-83943.rs b/src/test/ui/suggestions/issue-83943.rs new file mode 100644 index 000000000..68d50c177 --- /dev/null +++ b/src/test/ui/suggestions/issue-83943.rs @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + if true { + "A".to_string() + } else { + "B" //~ ERROR `if` and `else` have incompatible types + }; +} diff --git a/src/test/ui/suggestions/issue-83943.stderr b/src/test/ui/suggestions/issue-83943.stderr new file mode 100644 index 000000000..885106e84 --- /dev/null +++ b/src/test/ui/suggestions/issue-83943.stderr @@ -0,0 +1,17 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-83943.rs:7:9 + | +LL | / if true { +LL | | "A".to_string() + | | --------------- expected because of this +LL | | } else { +LL | | "B" + | | ^^^- help: try using a conversion method: `.to_string()` + | | | + | | expected struct `String`, found `&str` +LL | | }; + | |_____- `if` and `else` have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-84592.rs b/src/test/ui/suggestions/issue-84592.rs new file mode 100644 index 000000000..aa246aaa3 --- /dev/null +++ b/src/test/ui/suggestions/issue-84592.rs @@ -0,0 +1,17 @@ +/* Checks whether issue #84592 has been resolved. The issue was + * that in this example, there are two expected/missing lifetime + * parameters with *different spans*, leading to incorrect + * suggestions from rustc. + */ + +struct TwoLifetimes<'x, 'y> { + x: &'x (), + y: &'y (), +} + +fn two_lifetimes_needed(a: &(), b: &()) -> TwoLifetimes<'_, '_> { +//~^ ERROR missing lifetime specifiers [E0106] + TwoLifetimes { x: &(), y: &() } +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-84592.stderr b/src/test/ui/suggestions/issue-84592.stderr new file mode 100644 index 000000000..70c96feb1 --- /dev/null +++ b/src/test/ui/suggestions/issue-84592.stderr @@ -0,0 +1,17 @@ +error[E0106]: missing lifetime specifiers + --> $DIR/issue-84592.rs:12:57 + | +LL | fn two_lifetimes_needed(a: &(), b: &()) -> TwoLifetimes<'_, '_> { + | --- --- ^^ ^^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b` +help: consider introducing a named lifetime parameter + | +LL | fn two_lifetimes_needed<'a>(a: &'a (), b: &'a ()) -> TwoLifetimes<'a, 'a> { + | ++++ ++ ++ ~~ ~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/issue-84700.rs b/src/test/ui/suggestions/issue-84700.rs new file mode 100644 index 000000000..a27169fdb --- /dev/null +++ b/src/test/ui/suggestions/issue-84700.rs @@ -0,0 +1,26 @@ +// test for suggestion on fieldless enum variant + +#[derive(PartialEq, Debug)] +enum FarmAnimal { + Worm, + Cow, + Bull, + Chicken { num_eggs: usize }, + Dog (String), +} + +fn what_does_the_animal_say(animal: &FarmAnimal) { + + let noise = match animal { + FarmAnimal::Cow(_) => "moo".to_string(), + //~^ ERROR expected tuple struct or tuple variant, found unit variant `FarmAnimal::Cow` + FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(), + //~^ ERROR expected tuple struct or tuple variant, found struct variant `FarmAnimal::Chicken` + FarmAnimal::Dog{..} => "woof!".to_string(), + _ => todo!() + }; + + println!("{:?} says: {:?}", animal, noise); +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-84700.stderr b/src/test/ui/suggestions/issue-84700.stderr new file mode 100644 index 000000000..b36d8aba3 --- /dev/null +++ b/src/test/ui/suggestions/issue-84700.stderr @@ -0,0 +1,21 @@ +error[E0532]: expected tuple struct or tuple variant, found unit variant `FarmAnimal::Cow` + --> $DIR/issue-84700.rs:15:9 + | +LL | Cow, + | --- `FarmAnimal::Cow` defined here +... +LL | FarmAnimal::Cow(_) => "moo".to_string(), + | ^^^^^^^^^^^^^^^^^^ help: use this syntax instead: `FarmAnimal::Cow` + +error[E0532]: expected tuple struct or tuple variant, found struct variant `FarmAnimal::Chicken` + --> $DIR/issue-84700.rs:17:9 + | +LL | Chicken { num_eggs: usize }, + | --------------------------- `FarmAnimal::Chicken` defined here +... +LL | FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(), + | ^^^^^^^^^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `FarmAnimal::Chicken { num_eggs }` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0532`. diff --git a/src/test/ui/suggestions/issue-84973-2.rs b/src/test/ui/suggestions/issue-84973-2.rs new file mode 100644 index 000000000..050cf8c64 --- /dev/null +++ b/src/test/ui/suggestions/issue-84973-2.rs @@ -0,0 +1,13 @@ +// A slight variation of issue-84973.rs. Here, a mutable borrow is +// required (and the obligation kind is different). + +trait Tr {} +impl Tr for &mut i32 {} + +fn foo<T: Tr>(i: T) {} + +fn main() { + let a: i32 = 32; + foo(a); + //~^ ERROR: the trait bound `i32: Tr` is not satisfied [E0277] +} diff --git a/src/test/ui/suggestions/issue-84973-2.stderr b/src/test/ui/suggestions/issue-84973-2.stderr new file mode 100644 index 000000000..2c54ea672 --- /dev/null +++ b/src/test/ui/suggestions/issue-84973-2.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `i32: Tr` is not satisfied + --> $DIR/issue-84973-2.rs:11:9 + | +LL | foo(a); + | --- ^ expected an implementor of trait `Tr` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/issue-84973-2.rs:7:11 + | +LL | fn foo<T: Tr>(i: T) {} + | ^^ required by this bound in `foo` +help: consider mutably borrowing here + | +LL | foo(&mut a); + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-84973-blacklist.rs b/src/test/ui/suggestions/issue-84973-blacklist.rs new file mode 100644 index 000000000..6813b07a2 --- /dev/null +++ b/src/test/ui/suggestions/issue-84973-blacklist.rs @@ -0,0 +1,28 @@ +// Checks that certain traits for which we don't want to suggest borrowing +// are blacklisted and don't cause the suggestion to be issued. + +#![feature(generators)] + +fn f_copy<T: Copy>(t: T) {} +fn f_clone<T: Clone>(t: T) {} +fn f_unpin<T: Unpin>(t: T) {} +fn f_sized<T: Sized>(t: T) {} +fn f_send<T: Send>(t: T) {} + +struct S; + +fn main() { + f_copy("".to_string()); //~ ERROR: the trait bound `String: Copy` is not satisfied [E0277] + f_clone(S); //~ ERROR: the trait bound `S: Clone` is not satisfied [E0277] + f_unpin(static || { yield; }); + //~^ ERROR: cannot be unpinned [E0277] + + let cl = || (); + let ref_cl: &dyn Fn() -> () = &cl; + f_sized(*ref_cl); + //~^ ERROR: the size for values of type `dyn Fn()` cannot be known at compilation time [E0277] + + use std::rc::Rc; + let rc = Rc::new(0); + f_send(rc); //~ ERROR: `Rc<{integer}>` cannot be sent between threads safely [E0277] +} diff --git a/src/test/ui/suggestions/issue-84973-blacklist.stderr b/src/test/ui/suggestions/issue-84973-blacklist.stderr new file mode 100644 index 000000000..ae0d3efca --- /dev/null +++ b/src/test/ui/suggestions/issue-84973-blacklist.stderr @@ -0,0 +1,78 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/issue-84973-blacklist.rs:15:12 + | +LL | f_copy("".to_string()); + | ------ ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | | + | required by a bound introduced by this call + | +note: required by a bound in `f_copy` + --> $DIR/issue-84973-blacklist.rs:6:14 + | +LL | fn f_copy<T: Copy>(t: T) {} + | ^^^^ required by this bound in `f_copy` + +error[E0277]: the trait bound `S: Clone` is not satisfied + --> $DIR/issue-84973-blacklist.rs:16:13 + | +LL | f_clone(S); + | ------- ^ the trait `Clone` is not implemented for `S` + | | + | required by a bound introduced by this call + | +note: required by a bound in `f_clone` + --> $DIR/issue-84973-blacklist.rs:7:15 + | +LL | fn f_clone<T: Clone>(t: T) {} + | ^^^^^ required by this bound in `f_clone` +help: consider annotating `S` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error[E0277]: `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]` cannot be unpinned + --> $DIR/issue-84973-blacklist.rs:17:5 + | +LL | f_unpin(static || { yield; }); + | ^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]` + | + = note: consider using `Box::pin` +note: required by a bound in `f_unpin` + --> $DIR/issue-84973-blacklist.rs:8:15 + | +LL | fn f_unpin<T: Unpin>(t: T) {} + | ^^^^^ required by this bound in `f_unpin` + +error[E0277]: the size for values of type `dyn Fn()` cannot be known at compilation time + --> $DIR/issue-84973-blacklist.rs:22:13 + | +LL | f_sized(*ref_cl); + | ------- ^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `dyn Fn()` +note: required by a bound in `f_sized` + --> $DIR/issue-84973-blacklist.rs:9:12 + | +LL | fn f_sized<T: Sized>(t: T) {} + | ^ required by this bound in `f_sized` + +error[E0277]: `Rc<{integer}>` cannot be sent between threads safely + --> $DIR/issue-84973-blacklist.rs:27:12 + | +LL | f_send(rc); + | ------ ^^ `Rc<{integer}>` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `Rc<{integer}>` +note: required by a bound in `f_send` + --> $DIR/issue-84973-blacklist.rs:10:14 + | +LL | fn f_send<T: Send>(t: T) {} + | ^^^^ required by this bound in `f_send` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-84973-negative.rs b/src/test/ui/suggestions/issue-84973-negative.rs new file mode 100644 index 000000000..f339251e5 --- /dev/null +++ b/src/test/ui/suggestions/issue-84973-negative.rs @@ -0,0 +1,12 @@ +// Checks that we only suggest borrowing if &T actually implements the trait. + +trait Tr {} +impl Tr for &f32 {} +fn bar<T: Tr>(t: T) {} + +fn main() { + let a = 0i32; + let b = 0.0f32; + bar(a); //~ ERROR: the trait bound `i32: Tr` is not satisfied [E0277] + bar(b); //~ ERROR: the trait bound `f32: Tr` is not satisfied [E0277] +} diff --git a/src/test/ui/suggestions/issue-84973-negative.stderr b/src/test/ui/suggestions/issue-84973-negative.stderr new file mode 100644 index 000000000..15559d4ae --- /dev/null +++ b/src/test/ui/suggestions/issue-84973-negative.stderr @@ -0,0 +1,36 @@ +error[E0277]: the trait bound `i32: Tr` is not satisfied + --> $DIR/issue-84973-negative.rs:10:9 + | +LL | bar(a); + | --- ^ the trait `Tr` is not implemented for `i32` + | | + | required by a bound introduced by this call + | + = help: the trait `Tr` is implemented for `&f32` +note: required by a bound in `bar` + --> $DIR/issue-84973-negative.rs:5:11 + | +LL | fn bar<T: Tr>(t: T) {} + | ^^ required by this bound in `bar` + +error[E0277]: the trait bound `f32: Tr` is not satisfied + --> $DIR/issue-84973-negative.rs:11:9 + | +LL | bar(b); + | --- ^ expected an implementor of trait `Tr` + | | + | required by a bound introduced by this call + | +note: required by a bound in `bar` + --> $DIR/issue-84973-negative.rs:5:11 + | +LL | fn bar<T: Tr>(t: T) {} + | ^^ required by this bound in `bar` +help: consider borrowing here + | +LL | bar(&b); + | + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-84973.rs b/src/test/ui/suggestions/issue-84973.rs new file mode 100644 index 000000000..42468478e --- /dev/null +++ b/src/test/ui/suggestions/issue-84973.rs @@ -0,0 +1,33 @@ +// Checks whether borrowing is suggested when a trait bound is not satisfied +// for found type `T`, but is for `&/&mut T`. + +fn main() { + let f = Fancy{}; + let o = Other::new(f); + //~^ ERROR: the trait bound `Fancy: SomeTrait` is not satisfied [E0277] +} + +struct Fancy {} + +impl <'a> SomeTrait for &'a Fancy { +} + +trait SomeTrait {} + +struct Other<'a, G> { + a: &'a str, + g: G, +} + +// Broadly copied from https://docs.rs/petgraph/0.5.1/src/petgraph/dot.rs.html#70 +impl<'a, G> Other<'a, G> +where + G: SomeTrait, +{ + pub fn new(g: G) -> Self { + Other { + a: "hi", + g: g, + } + } +} diff --git a/src/test/ui/suggestions/issue-84973.stderr b/src/test/ui/suggestions/issue-84973.stderr new file mode 100644 index 000000000..24c989ec3 --- /dev/null +++ b/src/test/ui/suggestions/issue-84973.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `Fancy: SomeTrait` is not satisfied + --> $DIR/issue-84973.rs:6:24 + | +LL | let o = Other::new(f); + | ---------- ^ expected an implementor of trait `SomeTrait` + | | + | required by a bound introduced by this call + | +note: required by a bound in `Other::<'a, G>::new` + --> $DIR/issue-84973.rs:25:8 + | +LL | G: SomeTrait, + | ^^^^^^^^^ required by this bound in `Other::<'a, G>::new` +LL | { +LL | pub fn new(g: G) -> Self { + | --- required by a bound in this +help: consider borrowing here + | +LL | let o = Other::new(&f); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-85347.rs b/src/test/ui/suggestions/issue-85347.rs new file mode 100644 index 000000000..f08e38689 --- /dev/null +++ b/src/test/ui/suggestions/issue-85347.rs @@ -0,0 +1,10 @@ +#![allow(incomplete_features)] +#![feature(generic_associated_types)] +use std::ops::Deref; +trait Foo { + type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>; + //~^ ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + //~| HELP add missing +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-85347.stderr b/src/test/ui/suggestions/issue-85347.stderr new file mode 100644 index 000000000..fccd2ef8d --- /dev/null +++ b/src/test/ui/suggestions/issue-85347.stderr @@ -0,0 +1,19 @@ +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/issue-85347.rs:5:42 + | +LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>; + | ^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-85347.rs:5:10 + | +LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>; + | ^^^ -- +help: add missing lifetime argument + | +LL | type Bar<'a>: Deref<Target = <Self>::Bar<'a, Target = Self>>; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs b/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs new file mode 100644 index 000000000..390d8bbdd --- /dev/null +++ b/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs @@ -0,0 +1,9 @@ +// Regression test for #85943: should not emit suggestions for adding +// indirection to type parameters in where-clauses when suggesting +// adding `?Sized`. +struct A<T>(T) where T: Send; +struct B(A<[u8]>); +//~^ ERROR the size for values of type + +pub fn main() { +} diff --git a/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr b/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr new file mode 100644 index 000000000..752533cdc --- /dev/null +++ b/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr @@ -0,0 +1,23 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:5:10 + | +LL | struct B(A<[u8]>); + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `A` + --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10 + | +LL | struct A<T>(T) where T: Send; + | ^ required by this bound in `A` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>` + --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10 + | +LL | struct A<T>(T) where T: Send; + | ^ - ...if indirection were used here: `Box<T>` + | | + | this could be changed to `T: ?Sized`... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs new file mode 100644 index 000000000..1a36f6e8e --- /dev/null +++ b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs @@ -0,0 +1,8 @@ +// Regression test for #85945: Don't suggest `?Sized` bound if an explicit +// `Sized` bound is already in a `where` clause. +fn foo<T>(_: &T) where T: Sized {} +fn bar() { foo(""); } +//~^ ERROR the size for values of type + +pub fn main() { +} diff --git a/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr new file mode 100644 index 000000000..92be9f764 --- /dev/null +++ b/src/test/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr @@ -0,0 +1,18 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:4:16 + | +LL | fn bar() { foo(""); } + | --- ^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound in `foo` + --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:3:8 + | +LL | fn foo<T>(_: &T) where T: Sized {} + | ^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-86100-tuple-paren-comma.rs b/src/test/ui/suggestions/issue-86100-tuple-paren-comma.rs new file mode 100644 index 000000000..fa9d1a889 --- /dev/null +++ b/src/test/ui/suggestions/issue-86100-tuple-paren-comma.rs @@ -0,0 +1,25 @@ +// Tests that a suggestion is issued for type mismatch errors when a +// 1-tuple is expected and a parenthesized expression of non-tuple +// type is supplied. + +fn foo<T>(_t: (T,)) {} +struct S { _s: (String,) } + +fn main() { + let _x: (i32,) = (5); + //~^ ERROR: mismatched types [E0308] + //~| HELP: use a trailing comma to create a tuple with one element + + foo((Some(3))); + //~^ ERROR: mismatched types [E0308] + //~| HELP: use a trailing comma to create a tuple with one element + + let _s = S { _s: ("abc".to_string()) }; + //~^ ERROR: mismatched types [E0308] + //~| HELP: use a trailing comma to create a tuple with one element + + // Do not issue the suggestion if the found type is already a tuple. + let t = (1, 2); + let _x: (i32,) = (t); + //~^ ERROR: mismatched types [E0308] +} diff --git a/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr b/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr new file mode 100644 index 000000000..8c9a41a20 --- /dev/null +++ b/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr @@ -0,0 +1,62 @@ +error[E0308]: mismatched types + --> $DIR/issue-86100-tuple-paren-comma.rs:9:22 + | +LL | let _x: (i32,) = (5); + | ------ ^^^ expected tuple, found integer + | | + | expected due to this + | + = note: expected tuple `(i32,)` + found type `{integer}` +help: use a trailing comma to create a tuple with one element + | +LL | let _x: (i32,) = (5,); + | + + +error[E0308]: mismatched types + --> $DIR/issue-86100-tuple-paren-comma.rs:13:9 + | +LL | foo((Some(3))); + | --- ^^^^^^^^^ expected tuple, found enum `Option` + | | + | arguments to this function are incorrect + | + = note: expected tuple `(_,)` + found enum `Option<{integer}>` +note: function defined here + --> $DIR/issue-86100-tuple-paren-comma.rs:5:4 + | +LL | fn foo<T>(_t: (T,)) {} + | ^^^ -------- +help: use a trailing comma to create a tuple with one element + | +LL | foo((Some(3),)); + | + + +error[E0308]: mismatched types + --> $DIR/issue-86100-tuple-paren-comma.rs:17:22 + | +LL | let _s = S { _s: ("abc".to_string()) }; + | ^^^^^^^^^^^^^^^^^^^ expected tuple, found struct `String` + | + = note: expected tuple `(String,)` + found struct `String` +help: use a trailing comma to create a tuple with one element + | +LL | let _s = S { _s: ("abc".to_string(),) }; + | + + +error[E0308]: mismatched types + --> $DIR/issue-86100-tuple-paren-comma.rs:23:22 + | +LL | let _x: (i32,) = (t); + | ------ ^^^ expected a tuple with 1 element, found one with 2 elements + | | + | expected due to this + | + = note: expected tuple `(i32,)` + found tuple `({integer}, {integer})` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-86667.rs b/src/test/ui/suggestions/issue-86667.rs new file mode 100644 index 000000000..366787df1 --- /dev/null +++ b/src/test/ui/suggestions/issue-86667.rs @@ -0,0 +1,17 @@ +// Regression test for #86667, where a garbled suggestion was issued for +// a missing named lifetime parameter. + +// compile-flags: --edition 2018 + +async fn a(s1: &str, s2: &str) -> &str { +//~^ ERROR: missing lifetime specifier [E0106] + s1 +//~^ ERROR: lifetime may not live long enough +} + +fn b(s1: &str, s2: &str) -> &str { +//~^ ERROR: missing lifetime specifier [E0106] + s1 +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-86667.stderr b/src/test/ui/suggestions/issue-86667.stderr new file mode 100644 index 000000000..8d6116416 --- /dev/null +++ b/src/test/ui/suggestions/issue-86667.stderr @@ -0,0 +1,36 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-86667.rs:6:35 + | +LL | async fn a(s1: &str, s2: &str) -> &str { + | ---- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `s1` or `s2` +help: consider introducing a named lifetime parameter + | +LL | async fn a<'a>(s1: &'a str, s2: &'a str) -> &'a str { + | ++++ ++ ++ ++ + +error[E0106]: missing lifetime specifier + --> $DIR/issue-86667.rs:12:29 + | +LL | fn b(s1: &str, s2: &str) -> &str { + | ---- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `s1` or `s2` +help: consider introducing a named lifetime parameter + | +LL | fn b<'a>(s1: &'a str, s2: &'a str) -> &'a str { + | ++++ ++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/issue-86667.rs:8:5 + | +LL | async fn a(s1: &str, s2: &str) -> &str { + | - let's call the lifetime of this reference `'1` +LL | +LL | s1 + | ^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/issue-88730.rs b/src/test/ui/suggestions/issue-88730.rs new file mode 100644 index 000000000..e63210a3e --- /dev/null +++ b/src/test/ui/suggestions/issue-88730.rs @@ -0,0 +1,16 @@ +#![allow(unused, nonstandard_style)] +#![deny(bindings_with_variant_name)] + +// If an enum has two different variants, +// then it cannot be matched upon in a function argument. +// It still gets a warning, but no suggestions. +enum Foo { + C, + D, +} + +fn foo(C: Foo) {} //~ERROR + +fn main() { + let C = Foo::D; //~ERROR +} diff --git a/src/test/ui/suggestions/issue-88730.stderr b/src/test/ui/suggestions/issue-88730.stderr new file mode 100644 index 000000000..eb22b0ea5 --- /dev/null +++ b/src/test/ui/suggestions/issue-88730.stderr @@ -0,0 +1,21 @@ +error[E0170]: pattern binding `C` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-88730.rs:12:8 + | +LL | fn foo(C: Foo) {} + | ^ + | +note: the lint level is defined here + --> $DIR/issue-88730.rs:2:9 + | +LL | #![deny(bindings_with_variant_name)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0170]: pattern binding `C` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-88730.rs:15:9 + | +LL | let C = Foo::D; + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0170`. diff --git a/src/test/ui/suggestions/issue-89333.rs b/src/test/ui/suggestions/issue-89333.rs new file mode 100644 index 000000000..03ed28ede --- /dev/null +++ b/src/test/ui/suggestions/issue-89333.rs @@ -0,0 +1,11 @@ +// check-fail +// Ensure we don't error when emitting trait bound not satisfied when self type +// has late bound var + +fn main() { + test(&|| 0); //~ ERROR the trait bound +} + +trait Trait {} + +fn test<T>(arg: &impl Fn() -> T) where for<'a> &'a T: Trait {} diff --git a/src/test/ui/suggestions/issue-89333.stderr b/src/test/ui/suggestions/issue-89333.stderr new file mode 100644 index 000000000..f73f1147d --- /dev/null +++ b/src/test/ui/suggestions/issue-89333.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `for<'a> &'a _: Trait` is not satisfied + --> $DIR/issue-89333.rs:6:5 + | +LL | test(&|| 0); + | ^^^^ the trait `for<'a> Trait` is not implemented for `&'a _` + | +note: required by a bound in `test` + --> $DIR/issue-89333.rs:11:55 + | +LL | fn test<T>(arg: &impl Fn() -> T) where for<'a> &'a T: Trait {} + | ^^^^^ required by this bound in `test` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs b/src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs new file mode 100644 index 000000000..1e36b2fab --- /dev/null +++ b/src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs @@ -0,0 +1,13 @@ +// Checks that we do not ICE when comparing `Self` to `Pin` +// edition:2021 + +struct S; + +impl S { + fn foo(_: Box<Option<S>>) {} + fn bar() { + Self::foo(None) //~ ERROR mismatched types + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr b/src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr new file mode 100644 index 000000000..611f7d5dd --- /dev/null +++ b/src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/issue-90213-expected-boxfuture-self-ice.rs:9:19 + | +LL | Self::foo(None) + | --------- ^^^^ expected struct `Box`, found enum `Option` + | | + | arguments to this function are incorrect + | + = note: expected struct `Box<Option<S>>` + found enum `Option<_>` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +note: associated function defined here + --> $DIR/issue-90213-expected-boxfuture-self-ice.rs:7:8 + | +LL | fn foo(_: Box<Option<S>>) {} + | ^^^ ----------------- +help: store this in the heap by calling `Box::new` + | +LL | Self::foo(Box::new(None)) + | +++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-90974.rs b/src/test/ui/suggestions/issue-90974.rs new file mode 100644 index 000000000..83590dbf7 --- /dev/null +++ b/src/test/ui/suggestions/issue-90974.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{}", (3.).recip()); //~ERROR +} diff --git a/src/test/ui/suggestions/issue-90974.stderr b/src/test/ui/suggestions/issue-90974.stderr new file mode 100644 index 000000000..e1fb479a3 --- /dev/null +++ b/src/test/ui/suggestions/issue-90974.stderr @@ -0,0 +1,14 @@ +error[E0689]: can't call method `recip` on ambiguous numeric type `{float}` + --> $DIR/issue-90974.rs:2:25 + | +LL | println!("{}", (3.).recip()); + | ^^^^^ + | +help: you must specify a concrete type for this numeric value, like `f32` + | +LL | println!("{}", (3_f32).recip()); + | ~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0689`. diff --git a/src/test/ui/suggestions/issue-96223.rs b/src/test/ui/suggestions/issue-96223.rs new file mode 100644 index 000000000..85667bb84 --- /dev/null +++ b/src/test/ui/suggestions/issue-96223.rs @@ -0,0 +1,52 @@ +// Previously ICEd because we didn't properly track binders in suggestions +// check-fail + +pub trait Foo<'de>: Sized {} + +pub trait Bar<'a>: 'static { + type Inner: 'a; +} + +pub trait Fubar { + type Bar: for<'a> Bar<'a>; +} + +pub struct Baz<T>(pub T); + +impl<'de, T> Foo<'de> for Baz<T> where T: Foo<'de> {} + +struct Empty; + +impl<M> Dummy<M> for Empty +where + M: Fubar, + for<'de> Baz<<M::Bar as Bar<'de>>::Inner>: Foo<'de>, +{ +} + +pub trait Dummy<M> +where + M: Fubar, +{ +} + +pub struct EmptyBis<'a>(&'a [u8]); + +impl<'a> Bar<'a> for EmptyBis<'static> { + type Inner = EmptyBis<'a>; +} + +pub struct EmptyMarker; + +impl Fubar for EmptyMarker { + type Bar = EmptyBis<'static>; +} + +fn icey_bounds<D: Dummy<EmptyMarker>>(p: &D) {} + +fn trigger_ice() { + let p = Empty; + icey_bounds(&p); //~ERROR the trait bound +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-96223.stderr b/src/test/ui/suggestions/issue-96223.stderr new file mode 100644 index 000000000..513725d99 --- /dev/null +++ b/src/test/ui/suggestions/issue-96223.stderr @@ -0,0 +1,28 @@ +error[E0277]: the trait bound `for<'de> EmptyBis<'de>: Foo<'_>` is not satisfied + --> $DIR/issue-96223.rs:49:17 + | +LL | icey_bounds(&p); + | ----------- ^^ the trait `for<'de> Foo<'_>` is not implemented for `EmptyBis<'de>` + | | + | required by a bound introduced by this call + | + = help: the trait `Foo<'de>` is implemented for `Baz<T>` +note: required because of the requirements on the impl of `for<'de> Foo<'de>` for `Baz<EmptyBis<'de>>` + --> $DIR/issue-96223.rs:16:14 + | +LL | impl<'de, T> Foo<'de> for Baz<T> where T: Foo<'de> {} + | ^^^^^^^^ ^^^^^^ +note: required because of the requirements on the impl of `Dummy<EmptyMarker>` for `Empty` + --> $DIR/issue-96223.rs:20:9 + | +LL | impl<M> Dummy<M> for Empty + | ^^^^^^^^ ^^^^^ +note: required by a bound in `icey_bounds` + --> $DIR/issue-96223.rs:45:19 + | +LL | fn icey_bounds<D: Dummy<EmptyMarker>>(p: &D) {} + | ^^^^^^^^^^^^^^^^^^ required by this bound in `icey_bounds` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-96555.rs b/src/test/ui/suggestions/issue-96555.rs new file mode 100644 index 000000000..9f0a047c6 --- /dev/null +++ b/src/test/ui/suggestions/issue-96555.rs @@ -0,0 +1,19 @@ +// edition:2018 + +async fn f() { + m::f1().await; //~ ERROR `()` is not a future + m::f2().await; //~ ERROR `()` is not a future + m::f3().await; //~ ERROR `()` is not a future +} + +mod m { + pub fn f1() {} + + pub(crate) fn f2() {} + + pub + fn + f3() {} +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-96555.stderr b/src/test/ui/suggestions/issue-96555.stderr new file mode 100644 index 000000000..a1a603cf2 --- /dev/null +++ b/src/test/ui/suggestions/issue-96555.stderr @@ -0,0 +1,66 @@ +error[E0277]: `()` is not a future + --> $DIR/issue-96555.rs:4:12 + | +LL | m::f1().await; + | -------^^^^^^ `()` is not a future + | | + | this call returns `()` + | + = help: the trait `Future` is not implemented for `()` + = note: () must be a future or must implement `IntoFuture` to be awaited + = note: required because of the requirements on the impl of `IntoFuture` for `()` +help: remove the `.await` + | +LL - m::f1().await; +LL + m::f1(); + | +help: alternatively, consider making `fn f1` asynchronous + | +LL | pub async fn f1() {} + | +++++ + +error[E0277]: `()` is not a future + --> $DIR/issue-96555.rs:5:12 + | +LL | m::f2().await; + | -------^^^^^^ `()` is not a future + | | + | this call returns `()` + | + = help: the trait `Future` is not implemented for `()` + = note: () must be a future or must implement `IntoFuture` to be awaited + = note: required because of the requirements on the impl of `IntoFuture` for `()` +help: remove the `.await` + | +LL - m::f2().await; +LL + m::f2(); + | +help: alternatively, consider making `fn f2` asynchronous + | +LL | pub(crate) async fn f2() {} + | +++++ + +error[E0277]: `()` is not a future + --> $DIR/issue-96555.rs:6:12 + | +LL | m::f3().await; + | -------^^^^^^ `()` is not a future + | | + | this call returns `()` + | + = help: the trait `Future` is not implemented for `()` + = note: () must be a future or must implement `IntoFuture` to be awaited + = note: required because of the requirements on the impl of `IntoFuture` for `()` +help: remove the `.await` + | +LL - m::f3().await; +LL + m::f3(); + | +help: alternatively, consider making `fn f3` asynchronous + | +LL | pub async + | +++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-97677.fixed b/src/test/ui/suggestions/issue-97677.fixed new file mode 100644 index 000000000..73ca9f97b --- /dev/null +++ b/src/test/ui/suggestions/issue-97677.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +fn add_ten<N: std::ops::Add<i32, Output=N>>(n: N) -> N { + n + 10 + //~^ ERROR cannot add `{integer}` to `N` +} + +fn main() { add_ten(0); } diff --git a/src/test/ui/suggestions/issue-97677.rs b/src/test/ui/suggestions/issue-97677.rs new file mode 100644 index 000000000..2abf2af33 --- /dev/null +++ b/src/test/ui/suggestions/issue-97677.rs @@ -0,0 +1,8 @@ +// run-rustfix + +fn add_ten<N>(n: N) -> N { + n + 10 + //~^ ERROR cannot add `{integer}` to `N` +} + +fn main() { add_ten(0); } diff --git a/src/test/ui/suggestions/issue-97677.stderr b/src/test/ui/suggestions/issue-97677.stderr new file mode 100644 index 000000000..069b184ac --- /dev/null +++ b/src/test/ui/suggestions/issue-97677.stderr @@ -0,0 +1,16 @@ +error[E0369]: cannot add `{integer}` to `N` + --> $DIR/issue-97677.rs:4:7 + | +LL | n + 10 + | - ^ -- {integer} + | | + | N + | +help: consider restricting type parameter `N` + | +LL | fn add_ten<N: std::ops::Add<i32, Output=N>>(n: N) -> N { + | ++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/suggestions/issue-97704.fixed b/src/test/ui/suggestions/issue-97704.fixed new file mode 100644 index 000000000..c42bdfff5 --- /dev/null +++ b/src/test/ui/suggestions/issue-97704.fixed @@ -0,0 +1,19 @@ +// edition:2021 +// run-rustfix + +#![allow(unused)] + +use std::future::Future; + +async fn foo() -> Result<(), i32> { + func(async { Ok::<_, i32>(()) }).await?; + //~^ ERROR the `?` operator can only be applied to values that implement `Try` + + Ok(()) +} + +async fn func<T>(fut: impl Future<Output = T>) -> T { + fut.await +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-97704.rs b/src/test/ui/suggestions/issue-97704.rs new file mode 100644 index 000000000..5dfee6cac --- /dev/null +++ b/src/test/ui/suggestions/issue-97704.rs @@ -0,0 +1,19 @@ +// edition:2021 +// run-rustfix + +#![allow(unused)] + +use std::future::Future; + +async fn foo() -> Result<(), i32> { + func(async { Ok::<_, i32>(()) })?; + //~^ ERROR the `?` operator can only be applied to values that implement `Try` + + Ok(()) +} + +async fn func<T>(fut: impl Future<Output = T>) -> T { + fut.await +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-97704.stderr b/src/test/ui/suggestions/issue-97704.stderr new file mode 100644 index 000000000..ca017be45 --- /dev/null +++ b/src/test/ui/suggestions/issue-97704.stderr @@ -0,0 +1,15 @@ +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/issue-97704.rs:9:5 + | +LL | func(async { Ok::<_, i32>(()) })?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future<Output = Result<(), i32>>` + | + = help: the trait `Try` is not implemented for `impl Future<Output = Result<(), i32>>` +help: consider `await`ing on the `Future` + | +LL | func(async { Ok::<_, i32>(()) }).await?; + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-97760.rs b/src/test/ui/suggestions/issue-97760.rs new file mode 100644 index 000000000..cf9c3c58d --- /dev/null +++ b/src/test/ui/suggestions/issue-97760.rs @@ -0,0 +1,9 @@ +pub fn print_values(values: &impl IntoIterator) +where { + for x in values.into_iter() { + println!("{x}"); + //~^ ERROR <impl IntoIterator as IntoIterator>::Item` doesn't implement `std::fmt::Display + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-97760.stderr b/src/test/ui/suggestions/issue-97760.stderr new file mode 100644 index 000000000..bbcc3693f --- /dev/null +++ b/src/test/ui/suggestions/issue-97760.stderr @@ -0,0 +1,18 @@ +error[E0277]: `<impl IntoIterator as IntoIterator>::Item` doesn't implement `std::fmt::Display` + --> $DIR/issue-97760.rs:4:20 + | +LL | println!("{x}"); + | ^ `<impl IntoIterator as IntoIterator>::Item` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `<impl IntoIterator as IntoIterator>::Item` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL ~ pub fn print_values<I: IntoIterator>(values: &I) +LL ~ where <I as IntoIterator>::Item: std::fmt::Display { + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-98500.rs b/src/test/ui/suggestions/issue-98500.rs new file mode 100644 index 000000000..a2717fd92 --- /dev/null +++ b/src/test/ui/suggestions/issue-98500.rs @@ -0,0 +1,14 @@ +// aux-build:not-object-safe.rs + +extern crate not_object_safe; + +pub trait B where + Self: not_object_safe::A, +{ + fn f2(&self); +} + +struct S(Box<dyn B>); +//~^ ERROR the trait `B` cannot be made into an object + +fn main() {} diff --git a/src/test/ui/suggestions/issue-98500.stderr b/src/test/ui/suggestions/issue-98500.stderr new file mode 100644 index 000000000..e7251d735 --- /dev/null +++ b/src/test/ui/suggestions/issue-98500.stderr @@ -0,0 +1,24 @@ +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/issue-98500.rs:11:14 + | +LL | struct S(Box<dyn B>); + | ^^^^^ `B` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/auxiliary/not-object-safe.rs:4:8 + | +LL | fn f(); + | ^ ...because associated function `f` has no `self` parameter +LL | fn f2(self: &Arc<Self>); + | ^^ ...because method `f2`'s `self` parameter cannot be dispatched on + | + ::: $DIR/issue-98500.rs:5:11 + | +LL | pub trait B where + | - this trait cannot be made into an object... + = help: consider moving `f` to another trait + = help: consider moving `f2` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/suggestions/issue-99080.rs b/src/test/ui/suggestions/issue-99080.rs new file mode 100644 index 000000000..91f574f35 --- /dev/null +++ b/src/test/ui/suggestions/issue-99080.rs @@ -0,0 +1,16 @@ +// aux-build:meow.rs + +extern crate meow; + +use meow::Meow; + +fn needs_meow<T: Meow>(t: T) {} + +fn main() { + needs_meow(1usize); + //~^ ERROR the trait bound `usize: Meow` is not satisfied +} + +struct LocalMeow; + +impl Meow for LocalMeow {} diff --git a/src/test/ui/suggestions/issue-99080.stderr b/src/test/ui/suggestions/issue-99080.stderr new file mode 100644 index 000000000..d1908dd9d --- /dev/null +++ b/src/test/ui/suggestions/issue-99080.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `usize: Meow` is not satisfied + --> $DIR/issue-99080.rs:10:16 + | +LL | needs_meow(1usize); + | ---------- ^^^^^^ the trait `Meow` is not implemented for `usize` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Meow`: + GlobalMeow + LocalMeow +note: required by a bound in `needs_meow` + --> $DIR/issue-99080.rs:7:18 + | +LL | fn needs_meow<T: Meow>(t: T) {} + | ^^^^ required by this bound in `needs_meow` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-99240-2.rs b/src/test/ui/suggestions/issue-99240-2.rs new file mode 100644 index 000000000..0a418b5ae --- /dev/null +++ b/src/test/ui/suggestions/issue-99240-2.rs @@ -0,0 +1,10 @@ +enum Enum { + Unit, +} +type Alias = Enum; + +fn main() { + Alias:: + Unit(); + //~^^ ERROR expected function, found enum variant `Alias::Unit` +} diff --git a/src/test/ui/suggestions/issue-99240-2.stderr b/src/test/ui/suggestions/issue-99240-2.stderr new file mode 100644 index 000000000..2af60f597 --- /dev/null +++ b/src/test/ui/suggestions/issue-99240-2.stderr @@ -0,0 +1,24 @@ +error[E0618]: expected function, found enum variant `Alias::Unit` + --> $DIR/issue-99240-2.rs:7:5 + | +LL | Unit, + | ---- enum variant `Alias::Unit` defined here +... +LL | Alias:: + | _____^ + | |_____| + | || +LL | || Unit(); + | ||________^_- call expression requires function + | |_________| + | + | +help: `Alias::Unit` is a unit enum variant, and does not take parentheses to be constructed + | +LL - Unit(); +LL + Unit; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/src/test/ui/suggestions/issue-99240.rs b/src/test/ui/suggestions/issue-99240.rs new file mode 100644 index 000000000..2115a4266 --- /dev/null +++ b/src/test/ui/suggestions/issue-99240.rs @@ -0,0 +1,6 @@ +fn fmt(it: &(std::cell::Cell<Option<impl FnOnce()>>,)) { + (it.0.take())() + //~^ ERROR expected function +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-99240.stderr b/src/test/ui/suggestions/issue-99240.stderr new file mode 100644 index 000000000..f1bea688b --- /dev/null +++ b/src/test/ui/suggestions/issue-99240.stderr @@ -0,0 +1,11 @@ +error[E0618]: expected function, found `Option<impl FnOnce()>` + --> $DIR/issue-99240.rs:2:5 + | +LL | (it.0.take())() + | ^^^^^^^^^^^^^-- + | | + | call expression requires function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/src/test/ui/suggestions/js-style-comparison-op-separate-eq-token.rs b/src/test/ui/suggestions/js-style-comparison-op-separate-eq-token.rs new file mode 100644 index 000000000..b24d25648 --- /dev/null +++ b/src/test/ui/suggestions/js-style-comparison-op-separate-eq-token.rs @@ -0,0 +1,5 @@ +fn main() { + if 1 == = 1 { //~ ERROR expected expression + println!("yup!"); + } +} diff --git a/src/test/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr b/src/test/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr new file mode 100644 index 000000000..6adefe3de --- /dev/null +++ b/src/test/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr @@ -0,0 +1,8 @@ +error: expected expression, found `=` + --> $DIR/js-style-comparison-op-separate-eq-token.rs:2:13 + | +LL | if 1 == = 1 { + | ^ expected expression + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/js-style-comparison-op.fixed b/src/test/ui/suggestions/js-style-comparison-op.fixed new file mode 100644 index 000000000..f7e977b91 --- /dev/null +++ b/src/test/ui/suggestions/js-style-comparison-op.fixed @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + if 1 == 1 { //~ ERROR invalid comparison operator `===` + println!("yup!"); + } else if 1 != 1 { //~ ERROR invalid comparison operator `!==` + println!("nope!"); + } +} diff --git a/src/test/ui/suggestions/js-style-comparison-op.rs b/src/test/ui/suggestions/js-style-comparison-op.rs new file mode 100644 index 000000000..c89c1052e --- /dev/null +++ b/src/test/ui/suggestions/js-style-comparison-op.rs @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + if 1 === 1 { //~ ERROR invalid comparison operator `===` + println!("yup!"); + } else if 1 !== 1 { //~ ERROR invalid comparison operator `!==` + println!("nope!"); + } +} diff --git a/src/test/ui/suggestions/js-style-comparison-op.stderr b/src/test/ui/suggestions/js-style-comparison-op.stderr new file mode 100644 index 000000000..33f7a0844 --- /dev/null +++ b/src/test/ui/suggestions/js-style-comparison-op.stderr @@ -0,0 +1,14 @@ +error: invalid comparison operator `===` + --> $DIR/js-style-comparison-op.rs:3:10 + | +LL | if 1 === 1 { + | ^^^ help: `===` is not a valid comparison operator, use `==` + +error: invalid comparison operator `!==` + --> $DIR/js-style-comparison-op.rs:5:17 + | +LL | } else if 1 !== 1 { + | ^^^ help: `!==` is not a valid comparison operator, use `!=` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/suggestions/let-binding-init-expr-as-ty.rs b/src/test/ui/suggestions/let-binding-init-expr-as-ty.rs new file mode 100644 index 000000000..06ee421fc --- /dev/null +++ b/src/test/ui/suggestions/let-binding-init-expr-as-ty.rs @@ -0,0 +1,11 @@ +pub fn foo(num: i32) -> i32 { + let foo: i32::from_be(num); + //~^ ERROR expected type, found local variable `num` + //~| ERROR parenthesized type parameters may only be used with a `Fn` trait + //~| ERROR ambiguous associated type + foo +} + +fn main() { + let _ = foo(42); +} diff --git a/src/test/ui/suggestions/let-binding-init-expr-as-ty.stderr b/src/test/ui/suggestions/let-binding-init-expr-as-ty.stderr new file mode 100644 index 000000000..2bf072ef5 --- /dev/null +++ b/src/test/ui/suggestions/let-binding-init-expr-as-ty.stderr @@ -0,0 +1,29 @@ +error[E0573]: expected type, found local variable `num` + --> $DIR/let-binding-init-expr-as-ty.rs:2:27 + | +LL | let foo: i32::from_be(num); + | -- ^^^ not a type + | | + | help: use `=` if you meant to assign + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/let-binding-init-expr-as-ty.rs:2:19 + | +LL | let foo: i32::from_be(num); + | ^^^^^^^^^^^^ only `Fn` traits may use parentheses + | +help: use angle brackets instead + | +LL | let foo: i32::from_be<num>; + | ~ ~ + +error[E0223]: ambiguous associated type + --> $DIR/let-binding-init-expr-as-ty.rs:2:14 + | +LL | let foo: i32::from_be(num); + | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<i32 as Trait>::from_be` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0214, E0223, E0573. +For more information about an error, try `rustc --explain E0214`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs new file mode 100644 index 000000000..c6802ac6c --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs @@ -0,0 +1,26 @@ +// Regression test for #81650 + +struct Foo<'a> { + x: &'a mut &'a i32, +} + +impl<'a> Foo<'a> { + fn bar<F, T>(&self, f: F) + where + F: FnOnce(&Foo<'a>) -> T, + F: 'a, + {} +} + +trait Test { + fn test(&self); +} + +fn func<T: Test>(foo: &Foo, t: T) { + foo.bar(move |_| { + //~^ ERROR the parameter type `T` may not live long enough + t.test(); + }); +} + +fn main() {} diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr new file mode 100644 index 000000000..0212c2d71 --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr @@ -0,0 +1,29 @@ +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/missing-lifetimes-in-signature-2.rs:20:5 + | +LL | / foo.bar(move |_| { +LL | | +LL | | t.test(); +LL | | }); + | |______^ + | +note: the parameter type `T` must be valid for the anonymous lifetime defined here... + --> $DIR/missing-lifetimes-in-signature-2.rs:19:24 + | +LL | fn func<T: Test>(foo: &Foo, t: T) { + | ^^^ +note: ...so that the type `T` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature-2.rs:20:5 + | +LL | / foo.bar(move |_| { +LL | | +LL | | t.test(); +LL | | }); + | |______^ +help: consider adding an explicit lifetime bound... + | +LL | fn func<T: Test + 'a>(foo: &Foo, t: T) { + | ++++ + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed new file mode 100644 index 000000000..3c06f4f88 --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed @@ -0,0 +1,10 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/95616 + +fn buggy_const<'a, const N: usize>(_a: &'a Option<[u8; N]>, _f: &'a str) -> &'a str { //~ERROR [E0106] + return ""; +} + +fn main() { + buggy_const(&Some([69,69,69,69,0]), "test"); +} diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.rs new file mode 100644 index 000000000..110468cbb --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.rs @@ -0,0 +1,10 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/95616 + +fn buggy_const<const N: usize>(_a: &Option<[u8; N]>, _f: &str) -> &str { //~ERROR [E0106] + return ""; +} + +fn main() { + buggy_const(&Some([69,69,69,69,0]), "test"); +} diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr new file mode 100644 index 000000000..7b126c90e --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetimes-in-signature-before-const.rs:4:67 + | +LL | fn buggy_const<const N: usize>(_a: &Option<[u8; N]>, _f: &str) -> &str { + | ---------------- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_a` or `_f` +help: consider introducing a named lifetime parameter + | +LL | fn buggy_const<'a, const N: usize>(_a: &'a Option<[u8; N]>, _f: &'a str) -> &'a str { + | +++ ++ ++ ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs new file mode 100644 index 000000000..b641f5941 --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs @@ -0,0 +1,111 @@ +pub trait Get<T> { + fn get(self) -> T; +} + +struct Foo { + x: usize, +} + +impl Get<usize> for Foo { + fn get(self) -> usize { + self.x + } +} + +fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() +where + G: Get<T>, +{ + move || { + //~^ ERROR hidden type for `impl FnOnce()` captures lifetime + *dest = g.get(); + } +} + +// After applying suggestion for `foo`: +fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ +where + G: Get<T>, +{ + move || { + //~^ ERROR the parameter type `G` may not live long enough + *dest = g.get(); + } +} + +// After applying suggestion for `bar`: +fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ +//~^ ERROR undeclared lifetime name `'a` +where + G: Get<T>, +{ + move || { + *dest = g.get(); + } +} + +// After applying suggestion for `baz`: +fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ +where + G: Get<T>, +{ + move || { + //~^ ERROR the parameter type `G` may not live long enough + *dest = g.get(); + } +} + +// Same as above, but show that we pay attention to lifetime names from parent item +impl<'a> Foo { + fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + move || { + //~^ ERROR the parameter type `G` may not live long enough + *dest = g.get(); + } + } +} + +// After applying suggestion for `qux`: +fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a +where + G: Get<T>, +{ + move || { + //~^ ERROR the parameter type `G` may not live long enough + //~| ERROR explicit lifetime required + *dest = g.get(); + } +} + +// Potential incorrect attempt: +fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a +where + G: Get<T>, +{ + move || { + //~^ ERROR the parameter type `G` may not live long enough + *dest = g.get(); + } +} + +// We need to tie the lifetime of `G` with the lifetime of `&mut T` and the returned closure: +fn ok<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a +where + G: Get<T>, +{ + move || { + *dest = g.get(); + } +} + +// This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions: +fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a +where + G: Get<T>, +{ + move || { + *dest = g.get(); + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr new file mode 100644 index 000000000..0d749f04b --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -0,0 +1,166 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/missing-lifetimes-in-signature.rs:37:11 + | +LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `'a,` + +error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not appear in bounds + --> $DIR/missing-lifetimes-in-signature.rs:19:5 + | +LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + | ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 19:12]` captures the anonymous lifetime defined here +... +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ + | +help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound + | +LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ++++ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:30:5 + | +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ + | +note: the parameter type `G` must be valid for the anonymous lifetime defined here... + --> $DIR/missing-lifetimes-in-signature.rs:26:26 + | +LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^ +note: ...so that the type `G` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:30:5 + | +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ +help: consider adding an explicit lifetime bound... + | +LL | G: Get<T> + 'a, + | ++++ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:52:5 + | +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ + | +note: the parameter type `G` must be valid for the anonymous lifetime defined here... + --> $DIR/missing-lifetimes-in-signature.rs:48:34 + | +LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^ +note: ...so that the type `G` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:52:5 + | +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ +help: consider adding an explicit lifetime bound... + | +LL | fn qux<'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ++++ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:61:9 + | +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_________^ + | +note: the parameter type `G` must be valid for the anonymous lifetime defined here... + --> $DIR/missing-lifetimes-in-signature.rs:60:47 + | +LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + | ^^^^^^ +note: ...so that the type `G` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:61:9 + | +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_________^ +help: consider adding an explicit lifetime bound... + | +LL | fn qux<'b, G: Get<T> + 'b + 'c, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + | ++++ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:73:5 + | +LL | / move || { +LL | | +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ + | +note: the parameter type `G` must be valid for the anonymous lifetime defined here... + --> $DIR/missing-lifetimes-in-signature.rs:69:34 + | +LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ^^^^^^ +note: ...so that the type `G` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:73:5 + | +LL | / move || { +LL | | +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ +help: consider adding an explicit lifetime bound... + | +LL | fn bat<'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ++++ + +error[E0621]: explicit lifetime required in the type of `dest` + --> $DIR/missing-lifetimes-in-signature.rs:73:5 + | +LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T` +... +LL | / move || { +LL | | +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ lifetime `'a` required + +error[E0309]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:85:5 + | +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ ...so that the type `G` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | G: Get<T> + 'a, + | ++++ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0261, E0309, E0621, E0700. +For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs new file mode 100644 index 000000000..ff27011f8 --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs @@ -0,0 +1,72 @@ +trait Foo {} +impl<'a, T: Foo> Foo for &'a T {} +impl<T: Foo + ?Sized> Foo for Box<T> {} + +struct Iter<'a, T> { + current: Option<Box<dyn Foo + 'a>>, + remaining: T, +} + +impl<'a, T> Iterator for Iter<'a, T> +where + T: Iterator, + T::Item: Foo + 'a, +{ + type Item = Box<dyn Foo + 'a>; + + fn next(&mut self) -> Option<Self::Item> { + let result = self.current.take(); + self.current = Box::new(self.remaining.next()).map(|f| Box::new(f) as _); + result + } +} + +struct Bar(Vec<Box<dyn Foo>>); + +impl Bar { + fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> { + Iter { + //~^ ERROR lifetime may not live long enough + current: None, + remaining: self.0.iter(), + } + } +} + +struct Baz(Vec<Box<dyn Foo>>); + +impl Baz { + fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ { + Iter { + //~^ ERROR lifetime may not live long enough + current: None, + remaining: self.0.iter(), + } + } +} + +struct Bat(Vec<Box<dyn Foo>>); + +impl Bat { + fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a { + Iter { + //~^ ERROR lifetime may not live long enough + current: None, + remaining: self.0.iter(), + } + } +} + +struct Ban(Vec<Box<dyn Foo>>); + +impl Ban { + fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> { + Iter { + //~^ ERROR lifetime may not live long enough + current: None, + remaining: self.0.iter(), + } + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr new file mode 100644 index 000000000..f49876bcd --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr @@ -0,0 +1,78 @@ +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:28:9 + | +LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> { + | - let's call the lifetime of this reference `'1` +LL | / Iter { +LL | | +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________^ returning this value requires that `'1` must outlive `'static` + | +help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound + | +LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ { + | ++++ +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound + | +LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo + '_>> { + | ++++ + +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:40:9 + | +LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ { + | - let's call the lifetime of this reference `'1` +LL | / Iter { +LL | | +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________^ returning this value requires that `'1` must outlive `'static` + | +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound + | +LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo + '_>> + '_ { + | ++++ + +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:52:9 + | +LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a { + | -- lifetime `'a` defined here +LL | / Iter { +LL | | +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________^ returning this value requires that `'a` must outlive `'static` + | +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'a` lifetime bound + | +LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo + 'a>> + 'a { + | ++++ + +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:64:9 + | +LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> { + | -- lifetime `'a` defined here +LL | / Iter { +LL | | +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________^ returning this value requires that `'a` must outlive `'static` + | +help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound + | +LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a { + | ++++ +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'a` lifetime bound + | +LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo + 'a>> { + | ++++ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/suggestions/match-ergonomics.rs b/src/test/ui/suggestions/match-ergonomics.rs new file mode 100644 index 000000000..c4fc01469 --- /dev/null +++ b/src/test/ui/suggestions/match-ergonomics.rs @@ -0,0 +1,41 @@ +fn main() { + let x = vec![1i32]; + match &x[..] { + [&v] => {}, //~ ERROR mismatched types + _ => {}, + } + match x { + [&v] => {}, //~ ERROR expected an array or slice + _ => {}, + } + match &x[..] { + [v] => {}, + _ => {}, + } + match &x[..] { + &[v] => {}, + _ => {}, + } + match x { + [v] => {}, //~ ERROR expected an array or slice + _ => {}, + } + let y = 1i32; + match &y { + &v => {}, + _ => {}, + } + match y { + &v => {}, //~ ERROR mismatched types + _ => {}, + } + match &y { + v => {}, + _ => {}, + } + match y { + v => {}, + _ => {}, + } + if let [&v] = &x[..] {} //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/match-ergonomics.stderr b/src/test/ui/suggestions/match-ergonomics.stderr new file mode 100644 index 000000000..aa2b407bf --- /dev/null +++ b/src/test/ui/suggestions/match-ergonomics.stderr @@ -0,0 +1,68 @@ +error[E0308]: mismatched types + --> $DIR/match-ergonomics.rs:4:10 + | +LL | match &x[..] { + | ------ this expression has type `&[i32]` +LL | [&v] => {}, + | ^^ expected `i32`, found reference + | + = note: expected type `i32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - [&v] => {}, +LL + [v] => {}, + | + +error[E0529]: expected an array or slice, found `Vec<i32>` + --> $DIR/match-ergonomics.rs:8:9 + | +LL | match x { + | - help: consider slicing here: `x[..]` +LL | [&v] => {}, + | ^^^^ pattern cannot match with input type `Vec<i32>` + +error[E0529]: expected an array or slice, found `Vec<i32>` + --> $DIR/match-ergonomics.rs:20:9 + | +LL | match x { + | - help: consider slicing here: `x[..]` +LL | [v] => {}, + | ^^^ pattern cannot match with input type `Vec<i32>` + +error[E0308]: mismatched types + --> $DIR/match-ergonomics.rs:29:9 + | +LL | match y { + | - this expression has type `i32` +LL | &v => {}, + | ^^ expected `i32`, found reference + | + = note: expected type `i32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - &v => {}, +LL + v => {}, + | + +error[E0308]: mismatched types + --> $DIR/match-ergonomics.rs:40:13 + | +LL | if let [&v] = &x[..] {} + | ^^ ------ this expression has type `&[i32]` + | | + | expected `i32`, found reference + | + = note: expected type `i32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - if let [&v] = &x[..] {} +LL + if let [v] = &x[..] {} + | + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0308, E0529. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/match-needing-semi.rs b/src/test/ui/suggestions/match-needing-semi.rs new file mode 100644 index 000000000..833555d0e --- /dev/null +++ b/src/test/ui/suggestions/match-needing-semi.rs @@ -0,0 +1,21 @@ +// check-only + +fn main() { + match 3 { + 4 => 1, + 3 => { + foo() //~ ERROR mismatched types + } + _ => 2 + } + match 3 { //~ ERROR mismatched types + 4 => 1, + 3 => 2, + _ => 2 + } + let _ = (); +} + +fn foo() -> i32 { + 42 +} diff --git a/src/test/ui/suggestions/match-needing-semi.stderr b/src/test/ui/suggestions/match-needing-semi.stderr new file mode 100644 index 000000000..b5f01d703 --- /dev/null +++ b/src/test/ui/suggestions/match-needing-semi.stderr @@ -0,0 +1,37 @@ +error[E0308]: mismatched types + --> $DIR/match-needing-semi.rs:7:13 + | +LL | / match 3 { +LL | | 4 => 1, +LL | | 3 => { +LL | | foo() + | | ^^^^^ expected `()`, found `i32` +LL | | } +LL | | _ => 2 +LL | | } + | |_____- expected this to be `()` + | +help: consider using a semicolon here + | +LL | foo(); + | + +help: consider using a semicolon here + | +LL | }; + | + + +error[E0308]: mismatched types + --> $DIR/match-needing-semi.rs:11:5 + | +LL | / match 3 { +LL | | 4 => 1, +LL | | 3 => 2, +LL | | _ => 2 +LL | | } + | | ^- help: consider using a semicolon here + | |_____| + | expected `()`, found integer + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs new file mode 100644 index 000000000..8c8abe047 --- /dev/null +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs @@ -0,0 +1,66 @@ +// edition:2018 + +fn dummy() -> i32 { 42 } + +fn extra_semicolon() { + let _ = match true { //~ NOTE `match` arms have incompatible types + true => { + dummy(); //~ NOTE this is found to be + //~^ HELP consider removing this semicolon + } + false => dummy(), //~ ERROR `match` arms have incompatible types + //~^ NOTE expected `()`, found `i32` + }; +} + +async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE checked the `Output` of this `async fn`, expected opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function + +async fn async_extra_semicolon_same() { + let _ = match true { //~ NOTE `match` arms have incompatible types + true => { + async_dummy(); //~ NOTE this is found to be + //~^ HELP consider removing this semicolon + } + false => async_dummy(), //~ ERROR `match` arms have incompatible types + //~^ NOTE expected `()`, found opaque type + //~| NOTE expected unit type `()` + //~| HELP consider `await`ing on the `Future` + }; +} + +async fn async_extra_semicolon_different() { + let _ = match true { //~ NOTE `match` arms have incompatible types + true => { + async_dummy(); //~ NOTE this is found to be + //~^ HELP consider removing this semicolon + } + false => async_dummy2(), //~ ERROR `match` arms have incompatible types + //~^ NOTE expected `()`, found opaque type + //~| NOTE expected unit type `()` + //~| HELP consider `await`ing on the `Future` + }; +} + +async fn async_different_futures() { + let _ = match true { //~ NOTE `match` arms have incompatible types + true => async_dummy(), //~ NOTE this is found to be + //~| HELP consider `await`ing on both `Future`s + false => async_dummy2(), //~ ERROR `match` arms have incompatible types + //~^ NOTE expected opaque type, found a different opaque type + //~| NOTE expected opaque type `impl Future<Output = ()>` + //~| NOTE distinct uses of `impl Trait` result in different opaque types + }; +} + +fn main() {} diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr new file mode 100644 index 000000000..8d735b71f --- /dev/null +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr @@ -0,0 +1,127 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/match-prev-arm-needing-semi.rs:35:18 + | +LL | let _ = match true { + | _____________- +LL | | true => { +LL | | async_dummy(); + | | -------------- this is found to be of type `()` +LL | | +LL | | } +LL | | false => async_dummy(), + | | ^^^^^^^^^^^^^ expected `()`, found opaque type +... | +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/match-prev-arm-needing-semi.rs:16:24 + | +LL | async fn async_dummy() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future<Output = ()>` +help: consider `await`ing on the `Future` + | +LL | false => async_dummy().await, + | ++++++ +help: consider removing this semicolon + | +LL - async_dummy(); +LL + async_dummy() + | + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-prev-arm-needing-semi.rs:48:18 + | +LL | let _ = match true { + | _____________- +LL | | true => { +LL | | async_dummy(); + | | -------------- this is found to be of type `()` +LL | | +LL | | } +LL | | false => async_dummy2(), + | | ^^^^^^^^^^^^^^ expected `()`, found opaque type +... | +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/match-prev-arm-needing-semi.rs:22:25 + | +LL | async fn async_dummy2() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future<Output = ()>` +help: consider `await`ing on the `Future` + | +LL | false => async_dummy2().await, + | ++++++ +help: consider removing this semicolon and boxing the expressions + | +LL ~ Box::new(async_dummy()) +LL | +LL | } +LL ~ false => Box::new(async_dummy2()), + | + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-prev-arm-needing-semi.rs:59:18 + | +LL | let _ = match true { + | _____________- +LL | | true => async_dummy(), + | | ------------- this is found to be of type `impl Future<Output = ()>` +LL | | +LL | | false => async_dummy2(), + | | ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type +... | +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/match-prev-arm-needing-semi.rs:16:24 + | +LL | async fn async_dummy() {} + | ^ checked the `Output` of this `async fn`, expected opaque type +note: while checking the return type of the `async fn` + --> $DIR/match-prev-arm-needing-semi.rs:22:25 + | +LL | async fn async_dummy2() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>) + found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:22:25>) + = note: distinct uses of `impl Trait` result in different opaque types +help: consider `await`ing on both `Future`s + | +LL ~ true => async_dummy().await, +LL | +LL ~ false => async_dummy2().await, + | + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-prev-arm-needing-semi.rs:11:18 + | +LL | let _ = match true { + | _____________- +LL | | true => { +LL | | dummy(); + | | -------- + | | | | + | | | help: consider removing this semicolon + | | this is found to be of type `()` +LL | | +LL | | } +LL | | false => dummy(), + | | ^^^^^^^ expected `()`, found `i32` +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.rs b/src/test/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.rs new file mode 100644 index 000000000..0360ce6e6 --- /dev/null +++ b/src/test/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.rs @@ -0,0 +1,30 @@ +pub trait Foo {} + +struct Bar; +struct Baz; + +impl Foo for Bar { } +impl Foo for Baz { } + +fn not_all_paths(a: &str) -> u32 { //~ ERROR mismatched types + match a { + "baz" => 0, + _ => 1, + }; +} + +fn right(b: &str) -> Box<dyn Foo> { + match b { + "baz" => Box::new(Baz), + _ => Box::new(Bar), + } +} + +fn wrong(c: &str) -> Box<dyn Foo> { //~ ERROR mismatched types + match c { + "baz" => Box::new(Baz), + _ => Box::new(Bar), //~ ERROR `match` arms have incompatible types + }; +} + +fn main() {} diff --git a/src/test/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr b/src/test/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr new file mode 100644 index 000000000..be6fc2615 --- /dev/null +++ b/src/test/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr @@ -0,0 +1,51 @@ +error[E0308]: mismatched types + --> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:9:30 + | +LL | fn not_all_paths(a: &str) -> u32 { + | ------------- ^^^ expected `u32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +... +LL | }; + | - help: remove this semicolon + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:26:14 + | +LL | / match c { +LL | | "baz" => Box::new(Baz), + | | ------------- this is found to be of type `Box<Baz>` +LL | | _ => Box::new(Bar), + | | ^^^^^^^^^^^^^ expected struct `Baz`, found struct `Bar` +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected struct `Box<Baz>` + found struct `Box<Bar>` +note: you might have meant to return the `match` expression + --> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:27:6 + | +LL | fn wrong(c: &str) -> Box<dyn Foo> { + | ------------ the `match` arms can conform to this return type +LL | / match c { +LL | | "baz" => Box::new(Baz), +LL | | _ => Box::new(Bar), +LL | | }; + | | -^ the `match` is a statement because of this semicolon, consider removing it + | |_____| + | this could be implicitly returned but it is a statement, not a tail expression + +error[E0308]: mismatched types + --> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:23:22 + | +LL | fn wrong(c: &str) -> Box<dyn Foo> { + | ----- ^^^^^^^^^^^^ expected struct `Box`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected struct `Box<(dyn Foo + 'static)>` + found unit type `()` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/method-missing-parentheses.rs b/src/test/ui/suggestions/method-missing-parentheses.rs new file mode 100644 index 000000000..f10bfb56d --- /dev/null +++ b/src/test/ui/suggestions/method-missing-parentheses.rs @@ -0,0 +1,5 @@ +fn main() { + let _ = vec![].into_iter().collect::<usize>; + //~^ ERROR attempted to take value of method `collect` on type `std::vec::IntoIter<_>` + //~| ERROR field expressions cannot have generic arguments +} diff --git a/src/test/ui/suggestions/method-missing-parentheses.stderr b/src/test/ui/suggestions/method-missing-parentheses.stderr new file mode 100644 index 000000000..1bfff56a6 --- /dev/null +++ b/src/test/ui/suggestions/method-missing-parentheses.stderr @@ -0,0 +1,20 @@ +error: field expressions cannot have generic arguments + --> $DIR/method-missing-parentheses.rs:2:41 + | +LL | let _ = vec![].into_iter().collect::<usize>; + | ^^^^^^^ + +error[E0615]: attempted to take value of method `collect` on type `std::vec::IntoIter<_>` + --> $DIR/method-missing-parentheses.rs:2:32 + | +LL | let _ = vec![].into_iter().collect::<usize>; + | ^^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let _ = vec![].into_iter().collect::<usize>(); + | ++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0615`. diff --git a/src/test/ui/suggestions/mismatched-types-numeric-from.rs b/src/test/ui/suggestions/mismatched-types-numeric-from.rs new file mode 100644 index 000000000..56549da9c --- /dev/null +++ b/src/test/ui/suggestions/mismatched-types-numeric-from.rs @@ -0,0 +1,3 @@ +fn main() { + let _: u32 = i32::from(0_u8); //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/mismatched-types-numeric-from.stderr b/src/test/ui/suggestions/mismatched-types-numeric-from.stderr new file mode 100644 index 000000000..4d44d893a --- /dev/null +++ b/src/test/ui/suggestions/mismatched-types-numeric-from.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/mismatched-types-numeric-from.rs:2:18 + | +LL | let _: u32 = i32::from(0_u8); + | --- ^^^^^^^^^^^^^^^ expected `u32`, found `i32` + | | + | 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/suggestions/missing-assoc-fn-applicable-suggestions.fixed b/src/test/ui/suggestions/missing-assoc-fn-applicable-suggestions.fixed new file mode 100644 index 000000000..a0cb39a3f --- /dev/null +++ b/src/test/ui/suggestions/missing-assoc-fn-applicable-suggestions.fixed @@ -0,0 +1,21 @@ +// run-rustfix +trait TraitB { + type Item; +} + +trait TraitA<A> { + type Type; + fn bar<T>(_: T) -> Self; + fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy; +} + +struct S; +struct Type; + +impl TraitA<()> for S { //~ ERROR not all trait items implemented +fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy { todo!() } +fn bar<T>(_: T) -> Self { todo!() } +type Type = Type; +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-assoc-fn-applicable-suggestions.rs b/src/test/ui/suggestions/missing-assoc-fn-applicable-suggestions.rs new file mode 100644 index 000000000..c80ede1b2 --- /dev/null +++ b/src/test/ui/suggestions/missing-assoc-fn-applicable-suggestions.rs @@ -0,0 +1,18 @@ +// run-rustfix +trait TraitB { + type Item; +} + +trait TraitA<A> { + type Type; + fn bar<T>(_: T) -> Self; + fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy; +} + +struct S; +struct Type; + +impl TraitA<()> for S { //~ ERROR not all trait items implemented +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr b/src/test/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr new file mode 100644 index 000000000..4c75fbe4c --- /dev/null +++ b/src/test/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr @@ -0,0 +1,16 @@ +error[E0046]: not all trait items implemented, missing: `Type`, `bar`, `baz` + --> $DIR/missing-assoc-fn-applicable-suggestions.rs:15:1 + | +LL | type Type; + | --------- `Type` from trait +LL | fn bar<T>(_: T) -> Self; + | ------------------------ `bar` from trait +LL | fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy; + | ------------------------------------------------------------------- `baz` from trait +... +LL | impl TraitA<()> for S { + | ^^^^^^^^^^^^^^^^^^^^^ missing `Type`, `bar`, `baz` in implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/src/test/ui/suggestions/missing-assoc-fn.rs b/src/test/ui/suggestions/missing-assoc-fn.rs new file mode 100644 index 000000000..9af8e5a93 --- /dev/null +++ b/src/test/ui/suggestions/missing-assoc-fn.rs @@ -0,0 +1,22 @@ +trait TraitB { + type Item; +} + +trait TraitA<A> { + fn foo<T: TraitB<Item = A>>(_: T) -> Self; + fn bar<T>(_: T) -> Self; + fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy; + fn bat<T: TraitB<Item: Copy>>(_: T) -> Self; //~ ERROR associated type bounds are unstable +} + +struct S; + +impl TraitA<()> for S { //~ ERROR not all trait items implemented +} + +use std::iter::FromIterator; +struct X; +impl FromIterator<()> for X { //~ ERROR not all trait items implemented +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-assoc-fn.stderr b/src/test/ui/suggestions/missing-assoc-fn.stderr new file mode 100644 index 000000000..136ec2152 --- /dev/null +++ b/src/test/ui/suggestions/missing-assoc-fn.stderr @@ -0,0 +1,36 @@ +error[E0658]: associated type bounds are unstable + --> $DIR/missing-assoc-fn.rs:9:22 + | +LL | fn bat<T: TraitB<Item: Copy>>(_: T) -> Self; + | ^^^^^^^^^^ + | + = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `baz`, `bat` + --> $DIR/missing-assoc-fn.rs:14:1 + | +LL | fn foo<T: TraitB<Item = A>>(_: T) -> Self; + | ------------------------------------------ `foo` from trait +LL | fn bar<T>(_: T) -> Self; + | ------------------------ `bar` from trait +LL | fn baz<T>(_: T) -> Self where T: TraitB, <T as TraitB>::Item: Copy; + | ------------------------------------------------------------------- `baz` from trait +LL | fn bat<T: TraitB<Item: Copy>>(_: T) -> Self; + | -------------------------------------------- `bat` from trait +... +LL | impl TraitA<()> for S { + | ^^^^^^^^^^^^^^^^^^^^^ missing `foo`, `bar`, `baz`, `bat` in implementation + +error[E0046]: not all trait items implemented, missing: `from_iter` + --> $DIR/missing-assoc-fn.rs:19:1 + | +LL | impl FromIterator<()> for X { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `from_iter` in implementation + | + = help: implement the missing item: `fn from_iter<T>(_: T) -> Self where T: IntoIterator, std::iter::IntoIterator::Item = A { todo!() }` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0046, E0658. +For more information about an error, try `rustc --explain E0046`. diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs new file mode 100644 index 000000000..4954a8a69 --- /dev/null +++ b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs @@ -0,0 +1,21 @@ +// check-pass + +trait Parent { + type Ty; + type Assoc: Child<Self::Ty>; +} + +trait Child<T> {} + +struct ChildWrapper<T>(T); + +impl<A, T> Child<A> for ChildWrapper<T> where T: Child<A> {} + +struct ParentWrapper<T>(T); + +impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> { + type Ty = A; + type Assoc = ChildWrapper<T::Assoc>; +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed new file mode 100644 index 000000000..ac0b14fba --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed @@ -0,0 +1,16 @@ +// run-rustfix +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2<T: Debug + Copy + Clone>{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] +pub struct AABB<K: Debug + std::marker::Copy>{ + pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied + pub size: Vector2<K> +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs new file mode 100644 index 000000000..31f8cd6fc --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs @@ -0,0 +1,16 @@ +// run-rustfix +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2<T: Debug + Copy + Clone>{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] +pub struct AABB<K: Debug>{ + pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied + pub size: Vector2<K> +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr new file mode 100644 index 000000000..03082be69 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `K: Copy` is not satisfied + --> $DIR/missing-bound-in-derive-copy-impl-2.rs:12:14 + | +LL | pub loc: Vector2<K>, + | ^^^^^^^^^^ the trait `Copy` is not implemented for `K` + | +note: required by a bound in `Vector2` + --> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:31 + | +LL | pub struct Vector2<T: Debug + Copy + Clone>{ + | ^^^^ required by this bound in `Vector2` +help: consider further restricting this bound + | +LL | pub struct AABB<K: Debug + std::marker::Copy>{ + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed new file mode 100644 index 000000000..304360d48 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed @@ -0,0 +1,16 @@ +//run-rustfix +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2<T: Debug + Copy + Clone>{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type +pub struct AABB<K: Copy + Debug>{ + pub loc: Vector2<K>, + pub size: Vector2<K> +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs new file mode 100644 index 000000000..14e1fbb33 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs @@ -0,0 +1,16 @@ +//run-rustfix +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2<T: Debug + Copy + Clone>{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type +pub struct AABB<K: Copy>{ + pub loc: Vector2<K>, + pub size: Vector2<K> +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr new file mode 100644 index 000000000..faf730a5c --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -0,0 +1,27 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:10:17 + | +LL | #[derive(Debug, Copy, Clone)] + | ^^^^ +LL | pub struct AABB<K: Copy>{ +LL | pub loc: Vector2<K>, + | ------------------- this field does not implement `Copy` +LL | pub size: Vector2<K> + | -------------------- this field does not implement `Copy` + | +note: the `Copy` impl for `Vector2<K>` requires that `K: Debug` + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:12:14 + | +LL | pub loc: Vector2<K>, + | ^^^^^^^^^^ +LL | pub size: Vector2<K> + | ^^^^^^^^^^ + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | pub struct AABB<K: Copy + Debug>{ + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs new file mode 100644 index 000000000..52163bddd --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs @@ -0,0 +1,15 @@ +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2<T: Debug + Copy + Clone>{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type +pub struct AABB<K>{ + pub loc: Vector2<K>, + pub size: Vector2<K> +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr new file mode 100644 index 000000000..11bc54099 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -0,0 +1,27 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/missing-bound-in-derive-copy-impl.rs:9:17 + | +LL | #[derive(Debug, Copy, Clone)] + | ^^^^ +LL | pub struct AABB<K>{ +LL | pub loc: Vector2<K>, + | ------------------- this field does not implement `Copy` +LL | pub size: Vector2<K> + | -------------------- this field does not implement `Copy` + | +note: the `Copy` impl for `Vector2<K>` requires that `K: Debug` + --> $DIR/missing-bound-in-derive-copy-impl.rs:11:14 + | +LL | pub loc: Vector2<K>, + | ^^^^^^^^^^ +LL | pub size: Vector2<K> + | ^^^^^^^^^^ + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `K` + | +LL | pub struct AABB<K: Debug>{ + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed new file mode 100644 index 000000000..691e7553a --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed @@ -0,0 +1,19 @@ +// run-rustfix + +#[derive(Clone)] +struct Wrapper<T>(T); + +struct OnlyCopyIfDisplay<T>(std::marker::PhantomData<T>); + +impl<T: std::fmt::Display> Clone for OnlyCopyIfDisplay<T> { + fn clone(&self) -> Self { + OnlyCopyIfDisplay(std::marker::PhantomData) + } +} + +impl<T: std::fmt::Display> Copy for OnlyCopyIfDisplay<T> {} + +impl<S: std::fmt::Display> Copy for Wrapper<OnlyCopyIfDisplay<S>> {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs new file mode 100644 index 000000000..e3185e7ef --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs @@ -0,0 +1,19 @@ +// run-rustfix + +#[derive(Clone)] +struct Wrapper<T>(T); + +struct OnlyCopyIfDisplay<T>(std::marker::PhantomData<T>); + +impl<T: std::fmt::Display> Clone for OnlyCopyIfDisplay<T> { + fn clone(&self) -> Self { + OnlyCopyIfDisplay(std::marker::PhantomData) + } +} + +impl<T: std::fmt::Display> Copy for OnlyCopyIfDisplay<T> {} + +impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr new file mode 100644 index 000000000..e0f405eed --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr @@ -0,0 +1,22 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:9 + | +LL | struct Wrapper<T>(T); + | - this field does not implement `Copy` +... +LL | impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {} + | ^^^^ + | +note: the `Copy` impl for `OnlyCopyIfDisplay<S>` requires that `S: std::fmt::Display` + --> $DIR/missing-bound-in-manual-copy-impl-2.rs:4:19 + | +LL | struct Wrapper<T>(T); + | ^ +help: consider restricting type parameter `S` + | +LL | impl<S: std::fmt::Display> Copy for Wrapper<OnlyCopyIfDisplay<S>> {} + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.fixed b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.fixed new file mode 100644 index 000000000..32a7215c5 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +#[derive(Clone)] +struct Wrapper<T>(T); + +impl<S: Copy> Copy for Wrapper<S> {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.rs b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.rs new file mode 100644 index 000000000..c688f4d41 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.rs @@ -0,0 +1,9 @@ +// run-rustfix + +#[derive(Clone)] +struct Wrapper<T>(T); + +impl<S> Copy for Wrapper<S> {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr new file mode 100644 index 000000000..218988511 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr @@ -0,0 +1,17 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/missing-bound-in-manual-copy-impl.rs:6:9 + | +LL | struct Wrapper<T>(T); + | - this field does not implement `Copy` +LL | +LL | impl<S> Copy for Wrapper<S> {} + | ^^^^ + | +help: consider restricting type parameter `S` + | +LL | impl<S: Copy> Copy for Wrapper<S> {} + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.rs b/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.rs new file mode 100644 index 000000000..38332627f --- /dev/null +++ b/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.rs @@ -0,0 +1,16 @@ +trait ZstAssert: Sized { + const A: &str = ""; //~ ERROR missing lifetime specifier + const B: S = S { s: &() }; //~ ERROR missing lifetime specifier + const C: &'_ str = ""; //~ ERROR missing lifetime specifier + const D: T = T { a: &(), b: &() }; //~ ERROR missing lifetime specifier +} + +struct S<'a> { + s: &'a (), +} +struct T<'a, 'b> { + a: &'a (), + b: &'b (), +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr b/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr new file mode 100644 index 000000000..233f1bc5a --- /dev/null +++ b/src/test/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr @@ -0,0 +1,57 @@ +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-in-assoc-const-type.rs:2:14 + | +LL | const A: &str = ""; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ trait ZstAssert<'a>: Sized { +LL ~ const A: &'a str = ""; + | + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-in-assoc-const-type.rs:3:14 + | +LL | const B: S = S { s: &() }; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ trait ZstAssert<'a>: Sized { +LL | const A: &str = ""; +LL ~ const B: S<'a> = S { s: &() }; + | + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-in-assoc-const-type.rs:4:15 + | +LL | const C: &'_ str = ""; + | ^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ trait ZstAssert<'a>: Sized { +LL | const A: &str = ""; +LL | const B: S = S { s: &() }; +LL ~ const C: &'a str = ""; + | + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-in-assoc-const-type.rs:5:14 + | +LL | const D: T = T { a: &(), b: &() }; + | ^ expected 2 lifetime parameters + | +help: consider introducing a named lifetime parameter + | +LL ~ trait ZstAssert<'a>: Sized { +LL | const A: &str = ""; +LL | const B: S = S { s: &() }; +LL | const C: &'_ str = ""; +LL ~ const D: T<'a, 'a> = T { a: &(), b: &() }; + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.rs b/src/test/ui/suggestions/missing-lifetime-specifier.rs new file mode 100644 index 000000000..24f5f782f --- /dev/null +++ b/src/test/ui/suggestions/missing-lifetime-specifier.rs @@ -0,0 +1,57 @@ +#![allow(bare_trait_objects)] +use std::collections::HashMap; +use std::cell::RefCell; + +pub union Foo<'t, 'k> { + i: &'t i64, + f: &'k f64, +} +trait Bar<'t, 'k> {} + +pub union Qux<'t, 'k, I> { + i: &'t I, + f: &'k I, +} +trait Tar<'t, 'k, I> {} + +thread_local! { + static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new()); + //~^ ERROR missing lifetime specifiers + //~| ERROR missing lifetime specifiers +} +thread_local! { + static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new()); + //~^ ERROR missing lifetime specifiers + //~| ERROR missing lifetime specifiers +} +thread_local! { + static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new()); + //~^ ERROR missing lifetime specifiers + //~| ERROR missing lifetime specifiers +} +thread_local! { + static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new()); + //~^ ERROR missing lifetime specifiers + //~| ERROR missing lifetime specifiers +} + +thread_local! { + static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new()); + //~^ ERROR this union takes 2 lifetime arguments but 1 lifetime argument + //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied +} +thread_local! { + static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); + //~^ ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR missing lifetime + //~| ERROR missing lifetime +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr new file mode 100644 index 000000000..10fb28c18 --- /dev/null +++ b/src/test/ui/suggestions/missing-lifetime-specifier.stderr @@ -0,0 +1,319 @@ +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:18:44 + | +LL | static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new()); + | ^^^ expected 2 lifetime parameters + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | static a: RefCell<HashMap<i32, Vec<Vec<Foo<'static, 'static>>>>> = RefCell::new(HashMap::new()); + | ++++++++++++++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:18:44 + | +LL | / thread_local! { +LL | | static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new()); + | | ^^^ expected 2 lifetime parameters +LL | | +LL | | +LL | | } + | |_- + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:23:44 + | +LL | static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new()); + | ^^^^ expected 2 lifetime parameters + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | static b: RefCell<HashMap<i32, Vec<Vec<&'static Bar<'static, 'static>>>>> = RefCell::new(HashMap::new()); + | +++++++ ++++++++++++++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:23:44 + | +LL | / thread_local! { +LL | | static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new()); + | | ^^^^ expected 2 lifetime parameters + | | | + | | expected named lifetime parameter +LL | | +LL | | +LL | | } + | |_- + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:28:47 + | +LL | static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new()); + | ^ expected 2 lifetime parameters + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | static c: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new()); + | +++++++++++++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:28:47 + | +LL | / thread_local! { +LL | | static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new()); + | | ^ expected 2 lifetime parameters +LL | | +LL | | +LL | | } + | |_- + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:33:44 + | +LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new()); + | ^ ^ expected 2 lifetime parameters + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | static d: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new()); + | +++++++ +++++++++++++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:33:44 + | +LL | / thread_local! { +LL | | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new()); + | | ^ ^ expected 2 lifetime parameters + | | | + | | expected named lifetime parameter +LL | | +LL | | +LL | | } + | |_- + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-specifier.rs:47:44 + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); + | +++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-specifier.rs:47:44 + | +LL | / thread_local! { +LL | | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); + | | ^ expected named lifetime parameter +LL | | +LL | | +... | +LL | | +LL | | } + | |_- + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from + +error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:39:44 + | +LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: union defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:11:11 + | +LL | pub union Qux<'t, 'k, I> { + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new()); + | +++++++++ + +error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:39:44 + | +LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: union defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:11:11 + | +LL | pub union Qux<'t, 'k, I> { + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new()); + | ++++ + +error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:39:44 + | +LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: union defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:11:11 + | +LL | pub union Qux<'t, 'k, I> { + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new()); + | ++++ + +error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:39:44 + | +LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: union defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:11:11 + | +LL | pub union Qux<'t, 'k, I> { + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new()); + | ++++ + +error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:39:44 + | +LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: union defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:11:11 + | +LL | pub union Qux<'t, 'k, I> { + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new()); + | +++++++++ + +error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:47:45 + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:15:7 + | +LL | trait Tar<'t, 'k, I> {} + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new()); + | +++++++++ + +error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:47:45 + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:15:7 + | +LL | trait Tar<'t, 'k, I> {} + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new()); + | ++++ + +error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:47:45 + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:15:7 + | +LL | trait Tar<'t, 'k, I> {} + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new()); + | ++++ + +error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:47:45 + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:15:7 + | +LL | trait Tar<'t, 'k, I> {} + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new()); + | ++++ + +error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:47:45 + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:15:7 + | +LL | trait Tar<'t, 'k, I> {} + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new()); + | +++++++++ + +error: aborting due to 20 previous errors + +Some errors have detailed explanations: E0106, E0107. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/missing-lt-for-hrtb.rs b/src/test/ui/suggestions/missing-lt-for-hrtb.rs new file mode 100644 index 000000000..04ea3d831 --- /dev/null +++ b/src/test/ui/suggestions/missing-lt-for-hrtb.rs @@ -0,0 +1,13 @@ +struct X<'a>(&'a ()); +struct S<'a>(&'a dyn Fn(&X) -> &X); +//~^ ERROR missing lifetime specifiers +struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X); +//~^ ERROR missing lifetime specifiers + +fn main() { + let x = S(&|x| { + println!("hi"); + x + }); + x.0(&X(&())); +} diff --git a/src/test/ui/suggestions/missing-lt-for-hrtb.stderr b/src/test/ui/suggestions/missing-lt-for-hrtb.stderr new file mode 100644 index 000000000..fa5156444 --- /dev/null +++ b/src/test/ui/suggestions/missing-lt-for-hrtb.stderr @@ -0,0 +1,36 @@ +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lt-for-hrtb.rs:2:32 + | +LL | struct S<'a>(&'a dyn Fn(&X) -> &X); + | -- ^^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from +help: consider using the `'a` lifetime + | +LL | struct S<'a>(&'a dyn Fn(&X) -> &'a X<'a>); + | ++ ++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lt-for-hrtb.rs:4:40 + | +LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X); + | -- ^^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from +note: these named lifetimes are available to use + --> $DIR/missing-lt-for-hrtb.rs:4:10 + | +LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X); + | ^^ ^^ +help: consider using one of the available lifetimes here + | +LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &'lifetime X<'lifetime>); + | +++++++++ +++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/missing-trait-item.fixed b/src/test/ui/suggestions/missing-trait-item.fixed new file mode 100644 index 000000000..a1cf359ec --- /dev/null +++ b/src/test/ui/suggestions/missing-trait-item.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +trait T { + unsafe fn foo(a: &usize, b: &usize) -> usize; + fn bar(&self, a: &usize, b: &usize) -> usize; +} + +mod foo { + use super::T; + impl T for () { fn bar(&self, _: &usize, _: &usize) -> usize { todo!() } + unsafe fn foo(_: &usize, _: &usize) -> usize { todo!() } + } //~ ERROR not all trait items + + impl T for usize { //~ ERROR not all trait items + fn bar(&self, _: &usize, _: &usize) -> usize { todo!() } + unsafe fn foo(_: &usize, _: &usize) -> usize { todo!() } + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-trait-item.rs b/src/test/ui/suggestions/missing-trait-item.rs new file mode 100644 index 000000000..b4fca25ba --- /dev/null +++ b/src/test/ui/suggestions/missing-trait-item.rs @@ -0,0 +1,16 @@ +// run-rustfix + +trait T { + unsafe fn foo(a: &usize, b: &usize) -> usize; + fn bar(&self, a: &usize, b: &usize) -> usize; +} + +mod foo { + use super::T; + impl T for () {} //~ ERROR not all trait items + + impl T for usize { //~ ERROR not all trait items + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-trait-item.stderr b/src/test/ui/suggestions/missing-trait-item.stderr new file mode 100644 index 000000000..4a9d7b472 --- /dev/null +++ b/src/test/ui/suggestions/missing-trait-item.stderr @@ -0,0 +1,25 @@ +error[E0046]: not all trait items implemented, missing: `foo`, `bar` + --> $DIR/missing-trait-item.rs:10:5 + | +LL | unsafe fn foo(a: &usize, b: &usize) -> usize; + | --------------------------------------------- `foo` from trait +LL | fn bar(&self, a: &usize, b: &usize) -> usize; + | --------------------------------------------- `bar` from trait +... +LL | impl T for () {} + | ^^^^^^^^^^^^^ missing `foo`, `bar` in implementation + +error[E0046]: not all trait items implemented, missing: `foo`, `bar` + --> $DIR/missing-trait-item.rs:12:5 + | +LL | unsafe fn foo(a: &usize, b: &usize) -> usize; + | --------------------------------------------- `foo` from trait +LL | fn bar(&self, a: &usize, b: &usize) -> usize; + | --------------------------------------------- `bar` from trait +... +LL | impl T for usize { + | ^^^^^^^^^^^^^^^^ missing `foo`, `bar` in implementation + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0046`. diff --git a/src/test/ui/suggestions/missing-type-param-used-in-param.fixed b/src/test/ui/suggestions/missing-type-param-used-in-param.fixed new file mode 100644 index 000000000..cc4120041 --- /dev/null +++ b/src/test/ui/suggestions/missing-type-param-used-in-param.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +fn two_type_params<A, B>(_: B) {} + +fn main() { + two_type_params::<String, _>(100); //~ ERROR this function takes 2 generic arguments + two_type_params::<String, _>(100); +} diff --git a/src/test/ui/suggestions/missing-type-param-used-in-param.rs b/src/test/ui/suggestions/missing-type-param-used-in-param.rs new file mode 100644 index 000000000..19286331b --- /dev/null +++ b/src/test/ui/suggestions/missing-type-param-used-in-param.rs @@ -0,0 +1,8 @@ +// run-rustfix + +fn two_type_params<A, B>(_: B) {} + +fn main() { + two_type_params::<String>(100); //~ ERROR this function takes 2 generic arguments + two_type_params::<String, _>(100); +} diff --git a/src/test/ui/suggestions/missing-type-param-used-in-param.stderr b/src/test/ui/suggestions/missing-type-param-used-in-param.stderr new file mode 100644 index 000000000..4f7058a64 --- /dev/null +++ b/src/test/ui/suggestions/missing-type-param-used-in-param.stderr @@ -0,0 +1,21 @@ +error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/missing-type-param-used-in-param.rs:6:5 + | +LL | two_type_params::<String>(100); + | ^^^^^^^^^^^^^^^ ------ supplied 1 generic argument + | | + | expected 2 generic arguments + | +note: function defined here, with 2 generic parameters: `A`, `B` + --> $DIR/missing-type-param-used-in-param.rs:3:4 + | +LL | fn two_type_params<A, B>(_: B) {} + | ^^^^^^^^^^^^^^^ - - +help: add missing generic argument + | +LL | two_type_params::<String, _>(100); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/suggestions/multibyte-escapes.rs b/src/test/ui/suggestions/multibyte-escapes.rs new file mode 100644 index 000000000..fd5d46a4e --- /dev/null +++ b/src/test/ui/suggestions/multibyte-escapes.rs @@ -0,0 +1,18 @@ +// Regression test for #87397. + +fn main() { + b'µ'; + //~^ ERROR: non-ASCII character in byte constant + //~| HELP: if you meant to use the unicode code point for 'µ', use a \xHH escape + //~| NOTE: byte constant must be ASCII + + b'å—'; + //~^ ERROR: non-ASCII character in byte constant + //~| NOTE: this multibyte character does not fit into a single byte + //~| NOTE: byte constant must be ASCII + + b"å—"; + //~^ ERROR: non-ASCII character in byte constant + //~| HELP: if you meant to use the UTF-8 encoding of 'å—', use \xHH escapes + //~| NOTE: byte constant must be ASCII +} diff --git a/src/test/ui/suggestions/multibyte-escapes.stderr b/src/test/ui/suggestions/multibyte-escapes.stderr new file mode 100644 index 000000000..6e26bc1f0 --- /dev/null +++ b/src/test/ui/suggestions/multibyte-escapes.stderr @@ -0,0 +1,33 @@ +error: non-ASCII character in byte constant + --> $DIR/multibyte-escapes.rs:4:7 + | +LL | b'µ'; + | ^ byte constant must be ASCII + | +help: if you meant to use the unicode code point for 'µ', use a \xHH escape + | +LL | b'\xB5'; + | ~~~~ + +error: non-ASCII character in byte constant + --> $DIR/multibyte-escapes.rs:9:7 + | +LL | b'å—'; + | ^^ + | | + | byte constant must be ASCII + | this multibyte character does not fit into a single byte + +error: non-ASCII character in byte constant + --> $DIR/multibyte-escapes.rs:14:7 + | +LL | b"å—"; + | ^^ byte constant must be ASCII + | +help: if you meant to use the UTF-8 encoding of 'å—', use \xHH escapes + | +LL | b"\xE5\xAD\x97"; + | ~~~~~~~~~~~~ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs new file mode 100644 index 000000000..66e1e77c9 --- /dev/null +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs @@ -0,0 +1,22 @@ +use std::env::args; +use std::fs::File; +use std::io::{stdout, Write, BufWriter}; + +fn main() { + let mut args = args(); + let _ = args.next(); + let dest = args.next(); + + let h1; let h2; let h3; + + let fp: &dyn Write = match dest { + Some(path) => { h1 = File::create(path).unwrap(); &h1 }, + None => { h2 = stdout(); h3 = h2.lock(); &h3 } + }; + + let fp = BufWriter::new(fp); + //~^ ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + + writeln!(fp, "hello world").unwrap(); //~ ERROR the method +} diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr new file mode 100644 index 000000000..d121932c8 --- /dev/null +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -0,0 +1,48 @@ +error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + --> $DIR/mut-borrow-needed-by-trait.rs:17:29 + | +LL | let fp = BufWriter::new(fp); + | -------------- ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` + | | + | required by a bound introduced by this call + | + = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` +note: required by a bound in `BufWriter::<W>::new` + --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL + | +LL | impl<W: Write> BufWriter<W> { + | ^^^^^ required by this bound in `BufWriter::<W>::new` + +error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + --> $DIR/mut-borrow-needed-by-trait.rs:17:14 + | +LL | let fp = BufWriter::new(fp); + | ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` + | + = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` +note: required by a bound in `BufWriter` + --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL + | +LL | pub struct BufWriter<W: Write> { + | ^^^^^ required by this bound in `BufWriter` + +error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn std::io::Write>`, but its trait bounds were not satisfied + --> $DIR/mut-borrow-needed-by-trait.rs:21:5 + | +LL | writeln!(fp, "hello world").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn std::io::Write>` due to unsatisfied trait bounds + | + ::: $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL + | +LL | pub struct BufWriter<W: Write> { + | ------------------------------ doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write` + | + = note: the following trait bounds were not satisfied: + `&dyn std::io::Write: std::io::Write` + which is required by `BufWriter<&dyn std::io::Write>: std::io::Write` + = note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/mut-ref-reassignment.rs b/src/test/ui/suggestions/mut-ref-reassignment.rs new file mode 100644 index 000000000..142832493 --- /dev/null +++ b/src/test/ui/suggestions/mut-ref-reassignment.rs @@ -0,0 +1,17 @@ +fn suggestion(opt: &mut Option<String>) { + opt = None; //~ ERROR mismatched types +} + +fn no_suggestion(opt: &mut Result<String, ()>) { + opt = None //~ ERROR mismatched types +} + +fn suggestion2(opt: &mut Option<String>) { + opt = Some(String::new())//~ ERROR mismatched types +} + +fn no_suggestion2(opt: &mut Option<String>) { + opt = Some(42)//~ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/suggestions/mut-ref-reassignment.stderr b/src/test/ui/suggestions/mut-ref-reassignment.stderr new file mode 100644 index 000000000..b3cb6dd06 --- /dev/null +++ b/src/test/ui/suggestions/mut-ref-reassignment.stderr @@ -0,0 +1,55 @@ +error[E0308]: mismatched types + --> $DIR/mut-ref-reassignment.rs:2:11 + | +LL | fn suggestion(opt: &mut Option<String>) { + | ------------------- expected due to this parameter type +LL | opt = None; + | ^^^^ expected mutable reference, found enum `Option` + | + = note: expected mutable reference `&mut Option<String>` + found enum `Option<_>` +help: consider dereferencing here to assign to the mutably borrowed value + | +LL | *opt = None; + | + + +error[E0308]: mismatched types + --> $DIR/mut-ref-reassignment.rs:6:11 + | +LL | fn no_suggestion(opt: &mut Result<String, ()>) { + | ----------------------- expected due to this parameter type +LL | opt = None + | ^^^^ expected mutable reference, found enum `Option` + | + = note: expected mutable reference `&mut Result<String, ()>` + found enum `Option<_>` + +error[E0308]: mismatched types + --> $DIR/mut-ref-reassignment.rs:10:11 + | +LL | fn suggestion2(opt: &mut Option<String>) { + | ------------------- expected due to this parameter type +LL | opt = Some(String::new()) + | ^^^^^^^^^^^^^^^^^^^ expected mutable reference, found enum `Option` + | + = note: expected mutable reference `&mut Option<String>` + found enum `Option<String>` +help: consider dereferencing here to assign to the mutably borrowed value + | +LL | *opt = Some(String::new()) + | + + +error[E0308]: mismatched types + --> $DIR/mut-ref-reassignment.rs:14:11 + | +LL | fn no_suggestion2(opt: &mut Option<String>) { + | ------------------- expected due to this parameter type +LL | opt = Some(42) + | ^^^^^^^^ expected mutable reference, found enum `Option` + | + = note: expected mutable reference `&mut Option<String>` + found enum `Option<{integer}>` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/negative-literal-index.fixed b/src/test/ui/suggestions/negative-literal-index.fixed new file mode 100644 index 000000000..e52714cf9 --- /dev/null +++ b/src/test/ui/suggestions/negative-literal-index.fixed @@ -0,0 +1,22 @@ +// run-rustfix + +use std::ops::Index; +struct X; +impl Index<i32> for X { + type Output = (); + + fn index(&self, _: i32) -> &() { + &() + } +} + +fn main() { + let x = vec![1, 2, 3]; + x[x.len() -1]; //~ ERROR negative integers cannot be used to index on a + let x = [1, 2, 3]; + x[x.len() -1]; //~ ERROR negative integers cannot be used to index on a + let x = &[1, 2, 3]; + x[x.len() -1]; //~ ERROR negative integers cannot be used to index on a + let _ = x; + X[-1]; +} diff --git a/src/test/ui/suggestions/negative-literal-index.rs b/src/test/ui/suggestions/negative-literal-index.rs new file mode 100644 index 000000000..d88b66e67 --- /dev/null +++ b/src/test/ui/suggestions/negative-literal-index.rs @@ -0,0 +1,22 @@ +// run-rustfix + +use std::ops::Index; +struct X; +impl Index<i32> for X { + type Output = (); + + fn index(&self, _: i32) -> &() { + &() + } +} + +fn main() { + let x = vec![1, 2, 3]; + x[-1]; //~ ERROR negative integers cannot be used to index on a + let x = [1, 2, 3]; + x[-1]; //~ ERROR negative integers cannot be used to index on a + let x = &[1, 2, 3]; + x[-1]; //~ ERROR negative integers cannot be used to index on a + let _ = x; + X[-1]; +} diff --git a/src/test/ui/suggestions/negative-literal-index.stderr b/src/test/ui/suggestions/negative-literal-index.stderr new file mode 100644 index 000000000..2b51bf7b7 --- /dev/null +++ b/src/test/ui/suggestions/negative-literal-index.stderr @@ -0,0 +1,35 @@ +error: negative integers cannot be used to index on a `Vec<{integer}>` + --> $DIR/negative-literal-index.rs:15:7 + | +LL | x[-1]; + | ^^ cannot use a negative integer for indexing on `Vec<{integer}>` + | +help: to access an element starting from the end of the `Vec<{integer}>`, compute the index + | +LL | x[x.len() -1]; + | +++++++ + +error: negative integers cannot be used to index on a `[{integer}; 3]` + --> $DIR/negative-literal-index.rs:17:7 + | +LL | x[-1]; + | ^^ cannot use a negative integer for indexing on `[{integer}; 3]` + | +help: to access an element starting from the end of the `[{integer}; 3]`, compute the index + | +LL | x[x.len() -1]; + | +++++++ + +error: negative integers cannot be used to index on a `[{integer}; 3]` + --> $DIR/negative-literal-index.rs:19:7 + | +LL | x[-1]; + | ^^ cannot use a negative integer for indexing on `[{integer}; 3]` + | +help: to access an element starting from the end of the `[{integer}; 3]`, compute the index + | +LL | x[x.len() -1]; + | +++++++ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs b/src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs new file mode 100644 index 000000000..308adcf01 --- /dev/null +++ b/src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs @@ -0,0 +1,18 @@ +pub struct S(f32, f32); + +pub enum E { + V(f32, f32), +} + +fn main() { + let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + //~^ ERROR struct `S` has no field named `x` + //~| ERROR struct `S` has no field named `y` + //~| ERROR struct `S` has no field named `x` + //~| ERROR struct `S` has no field named `y` + let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + //~^ ERROR variant `E::V` has no field named `x` + //~| ERROR variant `E::V` has no field named `y` + //~| ERROR variant `E::V` has no field named `x` + //~| ERROR variant `E::V` has no field named `y` +} diff --git a/src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr b/src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr new file mode 100644 index 000000000..948f09fc3 --- /dev/null +++ b/src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr @@ -0,0 +1,116 @@ +error[E0560]: struct `S` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:19 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `S` is a tuple struct, use the appropriate syntax + | +LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 }); + | ~~~~~~~~~~~~~~~ + +error[E0560]: struct `S` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:27 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `S` is a tuple struct, use the appropriate syntax + | +LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 }); + | ~~~~~~~~~~~~~~~ + +error[E0560]: struct `S` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:41 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `S` is a tuple struct, use the appropriate syntax + | +LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */)); + | ~~~~~~~~~~~~~~~ + +error[E0560]: struct `S` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:49 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `S` is a tuple struct, use the appropriate syntax + | +LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */)); + | ~~~~~~~~~~~~~~~ + +error[E0559]: variant `E::V` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:22 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `E::V` is a tuple variant, use the appropriate syntax + | +LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 }); + | ~~~~~~~~~~~~~~~~~~ + +error[E0559]: variant `E::V` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:30 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `E::V` is a tuple variant, use the appropriate syntax + | +LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 }); + | ~~~~~~~~~~~~~~~~~~ + +error[E0559]: variant `E::V` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:47 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `E::V` is a tuple variant, use the appropriate syntax + | +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */)); + | ~~~~~~~~~~~~~~~~~~ + +error[E0559]: variant `E::V` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:55 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `E::V` is a tuple variant, use the appropriate syntax + | +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */)); + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0559, E0560. +For more information about an error, try `rustc --explain E0559`. diff --git a/src/test/ui/suggestions/no-extern-crate-in-type.rs b/src/test/ui/suggestions/no-extern-crate-in-type.rs new file mode 100644 index 000000000..bb93ef454 --- /dev/null +++ b/src/test/ui/suggestions/no-extern-crate-in-type.rs @@ -0,0 +1,7 @@ +// aux-build:foo.rs + +extern crate foo; + +type Output = Option<Foo>; //~ ERROR cannot find type `Foo` + +fn main() {} diff --git a/src/test/ui/suggestions/no-extern-crate-in-type.stderr b/src/test/ui/suggestions/no-extern-crate-in-type.stderr new file mode 100644 index 000000000..876eef2b6 --- /dev/null +++ b/src/test/ui/suggestions/no-extern-crate-in-type.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `Foo` in this scope + --> $DIR/no-extern-crate-in-type.rs:5:22 + | +LL | type Output = Option<Foo>; + | ^^^ not found in this scope + | +help: consider importing this struct + | +LL | use foo::Foo; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs b/src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs new file mode 100644 index 000000000..98b408daa --- /dev/null +++ b/src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs @@ -0,0 +1,43 @@ +// In rustc_typeck::check::expr::no_such_field_err we recursively +// look in subfields for the field. This recursive search is limited +// in depth for compile-time reasons and to avoid infinite recursion +// in case of cycles. This file tests that the limit in the recursion +// depth is enforced. + +struct Foo { + first: Bar, + second: u32, + third: u32, +} + +struct Bar { + bar: C, +} + +struct C { + c: D, +} + +struct D { + test: E, +} + +struct E { + e: F, +} + +struct F { + f: u32, +} + +fn main() { + let f = F { f: 6 }; + let e = E { e: f }; + let d = D { test: e }; + let c = C { c: d }; + let bar = Bar { bar: c }; + let fooer = Foo { first: bar, second: 4, third: 5 }; + + let test = fooer.f; + //~^ ERROR no field +} diff --git a/src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr b/src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr new file mode 100644 index 000000000..b294f4da7 --- /dev/null +++ b/src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr @@ -0,0 +1,11 @@ +error[E0609]: no field `f` on type `Foo` + --> $DIR/non-existent-field-present-in-subfield-recursion-limit.rs:41:22 + | +LL | let test = fooer.f; + | ^ unknown field + | + = note: available fields are: `first`, `second`, `third` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/src/test/ui/suggestions/non-existent-field-present-in-subfield.fixed b/src/test/ui/suggestions/non-existent-field-present-in-subfield.fixed new file mode 100644 index 000000000..e58b4e6ca --- /dev/null +++ b/src/test/ui/suggestions/non-existent-field-present-in-subfield.fixed @@ -0,0 +1,42 @@ +// run-rustfix + +struct Foo { + first: Bar, + _second: u32, + _third: Vec<String>, +} + +struct Bar { + bar: C, +} + +struct C { + c: D, +} + +struct D { + test: E, +} + +struct E { + _e: F, +} + +struct F { + _f: u32, +} + +fn main() { + let f = F { _f: 6 }; + let e = E { _e: f }; + let d = D { test: e }; + let c = C { c: d }; + let bar = Bar { bar: c }; + let fooer = Foo { first: bar, _second: 4, _third: Vec::new() }; + + let _test = &fooer.first.bar.c; + //~^ ERROR no field + + let _test2 = fooer.first.bar.c.test; + //~^ ERROR no field +} diff --git a/src/test/ui/suggestions/non-existent-field-present-in-subfield.rs b/src/test/ui/suggestions/non-existent-field-present-in-subfield.rs new file mode 100644 index 000000000..7e273ac23 --- /dev/null +++ b/src/test/ui/suggestions/non-existent-field-present-in-subfield.rs @@ -0,0 +1,42 @@ +// run-rustfix + +struct Foo { + first: Bar, + _second: u32, + _third: Vec<String>, +} + +struct Bar { + bar: C, +} + +struct C { + c: D, +} + +struct D { + test: E, +} + +struct E { + _e: F, +} + +struct F { + _f: u32, +} + +fn main() { + let f = F { _f: 6 }; + let e = E { _e: f }; + let d = D { test: e }; + let c = C { c: d }; + let bar = Bar { bar: c }; + let fooer = Foo { first: bar, _second: 4, _third: Vec::new() }; + + let _test = &fooer.c; + //~^ ERROR no field + + let _test2 = fooer.test; + //~^ ERROR no field +} diff --git a/src/test/ui/suggestions/non-existent-field-present-in-subfield.stderr b/src/test/ui/suggestions/non-existent-field-present-in-subfield.stderr new file mode 100644 index 000000000..cc991b915 --- /dev/null +++ b/src/test/ui/suggestions/non-existent-field-present-in-subfield.stderr @@ -0,0 +1,27 @@ +error[E0609]: no field `c` on type `Foo` + --> $DIR/non-existent-field-present-in-subfield.rs:37:24 + | +LL | let _test = &fooer.c; + | ^ unknown field + | + = note: available fields are: `first`, `_second`, `_third` +help: one of the expressions' fields has a field of the same name + | +LL | let _test = &fooer.first.bar.c; + | ++++++++++ + +error[E0609]: no field `test` on type `Foo` + --> $DIR/non-existent-field-present-in-subfield.rs:40:24 + | +LL | let _test2 = fooer.test; + | ^^^^ unknown field + | + = note: available fields are: `first`, `_second`, `_third` +help: one of the expressions' fields has a field of the same name + | +LL | let _test2 = fooer.first.bar.c.test; + | ++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/src/test/ui/suggestions/object-unsafe-trait-references-self.rs b/src/test/ui/suggestions/object-unsafe-trait-references-self.rs new file mode 100644 index 000000000..07bf053e9 --- /dev/null +++ b/src/test/ui/suggestions/object-unsafe-trait-references-self.rs @@ -0,0 +1,12 @@ +trait Trait { + fn baz(&self, _: Self) {} + fn bat(&self) -> Self {} +} + +fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` cannot be made into an object + +trait Other: Sized {} + +fn foo(x: &dyn Other) {} //~ ERROR the trait `Other` cannot be made into an object + +fn main() {} diff --git a/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr b/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr new file mode 100644 index 000000000..54f19fe9d --- /dev/null +++ b/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr @@ -0,0 +1,35 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/object-unsafe-trait-references-self.rs:6:12 + | +LL | fn bar(x: &dyn Trait) {} + | ^^^^^^^^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/object-unsafe-trait-references-self.rs:2:22 + | +LL | trait Trait { + | ----- this trait cannot be made into an object... +LL | fn baz(&self, _: Self) {} + | ^^^^ ...because method `baz` references the `Self` type in this parameter +LL | fn bat(&self) -> Self {} + | ^^^^ ...because method `bat` references the `Self` type in its return type + = help: consider moving `baz` to another trait + = help: consider moving `bat` to another trait + +error[E0038]: the trait `Other` cannot be made into an object + --> $DIR/object-unsafe-trait-references-self.rs:10:12 + | +LL | fn foo(x: &dyn Other) {} + | ^^^^^^^^^ `Other` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/object-unsafe-trait-references-self.rs:8:14 + | +LL | trait Other: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/suggestions/object-unsafe-trait-should-use-self.rs b/src/test/ui/suggestions/object-unsafe-trait-should-use-self.rs new file mode 100644 index 000000000..75f99075e --- /dev/null +++ b/src/test/ui/suggestions/object-unsafe-trait-should-use-self.rs @@ -0,0 +1,16 @@ +#![allow(bare_trait_objects)] +trait A: Sized { + fn f(a: A) -> A; + //~^ ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `A` cannot be made into an object +} +trait B { + fn f(a: B) -> B; + //~^ ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `B` cannot be made into an object +} +trait C { + fn f(&self, a: C) -> C; +} + +fn main() {} diff --git a/src/test/ui/suggestions/object-unsafe-trait-should-use-self.stderr b/src/test/ui/suggestions/object-unsafe-trait-should-use-self.stderr new file mode 100644 index 000000000..55047b426 --- /dev/null +++ b/src/test/ui/suggestions/object-unsafe-trait-should-use-self.stderr @@ -0,0 +1,65 @@ +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self.rs:3:13 + | +LL | trait A: Sized { + | - in this trait +LL | fn f(a: A) -> A; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self.rs:3:13 + | +LL | fn f(a: A) -> A; + | ^ `A` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/object-unsafe-trait-should-use-self.rs:2:10 + | +LL | trait A: Sized { + | - ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self.rs:8:13 + | +LL | trait B { + | - in this trait +LL | fn f(a: B) -> B; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self.rs:8:13 + | +LL | fn f(a: B) -> B; + | ^ `B` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/object-unsafe-trait-should-use-self.rs:8:8 + | +LL | trait B { + | - this trait cannot be made into an object... +LL | fn f(a: B) -> B; + | ^ ...because associated function `f` has no `self` parameter +help: consider turning `f` into a method by giving it a `&self` argument + | +LL | fn f(&self, a: B) -> B; + | ++++++ +help: alternatively, consider constraining `f` so it does not apply to trait objects + | +LL | fn f(a: B) -> B where Self: Sized; + | +++++++++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed new file mode 100644 index 000000000..69487c565 --- /dev/null +++ b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed @@ -0,0 +1,13 @@ +// run-rustfix +#![allow(unused_variables, dead_code)] + +trait Trait { + fn foo(&self) where Self: Other, Self: Sized { } + fn bar(self: &Self) {} //~ ERROR invalid `self` parameter type +} + +fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` cannot be made into an object + +trait Other {} + +fn main() {} diff --git a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs new file mode 100644 index 000000000..38d9aea16 --- /dev/null +++ b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs @@ -0,0 +1,13 @@ +// run-rustfix +#![allow(unused_variables, dead_code)] + +trait Trait { + fn foo() where Self: Other, { } + fn bar(self: ()) {} //~ ERROR invalid `self` parameter type +} + +fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` cannot be made into an object + +trait Other {} + +fn main() {} diff --git a/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr new file mode 100644 index 000000000..c0dc71df0 --- /dev/null +++ b/src/test/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr @@ -0,0 +1,41 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:12 + | +LL | fn bar(x: &dyn Trait) {} + | ^^^^^^^^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/object-unsafe-trait-should-use-where-sized.rs:5:8 + | +LL | trait Trait { + | ----- this trait cannot be made into an object... +LL | fn foo() where Self: Other, { } + | ^^^ ...because associated function `foo` has no `self` parameter +LL | fn bar(self: ()) {} + | ^^ ...because method `bar`'s `self` parameter cannot be dispatched on +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self) where Self: Other, { } + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() where Self: Other, Self: Sized { } + | ~~~~~~~~~~~~~ +help: consider changing method `bar`'s `self` parameter to be `&self` + | +LL | fn bar(self: &Self) {} + | ~~~~~ + +error[E0307]: invalid `self` parameter type: () + --> $DIR/object-unsafe-trait-should-use-where-sized.rs:6:18 + | +LL | fn bar(self: ()) {} + | ^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0307. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/suggestions/opaque-type-error.rs b/src/test/ui/suggestions/opaque-type-error.rs new file mode 100644 index 000000000..5e1147403 --- /dev/null +++ b/src/test/ui/suggestions/opaque-type-error.rs @@ -0,0 +1,24 @@ +// edition:2018 +use core::future::Future; + +async fn base_thing() -> Result<(), ()> { + Ok(()) +} + +fn thing_one() -> impl Future<Output = Result<(), ()>> { + base_thing() +} + +fn thing_two() -> impl Future<Output = Result<(), ()>> { + base_thing() +} + +async fn thing() -> Result<(), ()> { + if true { + thing_one() + } else { + thing_two() //~ ERROR `if` and `else` have incompatible types + }.await +} + +fn main() {} diff --git a/src/test/ui/suggestions/opaque-type-error.stderr b/src/test/ui/suggestions/opaque-type-error.stderr new file mode 100644 index 000000000..133ffb058 --- /dev/null +++ b/src/test/ui/suggestions/opaque-type-error.stderr @@ -0,0 +1,31 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/opaque-type-error.rs:20:9 + | +LL | fn thing_one() -> impl Future<Output = Result<(), ()>> { + | ------------------------------------ the expected opaque type +... +LL | fn thing_two() -> impl Future<Output = Result<(), ()>> { + | ------------------------------------ the found opaque type +... +LL | / if true { +LL | | thing_one() + | | ----------- expected because of this +LL | | } else { +LL | | thing_two() + | | ^^^^^^^^^^^ expected opaque type, found a different opaque type +LL | | }.await + | |_____- `if` and `else` have incompatible types + | + = note: expected opaque type `impl Future<Output = Result<(), ()>>` (opaque type at <$DIR/opaque-type-error.rs:8:19>) + found opaque type `impl Future<Output = Result<(), ()>>` (opaque type at <$DIR/opaque-type-error.rs:12:19>) + = note: distinct uses of `impl Trait` result in different opaque types +help: consider `await`ing on both `Future`s + | +LL ~ thing_one().await +LL | } else { +LL ~ thing_two().await + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/option-content-move-from-tuple-match.rs b/src/test/ui/suggestions/option-content-move-from-tuple-match.rs new file mode 100644 index 000000000..7f22d8136 --- /dev/null +++ b/src/test/ui/suggestions/option-content-move-from-tuple-match.rs @@ -0,0 +1,9 @@ +fn foo(a: &Option<String>, b: &Option<String>) { + match (a, b) { + //~^ ERROR cannot move out of a shared reference + (None, &c) => &c.unwrap(), + (&Some(ref c), _) => c, + }; +} + +fn main() {} diff --git a/src/test/ui/suggestions/option-content-move-from-tuple-match.stderr b/src/test/ui/suggestions/option-content-move-from-tuple-match.stderr new file mode 100644 index 000000000..debb8caba --- /dev/null +++ b/src/test/ui/suggestions/option-content-move-from-tuple-match.stderr @@ -0,0 +1,15 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/option-content-move-from-tuple-match.rs:2:11 + | +LL | match (a, b) { + | ^^^^^^ +LL | +LL | (None, &c) => &c.unwrap(), + | - + | | + | data moved here + | move occurs because `c` has type `Option<String>`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/suggestions/option-content-move.fixed b/src/test/ui/suggestions/option-content-move.fixed new file mode 100644 index 000000000..ba16bcc8a --- /dev/null +++ b/src/test/ui/suggestions/option-content-move.fixed @@ -0,0 +1,39 @@ +//run-rustfix + +pub struct LipogramCorpora { + selections: Vec<(char, Option<String>)>, +} + +impl LipogramCorpora { + pub fn validate_all(&mut self) -> Result<(), char> { + for selection in &self.selections { + if selection.1.is_some() { + if selection.1.as_ref().unwrap().contains(selection.0) { + //~^ ERROR cannot move out of `selection.1` + return Err(selection.0); + } + } + } + Ok(()) + } +} + +pub struct LipogramCorpora2 { + selections: Vec<(char, Result<String, String>)>, +} + +impl LipogramCorpora2 { + pub fn validate_all(&mut self) -> Result<(), char> { + for selection in &self.selections { + if selection.1.is_ok() { + if selection.1.as_ref().unwrap().contains(selection.0) { + //~^ ERROR cannot move out of `selection.1` + return Err(selection.0); + } + } + } + Ok(()) + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/option-content-move.rs b/src/test/ui/suggestions/option-content-move.rs new file mode 100644 index 000000000..ef38f114e --- /dev/null +++ b/src/test/ui/suggestions/option-content-move.rs @@ -0,0 +1,39 @@ +//run-rustfix + +pub struct LipogramCorpora { + selections: Vec<(char, Option<String>)>, +} + +impl LipogramCorpora { + pub fn validate_all(&mut self) -> Result<(), char> { + for selection in &self.selections { + if selection.1.is_some() { + if selection.1.unwrap().contains(selection.0) { + //~^ ERROR cannot move out of `selection.1` + return Err(selection.0); + } + } + } + Ok(()) + } +} + +pub struct LipogramCorpora2 { + selections: Vec<(char, Result<String, String>)>, +} + +impl LipogramCorpora2 { + pub fn validate_all(&mut self) -> Result<(), char> { + for selection in &self.selections { + if selection.1.is_ok() { + if selection.1.unwrap().contains(selection.0) { + //~^ ERROR cannot move out of `selection.1` + return Err(selection.0); + } + } + } + Ok(()) + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/option-content-move.stderr b/src/test/ui/suggestions/option-content-move.stderr new file mode 100644 index 000000000..fccfbe1d7 --- /dev/null +++ b/src/test/ui/suggestions/option-content-move.stderr @@ -0,0 +1,39 @@ +error[E0507]: cannot move out of `selection.1` which is behind a shared reference + --> $DIR/option-content-move.rs:11:20 + | +LL | if selection.1.unwrap().contains(selection.0) { + | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call + | | + | move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait + | +note: this function takes ownership of the receiver `self`, which moves `selection.1` + --> $SRC_DIR/core/src/option.rs:LL:COL + | +LL | pub const fn unwrap(self) -> T { + | ^^^^ +help: consider calling `.as_ref()` to borrow the type's contents + | +LL | if selection.1.as_ref().unwrap().contains(selection.0) { + | +++++++++ + +error[E0507]: cannot move out of `selection.1` which is behind a shared reference + --> $DIR/option-content-move.rs:29:20 + | +LL | if selection.1.unwrap().contains(selection.0) { + | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call + | | + | move occurs because `selection.1` has type `Result<String, String>`, which does not implement the `Copy` trait + | +note: this function takes ownership of the receiver `self`, which moves `selection.1` + --> $SRC_DIR/core/src/result.rs:LL:COL + | +LL | pub fn unwrap(self) -> T + | ^^^^ +help: consider calling `.as_ref()` to borrow the type's contents + | +LL | if selection.1.as_ref().unwrap().contains(selection.0) { + | +++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/suggestions/option-content-move2.rs b/src/test/ui/suggestions/option-content-move2.rs new file mode 100644 index 000000000..88e8a5b7a --- /dev/null +++ b/src/test/ui/suggestions/option-content-move2.rs @@ -0,0 +1,16 @@ +struct NotCopyable; + +fn func<F: FnMut() -> H, H: FnMut()>(_: F) {} + +fn parse() { + let mut var = None; + func(|| { + // Shouldn't suggest `move ||.as_ref()` here + move || { + //~^ ERROR: cannot move out of `var` + var = Some(NotCopyable); + } + }); +} + +fn main() {} diff --git a/src/test/ui/suggestions/option-content-move2.stderr b/src/test/ui/suggestions/option-content-move2.stderr new file mode 100644 index 000000000..1d3dff3be --- /dev/null +++ b/src/test/ui/suggestions/option-content-move2.stderr @@ -0,0 +1,20 @@ +error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure + --> $DIR/option-content-move2.rs:9:9 + | +LL | let mut var = None; + | ------- captured outer variable +LL | func(|| { + | -- captured by this `FnMut` closure +LL | // Shouldn't suggest `move ||.as_ref()` here +LL | move || { + | ^^^^^^^ move out of `var` occurs here +LL | +LL | var = Some(NotCopyable); + | --- + | | + | variable moved due to use in closure + | move occurs because `var` has type `Option<NotCopyable>`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/suggestions/parenthesized-deref-suggestion.rs b/src/test/ui/suggestions/parenthesized-deref-suggestion.rs new file mode 100644 index 000000000..0b4ccdd5a --- /dev/null +++ b/src/test/ui/suggestions/parenthesized-deref-suggestion.rs @@ -0,0 +1,11 @@ +struct Session { + opts: u8, +} + +fn main() { + let sess: &Session = &Session { opts: 0 }; + (sess as *const Session).opts; //~ ERROR no field `opts` on type `*const Session` + + let x = [0u32]; + (x as [u32; 1]).0; //~ ERROR no field `0` on type `[u32; 1]` +} diff --git a/src/test/ui/suggestions/parenthesized-deref-suggestion.stderr b/src/test/ui/suggestions/parenthesized-deref-suggestion.stderr new file mode 100644 index 000000000..cafddbe26 --- /dev/null +++ b/src/test/ui/suggestions/parenthesized-deref-suggestion.stderr @@ -0,0 +1,22 @@ +error[E0609]: no field `opts` on type `*const Session` + --> $DIR/parenthesized-deref-suggestion.rs:7:30 + | +LL | (sess as *const Session).opts; + | ^^^^ + | +help: `(sess as *const Session)` is a raw pointer; try dereferencing it + | +LL | (*(sess as *const Session)).opts; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0609]: no field `0` on type `[u32; 1]` + --> $DIR/parenthesized-deref-suggestion.rs:10:21 + | +LL | (x as [u32; 1]).0; + | ----------------^ + | | + | help: instead of using tuple indexing, use array indexing: `(x as [u32; 1])[0]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/src/test/ui/suggestions/path-by-value.rs b/src/test/ui/suggestions/path-by-value.rs new file mode 100644 index 000000000..c875ca674 --- /dev/null +++ b/src/test/ui/suggestions/path-by-value.rs @@ -0,0 +1,6 @@ +use std::path::Path; + +fn f(p: Path) { } +//~^ ERROR E0277 + +fn main() {} diff --git a/src/test/ui/suggestions/path-by-value.stderr b/src/test/ui/suggestions/path-by-value.stderr new file mode 100644 index 000000000..bbeaa26a9 --- /dev/null +++ b/src/test/ui/suggestions/path-by-value.stderr @@ -0,0 +1,17 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/path-by-value.rs:3:6 + | +LL | fn f(p: Path) { } + | ^ doesn't have a size known at compile-time + | + = help: within `Path`, the trait `Sized` is not implemented for `[u8]` + = note: required because it appears within the type `Path` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn f(p: &Path) { } + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/path-display.rs b/src/test/ui/suggestions/path-display.rs new file mode 100644 index 000000000..3a022e6b0 --- /dev/null +++ b/src/test/ui/suggestions/path-display.rs @@ -0,0 +1,11 @@ +use std::path::{Path, PathBuf}; + +fn main() { + let path = Path::new("/tmp/foo/bar.txt"); + println!("{}", path); + //~^ ERROR E0277 + + let path = PathBuf::from("/tmp/foo/bar.txt"); + println!("{}", path); + //~^ ERROR E0277 +} diff --git a/src/test/ui/suggestions/path-display.stderr b/src/test/ui/suggestions/path-display.stderr new file mode 100644 index 000000000..8359b3658 --- /dev/null +++ b/src/test/ui/suggestions/path-display.stderr @@ -0,0 +1,23 @@ +error[E0277]: `Path` doesn't implement `std::fmt::Display` + --> $DIR/path-display.rs:5:20 + | +LL | println!("{}", path); + | ^^^^ `Path` cannot be formatted with the default formatter; call `.display()` on it + | + = help: the trait `std::fmt::Display` is not implemented for `Path` + = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `PathBuf` doesn't implement `std::fmt::Display` + --> $DIR/path-display.rs:9:20 + | +LL | println!("{}", path); + | ^^^^ `PathBuf` cannot be formatted with the default formatter; call `.display()` on it + | + = help: the trait `std::fmt::Display` is not implemented for `PathBuf` + = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/pattern-slice-vec.fixed b/src/test/ui/suggestions/pattern-slice-vec.fixed new file mode 100644 index 000000000..f8144641f --- /dev/null +++ b/src/test/ui/suggestions/pattern-slice-vec.fixed @@ -0,0 +1,31 @@ +// Regression test for #87017. + +// run-rustfix + +fn main() { + fn foo() -> Vec<i32> { vec![1, 2, 3] } + + if let [_, _, _] = foo()[..] {} + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here + + if let [] = &foo()[..] {} + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here + + if let [] = foo()[..] {} + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here + + let v = vec![]; + match &v[..] { + //~^ HELP: consider slicing here + [5] => {} + //~^ ERROR: expected an array or slice + _ => {} + } + + let [..] = vec![1, 2, 3][..]; + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here +} diff --git a/src/test/ui/suggestions/pattern-slice-vec.rs b/src/test/ui/suggestions/pattern-slice-vec.rs new file mode 100644 index 000000000..444687c85 --- /dev/null +++ b/src/test/ui/suggestions/pattern-slice-vec.rs @@ -0,0 +1,31 @@ +// Regression test for #87017. + +// run-rustfix + +fn main() { + fn foo() -> Vec<i32> { vec![1, 2, 3] } + + if let [_, _, _] = foo() {} + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here + + if let [] = &foo() {} + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here + + if let [] = foo() {} + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here + + let v = vec![]; + match &v { + //~^ HELP: consider slicing here + [5] => {} + //~^ ERROR: expected an array or slice + _ => {} + } + + let [..] = vec![1, 2, 3]; + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here +} diff --git a/src/test/ui/suggestions/pattern-slice-vec.stderr b/src/test/ui/suggestions/pattern-slice-vec.stderr new file mode 100644 index 000000000..f69e7de97 --- /dev/null +++ b/src/test/ui/suggestions/pattern-slice-vec.stderr @@ -0,0 +1,44 @@ +error[E0529]: expected an array or slice, found `Vec<i32>` + --> $DIR/pattern-slice-vec.rs:8:12 + | +LL | if let [_, _, _] = foo() {} + | ^^^^^^^^^ ----- help: consider slicing here: `foo()[..]` + | | + | pattern cannot match with input type `Vec<i32>` + +error[E0529]: expected an array or slice, found `Vec<i32>` + --> $DIR/pattern-slice-vec.rs:12:12 + | +LL | if let [] = &foo() {} + | ^^ ------ help: consider slicing here: `&foo()[..]` + | | + | pattern cannot match with input type `Vec<i32>` + +error[E0529]: expected an array or slice, found `Vec<i32>` + --> $DIR/pattern-slice-vec.rs:16:12 + | +LL | if let [] = foo() {} + | ^^ ----- help: consider slicing here: `foo()[..]` + | | + | pattern cannot match with input type `Vec<i32>` + +error[E0529]: expected an array or slice, found `Vec<_>` + --> $DIR/pattern-slice-vec.rs:23:9 + | +LL | match &v { + | -- help: consider slicing here: `&v[..]` +LL | +LL | [5] => {} + | ^^^ pattern cannot match with input type `Vec<_>` + +error[E0529]: expected an array or slice, found `Vec<{integer}>` + --> $DIR/pattern-slice-vec.rs:28:9 + | +LL | let [..] = vec![1, 2, 3]; + | ^^^^ ------------- help: consider slicing here: `vec![1, 2, 3][..]` + | | + | pattern cannot match with input type `Vec<{integer}>` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0529`. diff --git a/src/test/ui/suggestions/pattern-struct-with-slice-vec-field.rs b/src/test/ui/suggestions/pattern-struct-with-slice-vec-field.rs new file mode 100644 index 000000000..5b223a91f --- /dev/null +++ b/src/test/ui/suggestions/pattern-struct-with-slice-vec-field.rs @@ -0,0 +1,35 @@ +use std::ops::Deref; + +struct Foo { + v: Vec<u32>, +} + +struct Bar { + v: Vec<u32>, +} + +impl Deref for Bar { + type Target = Vec<u32>; + + fn deref(&self) -> &Self::Target { + &self.v + } +} + +fn f(foo: &Foo) { + match foo { + Foo { v: [1, 2] } => {} + //~^ ERROR expected an array or slice, found `Vec<u32> + _ => {} + } +} + +fn bar(bar: &Bar) { + match bar { + Bar { v: [1, 2] } => {} + //~^ ERROR expected an array or slice, found `Vec<u32> + _ => {} + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/pattern-struct-with-slice-vec-field.stderr b/src/test/ui/suggestions/pattern-struct-with-slice-vec-field.stderr new file mode 100644 index 000000000..5b48a8b18 --- /dev/null +++ b/src/test/ui/suggestions/pattern-struct-with-slice-vec-field.stderr @@ -0,0 +1,15 @@ +error[E0529]: expected an array or slice, found `Vec<u32>` + --> $DIR/pattern-struct-with-slice-vec-field.rs:21:18 + | +LL | Foo { v: [1, 2] } => {} + | ^^^^^^ pattern cannot match with input type `Vec<u32>` + +error[E0529]: expected an array or slice, found `Vec<u32>` + --> $DIR/pattern-struct-with-slice-vec-field.rs:29:18 + | +LL | Bar { v: [1, 2] } => {} + | ^^^^^^ pattern cannot match with input type `Vec<u32>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0529`. diff --git a/src/test/ui/suggestions/private-field.rs b/src/test/ui/suggestions/private-field.rs new file mode 100644 index 000000000..1cc4d2a4d --- /dev/null +++ b/src/test/ui/suggestions/private-field.rs @@ -0,0 +1,19 @@ +// compile-flags: --crate-type lib +pub struct S { + pub val: string::MyString, +} + +pub fn test(s: S) { + dbg!(s.cap) //~ ERROR: no field `cap` on type `S` [E0609] +} + +pub(crate) mod string { + + pub struct MyString { + buf: MyVec, + } + + struct MyVec { + cap: usize, + } +} diff --git a/src/test/ui/suggestions/private-field.stderr b/src/test/ui/suggestions/private-field.stderr new file mode 100644 index 000000000..c38c795e0 --- /dev/null +++ b/src/test/ui/suggestions/private-field.stderr @@ -0,0 +1,11 @@ +error[E0609]: no field `cap` on type `S` + --> $DIR/private-field.rs:7:12 + | +LL | dbg!(s.cap) + | ^^^ unknown field + | + = note: available fields are: `val` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/src/test/ui/suggestions/raw-byte-string-prefix.rs b/src/test/ui/suggestions/raw-byte-string-prefix.rs new file mode 100644 index 000000000..576561c31 --- /dev/null +++ b/src/test/ui/suggestions/raw-byte-string-prefix.rs @@ -0,0 +1,10 @@ +// `br` and `rb` are easy to confuse; check that we issue a suggestion to help. + +// edition:2021 + +fn main() { + rb"abc"; + //~^ ERROR: prefix `rb` is unknown + //~| HELP: use `br` for a raw byte string + //~| ERROR: expected one of +} diff --git a/src/test/ui/suggestions/raw-byte-string-prefix.stderr b/src/test/ui/suggestions/raw-byte-string-prefix.stderr new file mode 100644 index 000000000..4f5106849 --- /dev/null +++ b/src/test/ui/suggestions/raw-byte-string-prefix.stderr @@ -0,0 +1,20 @@ +error: prefix `rb` is unknown + --> $DIR/raw-byte-string-prefix.rs:6:5 + | +LL | rb"abc"; + | ^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: use `br` for a raw byte string + | +LL | br"abc"; + | ~~ + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"abc"` + --> $DIR/raw-byte-string-prefix.rs:6:7 + | +LL | rb"abc"; + | ^^^^^ expected one of 8 possible tokens + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/suggestions/raw-name-use-suggestion.rs b/src/test/ui/suggestions/raw-name-use-suggestion.rs new file mode 100644 index 000000000..0a8073c0b --- /dev/null +++ b/src/test/ui/suggestions/raw-name-use-suggestion.rs @@ -0,0 +1,9 @@ +mod foo { + pub fn r#let() {} + pub fn break() {} //~ ERROR expected identifier, found keyword `break` +} + +fn main() { + foo::let(); //~ ERROR expected identifier, found keyword `let` + r#break(); //~ ERROR cannot find function `r#break` in this scope +} diff --git a/src/test/ui/suggestions/raw-name-use-suggestion.stderr b/src/test/ui/suggestions/raw-name-use-suggestion.stderr new file mode 100644 index 000000000..95c26b9ad --- /dev/null +++ b/src/test/ui/suggestions/raw-name-use-suggestion.stderr @@ -0,0 +1,36 @@ +error: expected identifier, found keyword `break` + --> $DIR/raw-name-use-suggestion.rs:3:12 + | +LL | pub fn break() {} + | ^^^^^ expected identifier, found keyword + | +help: escape `break` to use it as an identifier + | +LL | pub fn r#break() {} + | ++ + +error: expected identifier, found keyword `let` + --> $DIR/raw-name-use-suggestion.rs:7:10 + | +LL | foo::let(); + | ^^^ expected identifier, found keyword + | +help: escape `let` to use it as an identifier + | +LL | foo::r#let(); + | ++ + +error[E0425]: cannot find function `r#break` in this scope + --> $DIR/raw-name-use-suggestion.rs:8:5 + | +LL | r#break(); + | ^^^^^^^ not found in this scope + | +help: consider importing this function + | +LL | use foo::r#break; + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/suggestions/recover-from-semicolon-trailing-item.rs b/src/test/ui/suggestions/recover-from-semicolon-trailing-item.rs new file mode 100644 index 000000000..82935af0a --- /dev/null +++ b/src/test/ui/suggestions/recover-from-semicolon-trailing-item.rs @@ -0,0 +1,16 @@ +// verify that after encountering a semicolon after an item the parser recovers +mod M {}; +//~^ ERROR expected item, found `;` +struct S {}; +//~^ ERROR expected item, found `;` +fn foo(a: usize) {}; +//~^ ERROR expected item, found `;` +fn main() { + struct X {}; // ok + let _: usize = S {}; + //~^ ERROR mismatched types + let _: usize = X {}; + //~^ ERROR mismatched types + foo(""); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/recover-from-semicolon-trailing-item.stderr b/src/test/ui/suggestions/recover-from-semicolon-trailing-item.stderr new file mode 100644 index 000000000..9588eedc9 --- /dev/null +++ b/src/test/ui/suggestions/recover-from-semicolon-trailing-item.stderr @@ -0,0 +1,53 @@ +error: expected item, found `;` + --> $DIR/recover-from-semicolon-trailing-item.rs:2:9 + | +LL | mod M {}; + | ^ help: remove this semicolon + +error: expected item, found `;` + --> $DIR/recover-from-semicolon-trailing-item.rs:4:12 + | +LL | struct S {}; + | ^ help: remove this semicolon + | + = help: braced struct declarations are not followed by a semicolon + +error: expected item, found `;` + --> $DIR/recover-from-semicolon-trailing-item.rs:6:20 + | +LL | fn foo(a: usize) {}; + | ^ help: remove this semicolon + +error[E0308]: mismatched types + --> $DIR/recover-from-semicolon-trailing-item.rs:10:20 + | +LL | let _: usize = S {}; + | ----- ^^^^ expected `usize`, found struct `S` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/recover-from-semicolon-trailing-item.rs:12:20 + | +LL | let _: usize = X {}; + | ----- ^^^^ expected `usize`, found struct `X` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/recover-from-semicolon-trailing-item.rs:14:9 + | +LL | foo(""); + | --- ^^ expected `usize`, found `&str` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/recover-from-semicolon-trailing-item.rs:6:4 + | +LL | fn foo(a: usize) {}; + | ^^^ -------- + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/recover-invalid-float.fixed b/src/test/ui/suggestions/recover-invalid-float.fixed new file mode 100644 index 000000000..62389ba61 --- /dev/null +++ b/src/test/ui/suggestions/recover-invalid-float.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let _: f32 = 0.3; + //~^ ERROR float literals must have an integer part + let _: f32 = 0.42f32; + //~^ ERROR float literals must have an integer part + let _: f64 = 0.5f64; + //~^ ERROR float literals must have an integer part +} diff --git a/src/test/ui/suggestions/recover-invalid-float.rs b/src/test/ui/suggestions/recover-invalid-float.rs new file mode 100644 index 000000000..a5a7efe5e --- /dev/null +++ b/src/test/ui/suggestions/recover-invalid-float.rs @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let _: f32 = .3; + //~^ ERROR float literals must have an integer part + let _: f32 = .42f32; + //~^ ERROR float literals must have an integer part + let _: f64 = .5f64; + //~^ ERROR float literals must have an integer part +} diff --git a/src/test/ui/suggestions/recover-invalid-float.stderr b/src/test/ui/suggestions/recover-invalid-float.stderr new file mode 100644 index 000000000..dd24746ea --- /dev/null +++ b/src/test/ui/suggestions/recover-invalid-float.stderr @@ -0,0 +1,20 @@ +error: float literals must have an integer part + --> $DIR/recover-invalid-float.rs:4:18 + | +LL | let _: f32 = .3; + | ^^ help: must have an integer part: `0.3` + +error: float literals must have an integer part + --> $DIR/recover-invalid-float.rs:6:18 + | +LL | let _: f32 = .42f32; + | ^^^^^^ help: must have an integer part: `0.42f32` + +error: float literals must have an integer part + --> $DIR/recover-invalid-float.rs:8:18 + | +LL | let _: f64 = .5f64; + | ^^^^^ help: must have an integer part: `0.5f64` + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs b/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs new file mode 100644 index 000000000..333dce390 --- /dev/null +++ b/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs @@ -0,0 +1,10 @@ +fn main() { + let _ = vec![1, 2, 3].into_iter().collect::Vec<_>(); + //~^ ERROR generic parameters without surrounding angle brackets + let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>>(); + //~^ ERROR generic parameters without surrounding angle brackets + let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>(); + //~^ ERROR generic parameters without surrounding angle brackets + let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>(); + //~^ ERROR generic parameters without surrounding angle brackets +} diff --git a/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr b/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr new file mode 100644 index 000000000..618ccba0d --- /dev/null +++ b/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr @@ -0,0 +1,46 @@ +error: generic parameters without surrounding angle brackets + --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:2:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>(); + | ^^^^^^ + | +help: surround the type parameters with angle brackets + | +LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>(); + | + + + +error: generic parameters without surrounding angle brackets + --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:4:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>>(); + | ^^^^^^ + | +help: surround the type parameters with angle brackets + | +LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>(); + | + ~ + +error: generic parameters without surrounding angle brackets + --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:6:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>(); + | ^^^^^^ + | +help: surround the type parameters with angle brackets + | +LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>(); + | + ~ + +error: generic parameters without surrounding angle brackets + --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:8:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>(); + | ^^^^^^ + | +help: surround the type parameters with angle brackets + | +LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>(); + | + ~ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.rs b/src/test/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.rs new file mode 100644 index 000000000..56aed77c1 --- /dev/null +++ b/src/test/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.rs @@ -0,0 +1,30 @@ +struct Wrapper<T>(T); + +fn foo<T>(foo: Wrapper<T>) +//~^ ERROR the size for values of type `T` cannot be known at compilation time +where + T + : + ? + Sized +{ + // +} + +fn bar<T>(foo: Wrapper<T>) +//~^ ERROR the size for values of type `T` cannot be known at compilation time +where T: ?Sized +{ + // +} + +fn qux<T>(foo: Wrapper<T>) +//~^ ERROR the size for values of type `T` cannot be known at compilation time +where + T: ?Sized +{ + // +} + + +fn main() {} diff --git a/src/test/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr b/src/test/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr new file mode 100644 index 000000000..6071b10d3 --- /dev/null +++ b/src/test/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr @@ -0,0 +1,83 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:3:16 + | +LL | fn foo<T>(foo: Wrapper<T>) + | - ^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `Wrapper` + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 + | +LL | struct Wrapper<T>(T); + | ^ required by this bound in `Wrapper` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>` + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 + | +LL | struct Wrapper<T>(T); + | ^ - ...if indirection were used here: `Box<T>` + | | + | this could be changed to `T: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - where +LL - T +LL - : +LL - ? +LL - Sized + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:14:16 + | +LL | fn bar<T>(foo: Wrapper<T>) + | - ^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `Wrapper` + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 + | +LL | struct Wrapper<T>(T); + | ^ required by this bound in `Wrapper` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>` + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 + | +LL | struct Wrapper<T>(T); + | ^ - ...if indirection were used here: `Box<T>` + | | + | this could be changed to `T: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - where T: ?Sized + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:21:16 + | +LL | fn qux<T>(foo: Wrapper<T>) + | - ^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `Wrapper` + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 + | +LL | struct Wrapper<T>(T); + | ^ required by this bound in `Wrapper` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>` + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 + | +LL | struct Wrapper<T>(T); + | ^ - ...if indirection were used here: `Box<T>` + | | + | this could be changed to `T: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - where +LL - T: ?Sized + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/remove-as_str.rs b/src/test/ui/suggestions/remove-as_str.rs new file mode 100644 index 000000000..289a784ba --- /dev/null +++ b/src/test/ui/suggestions/remove-as_str.rs @@ -0,0 +1,21 @@ +fn foo1(s: &str) { + s.as_str(); + //~^ ERROR no method named `as_str` found +} + +fn foo2<'a>(s: &'a str) { + s.as_str(); + //~^ ERROR no method named `as_str` found +} + +fn foo3(s: &mut str) { + s.as_str(); + //~^ ERROR no method named `as_str` found +} + +fn foo4(s: &&str) { + s.as_str(); + //~^ ERROR no method named `as_str` found +} + +fn main() {} diff --git a/src/test/ui/suggestions/remove-as_str.stderr b/src/test/ui/suggestions/remove-as_str.stderr new file mode 100644 index 000000000..534c49778 --- /dev/null +++ b/src/test/ui/suggestions/remove-as_str.stderr @@ -0,0 +1,27 @@ +error[E0599]: no method named `as_str` found for reference `&str` in the current scope + --> $DIR/remove-as_str.rs:2:7 + | +LL | s.as_str(); + | -^^^^^^-- help: remove this method call + +error[E0599]: no method named `as_str` found for reference `&'a str` in the current scope + --> $DIR/remove-as_str.rs:7:7 + | +LL | s.as_str(); + | -^^^^^^-- help: remove this method call + +error[E0599]: no method named `as_str` found for mutable reference `&mut str` in the current scope + --> $DIR/remove-as_str.rs:12:7 + | +LL | s.as_str(); + | -^^^^^^-- help: remove this method call + +error[E0599]: no method named `as_str` found for reference `&&str` in the current scope + --> $DIR/remove-as_str.rs:17:7 + | +LL | s.as_str(); + | -^^^^^^-- help: remove this method call + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/restrict-type-argument.rs b/src/test/ui/suggestions/restrict-type-argument.rs new file mode 100644 index 000000000..c4ebfbe92 --- /dev/null +++ b/src/test/ui/suggestions/restrict-type-argument.rs @@ -0,0 +1,31 @@ +fn is_send<T: Send>(val: T) {} + +fn use_impl_sync(val: impl Sync) { + is_send(val); //~ ERROR `impl Sync` cannot be sent between threads safely +} + +fn use_where<S>(val: S) where S: Sync { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn use_bound<S: Sync>(val: S) { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn use_bound_2< + S // Make sure we can synthezise a correct suggestion span for this case + : + Sync +>(val: S) { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn use_bound_and_where<S: Sync>(val: S) where S: std::fmt::Debug { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn use_unbound<S>(val: S) { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn main() {} diff --git a/src/test/ui/suggestions/restrict-type-argument.stderr b/src/test/ui/suggestions/restrict-type-argument.stderr new file mode 100644 index 000000000..01c2de798 --- /dev/null +++ b/src/test/ui/suggestions/restrict-type-argument.stderr @@ -0,0 +1,111 @@ +error[E0277]: `impl Sync` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:4:13 + | +LL | is_send(val); + | ------- ^^^ `impl Sync` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | +note: required by a bound in `is_send` + --> $DIR/restrict-type-argument.rs:1:15 + | +LL | fn is_send<T: Send>(val: T) {} + | ^^^^ required by this bound in `is_send` +help: consider further restricting this bound + | +LL | fn use_impl_sync(val: impl Sync + std::marker::Send) { + | +++++++++++++++++++ + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:8:13 + | +LL | is_send(val); + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | +note: required by a bound in `is_send` + --> $DIR/restrict-type-argument.rs:1:15 + | +LL | fn is_send<T: Send>(val: T) {} + | ^^^^ required by this bound in `is_send` +help: consider further restricting this bound + | +LL | fn use_where<S>(val: S) where S: Sync + std::marker::Send { + | +++++++++++++++++++ + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:12:13 + | +LL | is_send(val); + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | +note: required by a bound in `is_send` + --> $DIR/restrict-type-argument.rs:1:15 + | +LL | fn is_send<T: Send>(val: T) {} + | ^^^^ required by this bound in `is_send` +help: consider further restricting this bound + | +LL | fn use_bound<S: Sync + std::marker::Send>(val: S) { + | +++++++++++++++++++ + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:20:13 + | +LL | is_send(val); + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | +note: required by a bound in `is_send` + --> $DIR/restrict-type-argument.rs:1:15 + | +LL | fn is_send<T: Send>(val: T) {} + | ^^^^ required by this bound in `is_send` +help: consider further restricting this bound + | +LL | Sync + std::marker::Send + | +++++++++++++++++++ + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:24:13 + | +LL | is_send(val); + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | +note: required by a bound in `is_send` + --> $DIR/restrict-type-argument.rs:1:15 + | +LL | fn is_send<T: Send>(val: T) {} + | ^^^^ required by this bound in `is_send` +help: consider further restricting this bound + | +LL | fn use_bound_and_where<S: Sync + std::marker::Send>(val: S) where S: std::fmt::Debug { + | +++++++++++++++++++ + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:28:13 + | +LL | is_send(val); + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | +note: required by a bound in `is_send` + --> $DIR/restrict-type-argument.rs:1:15 + | +LL | fn is_send<T: Send>(val: T) {} + | ^^^^ required by this bound in `is_send` +help: consider restricting type parameter `S` + | +LL | fn use_unbound<S: std::marker::Send>(val: S) { + | +++++++++++++++++++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/return-bindings-multi.rs b/src/test/ui/suggestions/return-bindings-multi.rs new file mode 100644 index 000000000..8c3bd641e --- /dev/null +++ b/src/test/ui/suggestions/return-bindings-multi.rs @@ -0,0 +1,9 @@ +fn a(i: i32) -> i32 { + //~^ ERROR mismatched types + let j = 2i32; +} + +fn b(i: i32, j: i32) -> i32 {} +//~^ ERROR mismatched types + +fn main() {} diff --git a/src/test/ui/suggestions/return-bindings-multi.stderr b/src/test/ui/suggestions/return-bindings-multi.stderr new file mode 100644 index 000000000..738e3f2f4 --- /dev/null +++ b/src/test/ui/suggestions/return-bindings-multi.stderr @@ -0,0 +1,34 @@ +error[E0308]: mismatched types + --> $DIR/return-bindings-multi.rs:1:17 + | +LL | fn a(i: i32) -> i32 { + | - ^^^ expected `i32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | +note: consider returning one of these bindings + --> $DIR/return-bindings-multi.rs:1:6 + | +LL | fn a(i: i32) -> i32 { + | ^ +LL | +LL | let j = 2i32; + | ^ + +error[E0308]: mismatched types + --> $DIR/return-bindings-multi.rs:6:25 + | +LL | fn b(i: i32, j: i32) -> i32 {} + | - ^^^ expected `i32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | +note: consider returning one of these bindings + --> $DIR/return-bindings-multi.rs:6:6 + | +LL | fn b(i: i32, j: i32) -> i32 {} + | ^ ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/return-bindings.rs b/src/test/ui/suggestions/return-bindings.rs new file mode 100644 index 000000000..fa1bad376 --- /dev/null +++ b/src/test/ui/suggestions/return-bindings.rs @@ -0,0 +1,51 @@ +#![allow(unused)] + +fn a(i: i32) -> i32 {} +//~^ ERROR mismatched types + +fn b(opt_str: Option<String>) { + let s: String = if let Some(s) = opt_str { + //~^ ERROR mismatched types + } else { + String::new() + }; +} + +fn c() -> Option<i32> { + //~^ ERROR mismatched types + let x = Some(1); +} + +fn d(opt_str: Option<String>) { + let s: String = if let Some(s) = opt_str { + //~^ ERROR mismatched types + } else { + String::new() + }; +} + +fn d2(opt_str: Option<String>) { + let s = if let Some(s) = opt_str { + } else { + String::new() + //~^ ERROR `if` and `else` have incompatible types + }; +} + +fn e(opt_str: Option<String>) { + let s: String = match opt_str { + Some(s) => {} + //~^ ERROR mismatched types + None => String::new(), + }; +} + +fn e2(opt_str: Option<String>) { + let s = match opt_str { + Some(s) => {} + None => String::new(), + //~^ ERROR `match` arms have incompatible types + }; +} + +fn main() {} diff --git a/src/test/ui/suggestions/return-bindings.stderr b/src/test/ui/suggestions/return-bindings.stderr new file mode 100644 index 000000000..c14fb3367 --- /dev/null +++ b/src/test/ui/suggestions/return-bindings.stderr @@ -0,0 +1,110 @@ +error[E0308]: mismatched types + --> $DIR/return-bindings.rs:3:17 + | +LL | fn a(i: i32) -> i32 {} + | - ^^^ expected `i32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | +help: consider returning the local binding `i` + | +LL | fn a(i: i32) -> i32 { i } + | + + +error[E0308]: mismatched types + --> $DIR/return-bindings.rs:7:46 + | +LL | let s: String = if let Some(s) = opt_str { + | ______________________________________________^ +LL | | +LL | | } else { + | |_____^ expected struct `String`, found `()` + | +help: consider returning the local binding `s` + | +LL ~ let s: String = if let Some(s) = opt_str { +LL + s +LL ~ + | + +error[E0308]: mismatched types + --> $DIR/return-bindings.rs:14:11 + | +LL | fn c() -> Option<i32> { + | - ^^^^^^^^^^^ expected enum `Option`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected enum `Option<i32>` + found unit type `()` +help: consider returning the local binding `x` + | +LL ~ let x = Some(1); +LL + x + | + +error[E0308]: mismatched types + --> $DIR/return-bindings.rs:20:46 + | +LL | let s: String = if let Some(s) = opt_str { + | ______________________________________________^ +LL | | +LL | | } else { + | |_____^ expected struct `String`, found `()` + | +help: consider returning the local binding `s` + | +LL ~ let s: String = if let Some(s) = opt_str { +LL + s +LL ~ + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/return-bindings.rs:30:9 + | +LL | let s = if let Some(s) = opt_str { + | ______________________________________- +LL | | } else { + | |_____- expected because of this +LL | String::new() + | ^^^^^^^^^^^^^ expected `()`, found struct `String` + | +help: consider returning the local binding `s` + | +LL ~ let s = if let Some(s) = opt_str { +LL + s +LL ~ } else { + | + +error[E0308]: mismatched types + --> $DIR/return-bindings.rs:37:20 + | +LL | Some(s) => {} + | ^^ expected struct `String`, found `()` + | +help: consider returning the local binding `s` + | +LL | Some(s) => { s } + | + + +error[E0308]: `match` arms have incompatible types + --> $DIR/return-bindings.rs:46:17 + | +LL | let s = match opt_str { + | _____________- +LL | | Some(s) => {} + | | -- this is found to be of type `()` +LL | | None => String::new(), + | | ^^^^^^^^^^^^^ expected `()`, found struct `String` +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | +help: consider returning the local binding `s` + | +LL | Some(s) => { s } + | + + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/return-elided-lifetime.rs b/src/test/ui/suggestions/return-elided-lifetime.rs new file mode 100644 index 000000000..012d5492a --- /dev/null +++ b/src/test/ui/suggestions/return-elided-lifetime.rs @@ -0,0 +1,32 @@ +/* Checks all four scenarios possible in report_elision_failure() of + * rustc_resolve::late::lifetimes::LifetimeContext related to returning + * borrowed values, in various configurations. + */ + +fn f1() -> &i32 { loop {} } +//~^ ERROR missing lifetime specifier [E0106] +fn f1_() -> (&i32, &i32) { loop {} } +//~^ ERROR missing lifetime specifiers [E0106] + +fn f2(a: i32, b: i32) -> &i32 { loop {} } +//~^ ERROR missing lifetime specifier [E0106] +fn f2_(a: i32, b: i32) -> (&i32, &i32) { loop {} } +//~^ ERROR missing lifetime specifiers [E0106] + +struct S<'a, 'b> { a: &'a i32, b: &'b i32 } +fn f3(s: &S) -> &i32 { loop {} } +//~^ ERROR missing lifetime specifier [E0106] +fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} } +//~^ ERROR missing lifetime specifiers [E0106] + +fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} } +//~^ ERROR missing lifetime specifier [E0106] +fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } +//~^ ERROR missing lifetime specifiers [E0106] + +fn f5<'a>(a: &'a i32, b: &i32) -> &i32 { loop {} } +//~^ ERROR missing lifetime specifier [E0106] +fn f5_<'a>(a: &'a i32, b: &i32) -> (&i32, &i32) { loop {} } +//~^ ERROR missing lifetime specifiers [E0106] + +fn main() {} diff --git a/src/test/ui/suggestions/return-elided-lifetime.stderr b/src/test/ui/suggestions/return-elided-lifetime.stderr new file mode 100644 index 000000000..273d95bc7 --- /dev/null +++ b/src/test/ui/suggestions/return-elided-lifetime.stderr @@ -0,0 +1,143 @@ +error[E0106]: missing lifetime specifier + --> $DIR/return-elided-lifetime.rs:6:12 + | +LL | fn f1() -> &i32 { loop {} } + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn f1() -> &'static i32 { loop {} } + | +++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/return-elided-lifetime.rs:8:14 + | +LL | fn f1_() -> (&i32, &i32) { loop {} } + | ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn f1_() -> (&'static i32, &'static i32) { loop {} } + | +++++++ +++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/return-elided-lifetime.rs:11:26 + | +LL | fn f2(a: i32, b: i32) -> &i32 { loop {} } + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn f2(a: i32, b: i32) -> &'static i32 { loop {} } + | +++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/return-elided-lifetime.rs:13:28 + | +LL | fn f2_(a: i32, b: i32) -> (&i32, &i32) { loop {} } + | ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn f2_(a: i32, b: i32) -> (&'static i32, &'static i32) { loop {} } + | +++++++ +++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/return-elided-lifetime.rs:17:17 + | +LL | fn f3(s: &S) -> &i32 { loop {} } + | -- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `s`'s 3 lifetimes it is borrowed from +help: consider introducing a named lifetime parameter + | +LL | fn f3<'a>(s: &'a S<'a, 'a>) -> &'a i32 { loop {} } + | ++++ ++ ++++++++ ++ + +error[E0106]: missing lifetime specifiers + --> $DIR/return-elided-lifetime.rs:19:26 + | +LL | fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} } + | -- -- ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `s`'s 3 lifetimes or one of `t`'s 3 lifetimes +help: consider introducing a named lifetime parameter + | +LL | fn f3_<'a>(s: &'a S<'a, 'a>, t: &'a S<'a, 'a>) -> (&'a i32, &'a i32) { loop {} } + | ++++ ++ ++++++++ ++ ++++++++ ++ ++ + +error[E0106]: missing lifetime specifier + --> $DIR/return-elided-lifetime.rs:22:42 + | +LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} } + | ------- ------- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +note: these named lifetimes are available to use + --> $DIR/return-elided-lifetime.rs:22:7 + | +LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} } + | ^^ ^^ +help: consider using one of the available lifetimes here + | +LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &'lifetime i32 { loop {} } + | +++++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/return-elided-lifetime.rs:24:44 + | +LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } + | ------- ------- ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +note: these named lifetimes are available to use + --> $DIR/return-elided-lifetime.rs:24:8 + | +LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } + | ^^ ^^ +help: consider using one of the available lifetimes here + | +LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&'lifetime i32, &'lifetime i32) { loop {} } + | +++++++++ +++++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/return-elided-lifetime.rs:27:35 + | +LL | fn f5<'a>(a: &'a i32, b: &i32) -> &i32 { loop {} } + | ------- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b` +help: consider using the `'a` lifetime + | +LL | fn f5<'a>(a: &'a i32, b: &i32) -> &'a i32 { loop {} } + | ++ + +error[E0106]: missing lifetime specifiers + --> $DIR/return-elided-lifetime.rs:29:37 + | +LL | fn f5_<'a>(a: &'a i32, b: &i32) -> (&i32, &i32) { loop {} } + | ------- ---- ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b` +help: consider using the `'a` lifetime + | +LL | fn f5_<'a>(a: &'a i32, b: &i32) -> (&'a i32, &'a i32) { loop {} } + | ++ ++ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/return-without-lifetime.rs b/src/test/ui/suggestions/return-without-lifetime.rs new file mode 100644 index 000000000..9bfce11be --- /dev/null +++ b/src/test/ui/suggestions/return-without-lifetime.rs @@ -0,0 +1,10 @@ +struct Thing<'a>(&'a ()); +struct Foo<'a>(&usize); +//~^ ERROR missing lifetime specifier + +fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() } +//~^ ERROR missing lifetime specifier +fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() } +//~^ ERROR missing lifetime specifier + +fn main() {} diff --git a/src/test/ui/suggestions/return-without-lifetime.stderr b/src/test/ui/suggestions/return-without-lifetime.stderr new file mode 100644 index 000000000..5028e8d62 --- /dev/null +++ b/src/test/ui/suggestions/return-without-lifetime.stderr @@ -0,0 +1,38 @@ +error[E0106]: missing lifetime specifier + --> $DIR/return-without-lifetime.rs:2:16 + | +LL | struct Foo<'a>(&usize); + | ^ expected named lifetime parameter + | +help: consider using the `'a` lifetime + | +LL | struct Foo<'a>(&'a usize); + | ++ + +error[E0106]: missing lifetime specifier + --> $DIR/return-without-lifetime.rs:5:34 + | +LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() } + | --------- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from +help: consider using the `'a` lifetime + | +LL | fn func1<'a>(_arg: &'a Thing) -> &'a () { unimplemented!() } + | ++ + +error[E0106]: missing lifetime specifier + --> $DIR/return-without-lifetime.rs:7:35 + | +LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() } + | ---------- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from +help: consider using the `'a` lifetime + | +LL | fn func2<'a>(_arg: &Thing<'a>) -> &'a () { unimplemented!() } + | ++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/suggestions/slice-issue-87994.rs b/src/test/ui/suggestions/slice-issue-87994.rs new file mode 100644 index 000000000..ecb7f54ea --- /dev/null +++ b/src/test/ui/suggestions/slice-issue-87994.rs @@ -0,0 +1,16 @@ +fn main() { + let v = vec![1i32, 2, 3]; + for _ in v[1..] { + //~^ ERROR [i32]` is not an iterator [E0277] + //~^^ ERROR known at compilation time + } + struct K { + n: i32, + } + let mut v2 = vec![K { n: 1 }, K { n: 1 }, K { n: 1 }]; + for i2 in v2[1..] { + //~^ ERROR [K]` is not an iterator [E0277] + //~^^ ERROR known at compilation time + i2.n = 2; + } +} diff --git a/src/test/ui/suggestions/slice-issue-87994.stderr b/src/test/ui/suggestions/slice-issue-87994.stderr new file mode 100644 index 000000000..fd2a44f9a --- /dev/null +++ b/src/test/ui/suggestions/slice-issue-87994.stderr @@ -0,0 +1,63 @@ +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/slice-issue-87994.rs:3:12 + | +LL | for _ in v[1..] { + | ^^^^^^ expected an implementor of trait `IntoIterator` + | + = note: the trait bound `[i32]: IntoIterator` is not satisfied + = note: required because of the requirements on the impl of `IntoIterator` for `[i32]` +help: consider borrowing here + | +LL | for _ in &v[1..] { + | + +LL | for _ in &mut v[1..] { + | ++++ + +error[E0277]: `[i32]` is not an iterator + --> $DIR/slice-issue-87994.rs:3:12 + | +LL | for _ in v[1..] { + | ^^^^^^ expected an implementor of trait `IntoIterator` + | + = note: the trait bound `[i32]: IntoIterator` is not satisfied + = note: required because of the requirements on the impl of `IntoIterator` for `[i32]` +help: consider borrowing here + | +LL | for _ in &v[1..] { + | + +LL | for _ in &mut v[1..] { + | ++++ + +error[E0277]: the size for values of type `[K]` cannot be known at compilation time + --> $DIR/slice-issue-87994.rs:11:13 + | +LL | for i2 in v2[1..] { + | ^^^^^^^ expected an implementor of trait `IntoIterator` + | + = note: the trait bound `[K]: IntoIterator` is not satisfied + = note: required because of the requirements on the impl of `IntoIterator` for `[K]` +help: consider borrowing here + | +LL | for i2 in &v2[1..] { + | + +LL | for i2 in &mut v2[1..] { + | ++++ + +error[E0277]: `[K]` is not an iterator + --> $DIR/slice-issue-87994.rs:11:13 + | +LL | for i2 in v2[1..] { + | ^^^^^^^ expected an implementor of trait `IntoIterator` + | + = note: the trait bound `[K]: IntoIterator` is not satisfied + = note: required because of the requirements on the impl of `IntoIterator` for `[K]` +help: consider borrowing here + | +LL | for i2 in &v2[1..] { + | + +LL | for i2 in &mut v2[1..] { + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/struct-field-type-including-single-colon.rs b/src/test/ui/suggestions/struct-field-type-including-single-colon.rs new file mode 100644 index 000000000..b7ad6d996 --- /dev/null +++ b/src/test/ui/suggestions/struct-field-type-including-single-colon.rs @@ -0,0 +1,20 @@ +mod foo { + struct A; + mod bar { + struct B; + } +} + +struct Foo { + a: foo:A, + //~^ ERROR found single colon in a struct field type path + //~| expected `,`, or `}`, found `:` +} + +struct Bar { + b: foo::bar:B, + //~^ ERROR found single colon in a struct field type path + //~| expected `,`, or `}`, found `:` +} + +fn main() {} diff --git a/src/test/ui/suggestions/struct-field-type-including-single-colon.stderr b/src/test/ui/suggestions/struct-field-type-including-single-colon.stderr new file mode 100644 index 000000000..189759d64 --- /dev/null +++ b/src/test/ui/suggestions/struct-field-type-including-single-colon.stderr @@ -0,0 +1,36 @@ +error: found single colon in a struct field type path + --> $DIR/struct-field-type-including-single-colon.rs:9:11 + | +LL | a: foo:A, + | ^ + | +help: write a path separator here + | +LL | a: foo::A, + | ~~ + +error: expected `,`, or `}`, found `:` + --> $DIR/struct-field-type-including-single-colon.rs:9:11 + | +LL | a: foo:A, + | ^ + +error: found single colon in a struct field type path + --> $DIR/struct-field-type-including-single-colon.rs:15:16 + | +LL | b: foo::bar:B, + | ^ + | +help: write a path separator here + | +LL | b: foo::bar::B, + | ~~ + +error: expected `,`, or `}`, found `:` + --> $DIR/struct-field-type-including-single-colon.rs:15:16 + | +LL | b: foo::bar:B, + | ^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/suggestions/struct-initializer-comma.fixed b/src/test/ui/suggestions/struct-initializer-comma.fixed new file mode 100644 index 000000000..6a4ee39b1 --- /dev/null +++ b/src/test/ui/suggestions/struct-initializer-comma.fixed @@ -0,0 +1,15 @@ +// run-rustfix + +pub struct Foo { + pub first: bool, + pub second: u8, +} + +fn main() { + let _ = Foo { + //~^ ERROR missing field + first: true, + second: 25 + //~^ ERROR expected one of + }; +} diff --git a/src/test/ui/suggestions/struct-initializer-comma.rs b/src/test/ui/suggestions/struct-initializer-comma.rs new file mode 100644 index 000000000..c137f0594 --- /dev/null +++ b/src/test/ui/suggestions/struct-initializer-comma.rs @@ -0,0 +1,15 @@ +// run-rustfix + +pub struct Foo { + pub first: bool, + pub second: u8, +} + +fn main() { + let _ = Foo { + //~^ ERROR missing field + first: true + second: 25 + //~^ ERROR expected one of + }; +} diff --git a/src/test/ui/suggestions/struct-initializer-comma.stderr b/src/test/ui/suggestions/struct-initializer-comma.stderr new file mode 100644 index 000000000..5eff43f32 --- /dev/null +++ b/src/test/ui/suggestions/struct-initializer-comma.stderr @@ -0,0 +1,23 @@ +error: expected one of `,`, `.`, `?`, `}`, or an operator, found `second` + --> $DIR/struct-initializer-comma.rs:12:9 + | +LL | let _ = Foo { + | --- while parsing this struct +LL | +LL | first: true + | - + | | + | expected one of `,`, `.`, `?`, `}`, or an operator + | help: try adding a comma: `,` +LL | second: 25 + | ^^^^^^ unexpected token + +error[E0063]: missing field `second` in initializer of `Foo` + --> $DIR/struct-initializer-comma.rs:9:13 + | +LL | let _ = Foo { + | ^^^ missing `second` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0063`. diff --git a/src/test/ui/suggestions/suggest-add-self.rs b/src/test/ui/suggestions/suggest-add-self.rs new file mode 100644 index 000000000..40692c8df --- /dev/null +++ b/src/test/ui/suggestions/suggest-add-self.rs @@ -0,0 +1,15 @@ +struct X(i32); + +impl X { + pub(crate) fn f() { + self.0 + //~^ ERROR expected value, found module `self` + } + + pub fn g() { + self.0 + //~^ ERROR expected value, found module `self` + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-add-self.stderr b/src/test/ui/suggestions/suggest-add-self.stderr new file mode 100644 index 000000000..a5e8f93de --- /dev/null +++ b/src/test/ui/suggestions/suggest-add-self.stderr @@ -0,0 +1,29 @@ +error[E0424]: expected value, found module `self` + --> $DIR/suggest-add-self.rs:5:9 + | +LL | pub(crate) fn f() { + | - this function doesn't have a `self` parameter +LL | self.0 + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | pub(crate) fn f(&self) { + | +++++ + +error[E0424]: expected value, found module `self` + --> $DIR/suggest-add-self.rs:10:9 + | +LL | pub fn g() { + | - this function doesn't have a `self` parameter +LL | self.0 + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | pub fn g(&self) { + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0424`. diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs new file mode 100644 index 000000000..f738a1f21 --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs @@ -0,0 +1,13 @@ +use std::cell::RefCell; + +struct HasAssocMethod; + +impl HasAssocMethod { + fn hello() {} +} +fn main() { + let shared_state = RefCell::new(HasAssocMethod); + let state = shared_state.borrow_mut(); + state.hello(); + //~^ ERROR no method named `hello` found +} diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr new file mode 100644 index 000000000..996d57731 --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr @@ -0,0 +1,19 @@ +error[E0599]: no method named `hello` found for struct `RefMut<'_, HasAssocMethod>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:11:11 + | +LL | state.hello(); + | ------^^^^^ + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `HasAssocMethod::hello` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `HasAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:6:5 + | +LL | fn hello() {} + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs new file mode 100644 index 000000000..2a829db53 --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs @@ -0,0 +1,11 @@ +struct GenericAssocMethod<T>(T); + +impl<T> GenericAssocMethod<T> { + fn default_hello() {} +} + +fn main() { + let x = GenericAssocMethod(33i32); + x.default_hello(); + //~^ ERROR no method named `default_hello` found +} diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr new file mode 100644 index 000000000..3fb418b1c --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr @@ -0,0 +1,22 @@ +error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<i32>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:9:7 + | +LL | struct GenericAssocMethod<T>(T); + | ---------------------------- method `default_hello` not found for this struct +... +LL | x.default_hello(); + | --^^^^^^^^^^^^^ + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::<i32>::default_hello` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod<T>` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:4:5 + | +LL | fn default_hello() {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/suggest-blanket-impl-local-trait.rs b/src/test/ui/suggestions/suggest-blanket-impl-local-trait.rs new file mode 100644 index 000000000..7cf536f79 --- /dev/null +++ b/src/test/ui/suggestions/suggest-blanket-impl-local-trait.rs @@ -0,0 +1,58 @@ +// Ensure that the compiler include the blanklet implementation suggestion +// when inside a `impl` statment are used two local traits. +// +// edition:2021 +use std::fmt; + +trait LocalTraitOne { } + +trait LocalTraitTwo { } + +trait GenericTrait<T> {} + +impl LocalTraitTwo for LocalTraitOne {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne` + +impl fmt::Display for LocalTraitOne { +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + todo!(); + } +} + +impl fmt::Display for LocalTraitTwo + Send { +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + todo!(); + } +} + +impl LocalTraitOne for fmt::Display {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display` + + +impl LocalTraitOne for fmt::Display + Send {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display + Send` + + +impl<E> GenericTrait<E> for LocalTraitOne {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `GenericTrait<E>` for all types that also implement `LocalTraitOne` + +trait GenericTraitTwo<T> {} + +impl<T, E> GenericTraitTwo<E> for GenericTrait<T> {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `GenericTraitTwo<E>` for all types that also implement `GenericTrait<T>` + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-blanket-impl-local-trait.stderr b/src/test/ui/suggestions/suggest-blanket-impl-local-trait.stderr new file mode 100644 index 000000000..d739a8272 --- /dev/null +++ b/src/test/ui/suggestions/suggest-blanket-impl-local-trait.stderr @@ -0,0 +1,107 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:13:24 + | +LL | impl LocalTraitTwo for LocalTraitOne {} + | ^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl LocalTraitTwo for LocalTraitOne {} +LL + impl LocalTraitTwo for dyn LocalTraitOne {} + | +help: alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne` + | +LL | impl<T: LocalTraitOne> LocalTraitTwo for T {} + | ++++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:18:23 + | +LL | impl fmt::Display for LocalTraitOne { + | ^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl fmt::Display for LocalTraitOne { +LL + impl fmt::Display for dyn LocalTraitOne { + | + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:26:23 + | +LL | impl fmt::Display for LocalTraitTwo + Send { + | ^^^^^^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl fmt::Display for LocalTraitTwo + Send { +LL + impl fmt::Display for dyn LocalTraitTwo + Send { + | + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:34:24 + | +LL | impl LocalTraitOne for fmt::Display {} + | ^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl LocalTraitOne for fmt::Display {} +LL + impl LocalTraitOne for dyn fmt::Display {} + | +help: alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display` + | +LL | impl<T: fmt::Display> LocalTraitOne for T {} + | +++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:40:24 + | +LL | impl LocalTraitOne for fmt::Display + Send {} + | ^^^^^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl LocalTraitOne for fmt::Display + Send {} +LL + impl LocalTraitOne for dyn fmt::Display + Send {} + | +help: alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display + Send` + | +LL | impl<T: fmt::Display + Send> LocalTraitOne for T {} + | ++++++++++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:46:29 + | +LL | impl<E> GenericTrait<E> for LocalTraitOne {} + | ^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl<E> GenericTrait<E> for LocalTraitOne {} +LL + impl<E> GenericTrait<E> for dyn LocalTraitOne {} + | +help: alternatively use a blanket implementation to implement `GenericTrait<E>` for all types that also implement `LocalTraitOne` + | +LL | impl<E, T: LocalTraitOne> GenericTrait<E> for T {} + | ++++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:53:35 + | +LL | impl<T, E> GenericTraitTwo<E> for GenericTrait<T> {} + | ^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl<T, E> GenericTraitTwo<E> for GenericTrait<T> {} +LL + impl<T, E> GenericTraitTwo<E> for dyn GenericTrait<T> {} + | +help: alternatively use a blanket implementation to implement `GenericTraitTwo<E>` for all types that also implement `GenericTrait<T>` + | +LL | impl<T, E, U: GenericTrait<T>> GenericTraitTwo<E> for U {} + | ++++++++++++++++++++ ~ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs new file mode 100644 index 000000000..120fc5383 --- /dev/null +++ b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs @@ -0,0 +1,16 @@ +use std::ffi::{OsStr, OsString}; +use std::path::Path; + +fn check(p: &dyn AsRef<Path>) { + let m = std::fs::metadata(&p); + println!("{:?}", &m); +} + +fn main() { + let s: OsString = ".".into(); + let s: &OsStr = &s; + check(s); + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + //~| HELP within `OsStr`, the trait `Sized` is not implemented for `[u8]` + //~| HELP consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef<Path>` +} diff --git a/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr new file mode 100644 index 000000000..6b6e40613 --- /dev/null +++ b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr @@ -0,0 +1,19 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/suggest-borrow-to-dyn-object.rs:12:11 + | +LL | check(s); + | ----- ^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: within `OsStr`, the trait `Sized` is not implemented for `[u8]` + = note: required because it appears within the type `OsStr` + = note: required for the cast from `OsStr` to the object type `dyn AsRef<Path>` +help: consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef<Path>` + | +LL | check(&s); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/suggest-box.fixed b/src/test/ui/suggestions/suggest-box.fixed new file mode 100644 index 000000000..3de02cd0b --- /dev/null +++ b/src/test/ui/suggestions/suggest-box.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +fn main() { + let _x: Box<dyn Fn() -> Result<(), ()>> = Box::new(|| { //~ ERROR mismatched types + Err(())?; + Ok(()) + }); +} diff --git a/src/test/ui/suggestions/suggest-box.rs b/src/test/ui/suggestions/suggest-box.rs new file mode 100644 index 000000000..e680a61db --- /dev/null +++ b/src/test/ui/suggestions/suggest-box.rs @@ -0,0 +1,8 @@ +// run-rustfix + +fn main() { + let _x: Box<dyn Fn() -> Result<(), ()>> = || { //~ ERROR mismatched types + Err(())?; + Ok(()) + }; +} diff --git a/src/test/ui/suggestions/suggest-box.stderr b/src/test/ui/suggestions/suggest-box.stderr new file mode 100644 index 000000000..2bdaa4e97 --- /dev/null +++ b/src/test/ui/suggestions/suggest-box.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/suggest-box.rs:4:47 + | +LL | let _x: Box<dyn Fn() -> Result<(), ()>> = || { + | _____________-------------------------------___^ + | | | + | | expected due to this +LL | | Err(())?; +LL | | Ok(()) +LL | | }; + | |_____^ expected struct `Box`, found closure + | + = note: expected struct `Box<dyn Fn() -> Result<(), ()>>` + found closure `[closure@$DIR/suggest-box.rs:4:47: 4:49]` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL ~ let _x: Box<dyn Fn() -> Result<(), ()>> = Box::new(|| { +LL | Err(())?; +LL | Ok(()) +LL ~ }); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/suggest-change-mut.rs b/src/test/ui/suggestions/suggest-change-mut.rs new file mode 100644 index 000000000..47dc7c343 --- /dev/null +++ b/src/test/ui/suggestions/suggest-change-mut.rs @@ -0,0 +1,21 @@ +#![allow(warnings)] + +use std::io::{BufRead, BufReader, Read, Write}; + +fn issue_81421<T: Read + Write>(mut stream: T) { //~ HELP consider introducing a `where` clause + let initial_message = format!("Hello world"); + let mut buffer: Vec<u8> = Vec::new(); + let bytes_written = stream.write_all(initial_message.as_bytes()); + let flush = stream.flush(); + + loop { + let mut stream_reader = BufReader::new(&stream); + //~^ ERROR the trait bound `&T: std::io::Read` is not satisfied [E0277] + //~| HELP consider removing the leading `&`-reference + //~| HELP consider changing this borrow's mutability + stream_reader.read_until(b'\n', &mut buffer).expect("Reading into buffer failed"); + //~^ ERROR the method `read_until` exists for struct `BufReader<&T>`, + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-change-mut.stderr b/src/test/ui/suggestions/suggest-change-mut.stderr new file mode 100644 index 000000000..889b11a74 --- /dev/null +++ b/src/test/ui/suggestions/suggest-change-mut.stderr @@ -0,0 +1,46 @@ +error[E0277]: the trait bound `&T: std::io::Read` is not satisfied + --> $DIR/suggest-change-mut.rs:12:48 + | +LL | let mut stream_reader = BufReader::new(&stream); + | -------------- ^^^^^^^ the trait `std::io::Read` is not implemented for `&T` + | | + | required by a bound introduced by this call + | +note: required by a bound in `BufReader::<R>::new` + --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL + | +LL | impl<R: Read> BufReader<R> { + | ^^^^ required by this bound in `BufReader::<R>::new` +help: consider removing the leading `&`-reference + | +LL - let mut stream_reader = BufReader::new(&stream); +LL + let mut stream_reader = BufReader::new(stream); + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn issue_81421<T: Read + Write>(mut stream: T) where &T: std::io::Read { + | +++++++++++++++++++++++ +help: consider changing this borrow's mutability + | +LL | let mut stream_reader = BufReader::new(&mut stream); + | ~~~~ + +error[E0599]: the method `read_until` exists for struct `BufReader<&T>`, but its trait bounds were not satisfied + --> $DIR/suggest-change-mut.rs:16:23 + | +LL | stream_reader.read_until(b'\n', &mut buffer).expect("Reading into buffer failed"); + | ^^^^^^^^^^ method cannot be called on `BufReader<&T>` due to unsatisfied trait bounds + | + ::: $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL + | +LL | pub struct BufReader<R> { + | ----------------------- doesn't satisfy `BufReader<&T>: BufRead` + | + = note: the following trait bounds were not satisfied: + `&T: std::io::Read` + which is required by `BufReader<&T>: BufRead` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/suggest-closure-return-type-1.rs b/src/test/ui/suggestions/suggest-closure-return-type-1.rs new file mode 100644 index 000000000..8bb421903 --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-1.rs @@ -0,0 +1,7 @@ +fn unbound_drop(_: impl Sized) {} + +fn main() { + unbound_drop(|| -> _ { [] }); + //~^ ERROR type annotations needed for `[_; 0]` + //~| HELP try giving this closure an explicit return type +} diff --git a/src/test/ui/suggestions/suggest-closure-return-type-1.stderr b/src/test/ui/suggestions/suggest-closure-return-type-1.stderr new file mode 100644 index 000000000..f4c2eb7ff --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-1.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `[_; 0]` + --> $DIR/suggest-closure-return-type-1.rs:4:18 + | +LL | unbound_drop(|| -> _ { [] }); + | ^^^^^^^ -- type must be known at this point + | +help: try giving this closure an explicit return type + | +LL | unbound_drop(|| -> [_; 0] { [] }); + | ~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/suggestions/suggest-closure-return-type-2.rs b/src/test/ui/suggestions/suggest-closure-return-type-2.rs new file mode 100644 index 000000000..25ed1882e --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-2.rs @@ -0,0 +1,7 @@ +fn unbound_drop(_: impl Sized) {} + +fn main() { + unbound_drop(|| { [] }) + //~^ ERROR type annotations needed for `[_; 0]` + //~| HELP try giving this closure an explicit return type +} diff --git a/src/test/ui/suggestions/suggest-closure-return-type-2.stderr b/src/test/ui/suggestions/suggest-closure-return-type-2.stderr new file mode 100644 index 000000000..88bf26304 --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-2.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `[_; 0]` + --> $DIR/suggest-closure-return-type-2.rs:4:18 + | +LL | unbound_drop(|| { [] }) + | ^^ -- type must be known at this point + | +help: try giving this closure an explicit return type + | +LL | unbound_drop(|| -> [_; 0] { [] }) + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/suggestions/suggest-closure-return-type-3.rs b/src/test/ui/suggestions/suggest-closure-return-type-3.rs new file mode 100644 index 000000000..3de6c55cf --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-3.rs @@ -0,0 +1,7 @@ +fn unbound_drop(_: impl Sized) {} + +fn main() { + unbound_drop(|| []); + //~^ ERROR type annotations needed for `[_; 0]` + //~| HELP try giving this closure an explicit return type +} diff --git a/src/test/ui/suggestions/suggest-closure-return-type-3.stderr b/src/test/ui/suggestions/suggest-closure-return-type-3.stderr new file mode 100644 index 000000000..bc4107528 --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-3.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `[_; 0]` + --> $DIR/suggest-closure-return-type-3.rs:4:18 + | +LL | unbound_drop(|| []); + | ^^ -- type must be known at this point + | +help: try giving this closure an explicit return type + | +LL | unbound_drop(|| -> [_; 0] { [] }); + | +++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/suggestions/suggest-dereferencing-index.fixed b/src/test/ui/suggestions/suggest-dereferencing-index.fixed new file mode 100644 index 000000000..dd4ae4eb1 --- /dev/null +++ b/src/test/ui/suggestions/suggest-dereferencing-index.fixed @@ -0,0 +1,7 @@ +// run-rustfix +#![allow(unused_variables)] + +fn main() { + let i: &usize = &1; + let one_item_please: i32 = [1, 2, 3][*i]; //~ ERROR the type `[{integer}]` cannot be indexed by `&usize` +} diff --git a/src/test/ui/suggestions/suggest-dereferencing-index.rs b/src/test/ui/suggestions/suggest-dereferencing-index.rs new file mode 100644 index 000000000..82ebacc49 --- /dev/null +++ b/src/test/ui/suggestions/suggest-dereferencing-index.rs @@ -0,0 +1,7 @@ +// run-rustfix +#![allow(unused_variables)] + +fn main() { + let i: &usize = &1; + let one_item_please: i32 = [1, 2, 3][i]; //~ ERROR the type `[{integer}]` cannot be indexed by `&usize` +} diff --git a/src/test/ui/suggestions/suggest-dereferencing-index.stderr b/src/test/ui/suggestions/suggest-dereferencing-index.stderr new file mode 100644 index 000000000..c8b87af7b --- /dev/null +++ b/src/test/ui/suggestions/suggest-dereferencing-index.stderr @@ -0,0 +1,17 @@ +error[E0277]: the type `[{integer}]` cannot be indexed by `&usize` + --> $DIR/suggest-dereferencing-index.rs:6:42 + | +LL | let one_item_please: i32 = [1, 2, 3][i]; + | ^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required because of the requirements on the impl of `Index<&usize>` for `[{integer}]` +help: dereference this index + | +LL | let one_item_please: i32 = [1, 2, 3][*i]; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.rs b/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.rs new file mode 100644 index 000000000..1dfc07866 --- /dev/null +++ b/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.rs @@ -0,0 +1,10 @@ +mod option { + pub enum O<T> { + Some(T), + None, + } +} + +fn main() { + let _: option::O<()> = (); //~ ERROR 9:28: 9:30: mismatched types [E0308] +} diff --git a/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr b/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr new file mode 100644 index 000000000..9b6dba7e9 --- /dev/null +++ b/src/test/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/suggest-full-enum-variant-for-local-module.rs:9:28 + | +LL | let _: option::O<()> = (); + | ------------- ^^ expected enum `O`, found `()` + | | + | expected due to this + | + = note: expected enum `O<()>` + found unit type `()` +help: try wrapping the expression in `option::O::Some` + | +LL | let _: option::O<()> = option::O::Some(()); + | ++++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.rs b/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.rs new file mode 100644 index 000000000..a62669d5b --- /dev/null +++ b/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.rs @@ -0,0 +1,23 @@ +trait Trait {} + +struct A; +struct B; +struct C; + +impl Trait for &A {} +impl Trait for &mut A {} + +impl Trait for &B {} + +impl Trait for &mut C {} + +fn foo<X: Trait>(_: X) {} + +fn main() { + let a = A; + let b = B; + let c = C; + foo(a); //~ ERROR the trait bound `A: Trait` is not satisfied + foo(b); //~ ERROR the trait bound `B: Trait` is not satisfied + foo(c); //~ ERROR the trait bound `C: Trait` is not satisfied +} diff --git a/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.stderr b/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.stderr new file mode 100644 index 000000000..6583cabe1 --- /dev/null +++ b/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.stderr @@ -0,0 +1,59 @@ +error[E0277]: the trait bound `A: Trait` is not satisfied + --> $DIR/suggest-imm-mut-trait-implementations.rs:20:9 + | +LL | foo(a); + | --- ^ expected an implementor of trait `Trait` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/suggest-imm-mut-trait-implementations.rs:14:11 + | +LL | fn foo<X: Trait>(_: X) {} + | ^^^^^ required by this bound in `foo` +help: consider borrowing here + | +LL | foo(&a); + | + +LL | foo(&mut a); + | ++++ + +error[E0277]: the trait bound `B: Trait` is not satisfied + --> $DIR/suggest-imm-mut-trait-implementations.rs:21:9 + | +LL | foo(b); + | --- ^ expected an implementor of trait `Trait` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/suggest-imm-mut-trait-implementations.rs:14:11 + | +LL | fn foo<X: Trait>(_: X) {} + | ^^^^^ required by this bound in `foo` +help: consider borrowing here + | +LL | foo(&b); + | + + +error[E0277]: the trait bound `C: Trait` is not satisfied + --> $DIR/suggest-imm-mut-trait-implementations.rs:22:9 + | +LL | foo(c); + | --- ^ expected an implementor of trait `Trait` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/suggest-imm-mut-trait-implementations.rs:14:11 + | +LL | fn foo<X: Trait>(_: X) {} + | ^^^^^ required by this bound in `foo` +help: consider mutably borrowing here + | +LL | foo(&mut c); + | ++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed b/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed new file mode 100644 index 000000000..589ee1a47 --- /dev/null +++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed @@ -0,0 +1,18 @@ +// run-rustfix + +use std::fmt::Debug; + +fn foo(d: impl Debug + 'static) { +//~^ HELP consider adding an explicit lifetime bound... + bar(d); +//~^ ERROR the parameter type `impl Debug` may not live long enough +//~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds +} + +fn bar(d: impl Debug + 'static) { + println!("{:?}", d) +} + +fn main() { + foo("hi"); +} diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs b/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs new file mode 100644 index 000000000..9a87129fb --- /dev/null +++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs @@ -0,0 +1,18 @@ +// run-rustfix + +use std::fmt::Debug; + +fn foo(d: impl Debug) { +//~^ HELP consider adding an explicit lifetime bound... + bar(d); +//~^ ERROR the parameter type `impl Debug` may not live long enough +//~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds +} + +fn bar(d: impl Debug + 'static) { + println!("{:?}", d) +} + +fn main() { + foo("hi"); +} diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr new file mode 100644 index 000000000..cf912f4aa --- /dev/null +++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `impl Debug` may not live long enough + --> $DIR/suggest-impl-trait-lifetime.rs:7:5 + | +LL | bar(d); + | ^^^^^^ ...so that the type `impl Debug` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn foo(d: impl Debug + 'static) { + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/suggestions/suggest-labels.rs b/src/test/ui/suggestions/suggest-labels.rs new file mode 100644 index 000000000..159f45855 --- /dev/null +++ b/src/test/ui/suggestions/suggest-labels.rs @@ -0,0 +1,16 @@ +#[allow(unreachable_code, unused_labels)] +fn main() { + 'foo: loop { + break 'fo; //~ ERROR use of undeclared label + } + + 'bar: loop { + continue 'bor; //~ ERROR use of undeclared label + } + + 'longlabel: loop { + 'longlabel1: loop { + break 'longlable; //~ ERROR use of undeclared label + } + } +} diff --git a/src/test/ui/suggestions/suggest-labels.stderr b/src/test/ui/suggestions/suggest-labels.stderr new file mode 100644 index 000000000..aac6515b5 --- /dev/null +++ b/src/test/ui/suggestions/suggest-labels.stderr @@ -0,0 +1,36 @@ +error[E0426]: use of undeclared label `'fo` + --> $DIR/suggest-labels.rs:4:15 + | +LL | 'foo: loop { + | ---- a label with a similar name is reachable +LL | break 'fo; + | ^^^ + | | + | undeclared label `'fo` + | help: try using similarly named label: `'foo` + +error[E0426]: use of undeclared label `'bor` + --> $DIR/suggest-labels.rs:8:18 + | +LL | 'bar: loop { + | ---- a label with a similar name is reachable +LL | continue 'bor; + | ^^^^ + | | + | undeclared label `'bor` + | help: try using similarly named label: `'bar` + +error[E0426]: use of undeclared label `'longlable` + --> $DIR/suggest-labels.rs:13:19 + | +LL | 'longlabel1: loop { + | ----------- a label with a similar name is reachable +LL | break 'longlable; + | ^^^^^^^^^^ + | | + | undeclared label `'longlable` + | help: try using similarly named label: `'longlabel1` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0426`. diff --git a/src/test/ui/suggestions/suggest-methods.rs b/src/test/ui/suggestions/suggest-methods.rs new file mode 100644 index 000000000..f40b9ed99 --- /dev/null +++ b/src/test/ui/suggestions/suggest-methods.rs @@ -0,0 +1,30 @@ +struct Foo; + +impl Foo { + fn bar(self) {} + fn baz(&self, x: f64) {} +} + +trait FooT { + fn bag(&self); +} + +impl FooT for Foo { + fn bag(&self) {} +} + +fn main() { + let f = Foo; + f.bat(1.0); //~ ERROR no method named + + let s = "foo".to_string(); + let _ = s.is_emtpy(); //~ ERROR no method named + + // Generates a warning for `count_zeros()`. `count_ones()` is also a close + // match, but the former is closer. + let _ = 63u32.count_eos(); //~ ERROR no method named + + // Does not generate a warning + let _ = 63u32.count_o(); //~ ERROR no method named + +} diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr new file mode 100644 index 000000000..97d7e6696 --- /dev/null +++ b/src/test/ui/suggestions/suggest-methods.stderr @@ -0,0 +1,30 @@ +error[E0599]: no method named `bat` found for struct `Foo` in the current scope + --> $DIR/suggest-methods.rs:18:7 + | +LL | struct Foo; + | ---------- method `bat` not found for this struct +... +LL | f.bat(1.0); + | ^^^ help: there is an associated function with a similar name: `bar` + +error[E0599]: no method named `is_emtpy` found for struct `String` in the current scope + --> $DIR/suggest-methods.rs:21:15 + | +LL | let _ = s.is_emtpy(); + | ^^^^^^^^ help: there is an associated function with a similar name: `is_empty` + +error[E0599]: no method named `count_eos` found for type `u32` in the current scope + --> $DIR/suggest-methods.rs:25:19 + | +LL | let _ = 63u32.count_eos(); + | ^^^^^^^^^ help: there is an associated function with a similar name: `count_zeros` + +error[E0599]: no method named `count_o` found for type `u32` in the current scope + --> $DIR/suggest-methods.rs:28:19 + | +LL | let _ = 63u32.count_o(); + | ^^^^^^^ help: there is an associated function with a similar name: `count_ones` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.rs b/src/test/ui/suggestions/suggest-move-lifetimes.rs new file mode 100644 index 000000000..6b26f1214 --- /dev/null +++ b/src/test/ui/suggestions/suggest-move-lifetimes.rs @@ -0,0 +1,21 @@ +struct A<T, 'a> { //~ ERROR lifetime parameters must be declared + t: &'a T, +} + +struct B<T, 'a, U> { //~ ERROR lifetime parameters must be declared + t: &'a T, + u: U, +} + +struct C<T, U, 'a> { //~ ERROR lifetime parameters must be declared + t: &'a T, + u: U, +} + +struct D<T, U, 'a, 'b, V, 'c> { //~ ERROR lifetime parameters must be declared + t: &'a T, + u: &'b U, + v: &'c V, +} + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr new file mode 100644 index 000000000..f52631cae --- /dev/null +++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr @@ -0,0 +1,26 @@ +error: lifetime parameters must be declared prior to type parameters + --> $DIR/suggest-move-lifetimes.rs:1:13 + | +LL | struct A<T, 'a> { + | ----^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T>` + +error: lifetime parameters must be declared prior to type parameters + --> $DIR/suggest-move-lifetimes.rs:5:13 + | +LL | struct B<T, 'a, U> { + | ----^^---- help: reorder the parameters: lifetimes, then consts and types: `<'a, T, U>` + +error: lifetime parameters must be declared prior to type parameters + --> $DIR/suggest-move-lifetimes.rs:10:16 + | +LL | struct C<T, U, 'a> { + | -------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T, U>` + +error: lifetime parameters must be declared prior to type parameters + --> $DIR/suggest-move-lifetimes.rs:15:16 + | +LL | struct D<T, U, 'a, 'b, V, 'c> { + | -------^^--^^-----^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, 'c, T, U, V>` + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/suggestions/suggest-move-types.rs b/src/test/ui/suggestions/suggest-move-types.rs new file mode 100644 index 000000000..27930626a --- /dev/null +++ b/src/test/ui/suggestions/suggest-move-types.rs @@ -0,0 +1,91 @@ +#![allow(warnings)] + +// This test verifies that the suggestion to move types before associated type bindings +// is correct. + +trait One<T> { + type A; +} + +trait OneWithLifetime<'a, T> { + type A; +} + +trait Three<T, U, V> { + type A; + type B; + type C; +} + +trait ThreeWithLifetime<'a, 'b, 'c, T, U, V> { + type A; + type B; + type C; +} + +struct A<T, M: One<A=(), T>> { +//~^ ERROR generic arguments must come before the first constraint + m: M, + t: T, +} + + +struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> { +//~^ ERROR generic arguments must come before the first constraint +//~^^ ERROR type provided when a lifetime was expected + m: M, + t: &'a T, +} + +struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> { +//~^ ERROR generic arguments must come before the first constraint + m: M, + t: T, + u: U, + v: V, +} + +struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> { +//~^ ERROR generic arguments must come before the first constraint +//~^^ ERROR type provided when a lifetime was expected + m: M, + t: &'a T, + u: &'b U, + v: &'c V, +} + +struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> { +//~^ ERROR generic arguments must come before the first constraint + m: M, + t: T, + u: U, + v: V, +} + +struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> { +//~^ ERROR generic arguments must come before the first constraint +//~^^ ERROR lifetime provided when a type was expected + m: M, + t: &'a T, + u: &'b U, + v: &'c V, +} + +struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> { +//~^ ERROR generic arguments must come before the first constraint + m: M, + t: T, + u: U, + v: V, +} + +struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> { +//~^ ERROR generic arguments must come before the first constraint +//~^^ ERROR lifetime provided when a type was expected + m: M, + t: &'a T, + u: &'b U, + v: &'c V, +} + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-move-types.stderr b/src/test/ui/suggestions/suggest-move-types.stderr new file mode 100644 index 000000000..1a6032db0 --- /dev/null +++ b/src/test/ui/suggestions/suggest-move-types.stderr @@ -0,0 +1,137 @@ +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:26:26 + | +LL | struct A<T, M: One<A=(), T>> { + | ---- ^ generic argument + | | + | constraint + | +help: move the constraint after the generic argument + | +LL | struct A<T, M: One<T, A = ()>> { + | ~~~~~~~~~~~ + +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:33:43 + | +LL | struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> { + | ---- ^ ^^ generic arguments + | | + | constraint + | +help: move the constraint after the generic arguments + | +LL | struct Al<'a, T, M: OneWithLifetime<'a, T, A = ()>> { + | ~~~~~~~~~~~~~~~ + +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:40:46 + | +LL | struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> { + | ---- ---- ---- ^ ^ ^ generic arguments + | | + | constraints + | +help: move the constraints after the generic arguments + | +LL | struct B<T, U, V, M: Three<T, U, V, A = (), B = (), C = ()>> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:48:71 + | +LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> { + | ---- ---- ---- ^ ^ ^ ^^ ^^ ^^ generic arguments + | | + | constraints + | +help: move the constraints after the generic arguments + | +LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:57:28 + | +LL | struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> { + | ^ ---- ---- ---- ^ ^ generic arguments + | | + | constraints + | +help: move the constraints after the generic arguments + | +LL | struct C<T, U, V, M: Three<T, U, V, A = (), B = (), C = ()>> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:65:53 + | +LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> { + | ^ ^^ ---- ---- ---- ^ ^^ ^ ^^ generic arguments + | | + | constraints + | +help: move the constraints after the generic arguments + | +LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:74:28 + | +LL | struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> { + | ^ ---- ---- ^ ---- ^ generic arguments + | | + | constraints + | +help: move the constraints after the generic arguments + | +LL | struct D<T, U, V, M: Three<T, U, V, A = (), B = (), C = ()>> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:82:53 + | +LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> { + | ^ ^^ ---- ---- ^ ^^ ---- ^ ^^ generic arguments + | | + | constraints + | +help: move the constraints after the generic arguments + | +LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0747]: type provided when a lifetime was expected + --> $DIR/suggest-move-types.rs:33:43 + | +LL | struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> { + | ^ + +error[E0747]: type provided when a lifetime was expected + --> $DIR/suggest-move-types.rs:48:71 + | +LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> { + | ^ + +error[E0747]: lifetime provided when a type was expected + --> $DIR/suggest-move-types.rs:65:56 + | +LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> { + | ^^ + | + = note: lifetime arguments must be provided before type arguments + = help: reorder the arguments: lifetimes, then types: `<'a, 'b, 'c, T, U, V>` + +error[E0747]: lifetime provided when a type was expected + --> $DIR/suggest-move-types.rs:82:56 + | +LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> { + | ^^ + | + = note: lifetime arguments must be provided before type arguments + = help: reorder the arguments: lifetimes, then types: `<'a, 'b, 'c, T, U, V>` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed new file mode 100644 index 000000000..b69bad988 --- /dev/null +++ b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed @@ -0,0 +1,21 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/82081 + +use std::collections::HashMap; + +struct Test { + v: u32, +} + +fn main() { + let mut map = HashMap::new(); + map.insert("a", Test { v: 0 }); + + for (_k, mut v) in map.iter_mut() { + //~^ HELP use mutable method + //~| NOTE this iterator yields `&` references + v.v += 1; + //~^ ERROR cannot assign to `v.v` + //~| NOTE `v` is a `&` reference + } +} diff --git a/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs new file mode 100644 index 000000000..9284410df --- /dev/null +++ b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs @@ -0,0 +1,21 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/82081 + +use std::collections::HashMap; + +struct Test { + v: u32, +} + +fn main() { + let mut map = HashMap::new(); + map.insert("a", Test { v: 0 }); + + for (_k, mut v) in map.iter() { + //~^ HELP use mutable method + //~| NOTE this iterator yields `&` references + v.v += 1; + //~^ ERROR cannot assign to `v.v` + //~| NOTE `v` is a `&` reference + } +} diff --git a/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr new file mode 100644 index 000000000..74433daa6 --- /dev/null +++ b/src/test/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr @@ -0,0 +1,15 @@ +error[E0594]: cannot assign to `v.v`, which is behind a `&` reference + --> $DIR/suggest-mut-method-for-loop-hashmap.rs:17:9 + | +LL | for (_k, mut v) in map.iter() { + | ---------- + | | | + | | help: use mutable method: `iter_mut()` + | this iterator yields `&` references +... +LL | v.v += 1; + | ^^^^^^^^ `v` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/suggestions/suggest-mut-method-for-loop.rs b/src/test/ui/suggestions/suggest-mut-method-for-loop.rs new file mode 100644 index 000000000..756768bce --- /dev/null +++ b/src/test/ui/suggestions/suggest-mut-method-for-loop.rs @@ -0,0 +1,17 @@ +use std::collections::HashMap; +struct X(usize); +struct Y { + v: u32 +} + +fn main() { + let mut buzz = HashMap::new(); + buzz.insert("a", Y { v: 0 }); + + for mut t in buzz.values() { + //~^ HELP + //~| SUGGESTION values_mut() + t.v += 1; + //~^ ERROR cannot assign + } +} diff --git a/src/test/ui/suggestions/suggest-mut-method-for-loop.stderr b/src/test/ui/suggestions/suggest-mut-method-for-loop.stderr new file mode 100644 index 000000000..3eb9e1031 --- /dev/null +++ b/src/test/ui/suggestions/suggest-mut-method-for-loop.stderr @@ -0,0 +1,15 @@ +error[E0594]: cannot assign to `t.v`, which is behind a `&` reference + --> $DIR/suggest-mut-method-for-loop.rs:14:9 + | +LL | for mut t in buzz.values() { + | ------------- + | | | + | | help: use mutable method: `values_mut()` + | this iterator yields `&` references +... +LL | t.v += 1; + | ^^^^^^^^ `t` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/suggestions/suggest-on-bare-closure-call.rs b/src/test/ui/suggestions/suggest-on-bare-closure-call.rs new file mode 100644 index 000000000..496c305bc --- /dev/null +++ b/src/test/ui/suggestions/suggest-on-bare-closure-call.rs @@ -0,0 +1,11 @@ +// edition:2021 + +#![feature(async_closure)] + +fn main() { + let _ = ||{}(); + //~^ ERROR expected function, found `()` + + let _ = async ||{}(); + //~^ ERROR expected function, found `()` +} diff --git a/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr b/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr new file mode 100644 index 000000000..e65a6eb49 --- /dev/null +++ b/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr @@ -0,0 +1,29 @@ +error[E0618]: expected function, found `()` + --> $DIR/suggest-on-bare-closure-call.rs:6:15 + | +LL | let _ = ||{}(); + | ^^-- + | | + | call expression requires function + | +help: if you meant to create this closure and immediately call it, surround the closure with parentheses + | +LL | let _ = (||{})(); + | + + + +error[E0618]: expected function, found `()` + --> $DIR/suggest-on-bare-closure-call.rs:9:21 + | +LL | let _ = async ||{}(); + | ^^-- + | | + | call expression requires function + | +help: if you meant to create this closure and immediately call it, surround the closure with parentheses + | +LL | let _ = (async ||{})(); + | + + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0618`. diff --git a/src/test/ui/suggestions/suggest-ref-macro.rs b/src/test/ui/suggestions/suggest-ref-macro.rs new file mode 100644 index 000000000..6f780f32a --- /dev/null +++ b/src/test/ui/suggestions/suggest-ref-macro.rs @@ -0,0 +1,29 @@ +// run-check +// aux-build:proc-macro-type-error.rs + +extern crate proc_macro_type_error; + +use proc_macro_type_error::hello; + +#[hello] //~ERROR mismatched types +fn abc() {} + +fn x(_: &mut i32) {} + +macro_rules! bla { + () => { + x(123); + //~^ ERROR mismatched types + //~| SUGGESTION &mut 123 + }; + ($v:expr) => { + x($v) + } +} + +fn main() { + bla!(); + bla!(456); + //~^ ERROR mismatched types + //~| SUGGESTION &mut 456 +} diff --git a/src/test/ui/suggestions/suggest-ref-macro.stderr b/src/test/ui/suggestions/suggest-ref-macro.stderr new file mode 100644 index 000000000..84cbc9357 --- /dev/null +++ b/src/test/ui/suggestions/suggest-ref-macro.stderr @@ -0,0 +1,63 @@ +error[E0308]: mismatched types + --> $DIR/suggest-ref-macro.rs:8:1 + | +LL | #[hello] + | ^^^^^^^^ + | | + | expected `&mut i32`, found integer + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/suggest-ref-macro.rs:8:1 + | +LL | #[hello] + | _-^^^^^^^ +LL | | fn abc() {} +LL | | +LL | | fn x(_: &mut i32) {} +LL | | +LL | | macro_rules! bla { + | |_____________- + = note: this error originates in the attribute macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/suggest-ref-macro.rs:15:11 + | +LL | x(123); + | - ^^^ + | | | + | | expected `&mut i32`, found integer + | | help: consider mutably borrowing here: `&mut 123` + | arguments to this function are incorrect +... +LL | bla!(); + | ------ in this macro invocation + | +note: function defined here + --> $DIR/suggest-ref-macro.rs:11:4 + | +LL | fn x(_: &mut i32) {} + | ^ ----------- + = note: this error originates in the macro `bla` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/suggest-ref-macro.rs:26:10 + | +LL | x($v) + | - arguments to this function are incorrect +... +LL | bla!(456); + | ^^^ + | | + | expected `&mut i32`, found integer + | help: consider mutably borrowing here: `&mut 456` + | +note: function defined here + --> $DIR/suggest-ref-macro.rs:11:4 + | +LL | fn x(_: &mut i32) {} + | ^ ----------- + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/suggest-ref-mut.rs b/src/test/ui/suggestions/suggest-ref-mut.rs new file mode 100644 index 000000000..d04113ffc --- /dev/null +++ b/src/test/ui/suggestions/suggest-ref-mut.rs @@ -0,0 +1,30 @@ +struct X(usize); + +impl X { + fn zap(&self) { + //~^ HELP + //~| SUGGESTION &mut self + self.0 = 32; + //~^ ERROR + } +} + +fn main() { + let ref foo = 16; + //~^ HELP + //~| SUGGESTION ref mut foo + *foo = 32; + //~^ ERROR + if let Some(ref bar) = Some(16) { + //~^ HELP + //~| SUGGESTION ref mut bar + *bar = 32; + //~^ ERROR + } + match 16 { + ref quo => { *quo = 32; }, + //~^ ERROR + //~| HELP + //~| SUGGESTION ref mut quo + } +} diff --git a/src/test/ui/suggestions/suggest-ref-mut.stderr b/src/test/ui/suggestions/suggest-ref-mut.stderr new file mode 100644 index 000000000..9fd2658ec --- /dev/null +++ b/src/test/ui/suggestions/suggest-ref-mut.stderr @@ -0,0 +1,38 @@ +error[E0594]: cannot assign to `self.0`, which is behind a `&` reference + --> $DIR/suggest-ref-mut.rs:7:9 + | +LL | fn zap(&self) { + | ----- help: consider changing this to be a mutable reference: `&mut self` +... +LL | self.0 = 32; + | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + +error[E0594]: cannot assign to `*foo`, which is behind a `&` reference + --> $DIR/suggest-ref-mut.rs:16:5 + | +LL | let ref foo = 16; + | ------- help: consider changing this to be a mutable reference: `ref mut foo` +... +LL | *foo = 32; + | ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written + +error[E0594]: cannot assign to `*bar`, which is behind a `&` reference + --> $DIR/suggest-ref-mut.rs:21:9 + | +LL | if let Some(ref bar) = Some(16) { + | ------- help: consider changing this to be a mutable reference: `ref mut bar` +... +LL | *bar = 32; + | ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written + +error[E0594]: cannot assign to `*quo`, which is behind a `&` reference + --> $DIR/suggest-ref-mut.rs:25:22 + | +LL | ref quo => { *quo = 32; }, + | ------- ^^^^^^^^^ `quo` is a `&` reference, so the data it refers to cannot be written + | | + | help: consider changing this to be a mutable reference: `ref mut quo` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/suggestions/suggest-remove-refs-1.fixed b/src/test/ui/suggestions/suggest-remove-refs-1.fixed new file mode 100644 index 000000000..a39e0fbd1 --- /dev/null +++ b/src/test/ui/suggestions/suggest-remove-refs-1.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, _) in v.iter().enumerate() { + //~^ ERROR `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator + println!("{}", i); + } +} diff --git a/src/test/ui/suggestions/suggest-remove-refs-1.rs b/src/test/ui/suggestions/suggest-remove-refs-1.rs new file mode 100644 index 000000000..6f767f2c1 --- /dev/null +++ b/src/test/ui/suggestions/suggest-remove-refs-1.rs @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, _) in &v.iter().enumerate() { + //~^ ERROR `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator + println!("{}", i); + } +} diff --git a/src/test/ui/suggestions/suggest-remove-refs-1.stderr b/src/test/ui/suggestions/suggest-remove-refs-1.stderr new file mode 100644 index 000000000..1083b2f97 --- /dev/null +++ b/src/test/ui/suggestions/suggest-remove-refs-1.stderr @@ -0,0 +1,15 @@ +error[E0277]: `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator + --> $DIR/suggest-remove-refs-1.rs:6:19 + | +LL | for (i, _) in &v.iter().enumerate() { + | -^^^^^^^^^^^^^^^^^^^^ + | | + | `&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator + | help: consider removing the leading `&`-reference + | + = help: the trait `Iterator` is not implemented for `&Enumerate<std::slice::Iter<'_, {integer}>>` + = note: required because of the requirements on the impl of `IntoIterator` for `&Enumerate<std::slice::Iter<'_, {integer}>>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/suggest-remove-refs-2.fixed b/src/test/ui/suggestions/suggest-remove-refs-2.fixed new file mode 100644 index 000000000..0f9c3abfe --- /dev/null +++ b/src/test/ui/suggestions/suggest-remove-refs-2.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, _) in v.iter().enumerate() { + //~^ ERROR `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator + println!("{}", i); + } +} diff --git a/src/test/ui/suggestions/suggest-remove-refs-2.rs b/src/test/ui/suggestions/suggest-remove-refs-2.rs new file mode 100644 index 000000000..6c94b12d2 --- /dev/null +++ b/src/test/ui/suggestions/suggest-remove-refs-2.rs @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, _) in & & & & &v.iter().enumerate() { + //~^ ERROR `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator + println!("{}", i); + } +} diff --git a/src/test/ui/suggestions/suggest-remove-refs-2.stderr b/src/test/ui/suggestions/suggest-remove-refs-2.stderr new file mode 100644 index 000000000..197b19a1b --- /dev/null +++ b/src/test/ui/suggestions/suggest-remove-refs-2.stderr @@ -0,0 +1,15 @@ +error[E0277]: `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator + --> $DIR/suggest-remove-refs-2.rs:6:19 + | +LL | for (i, _) in & & & & &v.iter().enumerate() { + | ---------^^^^^^^^^^^^^^^^^^^^ + | | + | `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator + | help: consider removing 5 leading `&`-references + | + = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` + = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/suggest-remove-refs-3.fixed b/src/test/ui/suggestions/suggest-remove-refs-3.fixed new file mode 100644 index 000000000..3148fcbe5 --- /dev/null +++ b/src/test/ui/suggestions/suggest-remove-refs-3.fixed @@ -0,0 +1,12 @@ +// run-rustfix + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, _) in v + .iter() + .enumerate() { + //~^^^^ ERROR `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an + println!("{}", i); + } +} diff --git a/src/test/ui/suggestions/suggest-remove-refs-3.rs b/src/test/ui/suggestions/suggest-remove-refs-3.rs new file mode 100644 index 000000000..0622adada --- /dev/null +++ b/src/test/ui/suggestions/suggest-remove-refs-3.rs @@ -0,0 +1,13 @@ +// run-rustfix + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, _) in & & & + & &v + .iter() + .enumerate() { + //~^^^^ ERROR `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an + println!("{}", i); + } +} diff --git a/src/test/ui/suggestions/suggest-remove-refs-3.stderr b/src/test/ui/suggestions/suggest-remove-refs-3.stderr new file mode 100644 index 000000000..bb0cceac1 --- /dev/null +++ b/src/test/ui/suggestions/suggest-remove-refs-3.stderr @@ -0,0 +1,19 @@ +error[E0277]: `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator + --> $DIR/suggest-remove-refs-3.rs:6:19 + | +LL | for (i, _) in & & & + | ___________________^ + | |___________________| + | || +LL | || & &v + | ||___________- help: consider removing 5 leading `&`-references +LL | | .iter() +LL | | .enumerate() { + | |_____________________^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator + | + = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` + = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.fixed b/src/test/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.fixed new file mode 100644 index 000000000..5c55566ff --- /dev/null +++ b/src/test/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +#[allow(dead_code)] + +extern "C" { + fn foo(); //~ERROR expected `;` +} + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.rs b/src/test/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.rs new file mode 100644 index 000000000..91971cba3 --- /dev/null +++ b/src/test/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.rs @@ -0,0 +1,9 @@ +// run-rustfix + +#[allow(dead_code)] + +extern "C" { + fn foo() //~ERROR expected `;` +} + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr b/src/test/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr new file mode 100644 index 000000000..c5df72c4a --- /dev/null +++ b/src/test/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr @@ -0,0 +1,10 @@ +error: expected `;`, found `}` + --> $DIR/suggest-semicolon-for-fn-in-extern-block.rs:6:11 + | +LL | fn foo() + | ^ help: add `;` here +LL | } + | - unexpected token + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/suggest-split-at-mut.rs b/src/test/ui/suggestions/suggest-split-at-mut.rs new file mode 100644 index 000000000..d294c20b8 --- /dev/null +++ b/src/test/ui/suggestions/suggest-split-at-mut.rs @@ -0,0 +1,8 @@ +fn main() { + let mut foo = [1, 2, 3, 4]; + let a = &mut foo[2]; + let b = &mut foo[3]; //~ ERROR cannot borrow `foo[_]` as mutable more than once at a time + *a = 5; + *b = 6; + println!("{:?} {:?}", a, b); +} diff --git a/src/test/ui/suggestions/suggest-split-at-mut.stderr b/src/test/ui/suggestions/suggest-split-at-mut.stderr new file mode 100644 index 000000000..330f012b2 --- /dev/null +++ b/src/test/ui/suggestions/suggest-split-at-mut.stderr @@ -0,0 +1,15 @@ +error[E0499]: cannot borrow `foo[_]` as mutable more than once at a time + --> $DIR/suggest-split-at-mut.rs:4:13 + | +LL | let a = &mut foo[2]; + | ----------- first mutable borrow occurs here +LL | let b = &mut foo[3]; + | ^^^^^^^^^^^ second mutable borrow occurs here +LL | *a = 5; + | ------ first borrow later used here + | + = help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/suggestions/suggest-std-when-using-type.fixed b/src/test/ui/suggestions/suggest-std-when-using-type.fixed new file mode 100644 index 000000000..102c5c186 --- /dev/null +++ b/src/test/ui/suggestions/suggest-std-when-using-type.fixed @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + let pi = std::f32::consts::PI; //~ ERROR ambiguous associated type + let bytes = "hello world".as_bytes(); + let string = std::str::from_utf8(bytes).unwrap(); + //~^ ERROR no function or associated item named `from_utf8` found + println!("{pi} {bytes:?} {string}"); +} diff --git a/src/test/ui/suggestions/suggest-std-when-using-type.rs b/src/test/ui/suggestions/suggest-std-when-using-type.rs new file mode 100644 index 000000000..5abc016de --- /dev/null +++ b/src/test/ui/suggestions/suggest-std-when-using-type.rs @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + let pi = f32::consts::PI; //~ ERROR ambiguous associated type + let bytes = "hello world".as_bytes(); + let string = str::from_utf8(bytes).unwrap(); + //~^ ERROR no function or associated item named `from_utf8` found + println!("{pi} {bytes:?} {string}"); +} diff --git a/src/test/ui/suggestions/suggest-std-when-using-type.stderr b/src/test/ui/suggestions/suggest-std-when-using-type.stderr new file mode 100644 index 000000000..6f890b87b --- /dev/null +++ b/src/test/ui/suggestions/suggest-std-when-using-type.stderr @@ -0,0 +1,26 @@ +error[E0223]: ambiguous associated type + --> $DIR/suggest-std-when-using-type.rs:3:14 + | +LL | let pi = f32::consts::PI; + | ^^^^^^^^^^^ + | +help: you are looking for the module in `std`, not the primitive type + | +LL | let pi = std::f32::consts::PI; + | +++++ + +error[E0599]: no function or associated item named `from_utf8` found for type `str` in the current scope + --> $DIR/suggest-std-when-using-type.rs:5:23 + | +LL | let string = str::from_utf8(bytes).unwrap(); + | ^^^^^^^^^ function or associated item not found in `str` + | +help: you are looking for the module in `std`, not the primitive type + | +LL | let string = std::str::from_utf8(bytes).unwrap(); + | +++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0223, E0599. +For more information about an error, try `rustc --explain E0223`. diff --git a/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs b/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs new file mode 100644 index 000000000..03c7ed347 --- /dev/null +++ b/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs @@ -0,0 +1,22 @@ +// edition:2021 + +pub trait Trait<'a, T> {} + +pub struct Struct<T>; +pub enum Enum<T> {} + +pub union Union<T> { + f1: usize, +} + +impl<'a, T> Struct<T> for Trait<'a, T> {} +//~^ ERROR expected trait, found struct `Struct` +//~| ERROR trait objects must include the `dyn` keyword + +impl<'a, T> Enum<T> for Trait<'a, T> {} +//~^ ERROR expected trait, found enum `Enum` + +impl<'a, T> Union<T> for Trait<'a, T> {} +//~^ ERROR expected trait, found union `Union` + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr b/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr new file mode 100644 index 000000000..fc880d6b8 --- /dev/null +++ b/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr @@ -0,0 +1,49 @@ +error[E0404]: expected trait, found struct `Struct` + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:12:13 + | +LL | impl<'a, T> Struct<T> for Trait<'a, T> {} + | ^^^^^^^^^ not a trait + | +help: `impl` items mention the trait being implemented first and the type it is being implemented for second + | +LL | impl<'a, T> Trait<'a, T> for Struct<T> {} + | ~~~~~~~~~~~~ ~~~~~~~~~ + +error[E0404]: expected trait, found enum `Enum` + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:16:13 + | +LL | impl<'a, T> Enum<T> for Trait<'a, T> {} + | ^^^^^^^ not a trait + | +help: `impl` items mention the trait being implemented first and the type it is being implemented for second + | +LL | impl<'a, T> Trait<'a, T> for Enum<T> {} + | ~~~~~~~~~~~~ ~~~~~~~ + +error[E0404]: expected trait, found union `Union` + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:19:13 + | +LL | impl<'a, T> Union<T> for Trait<'a, T> {} + | ^^^^^^^^ not a trait + | +help: `impl` items mention the trait being implemented first and the type it is being implemented for second + | +LL | impl<'a, T> Trait<'a, T> for Union<T> {} + | ~~~~~~~~~~~~ ~~~~~~~~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:12:27 + | +LL | impl<'a, T> Struct<T> for Trait<'a, T> {} + | ^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl<'a, T> Struct<T> for Trait<'a, T> {} +LL + impl<'a, T> Struct<T> for dyn Trait<'a, T> {} + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0404, E0782. +For more information about an error, try `rustc --explain E0404`. diff --git a/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait.rs b/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait.rs new file mode 100644 index 000000000..947bc2c79 --- /dev/null +++ b/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait.rs @@ -0,0 +1,21 @@ +pub trait Trait<'a, T> {} + +pub struct Struct<T>; +pub enum Enum<T> {} + +pub union Union<T> { + f1: usize, +} + +impl<'a, T> Struct<T> for Trait<'a, T> {} +//~^ ERROR expected trait, found struct `Struct` +//~| WARNING trait objects without an explicit `dyn` are deprecated +//~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + +impl<'a, T> Enum<T> for Trait<'a, T> {} +//~^ ERROR expected trait, found enum `Enum` + +impl<'a, T> Union<T> for Trait<'a, T> {} +//~^ ERROR expected trait, found union `Union` + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr b/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr new file mode 100644 index 000000000..f5143762d --- /dev/null +++ b/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr @@ -0,0 +1,51 @@ +error[E0404]: expected trait, found struct `Struct` + --> $DIR/suggest-swapping-self-ty-and-trait.rs:10:13 + | +LL | impl<'a, T> Struct<T> for Trait<'a, T> {} + | ^^^^^^^^^ not a trait + | +help: `impl` items mention the trait being implemented first and the type it is being implemented for second + | +LL | impl<'a, T> Trait<'a, T> for Struct<T> {} + | ~~~~~~~~~~~~ ~~~~~~~~~ + +error[E0404]: expected trait, found enum `Enum` + --> $DIR/suggest-swapping-self-ty-and-trait.rs:15:13 + | +LL | impl<'a, T> Enum<T> for Trait<'a, T> {} + | ^^^^^^^ not a trait + | +help: `impl` items mention the trait being implemented first and the type it is being implemented for second + | +LL | impl<'a, T> Trait<'a, T> for Enum<T> {} + | ~~~~~~~~~~~~ ~~~~~~~ + +error[E0404]: expected trait, found union `Union` + --> $DIR/suggest-swapping-self-ty-and-trait.rs:18:13 + | +LL | impl<'a, T> Union<T> for Trait<'a, T> {} + | ^^^^^^^^ not a trait + | +help: `impl` items mention the trait being implemented first and the type it is being implemented for second + | +LL | impl<'a, T> Trait<'a, T> for Union<T> {} + | ~~~~~~~~~~~~ ~~~~~~~~ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/suggest-swapping-self-ty-and-trait.rs:10:27 + | +LL | impl<'a, T> Struct<T> for Trait<'a, T> {} + | ^^^^^^^^^^^^ + | + = note: `#[warn(bare_trait_objects)]` on by default + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL - impl<'a, T> Struct<T> for Trait<'a, T> {} +LL + impl<'a, T> Struct<T> for dyn Trait<'a, T> {} + | + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0404`. diff --git a/src/test/ui/suggestions/suggest-trait-items.rs b/src/test/ui/suggestions/suggest-trait-items.rs new file mode 100644 index 000000000..9d42a7342 --- /dev/null +++ b/src/test/ui/suggestions/suggest-trait-items.rs @@ -0,0 +1,48 @@ +trait Foo { + type Type; + + fn foo(); + fn bar(); + fn qux(); +} + +struct A; + +impl Foo for A { +//~^ ERROR not all trait items implemented + type Typ = (); + //~^ ERROR type `Typ` is not a member of trait + //~| HELP there is an associated type with a similar name + + fn fooo() {} + //~^ ERROR method `fooo` is not a member of trait + //~| HELP there is an associated function with a similar name + + fn barr() {} + //~^ ERROR method `barr` is not a member of trait + //~| HELP there is an associated function with a similar name + + fn quux() {} + //~^ ERROR method `quux` is not a member of trait + //~| HELP there is an associated function with a similar name +} +//~^ HELP implement the missing item +//~| HELP implement the missing item +//~| HELP implement the missing item +//~| HELP implement the missing item + +trait Bar { + const Const: i32; +} + +struct B; + +impl Bar for B { +//~^ ERROR not all trait items implemented + const Cnst: i32 = 0; + //~^ ERROR const `Cnst` is not a member of trait + //~| HELP there is an associated constant with a similar name +} +//~^ HELP implement the missing item + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-trait-items.stderr b/src/test/ui/suggestions/suggest-trait-items.stderr new file mode 100644 index 000000000..8bc3df7b8 --- /dev/null +++ b/src/test/ui/suggestions/suggest-trait-items.stderr @@ -0,0 +1,74 @@ +error[E0437]: type `Typ` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:13:5 + | +LL | type Typ = (); + | ^^^^^---^^^^^^ + | | | + | | help: there is an associated type with a similar name: `Type` + | not a member of trait `Foo` + +error[E0407]: method `fooo` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:17:5 + | +LL | fn fooo() {} + | ^^^----^^^^^ + | | | + | | help: there is an associated function with a similar name: `foo` + | not a member of trait `Foo` + +error[E0407]: method `barr` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:21:5 + | +LL | fn barr() {} + | ^^^----^^^^^ + | | | + | | help: there is an associated function with a similar name: `bar` + | not a member of trait `Foo` + +error[E0407]: method `quux` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:25:5 + | +LL | fn quux() {} + | ^^^----^^^^^ + | | | + | | help: there is an associated function with a similar name: `qux` + | not a member of trait `Foo` + +error[E0438]: const `Cnst` is not a member of trait `Bar` + --> $DIR/suggest-trait-items.rs:42:5 + | +LL | const Cnst: i32 = 0; + | ^^^^^^----^^^^^^^^^^ + | | | + | | help: there is an associated constant with a similar name: `Const` + | not a member of trait `Bar` + +error[E0046]: not all trait items implemented, missing: `Type`, `foo`, `bar`, `qux` + --> $DIR/suggest-trait-items.rs:11:1 + | +LL | type Type; + | --------- `Type` from trait +LL | +LL | fn foo(); + | --------- `foo` from trait +LL | fn bar(); + | --------- `bar` from trait +LL | fn qux(); + | --------- `qux` from trait +... +LL | impl Foo for A { + | ^^^^^^^^^^^^^^ missing `Type`, `foo`, `bar`, `qux` in implementation + +error[E0046]: not all trait items implemented, missing: `Const` + --> $DIR/suggest-trait-items.rs:40:1 + | +LL | const Const: i32; + | ---------------- `Const` from trait +... +LL | impl Bar for B { + | ^^^^^^^^^^^^^^ missing `Const` in implementation + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0046, E0407, E0437, E0438. +For more information about an error, try `rustc --explain E0046`. diff --git a/src/test/ui/suggestions/suggest-tryinto-edition-change.rs b/src/test/ui/suggestions/suggest-tryinto-edition-change.rs new file mode 100644 index 000000000..f03b42bbe --- /dev/null +++ b/src/test/ui/suggestions/suggest-tryinto-edition-change.rs @@ -0,0 +1,31 @@ +// Make sure that trying to access `TryInto`, `TryFrom`, `FromIterator` in pre-2021 mentions +// Edition 2021 change +// edition:2018 + +fn test() { + let _i: i16 = 0_i32.try_into().unwrap(); + //~^ ERROR no method named `try_into` found for type `i32` in the current scope + //~| NOTE method not found in `i32` + //~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021 + + let _i: i16 = TryFrom::try_from(0_i32).unwrap(); + //~^ ERROR failed to resolve: use of undeclared type + //~| NOTE not found in this scope + //~| NOTE 'std::convert::TryFrom' is included in the prelude starting in Edition 2021 + //~| NOTE 'core::convert::TryFrom' is included in the prelude starting in Edition 2021 + + let _i: i16 = TryInto::try_into(0_i32).unwrap(); + //~^ ERROR failed to resolve: use of undeclared type + //~| NOTE not found in this scope + //~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021 + //~| NOTE 'core::convert::TryInto' is included in the prelude starting in Edition 2021 + + let _v: Vec<_> = FromIterator::from_iter(&[1]); + //~^ ERROR failed to resolve: use of undeclared type + //~| NOTE 'std::iter::FromIterator' is included in the prelude starting in Edition 2021 + //~| NOTE 'core::iter::FromIterator' is included in the prelude starting in Edition 2021 +} + +fn main() { + test(); +} diff --git a/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr b/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr new file mode 100644 index 000000000..86f48716b --- /dev/null +++ b/src/test/ui/suggestions/suggest-tryinto-edition-change.stderr @@ -0,0 +1,76 @@ +error[E0433]: failed to resolve: use of undeclared type `TryFrom` + --> $DIR/suggest-tryinto-edition-change.rs:11:19 + | +LL | let _i: i16 = TryFrom::try_from(0_i32).unwrap(); + | ^^^^^^^ not found in this scope + | + = note: 'std::convert::TryFrom' is included in the prelude starting in Edition 2021 + = note: 'core::convert::TryFrom' is included in the prelude starting in Edition 2021 +help: consider importing one of these items + | +LL | use core::convert::TryFrom; + | +LL | use std::convert::TryFrom; + | + +error[E0433]: failed to resolve: use of undeclared type `TryInto` + --> $DIR/suggest-tryinto-edition-change.rs:17:19 + | +LL | let _i: i16 = TryInto::try_into(0_i32).unwrap(); + | ^^^^^^^ not found in this scope + | + = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021 + = note: 'core::convert::TryInto' is included in the prelude starting in Edition 2021 +help: consider importing one of these items + | +LL | use core::convert::TryInto; + | +LL | use std::convert::TryInto; + | + +error[E0433]: failed to resolve: use of undeclared type `FromIterator` + --> $DIR/suggest-tryinto-edition-change.rs:23:22 + | +LL | let _v: Vec<_> = FromIterator::from_iter(&[1]); + | ^^^^^^^^^^^^ + | + ::: $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | pub trait IntoIterator { + | ---------------------- similarly named trait `IntoIterator` defined here + | + = note: 'std::iter::FromIterator' is included in the prelude starting in Edition 2021 + = note: 'core::iter::FromIterator' is included in the prelude starting in Edition 2021 +help: a trait with a similar name exists + | +LL | let _v: Vec<_> = IntoIterator::from_iter(&[1]); + | ~~~~~~~~~~~~ +help: consider importing one of these items + | +LL | use core::iter::FromIterator; + | +LL | use std::iter::FromIterator; + | + +error[E0599]: no method named `try_into` found for type `i32` in the current scope + --> $DIR/suggest-tryinto-edition-change.rs:6:25 + | +LL | let _i: i16 = 0_i32.try_into().unwrap(); + | ^^^^^^^^ method not found in `i32` + | + ::: $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn try_into(self) -> Result<T, Self::Error>; + | -------- the method is available for `i32` here + | + = help: items from traits can only be used if the trait is in scope + = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021 +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::convert::TryInto; + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0433, E0599. +For more information about an error, try `rustc --explain E0433`. diff --git a/src/test/ui/suggestions/suggest-using-chars.rs b/src/test/ui/suggestions/suggest-using-chars.rs new file mode 100644 index 000000000..95732881b --- /dev/null +++ b/src/test/ui/suggestions/suggest-using-chars.rs @@ -0,0 +1,7 @@ +pub fn main() { + let _ = "foo".iter(); //~ ERROR no method named `iter` found for reference `&'static str` in the current scope + let _ = "foo".foo(); //~ ERROR no method named `foo` found for reference `&'static str` in the current scope + let _ = String::from("bar").iter(); //~ ERROR no method named `iter` found for struct `String` in the current scope + let _ = (&String::from("bar")).iter(); //~ ERROR no method named `iter` found for reference `&String` in the current scope + let _ = 0.iter(); //~ ERROR no method named `iter` found for type `{integer}` in the current scope +} diff --git a/src/test/ui/suggestions/suggest-using-chars.stderr b/src/test/ui/suggestions/suggest-using-chars.stderr new file mode 100644 index 000000000..99bcfb08a --- /dev/null +++ b/src/test/ui/suggestions/suggest-using-chars.stderr @@ -0,0 +1,48 @@ +error[E0599]: no method named `iter` found for reference `&'static str` in the current scope + --> $DIR/suggest-using-chars.rs:2:19 + | +LL | let _ = "foo".iter(); + | ^^^^ method not found in `&'static str` + | +help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars` + | +LL | let _ = "foo".chars(); + | ~~~~~ + +error[E0599]: no method named `foo` found for reference `&'static str` in the current scope + --> $DIR/suggest-using-chars.rs:3:19 + | +LL | let _ = "foo".foo(); + | ^^^ method not found in `&'static str` + +error[E0599]: no method named `iter` found for struct `String` in the current scope + --> $DIR/suggest-using-chars.rs:4:33 + | +LL | let _ = String::from("bar").iter(); + | ^^^^ method not found in `String` + | +help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars` + | +LL | let _ = String::from("bar").chars(); + | ~~~~~ + +error[E0599]: no method named `iter` found for reference `&String` in the current scope + --> $DIR/suggest-using-chars.rs:5:36 + | +LL | let _ = (&String::from("bar")).iter(); + | ^^^^ method not found in `&String` + | +help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars` + | +LL | let _ = (&String::from("bar")).chars(); + | ~~~~~ + +error[E0599]: no method named `iter` found for type `{integer}` in the current scope + --> $DIR/suggest-using-chars.rs:6:15 + | +LL | let _ = 0.iter(); + | ^^^^ method not found in `{integer}` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/suggest-variants.rs b/src/test/ui/suggestions/suggest-variants.rs new file mode 100644 index 000000000..dd05d0f04 --- /dev/null +++ b/src/test/ui/suggestions/suggest-variants.rs @@ -0,0 +1,18 @@ +#[derive(Debug)] +enum Shape { + Square { size: i32 }, + Circle { radius: i32 }, +} + +struct S { + x: usize, +} + +fn main() { + println!("My shape is {:?}", Shape::Squareee { size: 5}); //~ ERROR no variant named `Squareee` + println!("My shape is {:?}", Shape::Circl { size: 5}); //~ ERROR no variant named `Circl` + println!("My shape is {:?}", Shape::Rombus{ size: 5}); //~ ERROR no variant named `Rombus` + Shape::Squareee; //~ ERROR no variant + Shape::Circl; //~ ERROR no variant + Shape::Rombus; //~ ERROR no variant +} diff --git a/src/test/ui/suggestions/suggest-variants.stderr b/src/test/ui/suggestions/suggest-variants.stderr new file mode 100644 index 000000000..a422bc656 --- /dev/null +++ b/src/test/ui/suggestions/suggest-variants.stderr @@ -0,0 +1,63 @@ +error[E0599]: no variant named `Squareee` found for enum `Shape` + --> $DIR/suggest-variants.rs:12:41 + | +LL | enum Shape { + | ---------- variant `Squareee` not found here +... +LL | println!("My shape is {:?}", Shape::Squareee { size: 5}); + | ^^^^^^^^ help: there is a variant with a similar name: `Square` + +error[E0599]: no variant named `Circl` found for enum `Shape` + --> $DIR/suggest-variants.rs:13:41 + | +LL | enum Shape { + | ---------- variant `Circl` not found here +... +LL | println!("My shape is {:?}", Shape::Circl { size: 5}); + | ^^^^^ help: there is a variant with a similar name: `Circle` + +error[E0599]: no variant named `Rombus` found for enum `Shape` + --> $DIR/suggest-variants.rs:14:41 + | +LL | enum Shape { + | ---------- variant `Rombus` not found here +... +LL | println!("My shape is {:?}", Shape::Rombus{ size: 5}); + | ^^^^^^ variant not found in `Shape` + +error[E0599]: no variant or associated item named `Squareee` found for enum `Shape` in the current scope + --> $DIR/suggest-variants.rs:15:12 + | +LL | enum Shape { + | ---------- variant or associated item `Squareee` not found for this enum +... +LL | Shape::Squareee; + | ^^^^^^^^ + | | + | variant or associated item not found in `Shape` + | help: there is a variant with a similar name: `Square` + +error[E0599]: no variant or associated item named `Circl` found for enum `Shape` in the current scope + --> $DIR/suggest-variants.rs:16:12 + | +LL | enum Shape { + | ---------- variant or associated item `Circl` not found for this enum +... +LL | Shape::Circl; + | ^^^^^ + | | + | variant or associated item not found in `Shape` + | help: there is a variant with a similar name: `Circle` + +error[E0599]: no variant or associated item named `Rombus` found for enum `Shape` in the current scope + --> $DIR/suggest-variants.rs:17:12 + | +LL | enum Shape { + | ---------- variant or associated item `Rombus` not found for this enum +... +LL | Shape::Rombus; + | ^^^^^^ variant or associated item not found in `Shape` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.fixed b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.fixed new file mode 100644 index 000000000..8ef7e34ab --- /dev/null +++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.fixed @@ -0,0 +1,43 @@ +// run-rustfix +#![allow(unused)] // for the fixed file + +trait Trait<T = Self> { + type A; + + fn func(&self) -> Self::A; +} + +struct S<T>(T); +impl<K> S<K> { + fn foo<'a, T: Trait + 'a>(&self, _: impl Trait, x: impl Trait<A = usize>, _: T) { + qux(x.func()) //~ ERROR mismatched types + } + + fn ban<T>(x: T) where T: Trait<A = usize> { + qux(x.func()) //~ ERROR mismatched types + } +} + +fn foo<'a, T: Trait + 'a>(_: impl Trait, x: impl Trait<A = usize>, _: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar<T: Trait<A = usize>>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn foo2(x: impl Trait<i32, A = usize>) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar2<T: Trait<i32, A = usize>>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn ban<T>(x: T) where T: Trait<A = usize> { + qux(x.func()) //~ ERROR mismatched types +} + +fn qux(_: usize) {} + +fn main() {} diff --git a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.rs b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.rs new file mode 100644 index 000000000..7bd38d0d4 --- /dev/null +++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.rs @@ -0,0 +1,43 @@ +// run-rustfix +#![allow(unused)] // for the fixed file + +trait Trait<T = Self> { + type A; + + fn func(&self) -> Self::A; +} + +struct S<T>(T); +impl<K> S<K> { + fn foo<'a, T: Trait + 'a>(&self, _: impl Trait, x: impl Trait, _: T) { + qux(x.func()) //~ ERROR mismatched types + } + + fn ban<T>(x: T) where T: Trait { + qux(x.func()) //~ ERROR mismatched types + } +} + +fn foo<'a, T: Trait + 'a>(_: impl Trait, x: impl Trait, _: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar<T: Trait>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn foo2(x: impl Trait<i32>) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar2<T: Trait<i32>>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn ban<T>(x: T) where T: Trait { + qux(x.func()) //~ ERROR mismatched types +} + +fn qux(_: usize) {} + +fn main() {} diff --git a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr new file mode 100644 index 000000000..ac839ff7e --- /dev/null +++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr @@ -0,0 +1,143 @@ +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:13:13 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `<impl Trait as Trait>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize` + | +LL | fn foo<'a, T: Trait + 'a>(&self, _: impl Trait, x: impl Trait<A = usize>, _: T) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:17:13 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `<T as Trait>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `<T as Trait>::A` to `usize` + | +LL | fn ban<T>(x: T) where T: Trait<A = usize> { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:22:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `<impl Trait as Trait>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize` + | +LL | fn foo<'a, T: Trait + 'a>(_: impl Trait, x: impl Trait<A = usize>, _: T) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:26:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `<T as Trait>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `<T as Trait>::A` to `usize` + | +LL | fn bar<T: Trait<A = usize>>(x: T) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:30:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `<impl Trait<i32> as Trait<i32>>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `<impl Trait<i32> as Trait<i32>>::A` to `usize` + | +LL | fn foo2(x: impl Trait<i32, A = usize>) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:34:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `<T as Trait<i32>>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `<T as Trait<i32>>::A` to `usize` + | +LL | fn bar2<T: Trait<i32, A = usize>>(x: T) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:38:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `<T as Trait>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `<T as Trait>::A` to `usize` + | +LL | fn ban<T>(x: T) where T: Trait<A = usize> { + | +++++++++++ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.rs b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.rs new file mode 100644 index 000000000..0d90e4495 --- /dev/null +++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.rs @@ -0,0 +1,44 @@ +// These are all the possible variations of this error I could think of for. +// `trait-with-missing-associated-type-restriction-fixable.rs` contains the subset of these that +// can be fixed with `rustfix`. + +trait Trait<T = Self> { + type A; + + fn func(&self) -> Self::A; + fn funk(&self, _: Self::A); + fn funq(&self) -> Self::A {} //~ ERROR mismatched types +} + +fn foo(_: impl Trait, x: impl Trait) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar<T: Trait>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn foo2(x: impl Trait<i32>) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar2<T: Trait<i32>>(x: T) { + x.funk(3); //~ ERROR mismatched types + qux(x.func()) //~ ERROR mismatched types +} + +fn baz<D: std::fmt::Debug, T: Trait<A = D>>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bat(x: &mut dyn Trait<(), A = ()>) { + qux(x.func()) //~ ERROR mismatched types +} + +fn ban<T>(x: T) where T: Trait { + qux(x.func()) //~ ERROR mismatched types +} + +fn qux(_: usize) {} + +fn main() {} diff --git a/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr new file mode 100644 index 000000000..7583c875a --- /dev/null +++ b/src/test/ui/suggestions/trait-with-missing-associated-type-restriction.stderr @@ -0,0 +1,177 @@ +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:10:31 + | +LL | fn funq(&self) -> Self::A {} + | ^^ expected associated type, found `()` + | + = note: expected associated type `<Self as Trait<T>>::A` + found unit type `()` +help: a method is available that returns `<Self as Trait<T>>::A` + --> $DIR/trait-with-missing-associated-type-restriction.rs:8:5 + | +LL | fn func(&self) -> Self::A; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::func` + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:14:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `<impl Trait as Trait>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize` + | +LL | fn foo(_: impl Trait, x: impl Trait<A = usize>) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:18:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `<T as Trait>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `<T as Trait>::A` to `usize` + | +LL | fn bar<T: Trait<A = usize>>(x: T) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:22:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `<impl Trait<i32> as Trait<i32>>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `<impl Trait<i32> as Trait<i32>>::A` to `usize` + | +LL | fn foo2(x: impl Trait<i32, A = usize>) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:26:12 + | +LL | x.funk(3); + | ---- ^ expected associated type, found integer + | | + | arguments to this function are incorrect + | + = note: expected associated type `<T as Trait<i32>>::A` + found type `{integer}` +help: some methods are available that return `<T as Trait<i32>>::A` + --> $DIR/trait-with-missing-associated-type-restriction.rs:8:5 + | +LL | fn func(&self) -> Self::A; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::func` +LL | fn funk(&self, _: Self::A); +LL | fn funq(&self) -> Self::A {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::funq` +note: associated function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:9:8 + | +LL | fn funk(&self, _: Self::A); + | ^^^^ +help: consider constraining the associated type `<T as Trait<i32>>::A` to `{integer}` + | +LL | fn bar2<T: Trait<i32, A = {integer}>>(x: T) { + | +++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:27:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `<T as Trait<i32>>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `<T as Trait<i32>>::A` to `usize` + | +LL | fn bar2<T: Trait<i32, A = usize>>(x: T) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:31:9 + | +LL | fn baz<D: std::fmt::Debug, T: Trait<A = D>>(x: T) { + | - this type parameter +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found type parameter `D` + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found type parameter `D` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:35:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found `()` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:39:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `<T as Trait>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `<T as Trait>::A` to `usize` + | +LL | fn ban<T>(x: T) where T: Trait<A = usize> { + | +++++++++++ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.rs b/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.rs new file mode 100644 index 000000000..f882a159f --- /dev/null +++ b/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.rs @@ -0,0 +1,27 @@ +// Regression test for #87051, where a double semicolon was erroneously +// suggested after a `?` operator. + +fn main() -> Result<(), ()> { + a(|| { + b() + //~^ ERROR: mismatched types [E0308] + //~| NOTE: expected `()`, found `i32` + //~| HELP: consider using a semicolon here + })?; + + // Here, we do want to suggest a semicolon: + let x = Ok(42); + if true { + //~^ NOTE: expected this to be `()` + x? + //~^ ERROR: mismatched types [E0308] + //~| NOTE: expected `()`, found integer + //~| HELP: consider using a semicolon here + } + //~^ HELP: consider using a semicolon here + + Ok(()) +} + +fn a<F>(f: F) -> Result<(), ()> where F: FnMut() { Ok(()) } +fn b() -> i32 { 42 } diff --git a/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.stderr b/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.stderr new file mode 100644 index 000000000..939285498 --- /dev/null +++ b/src/test/ui/suggestions/try-operator-dont-suggest-semicolon.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/try-operator-dont-suggest-semicolon.rs:6:9 + | +LL | b() + | ^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `i32` + +error[E0308]: mismatched types + --> $DIR/try-operator-dont-suggest-semicolon.rs:16:9 + | +LL | / if true { +LL | | +LL | | x? + | | ^^ expected `()`, found integer +LL | | +LL | | +LL | | +LL | | } + | |_____- expected this to be `()` + | +help: consider using a semicolon here + | +LL | x?; + | + +help: consider using a semicolon here + | +LL | }; + | + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/type-ascription-instead-of-let.rs b/src/test/ui/suggestions/type-ascription-instead-of-let.rs new file mode 100644 index 000000000..0e1c30750 --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-let.rs @@ -0,0 +1,10 @@ +fn fun(x: i32) -> i32 { x } + +fn main() { + let closure_annotated = |value: i32| -> i32 { + temp: i32 = fun(5i32); + //~^ ERROR cannot find value `temp` in this scope + temp + value + 1 + //~^ ERROR cannot find value `temp` in this scope + }; +} diff --git a/src/test/ui/suggestions/type-ascription-instead-of-let.stderr b/src/test/ui/suggestions/type-ascription-instead-of-let.stderr new file mode 100644 index 000000000..92e4b5798 --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-let.stderr @@ -0,0 +1,18 @@ +error[E0425]: cannot find value `temp` in this scope + --> $DIR/type-ascription-instead-of-let.rs:5:9 + | +LL | temp: i32 = fun(5i32); + | ^^^^ + | | + | not found in this scope + | help: maybe you meant to write an assignment here: `let temp` + +error[E0425]: cannot find value `temp` in this scope + --> $DIR/type-ascription-instead-of-let.rs:7:9 + | +LL | temp + value + 1 + | ^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/suggestions/type-ascription-instead-of-method.fixed b/src/test/ui/suggestions/type-ascription-instead-of-method.fixed new file mode 100644 index 000000000..56b740b0d --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-method.fixed @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let _ = Box::new("foo".to_string()); + //~^ ERROR expected type, found +} diff --git a/src/test/ui/suggestions/type-ascription-instead-of-method.rs b/src/test/ui/suggestions/type-ascription-instead-of-method.rs new file mode 100644 index 000000000..a603e09e7 --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-method.rs @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let _ = Box:new("foo".to_string()); + //~^ ERROR expected type, found +} diff --git a/src/test/ui/suggestions/type-ascription-instead-of-method.stderr b/src/test/ui/suggestions/type-ascription-instead-of-method.stderr new file mode 100644 index 000000000..83bc33f41 --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-method.stderr @@ -0,0 +1,12 @@ +error: expected type, found `"foo"` + --> $DIR/type-ascription-instead-of-method.rs:3:21 + | +LL | let _ = Box:new("foo".to_string()); + | - ^^^^^ expected type + | | + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>` + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-2.fixed b/src/test/ui/suggestions/type-ascription-instead-of-path-2.fixed new file mode 100644 index 000000000..787fcc120 --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-path-2.fixed @@ -0,0 +1,6 @@ +// run-rustfix +fn main() -> Result<(), ()> { + let _ = vec![Ok(2)].into_iter().collect::<Result<Vec<_>,_>>()?; + //~^ ERROR expected `::`, found `(` + Ok(()) +} diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-2.rs b/src/test/ui/suggestions/type-ascription-instead-of-path-2.rs new file mode 100644 index 000000000..934016b3b --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-path-2.rs @@ -0,0 +1,6 @@ +// run-rustfix +fn main() -> Result<(), ()> { + let _ = vec![Ok(2)].into_iter().collect:<Result<Vec<_>,_>>()?; + //~^ ERROR expected `::`, found `(` + Ok(()) +} diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr b/src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr new file mode 100644 index 000000000..970b220b7 --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr @@ -0,0 +1,12 @@ +error: expected `::`, found `(` + --> $DIR/type-ascription-instead-of-path-2.rs:3:63 + | +LL | let _ = vec![Ok(2)].into_iter().collect:<Result<Vec<_>,_>>()?; + | - ^ expected `::` + | | + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>` + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.rs b/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.rs new file mode 100644 index 000000000..48d19f6dd --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.rs @@ -0,0 +1,14 @@ +enum A { + B, +} + +fn main() { + let _: Vec<A:B> = A::B; + //~^ ERROR cannot find trait `B` in this scope + //~| HELP you might have meant to write a path instead of an associated type bound + //~| ERROR associated type bounds are unstable + //~| HELP add `#![feature(associated_type_bounds)]` to the crate attributes to enable + //~| ERROR struct takes at least 1 generic argument but 0 generic arguments were supplied + //~| HELP add missing generic argument + //~| ERROR associated type bindings are not allowed here +} diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr b/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr new file mode 100644 index 000000000..951ff23d6 --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr @@ -0,0 +1,46 @@ +error[E0405]: cannot find trait `B` in this scope + --> $DIR/type-ascription-instead-of-path-in-type.rs:6:18 + | +LL | let _: Vec<A:B> = A::B; + | ^ not found in this scope + | +help: you might have meant to write a path instead of an associated type bound + | +LL | let _: Vec<A::B> = A::B; + | ~~ + +error[E0658]: associated type bounds are unstable + --> $DIR/type-ascription-instead-of-path-in-type.rs:6:16 + | +LL | let _: Vec<A:B> = A::B; + | ^^^ + | + = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0107]: this struct takes at least 1 generic argument but 0 generic arguments were supplied + --> $DIR/type-ascription-instead-of-path-in-type.rs:6:12 + | +LL | let _: Vec<A:B> = A::B; + | ^^^ expected at least 1 generic argument + | +note: struct defined here, with at least 1 generic parameter: `T` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + | +LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> { + | ^^^ - +help: add missing generic argument + | +LL | let _: Vec<T, A:B> = A::B; + | ++ + +error[E0229]: associated type bindings are not allowed here + --> $DIR/type-ascription-instead-of-path-in-type.rs:6:16 + | +LL | let _: Vec<A:B> = A::B; + | ^^^ associated type not allowed here + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0107, E0229, E0405, E0658. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path.rs b/src/test/ui/suggestions/type-ascription-instead-of-path.rs new file mode 100644 index 000000000..ce40b55f1 --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-path.rs @@ -0,0 +1,5 @@ +fn main() { + std:io::stdin(); + //~^ ERROR failed to resolve: use of undeclared crate or module `io` + //~| ERROR expected value, found crate +} diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path.stderr b/src/test/ui/suggestions/type-ascription-instead-of-path.stderr new file mode 100644 index 000000000..518660cfa --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-path.stderr @@ -0,0 +1,18 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `io` + --> $DIR/type-ascription-instead-of-path.rs:2:9 + | +LL | std:io::stdin(); + | ^^ use of undeclared crate or module `io` + +error[E0423]: expected value, found crate `std` + --> $DIR/type-ascription-instead-of-path.rs:2:5 + | +LL | std:io::stdin(); + | ^^^- help: maybe you meant to write a path separator here: `::` + | | + | not a value + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0423, E0433. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/suggestions/type-ascription-instead-of-variant.fixed b/src/test/ui/suggestions/type-ascription-instead-of-variant.fixed new file mode 100644 index 000000000..b3247e128 --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-variant.fixed @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let _ = Option::Some(""); + //~^ ERROR expected type, found +} diff --git a/src/test/ui/suggestions/type-ascription-instead-of-variant.rs b/src/test/ui/suggestions/type-ascription-instead-of-variant.rs new file mode 100644 index 000000000..6fd2c1954 --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-variant.rs @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let _ = Option:Some(""); + //~^ ERROR expected type, found +} diff --git a/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr b/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr new file mode 100644 index 000000000..f59ba78d4 --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr @@ -0,0 +1,12 @@ +error: expected type, found `""` + --> $DIR/type-ascription-instead-of-variant.rs:3:25 + | +LL | let _ = Option:Some(""); + | - ^^ expected type + | | + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>` + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs new file mode 100644 index 000000000..2ce122207 --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs @@ -0,0 +1,9 @@ +struct RGB { r: f64, g: f64, b: f64 } + +fn main() { + let (r, g, c): (f32, f32, f32) = (0., 0., 0.); + let _ = RGB { r, g, c }; + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR struct `RGB` has no field named `c` +} diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr new file mode 100644 index 000000000..12466868f --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr @@ -0,0 +1,32 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:19 + | +LL | let _ = RGB { r, g, c }; + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r: r.into(), g, c }; + | ++ +++++++ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:22 + | +LL | let _ = RGB { r, g, c }; + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r, g: g.into(), c }; + | ++ +++++++ + +error[E0560]: struct `RGB` has no field named `c` + --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25 + | +LL | let _ = RGB { r, g, c }; + | ^ help: a field with a similar name exists: `b` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0560. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed new file mode 100644 index 000000000..91758c0b2 --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed @@ -0,0 +1,12 @@ +// run-rustfix +#![allow(dead_code)] + +struct RGB { r: f64, g: f64, b: f64 } + +fn main() { + let (r, g, b): (f32, f32, f32) = (0., 0., 0.); + let _ = RGB { r: r.into(), g: g.into(), b: b.into() }; + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs new file mode 100644 index 000000000..9d3a17a72 --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs @@ -0,0 +1,12 @@ +// run-rustfix +#![allow(dead_code)] + +struct RGB { r: f64, g: f64, b: f64 } + +fn main() { + let (r, g, b): (f32, f32, f32) = (0., 0., 0.); + let _ = RGB { r, g, b }; + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr new file mode 100644 index 000000000..72c84d167 --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr @@ -0,0 +1,36 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand.rs:8:19 + | +LL | let _ = RGB { r, g, b }; + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r: r.into(), g, b }; + | ++ +++++++ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand.rs:8:22 + | +LL | let _ = RGB { r, g, b }; + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r, g: g.into(), b }; + | ++ +++++++ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand.rs:8:25 + | +LL | let _ = RGB { r, g, b }; + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r, g, b: b.into() }; + | ++ +++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/type-not-found-in-adt-field.rs b/src/test/ui/suggestions/type-not-found-in-adt-field.rs new file mode 100644 index 000000000..4cbfe58d3 --- /dev/null +++ b/src/test/ui/suggestions/type-not-found-in-adt-field.rs @@ -0,0 +1,9 @@ +struct Struct { + m: Vec<Someunknownname<String, ()>>, //~ ERROR cannot find type `Someunknownname` in this scope + //~^ NOTE not found in this scope +} +struct OtherStruct { //~ HELP you might be missing a type parameter + m: K, //~ ERROR cannot find type `K` in this scope + //~^ NOTE not found in this scope +} +fn main() {} diff --git a/src/test/ui/suggestions/type-not-found-in-adt-field.stderr b/src/test/ui/suggestions/type-not-found-in-adt-field.stderr new file mode 100644 index 000000000..e990fb5ba --- /dev/null +++ b/src/test/ui/suggestions/type-not-found-in-adt-field.stderr @@ -0,0 +1,17 @@ +error[E0412]: cannot find type `Someunknownname` in this scope + --> $DIR/type-not-found-in-adt-field.rs:2:12 + | +LL | m: Vec<Someunknownname<String, ()>>, + | ^^^^^^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `K` in this scope + --> $DIR/type-not-found-in-adt-field.rs:6:8 + | +LL | struct OtherStruct { + | - help: you might be missing a type parameter: `<K>` +LL | m: K, + | ^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/suggestions/undeclared-module-alloc.rs b/src/test/ui/suggestions/undeclared-module-alloc.rs new file mode 100644 index 000000000..1defa1cef --- /dev/null +++ b/src/test/ui/suggestions/undeclared-module-alloc.rs @@ -0,0 +1,5 @@ +// edition:2018 + +use alloc::rc::Rc; //~ ERROR failed to resolve: use of undeclared crate or module `alloc` + +fn main() {} diff --git a/src/test/ui/suggestions/undeclared-module-alloc.stderr b/src/test/ui/suggestions/undeclared-module-alloc.stderr new file mode 100644 index 000000000..39169dfa9 --- /dev/null +++ b/src/test/ui/suggestions/undeclared-module-alloc.stderr @@ -0,0 +1,11 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `alloc` + --> $DIR/undeclared-module-alloc.rs:3:5 + | +LL | use alloc::rc::Rc; + | ^^^^^ use of undeclared crate or module `alloc` + | + = help: add `extern crate alloc` to use the `alloc` crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/suggestions/unnamable-types.rs b/src/test/ui/suggestions/unnamable-types.rs new file mode 100644 index 000000000..f2485041d --- /dev/null +++ b/src/test/ui/suggestions/unnamable-types.rs @@ -0,0 +1,39 @@ +// Test that we do not suggest to add type annotations for unnamable types. + +#![crate_type="lib"] +#![feature(generators)] + +const A = 5; +//~^ ERROR: missing type for `const` item +//~| HELP: provide a type for the constant + +static B: _ = "abc"; +//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for static variables +//~| NOTE: not allowed in type signatures +//~| HELP: replace with the correct type + + +// FIXME: this should also suggest a function pointer, as the closure is non-capturing +const C: _ = || 42; +//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for constants +//~| NOTE: not allowed in type signatures +//~| NOTE: however, the inferred type + +struct S<T> { t: T } +const D = S { t: { let i = 0; move || -> i32 { i } } }; +//~^ ERROR: missing type for `const` item +//~| NOTE: however, the inferred type + + +fn foo() -> i32 { 42 } +const E = foo; +//~^ ERROR: missing type for `const` item +//~| HELP: provide a type for the constant +const F = S { t: foo }; +//~^ ERROR: missing type for `const` item +//~| HELP: provide a type for the constant + + +const G = || -> i32 { yield 0; return 1; }; +//~^ ERROR: missing type for `const` item +//~| NOTE: however, the inferred type diff --git a/src/test/ui/suggestions/unnamable-types.stderr b/src/test/ui/suggestions/unnamable-types.stderr new file mode 100644 index 000000000..de64269d1 --- /dev/null +++ b/src/test/ui/suggestions/unnamable-types.stderr @@ -0,0 +1,66 @@ +error: missing type for `const` item + --> $DIR/unnamable-types.rs:6:7 + | +LL | const A = 5; + | ^ help: provide a type for the constant: `A: i32` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/unnamable-types.rs:10:11 + | +LL | static B: _ = "abc"; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `&str` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/unnamable-types.rs:17:10 + | +LL | const C: _ = || 42; + | ^ not allowed in type signatures + | +note: however, the inferred type `[closure@$DIR/unnamable-types.rs:17:14: 17:16]` cannot be named + --> $DIR/unnamable-types.rs:17:14 + | +LL | const C: _ = || 42; + | ^^^^^ + +error: missing type for `const` item + --> $DIR/unnamable-types.rs:23:7 + | +LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; + | ^ + | +note: however, the inferred type `S<[closure@$DIR/unnamable-types.rs:23:31: 23:45]>` cannot be named + --> $DIR/unnamable-types.rs:23:11 + | +LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing type for `const` item + --> $DIR/unnamable-types.rs:29:7 + | +LL | const E = foo; + | ^ help: provide a type for the constant: `E: fn() -> i32` + +error: missing type for `const` item + --> $DIR/unnamable-types.rs:32:7 + | +LL | const F = S { t: foo }; + | ^ help: provide a type for the constant: `F: S<fn() -> i32>` + +error: missing type for `const` item + --> $DIR/unnamable-types.rs:37:7 + | +LL | const G = || -> i32 { yield 0; return 1; }; + | ^ + | +note: however, the inferred type `[generator@$DIR/unnamable-types.rs:37:11: 37:20]` cannot be named + --> $DIR/unnamable-types.rs:37:11 + | +LL | const G = || -> i32 { yield 0; return 1; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/suggestions/unsized-function-parameter.fixed b/src/test/ui/suggestions/unsized-function-parameter.fixed new file mode 100644 index 000000000..18e93cb96 --- /dev/null +++ b/src/test/ui/suggestions/unsized-function-parameter.fixed @@ -0,0 +1,23 @@ +// run-rustfix + +#![allow(dead_code, unused_variables)] + +fn foo1(bar: &str) {} +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` +//~| HELP unsized fn params are gated as an unstable feature +//~| HELP function arguments must have a statically known size, borrowed types always have a known size + +fn foo2(_bar: &str) {} +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` +//~| HELP unsized fn params are gated as an unstable feature +//~| HELP function arguments must have a statically known size, borrowed types always have a known size + +fn foo3(_: &str) {} +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` +//~| HELP unsized fn params are gated as an unstable feature +//~| HELP function arguments must have a statically known size, borrowed types always have a known size + +fn main() {} diff --git a/src/test/ui/suggestions/unsized-function-parameter.rs b/src/test/ui/suggestions/unsized-function-parameter.rs new file mode 100644 index 000000000..344ee71c1 --- /dev/null +++ b/src/test/ui/suggestions/unsized-function-parameter.rs @@ -0,0 +1,23 @@ +// run-rustfix + +#![allow(dead_code, unused_variables)] + +fn foo1(bar: str) {} +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` +//~| HELP unsized fn params are gated as an unstable feature +//~| HELP function arguments must have a statically known size, borrowed types always have a known size + +fn foo2(_bar: str) {} +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` +//~| HELP unsized fn params are gated as an unstable feature +//~| HELP function arguments must have a statically known size, borrowed types always have a known size + +fn foo3(_: str) {} +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` +//~| HELP unsized fn params are gated as an unstable feature +//~| HELP function arguments must have a statically known size, borrowed types always have a known size + +fn main() {} diff --git a/src/test/ui/suggestions/unsized-function-parameter.stderr b/src/test/ui/suggestions/unsized-function-parameter.stderr new file mode 100644 index 000000000..55d8d1ab1 --- /dev/null +++ b/src/test/ui/suggestions/unsized-function-parameter.stderr @@ -0,0 +1,42 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-function-parameter.rs:5:9 + | +LL | fn foo1(bar: str) {} + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo1(bar: &str) {} + | + + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-function-parameter.rs:11:9 + | +LL | fn foo2(_bar: str) {} + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo2(_bar: &str) {} + | + + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-function-parameter.rs:17:9 + | +LL | fn foo3(_: str) {} + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo3(_: &str) {} + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/unused-closure-argument.rs b/src/test/ui/suggestions/unused-closure-argument.rs new file mode 100644 index 000000000..677003ebf --- /dev/null +++ b/src/test/ui/suggestions/unused-closure-argument.rs @@ -0,0 +1,20 @@ +#![deny(unused_variables)] + +struct Point { + x: i32, + y: i32, +} + +fn main() { + let points = vec!(Point { x: 1, y: 2 }, Point { x: 3, y: 4 }); + + let _: i32 = points.iter() + .map(|Point { x, y }| y) + //~^ ERROR unused variable + .sum(); + + let _: i32 = points.iter() + .map(|x| 4) + //~^ ERROR unused variable + .sum(); +} diff --git a/src/test/ui/suggestions/unused-closure-argument.stderr b/src/test/ui/suggestions/unused-closure-argument.stderr new file mode 100644 index 000000000..55195ce50 --- /dev/null +++ b/src/test/ui/suggestions/unused-closure-argument.stderr @@ -0,0 +1,20 @@ +error: unused variable: `x` + --> $DIR/unused-closure-argument.rs:12:23 + | +LL | .map(|Point { x, y }| y) + | ^ help: try ignoring the field: `x: _` + | +note: the lint level is defined here + --> $DIR/unused-closure-argument.rs:1:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: unused variable: `x` + --> $DIR/unused-closure-argument.rs:17:15 + | +LL | .map(|x| 4) + | ^ help: if this is intentional, prefix it with an underscore: `_x` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/suggestions/use-placement-resolve.fixed b/src/test/ui/suggestions/use-placement-resolve.fixed new file mode 100644 index 000000000..afe74cff2 --- /dev/null +++ b/src/test/ui/suggestions/use-placement-resolve.fixed @@ -0,0 +1,13 @@ +// compile-flags: --test +// run-rustfix +// Checks that the `use` suggestion appears *below* this inner attribute. +// There was an issue where the test synthetic #[allow(dead)] attribute on +// main which has a dummy span caused the suggestion to be placed at the top +// of the file. +#![allow(unused)] + +use std::fmt::Debug; + +fn main() {} + +fn foobar<T: Debug>(x: T) {} //~ ERROR expected trait, found derive macro diff --git a/src/test/ui/suggestions/use-placement-resolve.rs b/src/test/ui/suggestions/use-placement-resolve.rs new file mode 100644 index 000000000..b30ddb3af --- /dev/null +++ b/src/test/ui/suggestions/use-placement-resolve.rs @@ -0,0 +1,11 @@ +// compile-flags: --test +// run-rustfix +// Checks that the `use` suggestion appears *below* this inner attribute. +// There was an issue where the test synthetic #[allow(dead)] attribute on +// main which has a dummy span caused the suggestion to be placed at the top +// of the file. +#![allow(unused)] + +fn main() {} + +fn foobar<T: Debug>(x: T) {} //~ ERROR expected trait, found derive macro diff --git a/src/test/ui/suggestions/use-placement-resolve.stderr b/src/test/ui/suggestions/use-placement-resolve.stderr new file mode 100644 index 000000000..9da9e8e27 --- /dev/null +++ b/src/test/ui/suggestions/use-placement-resolve.stderr @@ -0,0 +1,14 @@ +error[E0404]: expected trait, found derive macro `Debug` + --> $DIR/use-placement-resolve.rs:11:14 + | +LL | fn foobar<T: Debug>(x: T) {} + | ^^^^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::fmt::Debug; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/src/test/ui/suggestions/use-placement-typeck.fixed b/src/test/ui/suggestions/use-placement-typeck.fixed new file mode 100644 index 000000000..37335da06 --- /dev/null +++ b/src/test/ui/suggestions/use-placement-typeck.fixed @@ -0,0 +1,21 @@ +// compile-flags: --test +// run-rustfix +// Checks that the `use` suggestion appears *below* this inner attribute. +// There was an issue where the test synthetic #[allow(dead)] attribute on +// main which has a dummy span caused the suggestion to be placed at the top +// of the file. +#![allow(unused)] + +use m::Foo; +fn main() { + let s = m::S; + s.abc(); //~ ERROR no method named `abc` +} + +mod m { + pub trait Foo { + fn abc(&self) {} + } + pub struct S; + impl Foo for S{} +} diff --git a/src/test/ui/suggestions/use-placement-typeck.rs b/src/test/ui/suggestions/use-placement-typeck.rs new file mode 100644 index 000000000..aab20d2e9 --- /dev/null +++ b/src/test/ui/suggestions/use-placement-typeck.rs @@ -0,0 +1,20 @@ +// compile-flags: --test +// run-rustfix +// Checks that the `use` suggestion appears *below* this inner attribute. +// There was an issue where the test synthetic #[allow(dead)] attribute on +// main which has a dummy span caused the suggestion to be placed at the top +// of the file. +#![allow(unused)] + +fn main() { + let s = m::S; + s.abc(); //~ ERROR no method named `abc` +} + +mod m { + pub trait Foo { + fn abc(&self) {} + } + pub struct S; + impl Foo for S{} +} diff --git a/src/test/ui/suggestions/use-placement-typeck.stderr b/src/test/ui/suggestions/use-placement-typeck.stderr new file mode 100644 index 000000000..3b2749773 --- /dev/null +++ b/src/test/ui/suggestions/use-placement-typeck.stderr @@ -0,0 +1,21 @@ +error[E0599]: no method named `abc` found for struct `S` in the current scope + --> $DIR/use-placement-typeck.rs:11:7 + | +LL | s.abc(); + | ^^^ method not found in `S` +... +LL | fn abc(&self) {} + | --- the method is available for `S` here +LL | } +LL | pub struct S; + | ------------ method `abc` not found for this struct + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use m::Foo; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs new file mode 100644 index 000000000..8b6e8cfd7 --- /dev/null +++ b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.rs @@ -0,0 +1,13 @@ +pub trait T<X, Y> { + type A; + type B; + type C; +} +pub struct Foo { + i: Box<dyn T<usize, usize, usize, usize, B=usize>>, + //~^ ERROR must be specified + //~| ERROR this trait takes 2 generic arguments but 4 generic arguments were supplied +} + + +fn main() {} diff --git a/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr new file mode 100644 index 000000000..7038a572b --- /dev/null +++ b/src/test/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr @@ -0,0 +1,32 @@ +error[E0107]: this trait takes 2 generic arguments but 4 generic arguments were supplied + --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16 + | +LL | i: Box<dyn T<usize, usize, usize, usize, B=usize>>, + | ^ expected 2 generic arguments + | +note: trait defined here, with 2 generic parameters: `X`, `Y` + --> $DIR/use-type-argument-instead-of-assoc-type.rs:1:11 + | +LL | pub trait T<X, Y> { + | ^ - - +help: replace the generic bounds with the associated types + | +LL | i: Box<dyn T<usize, usize, A = usize, C = usize, B=usize>>, + | ~~~~~~~~~ ~~~~~~~~~ + +error[E0191]: the value of the associated types `A` (from trait `T`), `C` (from trait `T`) must be specified + --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16 + | +LL | type A; + | ------ `A` defined here +LL | type B; +LL | type C; + | ------ `C` defined here +... +LL | i: Box<dyn T<usize, usize, usize, usize, B=usize>>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated types `A`, `C` must be specified + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0191. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/suggestions/while-let-typo.rs b/src/test/ui/suggestions/while-let-typo.rs new file mode 100644 index 000000000..dbbcdee3c --- /dev/null +++ b/src/test/ui/suggestions/while-let-typo.rs @@ -0,0 +1,9 @@ +fn main() { + let foo = Some(0); + let bar = None; + while Some(x) = foo {} //~ ERROR cannot find value `x` in this scope + while Some(foo) = bar {} + while 3 = foo {} //~ ERROR mismatched types + while Some(3) = foo {} //~ ERROR invalid left-hand side of assignment + while x = 5 {} //~ ERROR cannot find value `x` in this scope +} diff --git a/src/test/ui/suggestions/while-let-typo.stderr b/src/test/ui/suggestions/while-let-typo.stderr new file mode 100644 index 000000000..7cc2ed314 --- /dev/null +++ b/src/test/ui/suggestions/while-let-typo.stderr @@ -0,0 +1,45 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/while-let-typo.rs:4:16 + | +LL | while Some(x) = foo {} + | ^ not found in this scope + | +help: you might have meant to use pattern matching + | +LL | while let Some(x) = foo {} + | +++ + +error[E0425]: cannot find value `x` in this scope + --> $DIR/while-let-typo.rs:8:11 + | +LL | while x = 5 {} + | ^ not found in this scope + | +help: you might have meant to use pattern matching + | +LL | while let x = 5 {} + | +++ + +error[E0308]: mismatched types + --> $DIR/while-let-typo.rs:6:11 + | +LL | while 3 = foo {} + | ^^^^^^^ expected `bool`, found `()` + +error[E0070]: invalid left-hand side of assignment + --> $DIR/while-let-typo.rs:7:19 + | +LL | while Some(3) = foo {} + | - ^ + | | + | cannot assign to this expression + | +help: you might have meant to use pattern destructuring + | +LL | while let Some(3) = foo {} + | +++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0070, E0308, E0425. +For more information about an error, try `rustc --explain E0070`. |