diff options
Diffstat (limited to '')
25 files changed, 879 insertions, 0 deletions
diff --git a/src/test/ui/trivial-bounds/issue-73021-impossible-inline.inline.stderr b/src/test/ui/trivial-bounds/issue-73021-impossible-inline.inline.stderr new file mode 100644 index 000000000..40829f537 --- /dev/null +++ b/src/test/ui/trivial-bounds/issue-73021-impossible-inline.inline.stderr @@ -0,0 +1,46 @@ +warning: trait bound for<'any> &'any mut (): Clone does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:20:29 + | +LL | for<'any> &'any mut (): Clone, + | ^^^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:28:21 + | +LL | struct S where i32: Foo; + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:31:28 + | +LL | impl Foo for () where i32: Foo { + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:40:19 + | +LL | fn f() where i32: Foo { + | ^^^ + +warning: trait bound &'static str: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:48:28 + | +LL | fn g() where &'static str: Foo { + | ^^^ + +warning: trait bound String: Neg does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:57:13 + | +LL | String: ::std::ops::Neg<Output = String>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait bound i32: Iterator does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:65:10 + | +LL | i32: Iterator, + | ^^^^^^^^ + +warning: 7 warnings emitted + diff --git a/src/test/ui/trivial-bounds/issue-73021-impossible-inline.no-opt.stderr b/src/test/ui/trivial-bounds/issue-73021-impossible-inline.no-opt.stderr new file mode 100644 index 000000000..40829f537 --- /dev/null +++ b/src/test/ui/trivial-bounds/issue-73021-impossible-inline.no-opt.stderr @@ -0,0 +1,46 @@ +warning: trait bound for<'any> &'any mut (): Clone does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:20:29 + | +LL | for<'any> &'any mut (): Clone, + | ^^^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:28:21 + | +LL | struct S where i32: Foo; + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:31:28 + | +LL | impl Foo for () where i32: Foo { + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:40:19 + | +LL | fn f() where i32: Foo { + | ^^^ + +warning: trait bound &'static str: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:48:28 + | +LL | fn g() where &'static str: Foo { + | ^^^ + +warning: trait bound String: Neg does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:57:13 + | +LL | String: ::std::ops::Neg<Output = String>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait bound i32: Iterator does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:65:10 + | +LL | i32: Iterator, + | ^^^^^^^^ + +warning: 7 warnings emitted + diff --git a/src/test/ui/trivial-bounds/issue-73021-impossible-inline.rs b/src/test/ui/trivial-bounds/issue-73021-impossible-inline.rs new file mode 100644 index 000000000..ab6677e91 --- /dev/null +++ b/src/test/ui/trivial-bounds/issue-73021-impossible-inline.rs @@ -0,0 +1,71 @@ +// build-pass +// revisions: no-opt inline +// [inline]compile-flags: -Zmir-opt-level=3 --emit=mir +#![feature(trivial_bounds)] +#![allow(unused)] + +trait Foo { + fn test(&self); +} + +fn foo<'a>(s: &'a mut ()) +where + &'a mut (): Foo, +{ + s.test(); +} + +fn clone(it: &mut ()) -> &mut () +where + for<'any> &'any mut (): Clone, + //~^ WARN trait bound for<'any> &'any mut (): Clone does not depend on any type or lifetime parameters +{ + it.clone() +} + +fn generic_function<X: Foo>(x: X) {} + +struct S where i32: Foo; +//~^ WARN trait bound i32: Foo does not depend on any type or lifetime parameters + +impl Foo for () where i32: Foo { +//~^ WARN trait bound i32: Foo does not depend on any type or lifetime parameters + fn test(&self) { + 3i32.test(); + Foo::test(&4i32); + generic_function(5i32); + } +} + +fn f() where i32: Foo { +//~^ WARN trait bound i32: Foo does not depend on any type or lifetime parameters + let s = S; + 3i32.test(); + Foo::test(&4i32); + generic_function(5i32); +} + +fn g() where &'static str: Foo { +//~^ WARN trait bound &'static str: Foo does not depend on any type or lifetime parameters + "Foo".test(); + Foo::test(&"Foo"); + generic_function("Foo"); +} + +fn use_op(s: String) -> String +where + String: ::std::ops::Neg<Output = String>, +//~^ WARN trait bound String: Neg does not depend on any type or lifetime parameters +{ + -s +} + +fn use_for() +where + i32: Iterator, +//~^ WARN trait bound i32: Iterator does not depend on any type or lifetime parameters +{ + for _ in 2i32 {} +} + +fn main() {} diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-associated-functions.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-associated-functions.rs new file mode 100644 index 000000000..69eee66e6 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-associated-functions.rs @@ -0,0 +1,23 @@ +// check-pass +// compile-flags: --emit=mir,link +// Force mir to be emitted, to ensure that const +// propagation doesn't ICE on a function +// with an 'impossible' body. See issue #67696 +// Inconsistent bounds with trait implementations + +#![feature(trivial_bounds)] +#![allow(unused)] + +trait A { + fn foo(&self) -> Self where Self: Copy; +} + +impl A for str { + fn foo(&self) -> Self where Self: Copy { *"" } +} + +impl A for i32 { + fn foo(&self) -> Self { 3 } +} + +fn main() {} diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.rs new file mode 100644 index 000000000..b1ff23fd0 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.rs @@ -0,0 +1,13 @@ +// Check that reborrows are still illegal with Copy mutable references +#![feature(trivial_bounds)] +#![allow(unused)] + +fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { + *t //~ ERROR +} + +fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { + {*t} //~ ERROR +} + +fn main() {} diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr new file mode 100644 index 000000000..aac119afd --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr @@ -0,0 +1,19 @@ +error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference + --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:6:5 + | +LL | fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { + | --------------- help: consider changing this to be a mutable reference: `&'a mut &'a mut i32` +LL | *t + | ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable + +error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference + --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:10:6 + | +LL | fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { + | --------------- help: consider changing this to be a mutable reference: `&'a mut &'a mut i32` +LL | {*t} + | ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs new file mode 100644 index 000000000..3416503b8 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs @@ -0,0 +1,33 @@ +// check-pass +// Check tautalogically false `Copy` bounds +#![feature(trivial_bounds)] + +fn copy_string(t: String) -> String where String: Copy { //~ WARNING trivial_bounds + is_copy(&t); + let x = t; + drop(t); + t +} + +fn copy_out_string(t: &String) -> String where String: Copy { //~ WARNING trivial_bounds + *t +} + +fn copy_string_with_param<T>(x: String) where String: Copy { //~ WARNING trivial_bounds + let y = x; + let z = x; +} + +// Check that no reborrowing occurs +fn copy_mut<'a>(t: &&'a mut i32) -> &'a mut i32 where for<'b> &'b mut i32: Copy { + //~^ WARNING trivial_bounds + is_copy(t); + let x = *t; + drop(x); + x +} + +fn is_copy<T: Copy>(t: &T) {} + + +fn main() {} diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr new file mode 100644 index 000000000..1e2662389 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr @@ -0,0 +1,28 @@ +warning: trait bound String: Copy does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-copy.rs:5:51 + | +LL | fn copy_string(t: String) -> String where String: Copy { + | ^^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound String: Copy does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-copy.rs:12:56 + | +LL | fn copy_out_string(t: &String) -> String where String: Copy { + | ^^^^ + +warning: trait bound String: Copy does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-copy.rs:16:55 + | +LL | fn copy_string_with_param<T>(x: String) where String: Copy { + | ^^^^ + +warning: trait bound for<'b> &'b mut i32: Copy does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-copy.rs:22:76 + | +LL | fn copy_mut<'a>(t: &&'a mut i32) -> &'a mut i32 where for<'b> &'b mut i32: Copy { + | ^^^^ + +warning: 4 warnings emitted + diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.rs new file mode 100644 index 000000000..e0f299630 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.rs @@ -0,0 +1,23 @@ +#![feature(trivial_bounds)] +#![allow(unused)] + +struct B; + +trait A { + type X; + fn get_x() -> Self::X; +} + +impl A for B { + type X = u8; + fn get_x() -> u8 { 0 } +} + +fn global_bound_is_hidden() -> u8 +where + B: A<X = i32> +{ + B::get_x() //~ ERROR +} + +fn main () {} diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr new file mode 100644 index 000000000..26679e713 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/trivial-bounds-inconsistent-projection-error.rs:20:5 + | +LL | fn global_bound_is_hidden() -> u8 + | -- expected `u8` because of return type +... +LL | B::get_x() + | ^^^^^^^^^^ expected `u8`, found `i32` + | +help: you can convert an `i32` to a `u8` and panic if the converted value doesn't fit + | +LL | B::get_x().try_into().unwrap() + | ++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.rs new file mode 100644 index 000000000..b13956673 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.rs @@ -0,0 +1,58 @@ +// run-pass +// Check that global bounds result in the expected choice of associated type + +#![feature(trivial_bounds)] +#![allow(unused)] + +struct B; + +trait A { + type X; + fn get_x() -> Self::X; +} + +impl A for B { + type X = u8; + fn get_x() -> u8 { 0 } +} + +fn underspecified_bound() -> u8 +where + B: A //~ WARNING trivial_bounds +{ + B::get_x() +} + +fn inconsistent_bound() -> i32 +where + B: A<X = i32> //~ WARNING trivial_bounds +{ + B::get_x() +} + +fn redundant_bound() -> u8 +where + B: A<X = u8> //~ WARNING trivial_bounds +{ + B::get_x() +} + +fn inconsistent_dup_bound() -> i32 +where + B: A<X = i32> + A + //~^ WARNING trivial_bounds + //~| WARNING trivial_bounds +{ + B::get_x() +} + +fn redundant_dup_bound() -> u8 +where + B: A<X = u8> + A + //~^ WARNING trivial_bounds + //~| WARNING trivial_bounds +{ + B::get_x() +} + +fn main () {} diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.stderr new file mode 100644 index 000000000..ddc13c512 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.stderr @@ -0,0 +1,46 @@ +warning: trait bound B: A does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-projection.rs:21:8 + | +LL | B: A + | ^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound B: A does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-projection.rs:28:8 + | +LL | B: A<X = i32> + | ^^^^^^^^^^ + +warning: trait bound B: A does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-projection.rs:35:8 + | +LL | B: A<X = u8> + | ^^^^^^^^^ + +warning: trait bound B: A does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-projection.rs:42:8 + | +LL | B: A<X = i32> + A + | ^^^^^^^^^^ + +warning: trait bound B: A does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-projection.rs:42:21 + | +LL | B: A<X = i32> + A + | ^ + +warning: trait bound B: A does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-projection.rs:51:8 + | +LL | B: A<X = u8> + A + | ^^^^^^^^^ + +warning: trait bound B: A does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-projection.rs:51:20 + | +LL | B: A<X = u8> + A + | ^ + +warning: 7 warnings emitted + diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.rs new file mode 100644 index 000000000..bfa083655 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.rs @@ -0,0 +1,27 @@ +// run-pass +// Check tautalogically false `Sized` bounds +#![feature(trivial_bounds)] +#![allow(unused)] + +trait A {} + +impl A for i32 {} + +struct T<X: ?Sized> { + x: X, +} + +struct S(str, str) where str: Sized; +//~^ WARNING Sized does not depend on any type or lifetime + +fn unsized_local() where for<'a> T<dyn A + 'a>: Sized { + //~^ WARNING Sized does not depend on any type or lifetime + let x: T<dyn A> = *(Box::new(T { x: 1 }) as Box<T<dyn A>>); +} + +fn return_str() -> str where str: Sized { + //~^ WARNING Sized does not depend on any type or lifetime + *"Sized".to_string().into_boxed_str() +} + +fn main() {} diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.stderr new file mode 100644 index 000000000..cf24d811c --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.stderr @@ -0,0 +1,22 @@ +warning: trait bound str: Sized does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-sized.rs:14:31 + | +LL | struct S(str, str) where str: Sized; + | ^^^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound for<'a> T<(dyn A + 'a)>: Sized does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-sized.rs:17:49 + | +LL | fn unsized_local() where for<'a> T<dyn A + 'a>: Sized { + | ^^^^^ + +warning: trait bound str: Sized does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-sized.rs:22:35 + | +LL | fn return_str() -> str where str: Sized { + | ^^^^^ + +warning: 3 warnings emitted + diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.rs new file mode 100644 index 000000000..9efa22b10 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.rs @@ -0,0 +1,14 @@ +// run-pass +// Test that inconsistent bounds are used in well-formedness checks +#![feature(trivial_bounds)] + +use std::fmt::Debug; + +pub fn foo() where Vec<str>: Debug, str: Copy { + //~^ WARNING Debug does not depend on any type or lifetime + //~| WARNING Copy does not depend on any type or lifetime + let x = vec![*"1"]; + println!("{:?}", x); +} + +fn main() {} diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.stderr new file mode 100644 index 000000000..8f58a99a8 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.stderr @@ -0,0 +1,16 @@ +warning: trait bound Vec<str>: Debug does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-well-formed.rs:7:30 + | +LL | pub fn foo() where Vec<str>: Debug, str: Copy { + | ^^^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound str: Copy does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-well-formed.rs:7:42 + | +LL | pub fn foo() where Vec<str>: Debug, str: Copy { + | ^^^^ + +warning: 2 warnings emitted + diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.rs b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.rs new file mode 100644 index 000000000..7148f5d6d --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.rs @@ -0,0 +1,74 @@ +// run-pass + +// Check that tautalogically false bounds are accepted, and are used +// in type inference. +#![feature(trivial_bounds)] +#![allow(unused)] + +pub trait Foo { + fn test(&self); +} + +fn generic_function<X: Foo>(x: X) {} + +enum E where i32: Foo { V } //~ WARNING trivial_bounds + +struct S where i32: Foo; //~ WARNING trivial_bounds + +trait T where i32: Foo {} //~ WARNING trivial_bounds + +union U where i32: Foo { f: i32 } //~ WARNING trivial_bounds + +type Y where i32: Foo = (); +//~^ WARNING type_alias_bounds +//~| WARNING trivial_bounds + +impl Foo for () where i32: Foo { //~ WARNING trivial_bounds + fn test(&self) { + 3i32.test(); + Foo::test(&4i32); + generic_function(5i32); + } +} + +fn f() where i32: Foo { //~ WARNING trivial_bounds + let s = S; + 3i32.test(); + Foo::test(&4i32); + generic_function(5i32); +} + +fn g() where &'static str: Foo { //~ WARNING trivial_bounds + "Foo".test(); + Foo::test(&"Foo"); + generic_function("Foo"); +} + +trait A {} + +impl A for i32 {} + +struct Dst<X: ?Sized> { + x: X, +} + +struct TwoStrs(str, str) where str: Sized; //~ WARNING trivial_bounds + +fn unsized_local() where for<'a> Dst<dyn A + 'a>: Sized { //~ WARNING trivial_bounds + let x: Dst<dyn A> = *(Box::new(Dst { x: 1 }) as Box<Dst<dyn A>>); +} + +fn return_str() -> str where str: Sized { //~ WARNING trivial_bounds + *"Sized".to_string().into_boxed_str() +} + +fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> { + //~^ WARNING trivial_bounds + -s +} + +fn use_for() where i32: Iterator { //~ WARNING trivial_bounds + for _ in 2i32 {} +} + +fn main() {} diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr new file mode 100644 index 000000000..d66e46887 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr @@ -0,0 +1,95 @@ +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:14:19 + | +LL | enum E where i32: Foo { V } + | ^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:16:21 + | +LL | struct S where i32: Foo; + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:18:20 + | +LL | trait T where i32: Foo {} + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:20:20 + | +LL | union U where i32: Foo { f: i32 } + | ^^^ + +warning: where clauses are not enforced in type aliases + --> $DIR/trivial-bounds-inconsistent.rs:22:14 + | +LL | type Y where i32: Foo = (); + | ^^^^^^^^ + | + = note: `#[warn(type_alias_bounds)]` on by default +help: the clause will not be checked when the type alias is used, and should be removed + | +LL - type Y where i32: Foo = (); +LL + type Y = (); + | + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:22:19 + | +LL | type Y where i32: Foo = (); + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:26:28 + | +LL | impl Foo for () where i32: Foo { + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:34:19 + | +LL | fn f() where i32: Foo { + | ^^^ + +warning: trait bound &'static str: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:41:28 + | +LL | fn g() where &'static str: Foo { + | ^^^ + +warning: trait bound str: Sized does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:55:37 + | +LL | struct TwoStrs(str, str) where str: Sized; + | ^^^^^ + +warning: trait bound for<'a> Dst<(dyn A + 'a)>: Sized does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:57:51 + | +LL | fn unsized_local() where for<'a> Dst<dyn A + 'a>: Sized { + | ^^^^^ + +warning: trait bound str: Sized does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:61:35 + | +LL | fn return_str() -> str where str: Sized { + | ^^^^^ + +warning: trait bound String: Neg does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:65:46 + | +LL | fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait bound i32: Iterator does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:70:25 + | +LL | fn use_for() where i32: Iterator { + | ^^^^^^^^ + +warning: 14 warnings emitted + diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak-copy.rs b/src/test/ui/trivial-bounds/trivial-bounds-leak-copy.rs new file mode 100644 index 000000000..cecc0b2da --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak-copy.rs @@ -0,0 +1,12 @@ +// Check that false Copy bounds don't leak +#![feature(trivial_bounds)] + +fn copy_out_string(t: &String) -> String where String: Copy { + *t +} + +fn move_out_string(t: &String) -> String { + *t //~ ERROR +} + +fn main() {} diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak-copy.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak-copy.stderr new file mode 100644 index 000000000..b3ec3cd8d --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak-copy.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of `*t` which is behind a shared reference + --> $DIR/trivial-bounds-leak-copy.rs:9:5 + | +LL | *t + | ^^ move occurs because `*t` has type `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/trivial-bounds/trivial-bounds-leak.rs b/src/test/ui/trivial-bounds/trivial-bounds-leak.rs new file mode 100644 index 000000000..249051d80 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.rs @@ -0,0 +1,31 @@ +// Check that false bounds don't leak +#![feature(trivial_bounds)] + +pub trait Foo { + fn test(&self); +} + +fn return_str() -> str where str: Sized { + *"Sized".to_string().into_boxed_str() +} + +fn cant_return_str() -> str { //~ ERROR + *"Sized".to_string().into_boxed_str() +} + +fn my_function() where i32: Foo +{ + 3i32.test(); + Foo::test(&4i32); + generic_function(5i32); +} + +fn foo() { + 3i32.test(); //~ ERROR + Foo::test(&4i32); //~ ERROR + generic_function(5i32); //~ ERROR +} + +fn generic_function<T: Foo>(t: T) {} + +fn main() {} diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr new file mode 100644 index 000000000..02c5d5d24 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -0,0 +1,48 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/trivial-bounds-leak.rs:12:25 + | +LL | fn cant_return_str() -> str { + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: the return type of a function must have a statically known size + +error[E0599]: no method named `test` found for type `i32` in the current scope + --> $DIR/trivial-bounds-leak.rs:24:10 + | +LL | 3i32.test(); + | ^^^^ method not found in `i32` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `test`, perhaps you need to implement it + --> $DIR/trivial-bounds-leak.rs:4:1 + | +LL | pub trait Foo { + | ^^^^^^^^^^^^^ + +error[E0277]: the trait bound `i32: Foo` is not satisfied + --> $DIR/trivial-bounds-leak.rs:25:15 + | +LL | Foo::test(&4i32); + | --------- ^^^^^ the trait `Foo` is not implemented for `i32` + | | + | required by a bound introduced by this call + +error[E0277]: the trait bound `i32: Foo` is not satisfied + --> $DIR/trivial-bounds-leak.rs:26:22 + | +LL | generic_function(5i32); + | ---------------- ^^^^ the trait `Foo` is not implemented for `i32` + | | + | required by a bound introduced by this call + | +note: required by a bound in `generic_function` + --> $DIR/trivial-bounds-leak.rs:29:24 + | +LL | fn generic_function<T: Foo>(t: T) {} + | ^^^ required by this bound in `generic_function` + +error: aborting due to 4 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/trivial-bounds/trivial-bounds-lint.rs b/src/test/ui/trivial-bounds/trivial-bounds-lint.rs new file mode 100644 index 000000000..078578372 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-lint.rs @@ -0,0 +1,40 @@ +#![feature(trivial_bounds)] +#![allow(unused)] +#![deny(trivial_bounds)] + +struct A where i32: Copy; //~ ERROR + +trait X<T: Copy> {} + +trait Y<T>: Copy {} + +trait Z { + type S: Copy; +} + +// Check only the bound the user writes trigger the lint +fn trivial_elaboration<T>() where T: X<i32> + Z<S = i32>, i32: Y<T> {} // OK + +fn global_param() where i32: X<()> {} //~ ERROR + +// Should only error on the trait bound, not the implicit +// projection bound <i32 as Z>::S == i32. +fn global_projection() where i32: Z<S = i32> {} //~ ERROR + +impl A { + fn new() -> A { A } +} + +// Lifetime bounds should be linted as well +fn global_lifetimes() where i32: 'static, &'static str: 'static {} +//~^ ERROR +//~| ERROR + +fn local_lifetimes<'a>() where i32: 'a, &'a str: 'a {} // OK + +fn global_outlives() where 'static: 'static {} //~ ERROR + +// Check that each bound is checked individually +fn mixed_bounds<T: Copy>() where i32: X<T> + Copy {} //~ ERROR + +fn main() {} diff --git a/src/test/ui/trivial-bounds/trivial-bounds-lint.stderr b/src/test/ui/trivial-bounds/trivial-bounds-lint.stderr new file mode 100644 index 000000000..20e0ddfc2 --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-lint.stderr @@ -0,0 +1,50 @@ +error: trait bound i32: Copy does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-lint.rs:5:21 + | +LL | struct A where i32: Copy; + | ^^^^ + | +note: the lint level is defined here + --> $DIR/trivial-bounds-lint.rs:3:9 + | +LL | #![deny(trivial_bounds)] + | ^^^^^^^^^^^^^^ + +error: trait bound i32: X<()> does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-lint.rs:18:30 + | +LL | fn global_param() where i32: X<()> {} + | ^^^^^ + +error: trait bound i32: Z does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-lint.rs:22:35 + | +LL | fn global_projection() where i32: Z<S = i32> {} + | ^^^^^^^^^^ + +error: lifetime bound i32: 'static does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-lint.rs:29:34 + | +LL | fn global_lifetimes() where i32: 'static, &'static str: 'static {} + | ^^^^^^^ + +error: lifetime bound &'static str: 'static does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-lint.rs:29:57 + | +LL | fn global_lifetimes() where i32: 'static, &'static str: 'static {} + | ^^^^^^^ + +error: lifetime bound 'static: 'static does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-lint.rs:35:37 + | +LL | fn global_outlives() where 'static: 'static {} + | ^^^^^^^ + +error: trait bound i32: Copy does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-lint.rs:38:46 + | +LL | fn mixed_bounds<T: Copy>() where i32: X<T> + Copy {} + | ^^^^ + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/trivial-bounds/trivial-bounds-object.rs b/src/test/ui/trivial-bounds/trivial-bounds-object.rs new file mode 100644 index 000000000..f5feeea7c --- /dev/null +++ b/src/test/ui/trivial-bounds/trivial-bounds-object.rs @@ -0,0 +1,18 @@ +// run-pass +// Check that the object bound dyn A + 'a: A is preferred over the +// where clause bound dyn A + 'static: A. + +#![allow(unused)] + +trait A { + fn test(&self); +} + +fn foo(x: &dyn A) +where + dyn A + 'static: A, // Using this bound would lead to a lifetime error. +{ + x.test(); +} + +fn main () {} |