diff options
Diffstat (limited to 'tests/ui/span')
193 files changed, 7833 insertions, 0 deletions
diff --git a/tests/ui/span/E0046.rs b/tests/ui/span/E0046.rs new file mode 100644 index 000000000..961109892 --- /dev/null +++ b/tests/ui/span/E0046.rs @@ -0,0 +1,11 @@ +trait Foo { + fn foo(); +} + +struct Bar; + +impl Foo for Bar {} +//~^ ERROR E0046 + +fn main() { +} diff --git a/tests/ui/span/E0046.stderr b/tests/ui/span/E0046.stderr new file mode 100644 index 000000000..1323524f2 --- /dev/null +++ b/tests/ui/span/E0046.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `foo` + --> $DIR/E0046.rs:7:1 + | +LL | fn foo(); + | --------- `foo` from trait +... +LL | impl Foo for Bar {} + | ^^^^^^^^^^^^^^^^ missing `foo` in implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/span/E0072.rs b/tests/ui/span/E0072.rs new file mode 100644 index 000000000..bc284cdcb --- /dev/null +++ b/tests/ui/span/E0072.rs @@ -0,0 +1,7 @@ +struct ListNode { //~ ERROR has infinite size + head: u8, + tail: Option<ListNode>, +} + +fn main() { +} diff --git a/tests/ui/span/E0072.stderr b/tests/ui/span/E0072.stderr new file mode 100644 index 000000000..20f2e0df0 --- /dev/null +++ b/tests/ui/span/E0072.stderr @@ -0,0 +1,17 @@ +error[E0072]: recursive type `ListNode` has infinite size + --> $DIR/E0072.rs:1:1 + | +LL | struct ListNode { + | ^^^^^^^^^^^^^^^ +LL | head: u8, +LL | tail: Option<ListNode>, + | -------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | tail: Option<Box<ListNode>>, + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/span/E0204.rs b/tests/ui/span/E0204.rs new file mode 100644 index 000000000..174de8cdd --- /dev/null +++ b/tests/ui/span/E0204.rs @@ -0,0 +1,26 @@ +struct Foo { + foo: Vec<u32>, +} + +impl Copy for Foo { } //~ ERROR may not be implemented for this type + +#[derive(Copy)] //~ ERROR may not be implemented for this type +struct Foo2<'a> { + ty: &'a mut bool, +} + +enum EFoo { + Bar { x: Vec<u32> }, + Baz, +} + +impl Copy for EFoo { } //~ ERROR may not be implemented for this type + +#[derive(Copy)] //~ ERROR may not be implemented for this type +enum EFoo2<'a> { + Bar(&'a mut bool), + Baz, +} + +fn main() { +} diff --git a/tests/ui/span/E0204.stderr b/tests/ui/span/E0204.stderr new file mode 100644 index 000000000..0b2166eed --- /dev/null +++ b/tests/ui/span/E0204.stderr @@ -0,0 +1,43 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/E0204.rs:5:15 + | +LL | foo: Vec<u32>, + | ------------- this field does not implement `Copy` +... +LL | impl Copy for Foo { } + | ^^^ + +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/E0204.rs:7:10 + | +LL | #[derive(Copy)] + | ^^^^ +LL | struct Foo2<'a> { +LL | ty: &'a mut bool, + | ---------------- this field does not implement `Copy` + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/E0204.rs:17:15 + | +LL | Bar { x: Vec<u32> }, + | ----------- this field does not implement `Copy` +... +LL | impl Copy for EFoo { } + | ^^^^ + +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/E0204.rs:19:10 + | +LL | #[derive(Copy)] + | ^^^^ +LL | enum EFoo2<'a> { +LL | Bar(&'a mut bool), + | ------------ this field does not implement `Copy` + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/span/E0493.rs b/tests/ui/span/E0493.rs new file mode 100644 index 000000000..625da25a7 --- /dev/null +++ b/tests/ui/span/E0493.rs @@ -0,0 +1,21 @@ +struct Foo { + a: u32 +} + +impl Drop for Foo { + fn drop(&mut self) {} +} + +struct Bar { + a: u32 +} + +impl Drop for Bar { + fn drop(&mut self) {} +} + +const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; +//~^ ERROR destructor of + +fn main() { +} diff --git a/tests/ui/span/E0493.stderr b/tests/ui/span/E0493.stderr new file mode 100644 index 000000000..9db627562 --- /dev/null +++ b/tests/ui/span/E0493.stderr @@ -0,0 +1,11 @@ +error[E0493]: destructor of `(Foo, Foo)` cannot be evaluated at compile-time + --> $DIR/E0493.rs:17:17 + | +LL | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/span/E0535.rs b/tests/ui/span/E0535.rs new file mode 100644 index 000000000..e26334e9b --- /dev/null +++ b/tests/ui/span/E0535.rs @@ -0,0 +1,6 @@ +#[inline(unknown)] //~ ERROR E0535 +pub fn something() {} + +fn main() { + something(); +} diff --git a/tests/ui/span/E0535.stderr b/tests/ui/span/E0535.stderr new file mode 100644 index 000000000..b1411bc43 --- /dev/null +++ b/tests/ui/span/E0535.stderr @@ -0,0 +1,11 @@ +error[E0535]: invalid argument + --> $DIR/E0535.rs:1:10 + | +LL | #[inline(unknown)] + | ^^^^^^^ + | + = help: valid inline arguments are `always` and `never` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0535`. diff --git a/tests/ui/span/E0536.rs b/tests/ui/span/E0536.rs new file mode 100644 index 000000000..72de7b6f4 --- /dev/null +++ b/tests/ui/span/E0536.rs @@ -0,0 +1,4 @@ +#[cfg(not())] //~ ERROR E0536 +pub fn something() {} + +pub fn main() {} diff --git a/tests/ui/span/E0536.stderr b/tests/ui/span/E0536.stderr new file mode 100644 index 000000000..820b0d744 --- /dev/null +++ b/tests/ui/span/E0536.stderr @@ -0,0 +1,9 @@ +error[E0536]: expected 1 cfg-pattern + --> $DIR/E0536.rs:1:7 + | +LL | #[cfg(not())] + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0536`. diff --git a/tests/ui/span/E0537.rs b/tests/ui/span/E0537.rs new file mode 100644 index 000000000..4088a9ae5 --- /dev/null +++ b/tests/ui/span/E0537.rs @@ -0,0 +1,4 @@ +#[cfg(unknown())] //~ ERROR E0537 +pub fn something() {} + +pub fn main() {} diff --git a/tests/ui/span/E0537.stderr b/tests/ui/span/E0537.stderr new file mode 100644 index 000000000..5478c3fbc --- /dev/null +++ b/tests/ui/span/E0537.stderr @@ -0,0 +1,9 @@ +error[E0537]: invalid predicate `unknown` + --> $DIR/E0537.rs:1:7 + | +LL | #[cfg(unknown())] + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0537`. diff --git a/tests/ui/span/auxiliary/transitive_dep_three.rs b/tests/ui/span/auxiliary/transitive_dep_three.rs new file mode 100644 index 000000000..99b51625a --- /dev/null +++ b/tests/ui/span/auxiliary/transitive_dep_three.rs @@ -0,0 +1,9 @@ +#[macro_export] +macro_rules! define_parse_error { + () => { + #[macro_export] + macro_rules! parse_error { + () => { parse error } + } + } +} diff --git a/tests/ui/span/auxiliary/transitive_dep_two.rs b/tests/ui/span/auxiliary/transitive_dep_two.rs new file mode 100644 index 000000000..5110c4276 --- /dev/null +++ b/tests/ui/span/auxiliary/transitive_dep_two.rs @@ -0,0 +1,3 @@ +extern crate transitive_dep_three; + +transitive_dep_three::define_parse_error!(); diff --git a/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs new file mode 100644 index 000000000..76a1d12ea --- /dev/null +++ b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs @@ -0,0 +1,142 @@ +// Test how overloaded deref interacts with borrows when DerefMut +// is implemented. + +use std::ops::{Deref, DerefMut}; + +struct Own<T> { + value: *mut T +} + +impl<T> Deref for Own<T> { + type Target = T; + + fn deref(&self) -> &T { + unsafe { &*self.value } + } +} + +impl<T> DerefMut for Own<T> { + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.value } + } +} + +struct Point { + x: isize, + y: isize +} + +impl Point { + fn get(&self) -> (isize, isize) { + (self.x, self.y) + } + + fn set(&mut self, x: isize, y: isize) { + self.x = x; + self.y = y; + } + + fn x_ref(&self) -> &isize { + &self.x + } + + fn y_mut(&mut self) -> &mut isize { + &mut self.y + } +} + +fn deref_imm_field(x: Own<Point>) { + let __isize = &x.y; +} + +fn deref_mut_field1(x: Own<Point>) { + let __isize = &mut x.y; //~ ERROR cannot borrow +} + +fn deref_mut_field2(mut x: Own<Point>) { + let __isize = &mut x.y; +} + +fn deref_extend_field(x: &Own<Point>) -> &isize { + &x.y +} + +fn deref_extend_mut_field1(x: &Own<Point>) -> &mut isize { + &mut x.y //~ ERROR cannot borrow +} + +fn deref_extend_mut_field2(x: &mut Own<Point>) -> &mut isize { + &mut x.y +} + +fn deref_extend_mut_field3(x: &mut Own<Point>) { + // Hmm, this is unfortunate, because with box it would work, + // but it's presently the expected outcome. See `deref_extend_mut_field4` + // for the workaround. + + let _x = &mut x.x; + let _y = &mut x.y; //~ ERROR cannot borrow + use_mut(_x); +} +fn deref_extend_mut_field4<'a>(x: &'a mut Own<Point>) { + let p = &mut **x; + let _x = &mut p.x; + let _y = &mut p.y; +} + +fn assign_field1<'a>(x: Own<Point>) { + x.y = 3; //~ ERROR cannot borrow +} + +fn assign_field2<'a>(x: &'a Own<Point>) { + x.y = 3; //~ ERROR cannot borrow +} + +fn assign_field3<'a>(x: &'a mut Own<Point>) { + x.y = 3; +} + +fn assign_field4<'a>(x: &'a mut Own<Point>) { + let _p: &mut Point = &mut **x; + x.y = 3; //~ ERROR cannot borrow + use_mut(_p); +} +fn deref_imm_method(x: Own<Point>) { + let __isize = x.get(); +} + +fn deref_mut_method1(x: Own<Point>) { + x.set(0, 0); //~ ERROR cannot borrow +} + +fn deref_mut_method2(mut x: Own<Point>) { + x.set(0, 0); +} + +fn deref_extend_method(x: &Own<Point>) -> &isize { + x.x_ref() +} + +fn deref_extend_mut_method1(x: &Own<Point>) -> &mut isize { + x.y_mut() //~ ERROR cannot borrow +} + +fn deref_extend_mut_method2(x: &mut Own<Point>) -> &mut isize { + x.y_mut() +} + +fn assign_method1<'a>(x: Own<Point>) { + *x.y_mut() = 3; //~ ERROR cannot borrow +} + +fn assign_method2<'a>(x: &'a Own<Point>) { + *x.y_mut() = 3; //~ ERROR cannot borrow +} + +fn assign_method3<'a>(x: &'a mut Own<Point>) { + *x.y_mut() = 3; +} + +pub fn main() {} + +fn use_mut<T>(_: &mut T) {} diff --git a/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr new file mode 100644 index 000000000..570328fc2 --- /dev/null +++ b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr @@ -0,0 +1,112 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:53:24 + | +LL | let __isize = &mut x.y; + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn deref_mut_field1(mut x: Own<Point>) { + | +++ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:65:10 + | +LL | &mut x.y + | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn deref_extend_mut_field1(x: &mut Own<Point>) -> &mut isize { + | ~~~~~~~~~~~~~~~ + +error[E0499]: cannot borrow `*x` as mutable more than once at a time + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:78:19 + | +LL | let _x = &mut x.x; + | - first mutable borrow occurs here +LL | let _y = &mut x.y; + | ^ second mutable borrow occurs here +LL | use_mut(_x); + | -- first borrow later used here + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:88:5 + | +LL | x.y = 3; + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn assign_field1<'a>(mut x: Own<Point>) { + | +++ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:92:5 + | +LL | x.y = 3; + | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn assign_field2<'a>(x: &'a mut Own<Point>) { + | ~~~~~~~~~~~~~~~~~~ + +error[E0499]: cannot borrow `*x` as mutable more than once at a time + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:101:5 + | +LL | let _p: &mut Point = &mut **x; + | -- first mutable borrow occurs here +LL | x.y = 3; + | ^ second mutable borrow occurs here +LL | use_mut(_p); + | -- first borrow later used here + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:109:5 + | +LL | x.set(0, 0); + | ^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn deref_mut_method1(mut x: Own<Point>) { + | +++ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:121:5 + | +LL | x.y_mut() + | ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn deref_extend_mut_method1(x: &mut Own<Point>) -> &mut isize { + | ~~~~~~~~~~~~~~~ + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:129:6 + | +LL | *x.y_mut() = 3; + | ^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn assign_method1<'a>(mut x: Own<Point>) { + | +++ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:133:6 + | +LL | *x.y_mut() = 3; + | ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn assign_method2<'a>(x: &'a mut Own<Point>) { + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0499, E0596. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/span/borrowck-borrow-overloaded-deref-mut.rs b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.rs new file mode 100644 index 000000000..8d43d5da4 --- /dev/null +++ b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.rs @@ -0,0 +1,60 @@ +// Test how overloaded deref interacts with borrows when DerefMut +// is implemented. + +use std::ops::{Deref, DerefMut}; + +struct Own<T> { + value: *mut T +} + +impl<T> Deref for Own<T> { + type Target = T; + + fn deref<'a>(&'a self) -> &'a T { + unsafe { &*self.value } + } +} + +impl<T> DerefMut for Own<T> { + fn deref_mut<'a>(&'a mut self) -> &'a mut T { + unsafe { &mut *self.value } + } +} + +fn deref_imm(x: Own<isize>) { + let __isize = &*x; +} + +fn deref_mut1(x: Own<isize>) { + let __isize = &mut *x; //~ ERROR cannot borrow +} + +fn deref_mut2(mut x: Own<isize>) { + let __isize = &mut *x; +} + +fn deref_extend<'a>(x: &'a Own<isize>) -> &'a isize { + &**x +} + +fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize { + &mut **x //~ ERROR cannot borrow +} + +fn deref_extend_mut2<'a>(x: &'a mut Own<isize>) -> &'a mut isize { + &mut **x +} + +fn assign1<'a>(x: Own<isize>) { + *x = 3; //~ ERROR cannot borrow +} + +fn assign2<'a>(x: &'a Own<isize>) { + **x = 3; //~ ERROR cannot borrow +} + +fn assign3<'a>(x: &'a mut Own<isize>) { + **x = 3; +} + +pub fn main() {} diff --git a/tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr new file mode 100644 index 000000000..3fed7b3f4 --- /dev/null +++ b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr @@ -0,0 +1,47 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:29:25 + | +LL | let __isize = &mut *x; + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn deref_mut1(mut x: Own<isize>) { + | +++ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:41:11 + | +LL | &mut **x + | ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn deref_extend_mut1<'a>(x: &'a mut Own<isize>) -> &'a mut isize { + | ~~~~~~~~~~~~~~~~~~ + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:49:6 + | +LL | *x = 3; + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn assign1<'a>(mut x: Own<isize>) { + | +++ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:53:6 + | +LL | **x = 3; + | ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn assign2<'a>(x: &'a mut Own<isize>) { + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/span/borrowck-call-is-borrow-issue-12224.rs b/tests/ui/span/borrowck-call-is-borrow-issue-12224.rs new file mode 100644 index 000000000..938fdaf11 --- /dev/null +++ b/tests/ui/span/borrowck-call-is-borrow-issue-12224.rs @@ -0,0 +1,62 @@ +#![feature(fn_traits)] + +// Ensure that invoking a closure counts as a unique immutable borrow + +type Fn<'a> = Box<dyn FnMut() + 'a>; + +struct Test<'a> { + f: Box<dyn FnMut() + 'a> +} + +fn call<F>(mut f: F) where F: FnMut(Fn) { + f(Box::new(|| { + //~^ ERROR: cannot borrow `f` as mutable more than once + f((Box::new(|| {}))) + })); +} + +fn test1() { + call(|mut a| { + a.call_mut(()); + }); +} + +fn test2<F>(f: &F) where F: FnMut() { + (*f)(); + //~^ ERROR cannot borrow `*f` as mutable, as it is behind a `&` reference +} + +fn test3<F>(f: &mut F) where F: FnMut() { + (*f)(); +} + +fn test4(f: &Test) { + f.f.call_mut(()) + //~^ ERROR: cannot borrow `f.f` as mutable, as it is behind a `&` reference +} + +fn test5(f: &mut Test) { + f.f.call_mut(()) +} + +fn test6() { + let mut f = || {}; + (|| { + f(); + })(); +} + +fn test7() { + fn foo<F>(_: F) where F: FnMut(Box<dyn FnMut(isize)>, isize) {} + let s = String::new(); // Capture to make f !Copy + let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| { + let _ = s.len(); + }; + f(Box::new(|a| { + //~^ ERROR cannot move out of `f` because it is borrowed + foo(f); + //~^ ERROR cannot move out of `f`, a captured variable in an `FnMut` closure + }), 3); +} + +fn main() {} diff --git a/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr new file mode 100644 index 000000000..48b42bc78 --- /dev/null +++ b/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -0,0 +1,61 @@ +error[E0499]: cannot borrow `f` as mutable more than once at a time + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:12:16 + | +LL | f(Box::new(|| { + | - ^^ second mutable borrow occurs here + | | + | first mutable borrow occurs here + | first borrow later used by call +LL | +LL | f((Box::new(|| {}))) + | - second borrow occurs due to use of `f` in closure + +error[E0596]: cannot borrow `*f` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:25:5 + | +LL | (*f)(); + | ^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn test2<F>(f: &mut F) where F: FnMut() { + | ~~~~~~ + +error[E0596]: cannot borrow `f.f` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:34:5 + | +LL | f.f.call_mut(()) + | ^^^^^^^^^^^^^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn test4(f: &mut Test<'_>) { + | ~~~~~~~~~~~~~ + +error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:57:13 + | +LL | let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| { + | ----- captured outer variable +... +LL | f(Box::new(|a| { + | --- captured by this `FnMut` closure +LL | +LL | foo(f); + | ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 52:58]`, which does not implement the `Copy` trait + +error[E0505]: cannot move out of `f` because it is borrowed + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:55:16 + | +LL | f(Box::new(|a| { + | - ^^^ move out of `f` occurs here + | | + | borrow of `f` occurs here +LL | +LL | foo(f); + | - move occurs due to use in closure + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0499, E0505, E0507, E0596. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/span/borrowck-call-method-from-mut-aliasable.rs b/tests/ui/span/borrowck-call-method-from-mut-aliasable.rs new file mode 100644 index 000000000..caf2d2a55 --- /dev/null +++ b/tests/ui/span/borrowck-call-method-from-mut-aliasable.rs @@ -0,0 +1,21 @@ +struct Foo { + x: isize, +} + +impl Foo { + pub fn f(&self) {} + pub fn h(&mut self) {} +} + +fn a(x: &mut Foo) { + x.f(); + x.h(); +} + +fn b(x: &Foo) { + x.f(); + x.h(); //~ ERROR cannot borrow +} + +fn main() { +} diff --git a/tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr b/tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr new file mode 100644 index 000000000..2a842f5a2 --- /dev/null +++ b/tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-call-method-from-mut-aliasable.rs:17:5 + | +LL | x.h(); + | ^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn b(x: &mut Foo) { + | ~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/span/borrowck-fn-in-const-b.rs b/tests/ui/span/borrowck-fn-in-const-b.rs new file mode 100644 index 000000000..822083efe --- /dev/null +++ b/tests/ui/span/borrowck-fn-in-const-b.rs @@ -0,0 +1,14 @@ +// Check that we check fns appearing in constant declarations. +// Issue #22382. + +// How about mutating an immutable vector? +const MUTATE: fn(&Vec<String>) = { + fn broken(x: &Vec<String>) { + x.push(format!("this is broken")); + //~^ ERROR cannot borrow + } + broken +}; + +fn main() { +} diff --git a/tests/ui/span/borrowck-fn-in-const-b.stderr b/tests/ui/span/borrowck-fn-in-const-b.stderr new file mode 100644 index 000000000..1df19deb1 --- /dev/null +++ b/tests/ui/span/borrowck-fn-in-const-b.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-fn-in-const-b.rs:7:9 + | +LL | x.push(format!("this is broken")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn broken(x: &mut Vec<String>) { + | ~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/span/borrowck-let-suggestion-suffixes.rs b/tests/ui/span/borrowck-let-suggestion-suffixes.rs new file mode 100644 index 000000000..18abfb5c3 --- /dev/null +++ b/tests/ui/span/borrowck-let-suggestion-suffixes.rs @@ -0,0 +1,59 @@ +fn id<T>(x: T) -> T { x } + +fn f() { + let old = ['o']; // statement 0 + let mut v1 = Vec::new(); // statement 1 + + let mut v2 = Vec::new(); // statement 2 + + { + let young = ['y']; // statement 3 + + v2.push(&young[0]); // statement 4 + //~^ ERROR `young[_]` does not live long enough + //~| NOTE borrowed value does not live long enough + } //~ NOTE `young[_]` dropped here while still borrowed + + let mut v3 = Vec::new(); // statement 5 + + v3.push(&id('x')); // statement 6 + //~^ ERROR temporary value dropped while borrowed + //~| NOTE creates a temporary value which is freed while still in use + //~| NOTE temporary value is freed at the end of this statement + //~| HELP consider using a `let` binding to create a longer lived value + + { + + let mut v4 = Vec::new(); // (sub) statement 0 + + v4.push(&id('y')); + //~^ ERROR temporary value dropped while borrowed + //~| NOTE creates a temporary value which is freed while still in use + //~| NOTE temporary value is freed at the end of this statement + //~| NOTE consider using a `let` binding to create a longer lived value + v4.use_ref(); + //~^ NOTE borrow later used here + } // (statement 7) + + let mut v5 = Vec::new(); // statement 8 + + v5.push(&id('z')); + //~^ ERROR temporary value dropped while borrowed + //~| NOTE creates a temporary value which is freed while still in use + //~| NOTE temporary value is freed at the end of this statement + //~| HELP consider using a `let` binding to create a longer lived value + + v1.push(&old[0]); + + (v1, v2, v3, /* v4 is above. */ v5).use_ref(); + //~^ NOTE borrow later used here + //~| NOTE borrow later used here + //~| NOTE borrow later used here +} + +fn main() { + f(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl<T> Fake for T { } diff --git a/tests/ui/span/borrowck-let-suggestion-suffixes.stderr b/tests/ui/span/borrowck-let-suggestion-suffixes.stderr new file mode 100644 index 000000000..2dc29a78d --- /dev/null +++ b/tests/ui/span/borrowck-let-suggestion-suffixes.stderr @@ -0,0 +1,63 @@ +error[E0597]: `young[_]` does not live long enough + --> $DIR/borrowck-let-suggestion-suffixes.rs:12:17 + | +LL | v2.push(&young[0]); // statement 4 + | ^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - `young[_]` dropped here while still borrowed +... +LL | (v1, v2, v3, /* v4 is above. */ v5).use_ref(); + | -- borrow later used here + +error[E0716]: temporary value dropped while borrowed + --> $DIR/borrowck-let-suggestion-suffixes.rs:19:14 + | +LL | v3.push(&id('x')); // statement 6 + | ^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | (v1, v2, v3, /* v4 is above. */ v5).use_ref(); + | -- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = id('x'); +LL ~ v3.push(&binding); // statement 6 + | + +error[E0716]: temporary value dropped while borrowed + --> $DIR/borrowck-let-suggestion-suffixes.rs:29:18 + | +LL | v4.push(&id('y')); + | ^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | v4.use_ref(); + | ------------ borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + +error[E0716]: temporary value dropped while borrowed + --> $DIR/borrowck-let-suggestion-suffixes.rs:40:14 + | +LL | v5.push(&id('z')); + | ^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | (v1, v2, v3, /* v4 is above. */ v5).use_ref(); + | -- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = id('z'); +LL ~ v5.push(&binding); + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0597, E0716. +For more information about an error, try `rustc --explain E0597`. diff --git a/tests/ui/span/borrowck-object-mutability.rs b/tests/ui/span/borrowck-object-mutability.rs new file mode 100644 index 000000000..f5adc2cc1 --- /dev/null +++ b/tests/ui/span/borrowck-object-mutability.rs @@ -0,0 +1,26 @@ +trait Foo { + fn borrowed(&self); + fn borrowed_mut(&mut self); +} + +fn borrowed_receiver(x: &dyn Foo) { + x.borrowed(); + x.borrowed_mut(); //~ ERROR cannot borrow +} + +fn borrowed_mut_receiver(x: &mut dyn Foo) { + x.borrowed(); + x.borrowed_mut(); +} + +fn owned_receiver(x: Box<dyn Foo>) { + x.borrowed(); + x.borrowed_mut(); //~ ERROR cannot borrow +} + +fn mut_owned_receiver(mut x: Box<dyn Foo>) { + x.borrowed(); + x.borrowed_mut(); +} + +fn main() {} diff --git a/tests/ui/span/borrowck-object-mutability.stderr b/tests/ui/span/borrowck-object-mutability.stderr new file mode 100644 index 000000000..b6517e0b3 --- /dev/null +++ b/tests/ui/span/borrowck-object-mutability.stderr @@ -0,0 +1,25 @@ +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-object-mutability.rs:8:5 + | +LL | x.borrowed_mut(); + | ^^^^^^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn borrowed_receiver(x: &mut dyn Foo) { + | ~~~~~~~~~~~~ + +error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable + --> $DIR/borrowck-object-mutability.rs:18:5 + | +LL | x.borrowed_mut(); + | ^^^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn owned_receiver(mut x: Box<dyn Foo>) { + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/span/borrowck-ref-into-rvalue.fixed b/tests/ui/span/borrowck-ref-into-rvalue.fixed new file mode 100644 index 000000000..51f65e534 --- /dev/null +++ b/tests/ui/span/borrowck-ref-into-rvalue.fixed @@ -0,0 +1,13 @@ +// run-rustfix +fn main() { + let msg; + let binding = Some("Hello".to_string()); + match binding { + //~^ ERROR temporary value dropped while borrowed + Some(ref m) => { + msg = m; + }, + None => { panic!() } + } + println!("{}", *msg); +} diff --git a/tests/ui/span/borrowck-ref-into-rvalue.rs b/tests/ui/span/borrowck-ref-into-rvalue.rs new file mode 100644 index 000000000..7b09fad92 --- /dev/null +++ b/tests/ui/span/borrowck-ref-into-rvalue.rs @@ -0,0 +1,12 @@ +// run-rustfix +fn main() { + let msg; + match Some("Hello".to_string()) { + //~^ ERROR temporary value dropped while borrowed + Some(ref m) => { + msg = m; + }, + None => { panic!() } + } + println!("{}", *msg); +} diff --git a/tests/ui/span/borrowck-ref-into-rvalue.stderr b/tests/ui/span/borrowck-ref-into-rvalue.stderr new file mode 100644 index 000000000..25e344fed --- /dev/null +++ b/tests/ui/span/borrowck-ref-into-rvalue.stderr @@ -0,0 +1,20 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/borrowck-ref-into-rvalue.rs:4:11 + | +LL | match Some("Hello".to_string()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use +... +LL | } + | - temporary value is freed at the end of this statement +LL | println!("{}", *msg); + | ---- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = Some("Hello".to_string()); +LL ~ match binding { + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/span/coerce-suggestions.rs b/tests/ui/span/coerce-suggestions.rs new file mode 100644 index 000000000..7920ae0b2 --- /dev/null +++ b/tests/ui/span/coerce-suggestions.rs @@ -0,0 +1,23 @@ +fn test(_x: &mut String) {} + +fn test2(_x: &mut i32) {} + + +fn main() { + let x: usize = String::new(); + //~^ ERROR E0308 + let x: &str = String::new(); + //~^ ERROR E0308 + let y = String::new(); + test(&y); + //~^ ERROR E0308 + test2(&y); + //~^ ERROR E0308 + let f; + f = Box::new(f); + //~^ ERROR E0308 + + let s = &mut String::new(); + s = format!("foo"); + //~^ ERROR E0308 +} diff --git a/tests/ui/span/coerce-suggestions.stderr b/tests/ui/span/coerce-suggestions.stderr new file mode 100644 index 000000000..db784d5fe --- /dev/null +++ b/tests/ui/span/coerce-suggestions.stderr @@ -0,0 +1,72 @@ +error[E0308]: mismatched types + --> $DIR/coerce-suggestions.rs:7:20 + | +LL | let x: usize = String::new(); + | ----- ^^^^^^^^^^^^^ expected `usize`, found struct `String` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/coerce-suggestions.rs:9:19 + | +LL | let x: &str = String::new(); + | ---- ^^^^^^^^^^^^^ + | | | + | | expected `&str`, found struct `String` + | | help: consider borrowing here: `&String::new()` + | expected due to this + +error[E0308]: mismatched types + --> $DIR/coerce-suggestions.rs:12:10 + | +LL | test(&y); + | ---- ^^ types differ in mutability + | | + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut String` + found reference `&String` +note: function defined here + --> $DIR/coerce-suggestions.rs:1:4 + | +LL | fn test(_x: &mut String) {} + | ^^^^ --------------- + +error[E0308]: mismatched types + --> $DIR/coerce-suggestions.rs:14:11 + | +LL | test2(&y); + | ----- ^^ types differ in mutability + | | + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut i32` + found reference `&String` +note: function defined here + --> $DIR/coerce-suggestions.rs:3:4 + | +LL | fn test2(_x: &mut i32) {} + | ^^^^^ ------------ + +error[E0308]: mismatched types + --> $DIR/coerce-suggestions.rs:17:9 + | +LL | f = Box::new(f); + | ^^^^^^^^^^^ cyclic type of infinite size + | +help: consider unboxing the value + | +LL | f = *Box::new(f); + | + + +error[E0308]: mismatched types + --> $DIR/coerce-suggestions.rs:21:9 + | +LL | s = format!("foo"); + | ^^^^^^^^^^^^^^ expected `&mut String`, found struct `String` + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/span/destructor-restrictions.rs b/tests/ui/span/destructor-restrictions.rs new file mode 100644 index 000000000..7fb348a14 --- /dev/null +++ b/tests/ui/span/destructor-restrictions.rs @@ -0,0 +1,11 @@ +// Tests the new destructor semantics. + +use std::cell::RefCell; + +fn main() { + let b = { + let a = Box::new(RefCell::new(4)); + *a.borrow() + 1 + }; //~^ ERROR `*a` does not live long enough + println!("{}", b); +} diff --git a/tests/ui/span/destructor-restrictions.stderr b/tests/ui/span/destructor-restrictions.stderr new file mode 100644 index 000000000..53c940462 --- /dev/null +++ b/tests/ui/span/destructor-restrictions.stderr @@ -0,0 +1,23 @@ +error[E0597]: `*a` does not live long enough + --> $DIR/destructor-restrictions.rs:8:10 + | +LL | *a.borrow() + 1 + | ^^^^^^^^^^ + | | + | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... +LL | }; + | -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Ref<'_, i32>` + | | + | `*a` dropped here while still borrowed + | + = note: the temporary is part of an expression at the end of a block; + consider forcing this temporary to be dropped sooner, before the block's local variables are dropped +help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block + | +LL | let x = *a.borrow() + 1; x + | +++++++ +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs new file mode 100644 index 000000000..4559da91e --- /dev/null +++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs @@ -0,0 +1,18 @@ +// compile-flags: -Wrust-2021-incompatible-closure-captures + +pub struct A {} + +impl A { + async fn create(path: impl AsRef<std::path::Path>) { //~ ERROR `async fn` is not permitted in Rust 2015 + //~^ WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] + ; + crate(move || {} ).await //~ ERROR expected function, found module `crate` + } +} + +trait C{async fn new(val: T) {} //~ ERROR `async fn` is not permitted in Rust 2015 +//~^ ERROR functions in traits cannot be declared `async` +//~| ERROR cannot find type `T` in this scope +//~| WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] + +//~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr new file mode 100644 index 000000000..df1cafdb7 --- /dev/null +++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr @@ -0,0 +1,95 @@ +error: this file contains an unclosed delimiter + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:18:53 + | +LL | trait C{async fn new(val: T) {} + | - unclosed delimiter +... +LL | + | ^ + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:5 + | +LL | async fn create(path: impl AsRef<std::path::Path>) { + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9 + | +LL | trait C{async fn new(val: T) {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0412]: cannot find type `T` in this scope + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:27 + | +LL | pub struct A {} + | ------------ similarly named struct `A` defined here +... +LL | trait C{async fn new(val: T) {} + | ^ help: a struct with a similar name exists: `A` + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9 + | +LL | trait C{async fn new(val: T) {} + | -----^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0423]: expected function, found module `crate` + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:9:5 + | +LL | crate(move || {} ).await + | ^^^^^ not a function + +warning: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:57 + | +LL | async fn create(path: impl AsRef<std::path::Path>) { + | _____________________----_____________________________-__^ + | | | | + | | | in Rust 2018, `path` is dropped here along with the closure, but in Rust 2021 `path` is not part of the closure + | | in Rust 2018, this causes the closure to capture `path`, but in Rust 2021, it has no effect +LL | | +LL | | ; +LL | | crate(move || {} ).await +LL | | } + | |_____^ + | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> + = note: requested on the command line with `-W rust-2021-incompatible-closure-captures` +help: add a dummy let to cause `path` to be fully captured + | +LL | async fn create(path: impl AsRef<std::path::Path>) { let _ = &path; + | ++++++++++++++ + +warning: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30 + | +LL | trait C{async fn new(val: T) {} + | --- - ^^ + | | | + | | in Rust 2018, `val` is dropped here along with the closure, but in Rust 2021 `val` is not part of the closure + | in Rust 2018, this causes the closure to capture `val`, but in Rust 2021, it has no effect + | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> +help: add a dummy let to cause `val` to be fully captured + | +LL | trait C{async fn new(val: T) { let _ = &val;} + | +++++++++++++ + +error: aborting due to 6 previous errors; 2 warnings emitted + +Some errors have detailed explanations: E0412, E0423, E0670, E0706. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs new file mode 100644 index 000000000..a776e5089 --- /dev/null +++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs @@ -0,0 +1,15 @@ +// compile-flags -Wrust-2021-incompatible-closure-captures + +fn main() {} + +pub(crate) struct Numberer {} + +impl Numberer { + pub(crate) async fn new( + //~^ ERROR `async fn` is not permitted in Rust 2015 + interval: Duration, + //~^ ERROR cannot find type `Duration` in this scope + ) -> Numberer { + Numberer {} + } +} diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr new file mode 100644 index 000000000..37b2f4138 --- /dev/null +++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr @@ -0,0 +1,24 @@ +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:8:16 + | +LL | pub(crate) async fn new( + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0412]: cannot find type `Duration` in this scope + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:10:19 + | +LL | interval: Duration, + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL | use std::time::Duration; + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0412, E0670. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/span/dropck-object-cycle.rs b/tests/ui/span/dropck-object-cycle.rs new file mode 100644 index 000000000..a26123d52 --- /dev/null +++ b/tests/ui/span/dropck-object-cycle.rs @@ -0,0 +1,47 @@ +// This test used to be part of a run-pass test, but revised outlives +// rule means that it no longer compiles. + +#![allow(unused_variables)] + +trait Trait<'a> { + fn long(&'a self) -> isize; + fn short<'b>(&'b self) -> isize; +} + +fn object_invoke1<'d>(x: &'d dyn Trait<'d>) -> (isize, isize) { loop { } } + +trait MakerTrait { + fn mk() -> Self; +} + +fn make_val<T:MakerTrait>() -> T { + MakerTrait::mk() +} + +impl<'t> MakerTrait for Box<dyn Trait<'t>+'static> { + fn mk() -> Box<dyn Trait<'t>+'static> { loop { } } +} + +pub fn main() { + let m : Box<dyn Trait+'static> = make_val(); + assert_eq!(object_invoke1(&*m), (4,5)); + //~^ ERROR `*m` does not live long enough + + // the problem here is that the full type of `m` is + // + // Box<Trait<'m>+'static> + // + // Here `'m` must be exactly the lifetime of the variable `m`. + // This is because of two requirements: + // 1. First, the basic type rules require that the + // type of `m`'s value outlives the lifetime of `m`. This puts a lower + // bound `'m`. + // + // 2. Meanwhile, the signature of `object_invoke1` requires that + // we create a reference of type `&'d Trait<'d>` for some `'d`. + // `'d` cannot outlive `'m`, so that forces the lifetime to be `'m`. + // + // This then conflicts with the dropck rules, which require that + // the type of `m` *strictly outlives* `'m`. Hence we get an + // error. +} diff --git a/tests/ui/span/dropck-object-cycle.stderr b/tests/ui/span/dropck-object-cycle.stderr new file mode 100644 index 000000000..229d17e1c --- /dev/null +++ b/tests/ui/span/dropck-object-cycle.stderr @@ -0,0 +1,15 @@ +error[E0597]: `*m` does not live long enough + --> $DIR/dropck-object-cycle.rs:27:31 + | +LL | assert_eq!(object_invoke1(&*m), (4,5)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `*m` dropped here while still borrowed + | borrow might be used here, when `m` is dropped and runs the destructor for type `Box<dyn Trait<'_>>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/dropck_arr_cycle_checked.rs b/tests/ui/span/dropck_arr_cycle_checked.rs new file mode 100644 index 000000000..a14db5ff0 --- /dev/null +++ b/tests/ui/span/dropck_arr_cycle_checked.rs @@ -0,0 +1,106 @@ +// Reject mixing cyclic structure and Drop when using fixed length +// arrays. +// +// (Compare against ui/span/dropck_vec_cycle_checked.rs) + + + +use std::cell::Cell; +use id::Id; + +mod s { + use std::sync::atomic::{AtomicUsize, Ordering}; + + static S_COUNT: AtomicUsize = AtomicUsize::new(0); + + pub fn next_count() -> usize { + S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 + } +} + +mod id { + use s; + #[derive(Debug)] + pub struct Id { + orig_count: usize, + count: usize, + } + + impl Id { + pub fn new() -> Id { + let c = s::next_count(); + println!("building Id {}", c); + Id { orig_count: c, count: c } + } + pub fn count(&self) -> usize { + println!("Id::count on {} returns {}", self.orig_count, self.count); + self.count + } + } + + impl Drop for Id { + fn drop(&mut self) { + println!("dropping Id {}", self.count); + self.count = 0; + } + } +} + +trait HasId { + fn count(&self) -> usize; +} + +#[derive(Debug)] +struct CheckId<T:HasId> { + v: T +} + +#[allow(non_snake_case)] +fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } } + +impl<T:HasId> Drop for CheckId<T> { + fn drop(&mut self) { + assert!(self.v.count() > 0); + } +} + +#[derive(Debug)] +struct B<'a> { + id: Id, + a: [CheckId<Cell<Option<&'a B<'a>>>>; 2] +} + +impl<'a> HasId for Cell<Option<&'a B<'a>>> { + fn count(&self) -> usize { + match self.get() { + None => 1, + Some(b) => b.id.count(), + } + } +} + +impl<'a> B<'a> { + fn new() -> B<'a> { + B { id: Id::new(), a: [CheckId(Cell::new(None)), CheckId(Cell::new(None))] } + } +} + +fn f() { + let (b1, b2, b3); + b1 = B::new(); + b2 = B::new(); + b3 = B::new(); + b1.a[0].v.set(Some(&b2)); + //~^ ERROR `b2` does not live long enough + b1.a[1].v.set(Some(&b3)); + //~^ ERROR `b3` does not live long enough + b2.a[0].v.set(Some(&b2)); + b2.a[1].v.set(Some(&b3)); + b3.a[0].v.set(Some(&b1)); + //~^ ERROR `b1` does not live long enough + b3.a[1].v.set(Some(&b2)); +} + +fn main() { + f(); +} diff --git a/tests/ui/span/dropck_arr_cycle_checked.stderr b/tests/ui/span/dropck_arr_cycle_checked.stderr new file mode 100644 index 000000000..068c779ae --- /dev/null +++ b/tests/ui/span/dropck_arr_cycle_checked.stderr @@ -0,0 +1,43 @@ +error[E0597]: `b2` does not live long enough + --> $DIR/dropck_arr_cycle_checked.rs:93:24 + | +LL | b1.a[0].v.set(Some(&b2)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `b2` dropped here while still borrowed + | borrow might be used here, when `b1` is dropped and runs the destructor for type `B<'_>` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `b3` does not live long enough + --> $DIR/dropck_arr_cycle_checked.rs:95:24 + | +LL | b1.a[1].v.set(Some(&b3)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `b3` dropped here while still borrowed + | borrow might be used here, when `b1` is dropped and runs the destructor for type `B<'_>` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `b1` does not live long enough + --> $DIR/dropck_arr_cycle_checked.rs:99:24 + | +LL | b3.a[0].v.set(Some(&b1)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `b1` dropped here while still borrowed + | borrow might be used here, when `b1` is dropped and runs the destructor for type `B<'_>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/dropck_direct_cycle_with_drop.rs b/tests/ui/span/dropck_direct_cycle_with_drop.rs new file mode 100644 index 000000000..14d6e6654 --- /dev/null +++ b/tests/ui/span/dropck_direct_cycle_with_drop.rs @@ -0,0 +1,44 @@ +// A simple example of an unsound mixing of cyclic structure and Drop. +// +// Each `D` has a name and an optional reference to another `D` +// sibling, but also implements a drop method that prints out its own +// name as well as the name of its sibling. +// +// By setting up a cyclic structure, the drop code cannot possibly +// work. Therefore this code must be rejected. +// +// (As it turns out, essentially any attempt to install a sibling here +// will be rejected, regardless of whether it forms a cyclic +// structure or not. This is because the use of the same lifetime +// `'a` in `&'a D<'a>` cannot be satisfied when `D<'a>` implements +// `Drop`.) + +use std::cell::Cell; + +struct D<'a> { + name: String, + p: Cell<Option<&'a D<'a>>>, +} + +impl<'a> D<'a> { + fn new(name: String) -> D<'a> { D { name: name, p: Cell::new(None) } } +} + +impl<'a> Drop for D<'a> { + fn drop(&mut self) { + println!("dropping {} whose sibling is {:?}", + self.name, self.p.get().map(|d| &d.name)); + } +} + +fn g() { + let (d1, d2) = (D::new(format!("d1")), D::new(format!("d2"))); + d1.p.set(Some(&d2)); + //~^ ERROR `d2` does not live long enough + d2.p.set(Some(&d1)); + //~^ ERROR `d1` does not live long enough +} + +fn main() { + g(); +} diff --git a/tests/ui/span/dropck_direct_cycle_with_drop.stderr b/tests/ui/span/dropck_direct_cycle_with_drop.stderr new file mode 100644 index 000000000..07ae138ac --- /dev/null +++ b/tests/ui/span/dropck_direct_cycle_with_drop.stderr @@ -0,0 +1,29 @@ +error[E0597]: `d2` does not live long enough + --> $DIR/dropck_direct_cycle_with_drop.rs:36:19 + | +LL | d1.p.set(Some(&d2)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `d2` dropped here while still borrowed + | borrow might be used here, when `d1` is dropped and runs the `Drop` code for type `D` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `d1` does not live long enough + --> $DIR/dropck_direct_cycle_with_drop.rs:38:19 + | +LL | d2.p.set(Some(&d1)); + | ^^^ borrowed value does not live long enough +LL | +LL | } + | - + | | + | `d1` dropped here while still borrowed + | borrow might be used here, when `d1` is dropped and runs the `Drop` code for type `D` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/dropck_misc_variants.rs b/tests/ui/span/dropck_misc_variants.rs new file mode 100644 index 000000000..5818a94bc --- /dev/null +++ b/tests/ui/span/dropck_misc_variants.rs @@ -0,0 +1,37 @@ +// check that dropck does the right thing with misc. Ty variants + +use std::fmt; +struct NoisyDrop<T: fmt::Debug>(T); +impl<T: fmt::Debug> Drop for NoisyDrop<T> { + fn drop(&mut self) { + let _ = vec!["0wned"]; + println!("dropping {:?}", self.0) + } +} + +trait Associator { + type As; +} +impl<T: fmt::Debug> Associator for T { + type As = NoisyDrop<T>; +} +struct Wrap<A: Associator>(<A as Associator>::As); + +fn projection() { + let (_w, bomb); + bomb = vec![""]; + _w = Wrap::<&[&str]>(NoisyDrop(&bomb)); +} +//~^^ ERROR `bomb` does not live long enough + +fn closure() { + let (_w,v); + v = vec![""]; + _w = { + let u = NoisyDrop(&v); + //~^ ERROR `v` does not live long enough + move || u.0.len() + }; +} + +fn main() { closure(); projection() } diff --git a/tests/ui/span/dropck_misc_variants.stderr b/tests/ui/span/dropck_misc_variants.stderr new file mode 100644 index 000000000..76e90574c --- /dev/null +++ b/tests/ui/span/dropck_misc_variants.stderr @@ -0,0 +1,30 @@ +error[E0597]: `bomb` does not live long enough + --> $DIR/dropck_misc_variants.rs:23:36 + | +LL | _w = Wrap::<&[&str]>(NoisyDrop(&bomb)); + | ^^^^^ borrowed value does not live long enough +LL | } + | - + | | + | `bomb` dropped here while still borrowed + | borrow might be used here, when `_w` is dropped and runs the destructor for type `Wrap<&[&str]>` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `v` does not live long enough + --> $DIR/dropck_misc_variants.rs:31:27 + | +LL | let u = NoisyDrop(&v); + | ^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `v` dropped here while still borrowed + | borrow might be used here, when `_w` is dropped and runs the destructor for closure + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/dropck_vec_cycle_checked.rs b/tests/ui/span/dropck_vec_cycle_checked.rs new file mode 100644 index 000000000..c5d21507d --- /dev/null +++ b/tests/ui/span/dropck_vec_cycle_checked.rs @@ -0,0 +1,111 @@ +// Reject mixing cyclic structure and Drop when using Vec. +// +// (Compare against ui/span/dropck_arr_cycle_checked.rs) + +use std::cell::Cell; +use id::Id; + +mod s { + use std::sync::atomic::{AtomicUsize, Ordering}; + + static S_COUNT: AtomicUsize = AtomicUsize::new(0); + + pub fn next_count() -> usize { + S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 + } +} + +mod id { + use s; + #[derive(Debug)] + pub struct Id { + orig_count: usize, + count: usize, + } + + impl Id { + pub fn new() -> Id { + let c = s::next_count(); + println!("building Id {}", c); + Id { orig_count: c, count: c } + } + pub fn count(&self) -> usize { + println!("Id::count on {} returns {}", self.orig_count, self.count); + self.count + } + } + + impl Drop for Id { + fn drop(&mut self) { + println!("dropping Id {}", self.count); + self.count = 0; + } + } +} + +trait HasId { + fn count(&self) -> usize; +} + +#[derive(Debug)] +struct CheckId<T:HasId> { + v: T +} + +#[allow(non_snake_case)] +fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } } + +impl<T:HasId> Drop for CheckId<T> { + fn drop(&mut self) { + assert!(self.v.count() > 0); + } +} + +#[derive(Debug)] +struct C<'a> { + id: Id, + v: Vec<CheckId<Cell<Option<&'a C<'a>>>>>, +} + +impl<'a> HasId for Cell<Option<&'a C<'a>>> { + fn count(&self) -> usize { + match self.get() { + None => 1, + Some(c) => c.id.count(), + } + } +} + +impl<'a> C<'a> { + fn new() -> C<'a> { + C { id: Id::new(), v: Vec::new() } + } +} + +fn f() { + let (mut c1, mut c2, mut c3); + c1 = C::new(); + c2 = C::new(); + c3 = C::new(); + + c1.v.push(CheckId(Cell::new(None))); + c1.v.push(CheckId(Cell::new(None))); + c2.v.push(CheckId(Cell::new(None))); + c2.v.push(CheckId(Cell::new(None))); + c3.v.push(CheckId(Cell::new(None))); + c3.v.push(CheckId(Cell::new(None))); + + c1.v[0].v.set(Some(&c2)); + //~^ ERROR `c2` does not live long enough + c1.v[1].v.set(Some(&c3)); + //~^ ERROR `c3` does not live long enough + c2.v[0].v.set(Some(&c2)); + c2.v[1].v.set(Some(&c3)); + c3.v[0].v.set(Some(&c1)); + //~^ ERROR `c1` does not live long enough + c3.v[1].v.set(Some(&c2)); +} + +fn main() { + f(); +} diff --git a/tests/ui/span/dropck_vec_cycle_checked.stderr b/tests/ui/span/dropck_vec_cycle_checked.stderr new file mode 100644 index 000000000..7ff991c0c --- /dev/null +++ b/tests/ui/span/dropck_vec_cycle_checked.stderr @@ -0,0 +1,43 @@ +error[E0597]: `c2` does not live long enough + --> $DIR/dropck_vec_cycle_checked.rs:98:24 + | +LL | c1.v[0].v.set(Some(&c2)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `c2` dropped here while still borrowed + | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `c3` does not live long enough + --> $DIR/dropck_vec_cycle_checked.rs:100:24 + | +LL | c1.v[1].v.set(Some(&c3)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `c3` dropped here while still borrowed + | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `c1` does not live long enough + --> $DIR/dropck_vec_cycle_checked.rs:104:24 + | +LL | c3.v[0].v.set(Some(&c1)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `c1` dropped here while still borrowed + | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/gated-features-attr-spans.rs b/tests/ui/span/gated-features-attr-spans.rs new file mode 100644 index 000000000..69511ab8e --- /dev/null +++ b/tests/ui/span/gated-features-attr-spans.rs @@ -0,0 +1,7 @@ +#[repr(simd)] //~ ERROR are experimental +struct Coord { + x: u32, + y: u32, +} + +fn main() {} diff --git a/tests/ui/span/gated-features-attr-spans.stderr b/tests/ui/span/gated-features-attr-spans.stderr new file mode 100644 index 000000000..c8b8f346b --- /dev/null +++ b/tests/ui/span/gated-features-attr-spans.stderr @@ -0,0 +1,12 @@ +error[E0658]: SIMD types are experimental and possibly buggy + --> $DIR/gated-features-attr-spans.rs:1:1 + | +LL | #[repr(simd)] + | ^^^^^^^^^^^^^ + | + = note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information + = help: add `#![feature(repr_simd)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/span/impl-wrong-item-for-trait.rs b/tests/ui/span/impl-wrong-item-for-trait.rs new file mode 100644 index 000000000..bf3358686 --- /dev/null +++ b/tests/ui/span/impl-wrong-item-for-trait.rs @@ -0,0 +1,38 @@ +use std::fmt::Debug; + +trait Foo { + fn bar(&self); + const MY_CONST: u32; +} + +pub struct FooConstForMethod; + +impl Foo for FooConstForMethod { + //~^ ERROR E0046 + const bar: u64 = 1; + //~^ ERROR E0323 + const MY_CONST: u32 = 1; +} + +pub struct FooMethodForConst; + +impl Foo for FooMethodForConst { + //~^ ERROR E0046 + fn bar(&self) {} + fn MY_CONST() {} + //~^ ERROR E0324 +} + +pub struct FooTypeForMethod; + +impl Foo for FooTypeForMethod { + //~^ ERROR E0046 + type bar = u64; + //~^ ERROR E0325 + const MY_CONST: u32 = 1; +} + +impl Debug for FooTypeForMethod {} +//~^ ERROR E0046 + +fn main() {} diff --git a/tests/ui/span/impl-wrong-item-for-trait.stderr b/tests/ui/span/impl-wrong-item-for-trait.stderr new file mode 100644 index 000000000..f919092f9 --- /dev/null +++ b/tests/ui/span/impl-wrong-item-for-trait.stderr @@ -0,0 +1,66 @@ +error[E0323]: item `bar` is an associated const, which doesn't match its trait `Foo` + --> $DIR/impl-wrong-item-for-trait.rs:12:5 + | +LL | fn bar(&self); + | -------------- item in trait +... +LL | const bar: u64 = 1; + | ^^^^^^^^^^^^^^^^^^^ does not match trait + +error[E0324]: item `MY_CONST` is an associated method, which doesn't match its trait `Foo` + --> $DIR/impl-wrong-item-for-trait.rs:22:5 + | +LL | const MY_CONST: u32; + | -------------------- item in trait +... +LL | fn MY_CONST() {} + | ^^^^^^^^^^^^^^^^ does not match trait + +error[E0325]: item `bar` is an associated type, which doesn't match its trait `Foo` + --> $DIR/impl-wrong-item-for-trait.rs:30:5 + | +LL | fn bar(&self); + | -------------- item in trait +... +LL | type bar = u64; + | ^^^^^^^^^^^^^^^ does not match trait + +error[E0046]: not all trait items implemented, missing: `bar` + --> $DIR/impl-wrong-item-for-trait.rs:10:1 + | +LL | fn bar(&self); + | -------------- `bar` from trait +... +LL | impl Foo for FooConstForMethod { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `bar` in implementation + +error[E0046]: not all trait items implemented, missing: `MY_CONST` + --> $DIR/impl-wrong-item-for-trait.rs:19:1 + | +LL | const MY_CONST: u32; + | ------------------- `MY_CONST` from trait +... +LL | impl Foo for FooMethodForConst { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `MY_CONST` in implementation + +error[E0046]: not all trait items implemented, missing: `bar` + --> $DIR/impl-wrong-item-for-trait.rs:28:1 + | +LL | fn bar(&self); + | -------------- `bar` from trait +... +LL | impl Foo for FooTypeForMethod { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `bar` in implementation + +error[E0046]: not all trait items implemented, missing: `fmt` + --> $DIR/impl-wrong-item-for-trait.rs:35:1 + | +LL | impl Debug for FooTypeForMethod {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `fmt` in implementation + | + = help: implement the missing item: `fn fmt(&self, _: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { todo!() }` + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0046, E0323, E0324, E0325. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/span/import-ty-params.rs b/tests/ui/span/import-ty-params.rs new file mode 100644 index 000000000..313cd227b --- /dev/null +++ b/tests/ui/span/import-ty-params.rs @@ -0,0 +1,23 @@ +mod a { + pub mod b { + pub mod c { + pub struct S<T>(T); + } + } +} + +macro_rules! import { + ($p: path) => (use $p;); +} + +fn f1() { + import! { a::b::c::S<u8> } //~ ERROR unexpected generic arguments in path +} +fn f2() { + import! { a::b::c::S<> } //~ ERROR unexpected generic arguments in path +} +fn f3() { + import! { a::b<>::c<u8>::S<> } //~ ERROR unexpected generic arguments in path +} + +fn main() {} diff --git a/tests/ui/span/import-ty-params.stderr b/tests/ui/span/import-ty-params.stderr new file mode 100644 index 000000000..701cd0c04 --- /dev/null +++ b/tests/ui/span/import-ty-params.stderr @@ -0,0 +1,20 @@ +error: unexpected generic arguments in path + --> $DIR/import-ty-params.rs:14:25 + | +LL | import! { a::b::c::S<u8> } + | ^^^^ + +error: unexpected generic arguments in path + --> $DIR/import-ty-params.rs:17:25 + | +LL | import! { a::b::c::S<> } + | ^^ + +error: unexpected generic arguments in path + --> $DIR/import-ty-params.rs:20:19 + | +LL | import! { a::b<>::c<u8>::S<> } + | ^^ ^^^^ ^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/span/issue-11925.rs b/tests/ui/span/issue-11925.rs new file mode 100644 index 000000000..cac9fd5bf --- /dev/null +++ b/tests/ui/span/issue-11925.rs @@ -0,0 +1,13 @@ +#![feature(unboxed_closures, tuple_trait)] + +fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f } + +fn main() { + let r = { + let x: Box<_> = Box::new(42); + let f = to_fn_once(move|| &x); //~ ERROR cannot return reference to local data `x` + f() + }; + + drop(r); +} diff --git a/tests/ui/span/issue-11925.stderr b/tests/ui/span/issue-11925.stderr new file mode 100644 index 000000000..1d317fc33 --- /dev/null +++ b/tests/ui/span/issue-11925.stderr @@ -0,0 +1,9 @@ +error[E0515]: cannot return reference to local data `x` + --> $DIR/issue-11925.rs:8:35 + | +LL | let f = to_fn_once(move|| &x); + | ^^ returns a reference to data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/span/issue-15480.fixed b/tests/ui/span/issue-15480.fixed new file mode 100644 index 000000000..e6d1a4dd3 --- /dev/null +++ b/tests/ui/span/issue-15480.fixed @@ -0,0 +1,14 @@ +// run-rustfix +fn id<T>(x: T) -> T { x } + +fn main() { + let binding = id(3); + let v = vec![ + &binding + ]; + //~^^ ERROR temporary value dropped while borrowed + + for &&x in &v { + println!("{}", x + 3); + } +} diff --git a/tests/ui/span/issue-15480.rs b/tests/ui/span/issue-15480.rs new file mode 100644 index 000000000..916ce4b1e --- /dev/null +++ b/tests/ui/span/issue-15480.rs @@ -0,0 +1,13 @@ +// run-rustfix +fn id<T>(x: T) -> T { x } + +fn main() { + let v = vec![ + &id(3) + ]; + //~^^ ERROR temporary value dropped while borrowed + + for &&x in &v { + println!("{}", x + 3); + } +} diff --git a/tests/ui/span/issue-15480.stderr b/tests/ui/span/issue-15480.stderr new file mode 100644 index 000000000..d9cce2254 --- /dev/null +++ b/tests/ui/span/issue-15480.stderr @@ -0,0 +1,21 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-15480.rs:6:10 + | +LL | &id(3) + | ^^^^^ creates a temporary value which is freed while still in use +LL | ]; + | - temporary value is freed at the end of this statement +... +LL | for &&x in &v { + | -- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = id(3); +LL ~ let v = vec![ +LL ~ &binding + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/span/issue-23338-locals-die-before-temps-of-body.rs b/tests/ui/span/issue-23338-locals-die-before-temps-of-body.rs new file mode 100644 index 000000000..a92ea4ddc --- /dev/null +++ b/tests/ui/span/issue-23338-locals-die-before-temps-of-body.rs @@ -0,0 +1,28 @@ +// This is just checking that we still reject code where temp values +// are borrowing values for longer than they will be around. +// +// Compare to run-pass/issue-23338-params-outlive-temps-of-body.rs + +use std::cell::RefCell; + +fn foo(x: RefCell<String>) -> String { + let y = x; + y.borrow().clone() +} +//~^^ ERROR `y` does not live long enough + +fn foo2(x: RefCell<String>) -> String { + let ret = { + let y = x; + y.borrow().clone() + }; + //~^^ ERROR `y` does not live long enough + ret +} + +fn main() { + let r = RefCell::new(format!("data")); + assert_eq!(foo(r), "data"); + let r = RefCell::new(format!("data")); + assert_eq!(foo2(r), "data"); +} diff --git a/tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr b/tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr new file mode 100644 index 000000000..3c2022748 --- /dev/null +++ b/tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr @@ -0,0 +1,44 @@ +error[E0597]: `y` does not live long enough + --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:10:5 + | +LL | y.borrow().clone() + | ^^^^^^^^^^ + | | + | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... +LL | } + | - + | | + | `y` dropped here while still borrowed + | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Ref<'_, String>` + | + = note: the temporary is part of an expression at the end of a block; + consider forcing this temporary to be dropped sooner, before the block's local variables are dropped +help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block + | +LL | let x = y.borrow().clone(); x + | +++++++ +++ + +error[E0597]: `y` does not live long enough + --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:17:9 + | +LL | y.borrow().clone() + | ^^^^^^^^^^ + | | + | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... +LL | }; + | -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Ref<'_, String>` + | | + | `y` dropped here while still borrowed + | + = note: the temporary is part of an expression at the end of a block; + consider forcing this temporary to be dropped sooner, before the block's local variables are dropped +help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block + | +LL | let x = y.borrow().clone(); x + | +++++++ +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-23729.rs b/tests/ui/span/issue-23729.rs new file mode 100644 index 000000000..ca33f9c77 --- /dev/null +++ b/tests/ui/span/issue-23729.rs @@ -0,0 +1,33 @@ +// Regression test for #23729 + +fn main() { + let fib = { + struct Recurrence { + mem: [u64; 2], + pos: usize, + } + + impl Iterator for Recurrence { + //~^ ERROR E0046 + #[inline] + fn next(&mut self) -> Option<u64> { + if self.pos < 2 { + let next_val = self.mem[self.pos]; + self.pos += 1; + Some(next_val) + } else { + let next_val = self.mem[0] + self.mem[1]; + self.mem[0] = self.mem[1]; + self.mem[1] = next_val; + Some(next_val) + } + } + } + + Recurrence { mem: [0, 1], pos: 0 } + }; + + for e in fib.take(10) { + println!("{}", e) + } +} diff --git a/tests/ui/span/issue-23729.stderr b/tests/ui/span/issue-23729.stderr new file mode 100644 index 000000000..f88ce6c88 --- /dev/null +++ b/tests/ui/span/issue-23729.stderr @@ -0,0 +1,11 @@ +error[E0046]: not all trait items implemented, missing: `Item` + --> $DIR/issue-23729.rs:10:9 + | +LL | impl Iterator for Recurrence { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Item` in implementation + | + = help: implement the missing item: `type Item = Type;` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/span/issue-23827.rs b/tests/ui/span/issue-23827.rs new file mode 100644 index 000000000..6b065bf6c --- /dev/null +++ b/tests/ui/span/issue-23827.rs @@ -0,0 +1,33 @@ +// Regression test for #23827 + +#![feature(fn_traits, unboxed_closures)] + +pub struct Prototype { + pub target: u32 +} + +trait Component { + fn apply(self, e: u32); +} + +impl<C: Component> Fn<(C,)> for Prototype { + extern "rust-call" fn call(&self, (comp,): (C,)) -> Prototype { + comp.apply(self.target); + *self + } +} + +impl<C: Component> FnMut<(C,)> for Prototype { + extern "rust-call" fn call_mut(&mut self, (comp,): (C,)) -> Prototype { + Fn::call(*&self, (comp,)) + } +} + +impl<C: Component> FnOnce<(C,)> for Prototype { + //~^ ERROR E0046 + extern "rust-call" fn call_once(self, (comp,): (C,)) -> Prototype { + Fn::call(&self, (comp,)) + } +} + +fn main() {} diff --git a/tests/ui/span/issue-23827.stderr b/tests/ui/span/issue-23827.stderr new file mode 100644 index 000000000..46a820f1b --- /dev/null +++ b/tests/ui/span/issue-23827.stderr @@ -0,0 +1,11 @@ +error[E0046]: not all trait items implemented, missing: `Output` + --> $DIR/issue-23827.rs:26:1 + | +LL | impl<C: Component> FnOnce<(C,)> for Prototype { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Output` in implementation + | + = help: implement the missing item: `type Output = Type;` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/span/issue-24356.rs b/tests/ui/span/issue-24356.rs new file mode 100644 index 000000000..7ec05aab2 --- /dev/null +++ b/tests/ui/span/issue-24356.rs @@ -0,0 +1,27 @@ +// Regression test for #24356 + +fn main() { + { + use std::ops::Deref; + + struct Thing(i8); + + /* + // Correct impl + impl Deref for Thing { + type Target = i8; + fn deref(&self) -> &i8 { &self.0 } + } + */ + + // Causes ICE + impl Deref for Thing { + //~^ ERROR E0046 + fn deref(&self) -> i8 { self.0 } + } + + let thing = Thing(72); + + *thing + }; +} diff --git a/tests/ui/span/issue-24356.stderr b/tests/ui/span/issue-24356.stderr new file mode 100644 index 000000000..a1f9b2550 --- /dev/null +++ b/tests/ui/span/issue-24356.stderr @@ -0,0 +1,11 @@ +error[E0046]: not all trait items implemented, missing: `Target` + --> $DIR/issue-24356.rs:18:9 + | +LL | impl Deref for Thing { + | ^^^^^^^^^^^^^^^^^^^^ missing `Target` in implementation + | + = help: implement the missing item: `type Target = Type;` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/span/issue-24690.rs b/tests/ui/span/issue-24690.rs new file mode 100644 index 000000000..2b7349c55 --- /dev/null +++ b/tests/ui/span/issue-24690.rs @@ -0,0 +1,16 @@ +//! A test to ensure that helpful `note` messages aren't emitted more often +//! than necessary. + +// check-pass + +// Although there are three warnings, we should only get two "lint level defined +// here" notes pointing at the `warnings` span, one for each error type. +#![warn(unused)] + + +fn main() { + let theTwo = 2; //~ WARN should have a snake case name + let theOtherTwo = 2; //~ WARN should have a snake case name + //~^ WARN unused variable + println!("{}", theTwo); +} diff --git a/tests/ui/span/issue-24690.stderr b/tests/ui/span/issue-24690.stderr new file mode 100644 index 000000000..73e166e64 --- /dev/null +++ b/tests/ui/span/issue-24690.stderr @@ -0,0 +1,29 @@ +warning: unused variable: `theOtherTwo` + --> $DIR/issue-24690.rs:13:9 + | +LL | let theOtherTwo = 2; + | ^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_theOtherTwo` + | +note: the lint level is defined here + --> $DIR/issue-24690.rs:8:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: variable `theTwo` should have a snake case name + --> $DIR/issue-24690.rs:12:9 + | +LL | let theTwo = 2; + | ^^^^^^ help: convert the identifier to snake case: `the_two` + | + = note: `#[warn(non_snake_case)]` on by default + +warning: variable `theOtherTwo` should have a snake case name + --> $DIR/issue-24690.rs:13:9 + | +LL | let theOtherTwo = 2; + | ^^^^^^^^^^^ help: convert the identifier to snake case: `the_other_two` + +warning: 3 warnings emitted + diff --git a/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.rs b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.rs new file mode 100644 index 000000000..9c772052f --- /dev/null +++ b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.rs @@ -0,0 +1,37 @@ +// Check that child trait who only has items via its *parent* trait +// does cause dropck to inject extra region constraints. + +#![allow(non_camel_case_types)] + +trait Parent { fn foo(&self); } +trait Child: Parent { } + +impl Parent for i32 { fn foo(&self) { } } +impl<'a> Parent for &'a D_Child<i32> { + fn foo(&self) { + println!("accessing child value: {}", self.0); + } +} + +impl Child for i32 { } +impl<'a> Child for &'a D_Child<i32> { } + +struct D_Child<T:Child>(T); +impl <T:Child> Drop for D_Child<T> { fn drop(&mut self) { self.0.foo() } } + +fn f_child() { + // `_d` and `d1` are assigned the *same* lifetime by region inference ... + let (_d, d1); + + d1 = D_Child(1); + // ... we store a reference to `d1` within `_d` ... + _d = D_Child(&d1); + //~^ ERROR `d1` does not live long enough + + // ... dropck *should* complain, because Drop of _d could (and + // does) access the already dropped `d1` via the `foo` method. +} + +fn main() { + f_child(); +} diff --git a/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr new file mode 100644 index 000000000..809e60a8c --- /dev/null +++ b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr @@ -0,0 +1,17 @@ +error[E0597]: `d1` does not live long enough + --> $DIR/issue-24805-dropck-child-has-items-via-parent.rs:28:18 + | +LL | _d = D_Child(&d1); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `d1` dropped here while still borrowed + | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_Child` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-24805-dropck-trait-has-items.rs b/tests/ui/span/issue-24805-dropck-trait-has-items.rs new file mode 100644 index 000000000..b5c410cd3 --- /dev/null +++ b/tests/ui/span/issue-24805-dropck-trait-has-items.rs @@ -0,0 +1,57 @@ +// Check that traits with various kinds of associated items cause +// dropck to inject extra region constraints. + +#![allow(non_camel_case_types)] + +trait HasSelfMethod { fn m1(&self) { } } +trait HasMethodWithSelfArg { fn m2(x: &Self) { } } +trait HasType { type Something; } + +impl HasSelfMethod for i32 { } +impl HasMethodWithSelfArg for i32 { } +impl HasType for i32 { type Something = (); } + +impl<'a,T> HasSelfMethod for &'a T { } +impl<'a,T> HasMethodWithSelfArg for &'a T { } +impl<'a,T> HasType for &'a T { type Something = (); } + +// e.g., `impl_drop!(Send, D_Send)` expands to: +// ```rust +// struct D_Send<T:Send>(T); +// impl<T:Send> Drop for D_Send<T> { fn drop(&mut self) { } } +// ``` +macro_rules! impl_drop { + ($Bound:ident, $Id:ident) => { + struct $Id<T:$Bound>(T); + impl <T:$Bound> Drop for $Id<T> { fn drop(&mut self) { } } + } +} + +impl_drop!{HasSelfMethod, D_HasSelfMethod} +impl_drop!{HasMethodWithSelfArg, D_HasMethodWithSelfArg} +impl_drop!{HasType, D_HasType} + +fn f_sm() { + let (_d, d1); + d1 = D_HasSelfMethod(1); + _d = D_HasSelfMethod(&d1); +} +//~^^ ERROR `d1` does not live long enough +fn f_mwsa() { + let (_d, d1); + d1 = D_HasMethodWithSelfArg(1); + _d = D_HasMethodWithSelfArg(&d1); +} +//~^^ ERROR `d1` does not live long enough +fn f_t() { + let (_d, d1); + d1 = D_HasType(1); + _d = D_HasType(&d1); +} +//~^^ ERROR `d1` does not live long enough + +fn main() { + f_sm(); + f_mwsa(); + f_t(); +} diff --git a/tests/ui/span/issue-24805-dropck-trait-has-items.stderr b/tests/ui/span/issue-24805-dropck-trait-has-items.stderr new file mode 100644 index 000000000..2e2170669 --- /dev/null +++ b/tests/ui/span/issue-24805-dropck-trait-has-items.stderr @@ -0,0 +1,42 @@ +error[E0597]: `d1` does not live long enough + --> $DIR/issue-24805-dropck-trait-has-items.rs:37:26 + | +LL | _d = D_HasSelfMethod(&d1); + | ^^^ borrowed value does not live long enough +LL | } + | - + | | + | `d1` dropped here while still borrowed + | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_HasSelfMethod` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `d1` does not live long enough + --> $DIR/issue-24805-dropck-trait-has-items.rs:43:33 + | +LL | _d = D_HasMethodWithSelfArg(&d1); + | ^^^ borrowed value does not live long enough +LL | } + | - + | | + | `d1` dropped here while still borrowed + | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_HasMethodWithSelfArg` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `d1` does not live long enough + --> $DIR/issue-24805-dropck-trait-has-items.rs:49:20 + | +LL | _d = D_HasType(&d1); + | ^^^ borrowed value does not live long enough +LL | } + | - + | | + | `d1` dropped here while still borrowed + | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_HasType` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-24895-copy-clone-dropck.rs b/tests/ui/span/issue-24895-copy-clone-dropck.rs new file mode 100644 index 000000000..904cd8f67 --- /dev/null +++ b/tests/ui/span/issue-24895-copy-clone-dropck.rs @@ -0,0 +1,29 @@ +// Check that one cannot subvert Drop Check rule via a user-defined +// Clone implementation. + +#![allow(unused_variables, unused_assignments)] + +struct D<T:Copy>(T, &'static str); + +#[derive(Copy)] +struct S<'a>(&'a D<i32>, &'static str); +impl<'a> Clone for S<'a> { + fn clone(&self) -> S<'a> { + println!("cloning `S(_, {})` and thus accessing: {}", self.1, (self.0).0); + S(self.0, self.1) + } +} + +impl<T:Copy> Drop for D<T> { + fn drop(&mut self) { + println!("calling Drop for {}", self.1); + let _call = self.0.clone(); + } +} + +fn main() { + let (d2, d1); + d1 = D(34, "d1"); + d2 = D(S(&d1, "inner"), "d2"); +} +//~^^ ERROR `d1` does not live long enough diff --git a/tests/ui/span/issue-24895-copy-clone-dropck.stderr b/tests/ui/span/issue-24895-copy-clone-dropck.stderr new file mode 100644 index 000000000..18a3dc9e6 --- /dev/null +++ b/tests/ui/span/issue-24895-copy-clone-dropck.stderr @@ -0,0 +1,16 @@ +error[E0597]: `d1` does not live long enough + --> $DIR/issue-24895-copy-clone-dropck.rs:27:14 + | +LL | d2 = D(S(&d1, "inner"), "d2"); + | ^^^ borrowed value does not live long enough +LL | } + | - + | | + | `d1` dropped here while still borrowed + | borrow might be used here, when `d2` is dropped and runs the `Drop` code for type `D` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-25199.rs b/tests/ui/span/issue-25199.rs new file mode 100644 index 000000000..dbc3b1900 --- /dev/null +++ b/tests/ui/span/issue-25199.rs @@ -0,0 +1,74 @@ +// Regression test for Issue 25199: Check that one cannot hide a +// destructor's access to borrowed data behind a boxed trait object. +// +// Prior to fixing Issue 25199, this example was able to be compiled +// with rustc, and thus when you ran it, you would see the `Drop` impl +// for `Test` accessing state that had already been dropping (which is +// marked explicitly here with checking code within the `Drop` impl +// for `VecHolder`, but in the general case could just do unsound +// things like accessing memory that has been freed). +// +// Note that I would have liked to encode my go-to example of cyclic +// structure that accesses its neighbors in drop (and thus is +// fundamentally unsound) via this trick, but the closest I was able +// to come was dropck_trait_cycle_checked.rs, which is not quite as +// "good" as this regression test because the encoding of that example +// was forced to attach a lifetime to the trait definition itself +// (`trait Obj<'a>`) while *this* example is solely + +use std::cell::RefCell; + +trait Obj { } + +struct VecHolder { + v: Vec<(bool, &'static str)>, +} + +impl Drop for VecHolder { + fn drop(&mut self) { + println!("Dropping Vec"); + self.v[30].0 = false; + self.v[30].1 = "invalid access: VecHolder dropped already"; + } +} + +struct Container<'a> { + v: VecHolder, + d: RefCell<Vec<Box<dyn Obj+'a>>>, +} + +impl<'a> Container<'a> { + fn new() -> Container<'a> { + Container { + d: RefCell::new(Vec::new()), + v: VecHolder { + v: vec![(true, "valid"); 100] + } + } + } + + fn store<T: Obj+'a>(&'a self, val: T) { + self.d.borrow_mut().push(Box::new(val)); + } +} + +struct Test<'a> { + test: &'a Container<'a>, +} + +impl<'a> Obj for Test<'a> { } +impl<'a> Drop for Test<'a> { + fn drop(&mut self) { + for e in &self.test.v.v { + assert!(e.0, e.1); + } + } +} + +fn main() { + let container = Container::new(); + let test = Test{test: &container}; + //~^ ERROR `container` does not live long enough + println!("container.v[30]: {:?}", container.v.v[30]); + container.store(test); +} diff --git a/tests/ui/span/issue-25199.stderr b/tests/ui/span/issue-25199.stderr new file mode 100644 index 000000000..d70a4afc1 --- /dev/null +++ b/tests/ui/span/issue-25199.stderr @@ -0,0 +1,15 @@ +error[E0597]: `container` does not live long enough + --> $DIR/issue-25199.rs:70:27 + | +LL | let test = Test{test: &container}; + | ^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `container` dropped here while still borrowed + | borrow might be used here, when `container` is dropped and runs the destructor for type `Container<'_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-26656.rs b/tests/ui/span/issue-26656.rs new file mode 100644 index 000000000..cde68da18 --- /dev/null +++ b/tests/ui/span/issue-26656.rs @@ -0,0 +1,42 @@ +// Issue #26656: Verify that trait objects cannot bypass dropck. + +// Using this instead of Fn etc. to take HRTB out of the equation. +trait Trigger<B> { fn fire(&self, b: &mut B); } +impl<B: Button> Trigger<B> for () { + fn fire(&self, b: &mut B) { + b.push(); + } +} + +// Still unsound Zook +trait Button { fn push(&self); } +struct Zook<B> { button: B, trigger: Box<dyn Trigger<B>+'static> } + +impl<B> Drop for Zook<B> { + fn drop(&mut self) { + self.trigger.fire(&mut self.button); + } +} + +// AND +struct Bomb { usable: bool } +impl Drop for Bomb { fn drop(&mut self) { self.usable = false; } } +impl Bomb { fn activate(&self) { assert!(self.usable) } } + +enum B<'a> { HarmlessButton, BigRedButton(&'a Bomb) } +impl<'a> Button for B<'a> { + fn push(&self) { + if let B::BigRedButton(borrowed) = *self { + borrowed.activate(); + } + } +} + +fn main() { + let (mut zook, ticking); + zook = Zook { button: B::HarmlessButton, + trigger: Box::new(()) }; + ticking = Bomb { usable: true }; + zook.button = B::BigRedButton(&ticking); +} +//~^^ ERROR `ticking` does not live long enough diff --git a/tests/ui/span/issue-26656.stderr b/tests/ui/span/issue-26656.stderr new file mode 100644 index 000000000..1e939c484 --- /dev/null +++ b/tests/ui/span/issue-26656.stderr @@ -0,0 +1,16 @@ +error[E0597]: `ticking` does not live long enough + --> $DIR/issue-26656.rs:40:35 + | +LL | zook.button = B::BigRedButton(&ticking); + | ^^^^^^^^ borrowed value does not live long enough +LL | } + | - + | | + | `ticking` dropped here while still borrowed + | borrow might be used here, when `zook` is dropped and runs the `Drop` code for type `Zook` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-27522.rs b/tests/ui/span/issue-27522.rs new file mode 100644 index 000000000..7a0cfb679 --- /dev/null +++ b/tests/ui/span/issue-27522.rs @@ -0,0 +1,9 @@ +// Point at correct span for self type + +struct SomeType {} + +trait Foo { + fn handler(self: &SomeType); //~ ERROR invalid `self` parameter type +} + +fn main() {} diff --git a/tests/ui/span/issue-27522.stderr b/tests/ui/span/issue-27522.stderr new file mode 100644 index 000000000..8a254a968 --- /dev/null +++ b/tests/ui/span/issue-27522.stderr @@ -0,0 +1,12 @@ +error[E0307]: invalid `self` parameter type: &SomeType + --> $DIR/issue-27522.rs:6:22 + | +LL | fn handler(self: &SomeType); + | ^^^^^^^^^ + | + = 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 previous error + +For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/span/issue-29106.rs b/tests/ui/span/issue-29106.rs new file mode 100644 index 000000000..1be8d4cba --- /dev/null +++ b/tests/ui/span/issue-29106.rs @@ -0,0 +1,26 @@ +use std::rc::Rc; +use std::sync::Arc; + +struct Foo<'a>(&'a String); + +impl<'a> Drop for Foo<'a> { + fn drop(&mut self) { + println!("{:?}", self.0); + } +} + +fn main() { + { + let (y, x); + x = "alive".to_string(); + y = Arc::new(Foo(&x)); + } + //~^^ ERROR `x` does not live long enough + + { + let (y, x); + x = "alive".to_string(); + y = Rc::new(Foo(&x)); + } + //~^^ ERROR `x` does not live long enough +} diff --git a/tests/ui/span/issue-29106.stderr b/tests/ui/span/issue-29106.stderr new file mode 100644 index 000000000..71fbd60ee --- /dev/null +++ b/tests/ui/span/issue-29106.stderr @@ -0,0 +1,29 @@ +error[E0597]: `x` does not live long enough + --> $DIR/issue-29106.rs:16:26 + | +LL | y = Arc::new(Foo(&x)); + | ^^ borrowed value does not live long enough +LL | } + | - + | | + | `x` dropped here while still borrowed + | borrow might be used here, when `y` is dropped and runs the `Drop` code for type `Arc` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `x` does not live long enough + --> $DIR/issue-29106.rs:23:25 + | +LL | y = Rc::new(Foo(&x)); + | ^^ borrowed value does not live long enough +LL | } + | - + | | + | `x` dropped here while still borrowed + | borrow might be used here, when `y` is dropped and runs the `Drop` code for type `Rc` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-29595.rs b/tests/ui/span/issue-29595.rs new file mode 100644 index 000000000..87d7c4cfd --- /dev/null +++ b/tests/ui/span/issue-29595.rs @@ -0,0 +1,7 @@ +trait Tr { + const C: Self; +} + +fn main() { + let a: u8 = Tr::C; //~ ERROR the trait bound `u8: Tr` is not satisfied +} diff --git a/tests/ui/span/issue-29595.stderr b/tests/ui/span/issue-29595.stderr new file mode 100644 index 000000000..92445e407 --- /dev/null +++ b/tests/ui/span/issue-29595.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `u8: Tr` is not satisfied + --> $DIR/issue-29595.rs:6:17 + | +LL | let a: u8 = Tr::C; + | ^^^^^ the trait `Tr` is not implemented for `u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/span/issue-33884.rs b/tests/ui/span/issue-33884.rs new file mode 100644 index 000000000..5d927a5ac --- /dev/null +++ b/tests/ui/span/issue-33884.rs @@ -0,0 +1,18 @@ +use std::net::TcpListener; +use std::net::TcpStream; +use std::io::{self, Read, Write}; + +fn handle_client(stream: TcpStream) -> io::Result<()> { + stream.write_fmt(format!("message received")) + //~^ ERROR mismatched types +} + +fn main() { + if let Ok(listener) = TcpListener::bind("127.0.0.1:8080") { + for incoming in listener.incoming() { + if let Ok(stream) = incoming { + handle_client(stream); + } + } + } +} diff --git a/tests/ui/span/issue-33884.stderr b/tests/ui/span/issue-33884.stderr new file mode 100644 index 000000000..aee153085 --- /dev/null +++ b/tests/ui/span/issue-33884.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-33884.rs:6:22 + | +LL | stream.write_fmt(format!("message received")) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Arguments`, found struct `String` + | + = note: this error originates in the macro `format` (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/tests/ui/span/issue-34264.rs b/tests/ui/span/issue-34264.rs new file mode 100644 index 000000000..9227ee482 --- /dev/null +++ b/tests/ui/span/issue-34264.rs @@ -0,0 +1,11 @@ +fn foo(Option<i32>, String) {} //~ ERROR expected one of +//~^ ERROR expected one of +fn bar(x, y: usize) {} //~ ERROR expected one of + +fn main() { + foo(Some(42), 2); + foo(Some(42), 2, ""); //~ ERROR function takes + bar("", ""); //~ ERROR mismatched types + bar(1, 2); + bar(1, 2, 3); //~ ERROR function takes +} diff --git a/tests/ui/span/issue-34264.stderr b/tests/ui/span/issue-34264.stderr new file mode 100644 index 000000000..15179954a --- /dev/null +++ b/tests/ui/span/issue-34264.stderr @@ -0,0 +1,102 @@ +error: expected one of `:`, `@`, or `|`, found `<` + --> $DIR/issue-34264.rs:1:14 + | +LL | fn foo(Option<i32>, String) {} + | ^ 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 foo(self: Option<i32>, String) {} + | +++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn foo(_: Option<i32>, String) {} + | ++ + +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/issue-34264.rs:1:27 + | +LL | fn foo(Option<i32>, String) {} + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a parameter name, give it a type + | +LL | fn foo(Option<i32>, String: TypeName) {} + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn foo(Option<i32>, _: String) {} + | ++ + +error: expected one of `:`, `@`, or `|`, found `,` + --> $DIR/issue-34264.rs:3:9 + | +LL | fn bar(x, y: usize) {} + | ^ 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: x, y: usize) {} + | +++++ +help: if this is a parameter name, give it a type + | +LL | fn bar(x: TypeName, y: usize) {} + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn bar(_: x, y: usize) {} + | ++ + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/issue-34264.rs:7:5 + | +LL | foo(Some(42), 2, ""); + | ^^^ -- argument of type `&'static str` unexpected + | +note: function defined here + --> $DIR/issue-34264.rs:1:4 + | +LL | fn foo(Option<i32>, String) {} + | ^^^ ----------- ------ +help: remove the extra argument + | +LL | foo(Some(42), 2); + | ~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/issue-34264.rs:8:13 + | +LL | bar("", ""); + | --- ^^ expected `usize`, found `&str` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-34264.rs:3:4 + | +LL | fn bar(x, y: usize) {} + | ^^^ -------- + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/issue-34264.rs:10:5 + | +LL | bar(1, 2, 3); + | ^^^ - argument of type `{integer}` unexpected + | +note: function defined here + --> $DIR/issue-34264.rs:3:4 + | +LL | fn bar(x, y: usize) {} + | ^^^ - -------- +help: remove the extra argument + | +LL | bar(1, 2); + | ~~~~~~ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0061, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/span/issue-35987.rs b/tests/ui/span/issue-35987.rs new file mode 100644 index 000000000..3a6e6ffe2 --- /dev/null +++ b/tests/ui/span/issue-35987.rs @@ -0,0 +1,14 @@ +struct Foo<T: Clone>(T); + +use std::ops::Add; + +impl<T: Clone, Add> Add for Foo<T> { +//~^ ERROR expected trait, found type parameter + type Output = usize; + + fn add(self, rhs: Self) -> Self::Output { + unimplemented!(); + } +} + +fn main() {} diff --git a/tests/ui/span/issue-35987.stderr b/tests/ui/span/issue-35987.stderr new file mode 100644 index 000000000..057d40ac0 --- /dev/null +++ b/tests/ui/span/issue-35987.stderr @@ -0,0 +1,19 @@ +error[E0404]: expected trait, found type parameter `Add` + --> $DIR/issue-35987.rs:5:21 + | +LL | use std::ops::Add; + | --- you might have meant to refer to this trait +LL | +LL | impl<T: Clone, Add> Add for Foo<T> { + | --- ^^^ not a trait + | | + | found this type parameter + | +help: consider importing this trait instead + | +LL | use std::ops::Add; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/span/issue-36537.rs b/tests/ui/span/issue-36537.rs new file mode 100644 index 000000000..a5546ccbb --- /dev/null +++ b/tests/ui/span/issue-36537.rs @@ -0,0 +1,14 @@ +fn main() { + let p; + { + let a = 42; + p = &a; + //~^ ERROR `a` does not live long enough + + } + p.use_ref(); + +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl<T> Fake for T { } diff --git a/tests/ui/span/issue-36537.stderr b/tests/ui/span/issue-36537.stderr new file mode 100644 index 000000000..79a0ebaeb --- /dev/null +++ b/tests/ui/span/issue-36537.stderr @@ -0,0 +1,14 @@ +error[E0597]: `a` does not live long enough + --> $DIR/issue-36537.rs:5:13 + | +LL | p = &a; + | ^^ borrowed value does not live long enough +... +LL | } + | - `a` dropped here while still borrowed +LL | p.use_ref(); + | ----------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-37767.rs b/tests/ui/span/issue-37767.rs new file mode 100644 index 000000000..9e34c2c1f --- /dev/null +++ b/tests/ui/span/issue-37767.rs @@ -0,0 +1,41 @@ +trait A { + fn foo(&mut self) {} +} + +trait B : A { + fn foo(&mut self) {} +} + +fn bar<T: B>(a: &T) { + a.foo() //~ ERROR multiple applicable items +} + +trait C { + fn foo(&self) {} +} + +trait D : C { + fn foo(&self) {} +} + +fn quz<T: D>(a: &T) { + a.foo() //~ ERROR multiple applicable items +} + +trait E : Sized { + fn foo(self) {} +} + +trait F : E { + fn foo(self) {} +} + +fn foo<T: F>(a: T) { + a.foo() //~ ERROR multiple applicable items +} + +fn pass<T: C>(a: &T) { + a.foo() +} + +fn main() {} diff --git a/tests/ui/span/issue-37767.stderr b/tests/ui/span/issue-37767.stderr new file mode 100644 index 000000000..f7732847a --- /dev/null +++ b/tests/ui/span/issue-37767.stderr @@ -0,0 +1,78 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/issue-37767.rs:10:7 + | +LL | a.foo() + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in the trait `A` + --> $DIR/issue-37767.rs:2:5 + | +LL | fn foo(&mut self) {} + | ^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `B` + --> $DIR/issue-37767.rs:6:5 + | +LL | fn foo(&mut self) {} + | ^^^^^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | A::foo(&a) + | ~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | B::foo(&a) + | ~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/issue-37767.rs:22:7 + | +LL | a.foo() + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in the trait `C` + --> $DIR/issue-37767.rs:14:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `D` + --> $DIR/issue-37767.rs:18:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | C::foo(&a) + | ~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | D::foo(&a) + | ~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/issue-37767.rs:34:7 + | +LL | a.foo() + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in the trait `E` + --> $DIR/issue-37767.rs:26:5 + | +LL | fn foo(self) {} + | ^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `F` + --> $DIR/issue-37767.rs:30:5 + | +LL | fn foo(self) {} + | ^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | E::foo(a) + | ~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | F::foo(a) + | ~~~~~~~~~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/span/issue-39018.rs b/tests/ui/span/issue-39018.rs new file mode 100644 index 000000000..b6db4008d --- /dev/null +++ b/tests/ui/span/issue-39018.rs @@ -0,0 +1,38 @@ +pub fn main() { + let x = "Hello " + "World!"; + //~^ ERROR cannot add + + // Make sure that the span outputs a warning + // for not having an implementation for std::ops::Add + // that won't output for the above string concatenation + let y = World::Hello + World::Goodbye; + //~^ ERROR cannot add + + let x = "Hello " + "World!".to_owned(); + //~^ ERROR cannot add +} + +enum World { + Hello, + Goodbye, +} + +fn foo() { + let a = String::new(); + let b = String::new(); + let c = ""; + let d = ""; + let e = &a; + let _ = &a + &b; //~ ERROR cannot add + let _ = &a + b; //~ ERROR cannot add + let _ = a + &b; // ok + let _ = a + b; //~ ERROR mismatched types + let _ = e + b; //~ ERROR cannot add + let _ = e + &b; //~ ERROR cannot add + let _ = e + d; //~ ERROR cannot add + let _ = e + &d; //~ ERROR cannot add + let _ = &c + &d; //~ ERROR cannot add + let _ = &c + d; //~ ERROR cannot add + let _ = c + &d; //~ ERROR cannot add + let _ = c + d; //~ ERROR cannot add +} diff --git a/tests/ui/span/issue-39018.stderr b/tests/ui/span/issue-39018.stderr new file mode 100644 index 000000000..5d4d692b2 --- /dev/null +++ b/tests/ui/span/issue-39018.stderr @@ -0,0 +1,194 @@ +error[E0369]: cannot add `&str` to `&str` + --> $DIR/issue-39018.rs:2:22 + | +LL | let x = "Hello " + "World!"; + | -------- ^ -------- &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let x = "Hello ".to_owned() + "World!"; + | +++++++++++ + +error[E0369]: cannot add `World` to `World` + --> $DIR/issue-39018.rs:8:26 + | +LL | let y = World::Hello + World::Goodbye; + | ------------ ^ -------------- World + | | + | World + | +note: an implementation of `Add<_>` might be missing for `World` + --> $DIR/issue-39018.rs:15:1 + | +LL | enum World { + | ^^^^^^^^^^ must implement `Add<_>` +note: the trait `Add` must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + +error[E0369]: cannot add `String` to `&str` + --> $DIR/issue-39018.rs:11:22 + | +LL | let x = "Hello " + "World!".to_owned(); + | -------- ^ ------------------- String + | | | + | | `+` cannot be used to concatenate a `&str` with a `String` + | &str + | +help: create an owned `String` on the left and add a borrow on the right + | +LL | let x = "Hello ".to_owned() + &"World!".to_owned(); + | +++++++++++ + + +error[E0369]: cannot add `&String` to `&String` + --> $DIR/issue-39018.rs:26:16 + | +LL | let _ = &a + &b; + | -- ^ -- &String + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &String + | + = note: string concatenation requires an owned `String` on the left +help: remove the borrow to obtain an owned `String` + | +LL - let _ = &a + &b; +LL + let _ = a + &b; + | + +error[E0369]: cannot add `String` to `&String` + --> $DIR/issue-39018.rs:27:16 + | +LL | let _ = &a + b; + | -- ^ - String + | | | + | | `+` cannot be used to concatenate a `&str` with a `String` + | &String + | +help: remove the borrow on the left and add one on the right + | +LL - let _ = &a + b; +LL + let _ = a + &b; + | + +error[E0308]: mismatched types + --> $DIR/issue-39018.rs:29:17 + | +LL | let _ = a + b; + | ^ + | | + | expected `&str`, found struct `String` + | help: consider borrowing here: `&b` + +error[E0369]: cannot add `String` to `&String` + --> $DIR/issue-39018.rs:30:15 + | +LL | let _ = e + b; + | - ^ - String + | | | + | | `+` cannot be used to concatenate a `&str` with a `String` + | &String + | +help: create an owned `String` on the left and add a borrow on the right + | +LL | let _ = e.to_owned() + &b; + | +++++++++++ + + +error[E0369]: cannot add `&String` to `&String` + --> $DIR/issue-39018.rs:31:15 + | +LL | let _ = e + &b; + | - ^ -- &String + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &String + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = e.to_owned() + &b; + | +++++++++++ + +error[E0369]: cannot add `&str` to `&String` + --> $DIR/issue-39018.rs:32:15 + | +LL | let _ = e + d; + | - ^ - &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &String + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = e.to_owned() + d; + | +++++++++++ + +error[E0369]: cannot add `&&str` to `&String` + --> $DIR/issue-39018.rs:33:15 + | +LL | let _ = e + &d; + | - ^ -- &&str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &String + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = e.to_owned() + &d; + | +++++++++++ + +error[E0369]: cannot add `&&str` to `&&str` + --> $DIR/issue-39018.rs:34:16 + | +LL | let _ = &c + &d; + | -- ^ -- &&str + | | + | &&str + +error[E0369]: cannot add `&str` to `&&str` + --> $DIR/issue-39018.rs:35:16 + | +LL | let _ = &c + d; + | -- ^ - &str + | | + | &&str + +error[E0369]: cannot add `&&str` to `&str` + --> $DIR/issue-39018.rs:36:15 + | +LL | let _ = c + &d; + | - ^ -- &&str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = c.to_owned() + &d; + | +++++++++++ + +error[E0369]: cannot add `&str` to `&str` + --> $DIR/issue-39018.rs:37:15 + | +LL | let _ = c + d; + | - ^ - &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = c.to_owned() + d; + | +++++++++++ + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0308, E0369. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/span/issue-39698.rs b/tests/ui/span/issue-39698.rs new file mode 100644 index 000000000..1079bae2c --- /dev/null +++ b/tests/ui/span/issue-39698.rs @@ -0,0 +1,16 @@ +enum T { + T1(i32, i32), + T2(i32, i32), + T3(i32), + T4(i32), +} + +fn main() { + match T::T1(123, 456) { + T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + //~^ ERROR is not bound in all patterns + //~| ERROR is not bound in all patterns + //~| ERROR is not bound in all patterns + //~| ERROR is not bound in all patterns + } +} diff --git a/tests/ui/span/issue-39698.stderr b/tests/ui/span/issue-39698.stderr new file mode 100644 index 000000000..25c35fd54 --- /dev/null +++ b/tests/ui/span/issue-39698.stderr @@ -0,0 +1,43 @@ +error[E0408]: variable `d` is not bound in all patterns + --> $DIR/issue-39698.rs:10:37 + | +LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + | - - ^^^^^^^^ ^^^^^^^^ pattern doesn't bind `d` + | | | | + | | | pattern doesn't bind `d` + | | variable not in all patterns + | variable not in all patterns + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/issue-39698.rs:10:23 + | +LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + | - ^^^^^^^^^^^ ^^^^^^^^ - variable not in all patterns + | | | | + | | | pattern doesn't bind `a` + | | pattern doesn't bind `a` + | variable not in all patterns + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/issue-39698.rs:10:9 + | +LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + | ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern doesn't bind `b` + | | | | + | | | pattern doesn't bind `b` + | | variable not in all patterns + | pattern doesn't bind `b` + +error[E0408]: variable `c` is not bound in all patterns + --> $DIR/issue-39698.rs:10:9 + | +LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + | ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern doesn't bind `c` + | | | | + | | | variable not in all patterns + | | pattern doesn't bind `c` + | pattern doesn't bind `c` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/span/issue-40157.rs b/tests/ui/span/issue-40157.rs new file mode 100644 index 000000000..03ad21ae7 --- /dev/null +++ b/tests/ui/span/issue-40157.rs @@ -0,0 +1,4 @@ +fn main () { + {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x });} + //~^ ERROR does not live long enough +} diff --git a/tests/ui/span/issue-40157.stderr b/tests/ui/span/issue-40157.stderr new file mode 100644 index 000000000..57f80214a --- /dev/null +++ b/tests/ui/span/issue-40157.stderr @@ -0,0 +1,13 @@ +error[E0597]: `foo` does not live long enough + --> $DIR/issue-40157.rs:2:53 + | +LL | {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x });} + | ------------------------^^^^^^^^^^-- + | | | | + | | | `foo` dropped here while still borrowed + | | borrowed value does not live long enough + | borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr b/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr new file mode 100644 index 000000000..2b1789908 --- /dev/null +++ b/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr @@ -0,0 +1,27 @@ +error[E0282]: type annotations needed + --> $DIR/issue-42234-unknown-receiver-type.rs:9:24 + | +LL | let x: Option<_> = None; + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` +LL | x.unwrap().method_that_could_exist_on_some_type(); + | ---------- type must be known at this point + | +help: consider specifying the generic argument + | +LL | let x: Option<_> = None::<T>; + | +++++ + +error[E0282]: type annotations needed + --> $DIR/issue-42234-unknown-receiver-type.rs:15:10 + | +LL | .sum::<_>() + | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` + | +help: consider specifying the generic argument + | +LL | .sum::<_>() + | ~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr b/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr new file mode 100644 index 000000000..d93d54e87 --- /dev/null +++ b/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr @@ -0,0 +1,27 @@ +error[E0282]: type annotations needed + --> $DIR/issue-42234-unknown-receiver-type.rs:9:24 + | +LL | let x: Option<_> = None; + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` +LL | x.unwrap().method_that_could_exist_on_some_type(); + | ---------- type must be known at this point + | +help: consider specifying the generic argument + | +LL | let x: Option<_> = None::<T>; + | +++++ + +error[E0282]: type annotations needed + --> $DIR/issue-42234-unknown-receiver-type.rs:15:10 + | +LL | .sum::<_>() + | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` + | +help: consider specifying the generic argument + | +LL | .sum::<S>() + | ~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.rs b/tests/ui/span/issue-42234-unknown-receiver-type.rs new file mode 100644 index 000000000..fd5312120 --- /dev/null +++ b/tests/ui/span/issue-42234-unknown-receiver-type.rs @@ -0,0 +1,19 @@ +// revisions: full generic_arg +#![cfg_attr(generic_arg, feature(generic_arg_infer))] + +// When the type of a method call's receiver is unknown, the span should point +// to the receiver (and not the entire call, as was previously the case before +// the fix of which this tests). + +fn shines_a_beacon_through_the_darkness() { + let x: Option<_> = None; //~ ERROR type annotations needed + x.unwrap().method_that_could_exist_on_some_type(); +} + +fn courier_to_des_moines_and_points_west(data: &[u32]) -> String { + data.iter() + .sum::<_>() //~ ERROR type annotations needed + .to_string() +} + +fn main() {} diff --git a/tests/ui/span/issue-43927-non-ADT-derive.rs b/tests/ui/span/issue-43927-non-ADT-derive.rs new file mode 100644 index 000000000..935bfa001 --- /dev/null +++ b/tests/ui/span/issue-43927-non-ADT-derive.rs @@ -0,0 +1,6 @@ +#![derive(Debug, PartialEq, Eq)] // should be an outer attribute! +//~^ ERROR cannot determine resolution for the attribute macro `derive` +//~^^ ERROR `derive` attribute cannot be used at crate level +struct DerivedOn; + +fn main() {} diff --git a/tests/ui/span/issue-43927-non-ADT-derive.stderr b/tests/ui/span/issue-43927-non-ADT-derive.stderr new file mode 100644 index 000000000..e3ae37e36 --- /dev/null +++ b/tests/ui/span/issue-43927-non-ADT-derive.stderr @@ -0,0 +1,21 @@ +error: cannot determine resolution for the attribute macro `derive` + --> $DIR/issue-43927-non-ADT-derive.rs:1:4 + | +LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! + | ^^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: `derive` attribute cannot be used at crate level + --> $DIR/issue-43927-non-ADT-derive.rs:1:1 + | +LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[derive(Debug, PartialEq, Eq)] // should be an outer attribute! + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/span/issue-71363.rs b/tests/ui/span/issue-71363.rs new file mode 100644 index 000000000..8014f3796 --- /dev/null +++ b/tests/ui/span/issue-71363.rs @@ -0,0 +1,19 @@ +// compile-flags: -Z ui-testing=no + +struct MyError; +impl std::error::Error for MyError {} +//~^ ERROR: `MyError` doesn't implement `std::fmt::Display` +//~| ERROR: `MyError` doesn't implement `Debug` + +fn main() {} + +// This test relies on library/std/src/error.rs *not* being included in the error message, so that +// we can test whether a file not included in the error message affects it (more specifically +// whether the line number of the excluded file affects the indentation of the other line numbers). +// +// To test this we're simulating a remap of the rust src base (so that library/std/src/error.rs +// does not point to a local file) *and* we're disabling the code to try mapping a remapped path to +// a local file (which would defeat the purpose of the former flag). +// +// Note that this comment is at the bottom of the file intentionally, as we need the line number of +// the impl to be lower than 10. diff --git a/tests/ui/span/issue-71363.stderr b/tests/ui/span/issue-71363.stderr new file mode 100644 index 000000000..cb5cc3202 --- /dev/null +++ b/tests/ui/span/issue-71363.stderr @@ -0,0 +1,29 @@ +error[E0277]: `MyError` doesn't implement `std::fmt::Display` + --> $DIR/issue-71363.rs:4:28 + | +4 | impl std::error::Error for MyError {} + | ^^^^^^^ `MyError` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `MyError` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `std::error::Error` + --> $SRC_DIR/core/src/error.rs:LL:COL + +error[E0277]: `MyError` doesn't implement `Debug` + --> $DIR/issue-71363.rs:4:28 + | +4 | impl std::error::Error for MyError {} + | ^^^^^^^ `MyError` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `MyError` + = note: add `#[derive(Debug)]` to `MyError` or manually `impl Debug for MyError` +note: required by a bound in `std::error::Error` + --> $SRC_DIR/core/src/error.rs:LL:COL +help: consider annotating `MyError` with `#[derive(Debug)]` + | +3 | #[derive(Debug)] + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/span/issue-81800.rs b/tests/ui/span/issue-81800.rs new file mode 100644 index 000000000..6ac66fdcb --- /dev/null +++ b/tests/ui/span/issue-81800.rs @@ -0,0 +1,2 @@ +fn x˂- //~ ERROR: unknown start of token + //~^ ERROR: expected one of `#`, `>`, `const`, identifier, or lifetime, found `-` diff --git a/tests/ui/span/issue-81800.stderr b/tests/ui/span/issue-81800.stderr new file mode 100644 index 000000000..86c64573b --- /dev/null +++ b/tests/ui/span/issue-81800.stderr @@ -0,0 +1,19 @@ +error: unknown start of token: \u{2c2} + --> $DIR/issue-81800.rs:1:5 + | +LL | fn x˂- + | ^ + | +help: Unicode character '˂' (Modifier Letter Left Arrowhead) looks like '<' (Less-Than Sign), but it is not + | +LL | fn x<- + | ~ + +error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `-` + --> $DIR/issue-81800.rs:1:6 + | +LL | fn x˂- + | ^ expected one of `#`, `>`, `const`, identifier, or lifetime + +error: aborting due to 2 previous errors + diff --git a/tests/ui/span/issue28498-reject-ex1.rs b/tests/ui/span/issue28498-reject-ex1.rs new file mode 100644 index 000000000..4d1b41255 --- /dev/null +++ b/tests/ui/span/issue28498-reject-ex1.rs @@ -0,0 +1,37 @@ +// Example taken from RFC 1238 text + +// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md +// #examples-of-code-that-will-start-to-be-rejected + +// Compare against test/run-pass/issue28498-must-work-ex2.rs + +use std::cell::Cell; + +struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>); + +struct Foo<T> { data: Vec<T> } + +fn potentially_specialized_wrt_t<T>(t: &T) { + // Hypothetical code that does one thing for generic T and then is + // specialized for T == Concrete (and the specialized form can + // then access a reference held in concrete tuple). + // + // (We don't have specialization yet, but we want to allow for it + // in the future.) +} + +impl<T> Drop for Foo<T> { + fn drop(&mut self) { + potentially_specialized_wrt_t(&self.data[0]) + } +} + +fn main() { + let mut foo = Foo { data: Vec::new() }; + foo.data.push(Concrete(0, Cell::new(None))); + foo.data.push(Concrete(0, Cell::new(None))); + + foo.data[0].1.set(Some(&foo.data[1])); + //~^ ERROR borrow may still be in use when destructor runs + foo.data[1].1.set(Some(&foo.data[0])); +} diff --git a/tests/ui/span/issue28498-reject-ex1.stderr b/tests/ui/span/issue28498-reject-ex1.stderr new file mode 100644 index 000000000..86e2d8c56 --- /dev/null +++ b/tests/ui/span/issue28498-reject-ex1.stderr @@ -0,0 +1,17 @@ +error[E0713]: borrow may still be in use when destructor runs + --> $DIR/issue28498-reject-ex1.rs:34:29 + | +LL | foo.data[0].1.set(Some(&foo.data[1])); + | ^^^^^^^^ +... +LL | } + | - + | | + | here, drop of `foo` needs exclusive access to `foo.data`, because the type `Foo<Concrete<'_>>` implements the `Drop` trait + | borrow might be used here, when `foo` is dropped and runs the `Drop` code for type `Foo` + | + = note: consider using a `let` binding to create a longer lived value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0713`. diff --git a/tests/ui/span/issue28498-reject-lifetime-param.rs b/tests/ui/span/issue28498-reject-lifetime-param.rs new file mode 100644 index 000000000..1e7190157 --- /dev/null +++ b/tests/ui/span/issue28498-reject-lifetime-param.rs @@ -0,0 +1,36 @@ +// Demonstrate that having a lifetime param causes dropck to reject code +// that might indirectly access previously dropped value. +// +// Compare with run-pass/issue28498-ugeh-with-lifetime-param.rs + +#[derive(Debug)] +struct ScribbleOnDrop(String); + +impl Drop for ScribbleOnDrop { + fn drop(&mut self) { + self.0 = format!("DROPPED"); + } +} + +struct Foo<'a>(u32, &'a ScribbleOnDrop); + +impl<'a> Drop for Foo<'a> { + fn drop(&mut self) { + // Use of `may_dangle` is unsound, because destructor accesses borrowed data + // in `self.1` and we must force that to strictly outlive `self`. + println!("Dropping Foo({}, {:?})", self.0, self.1); + } +} + +fn main() { + let (last_dropped, foo0); + let (foo1, first_dropped); + + last_dropped = ScribbleOnDrop(format!("last")); + first_dropped = ScribbleOnDrop(format!("first")); + foo0 = Foo(0, &last_dropped); // OK + foo1 = Foo(1, &first_dropped); + //~^ ERROR `first_dropped` does not live long enough + + println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1); +} diff --git a/tests/ui/span/issue28498-reject-lifetime-param.stderr b/tests/ui/span/issue28498-reject-lifetime-param.stderr new file mode 100644 index 000000000..3119ddd03 --- /dev/null +++ b/tests/ui/span/issue28498-reject-lifetime-param.stderr @@ -0,0 +1,17 @@ +error[E0597]: `first_dropped` does not live long enough + --> $DIR/issue28498-reject-lifetime-param.rs:32:19 + | +LL | foo1 = Foo(1, &first_dropped); + | ^^^^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `first_dropped` dropped here while still borrowed + | borrow might be used here, when `foo1` is dropped and runs the `Drop` code for type `Foo` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue28498-reject-passed-to-fn.rs b/tests/ui/span/issue28498-reject-passed-to-fn.rs new file mode 100644 index 000000000..dcd2e9ad4 --- /dev/null +++ b/tests/ui/span/issue28498-reject-passed-to-fn.rs @@ -0,0 +1,38 @@ +// Demonstrate that a type param in negative position causes dropck to reject code +// that might indirectly access previously dropped value. +// +// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs + +#[derive(Debug)] +struct ScribbleOnDrop(String); + +impl Drop for ScribbleOnDrop { + fn drop(&mut self) { + self.0 = format!("DROPPED"); + } +} + +struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>); + +impl<T> Drop for Foo<T> { + fn drop(&mut self) { + // Use of `may_dangle` is unsound, because we pass `T` to the callback in `self.2` + // below, and thus potentially read from borrowed data. + println!("Dropping Foo({}, {})", self.0, (self.2)(&self.1)); + } +} + +fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) } + +fn main() { + let (last_dropped, foo0); + let (foo1, first_dropped); + + last_dropped = ScribbleOnDrop(format!("last")); + first_dropped = ScribbleOnDrop(format!("first")); + foo0 = Foo(0, &last_dropped, Box::new(callback)); // OK + foo1 = Foo(1, &first_dropped, Box::new(callback)); + //~^ ERROR `first_dropped` does not live long enough + + println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1); +} diff --git a/tests/ui/span/issue28498-reject-passed-to-fn.stderr b/tests/ui/span/issue28498-reject-passed-to-fn.stderr new file mode 100644 index 000000000..60e8a648c --- /dev/null +++ b/tests/ui/span/issue28498-reject-passed-to-fn.stderr @@ -0,0 +1,17 @@ +error[E0597]: `first_dropped` does not live long enough + --> $DIR/issue28498-reject-passed-to-fn.rs:34:19 + | +LL | foo1 = Foo(1, &first_dropped, Box::new(callback)); + | ^^^^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `first_dropped` dropped here while still borrowed + | borrow might be used here, when `foo1` is dropped and runs the `Drop` code for type `Foo` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue28498-reject-trait-bound.rs b/tests/ui/span/issue28498-reject-trait-bound.rs new file mode 100644 index 000000000..444cebb19 --- /dev/null +++ b/tests/ui/span/issue28498-reject-trait-bound.rs @@ -0,0 +1,38 @@ +// Demonstrate that having a trait bound causes dropck to reject code +// that might indirectly access previously dropped value. +// +// Compare with run-pass/issue28498-ugeh-with-trait-bound.rs + +use std::fmt; + +#[derive(Debug)] +struct ScribbleOnDrop(String); + +impl Drop for ScribbleOnDrop { + fn drop(&mut self) { + self.0 = format!("DROPPED"); + } +} + +struct Foo<T: fmt::Debug>(u32, T); + +impl<T: fmt::Debug> Drop for Foo<T> { + fn drop(&mut self) { + // Use of `may_dangle` is unsound, because we access `T` fmt method when we pass + // `self.1` below, and thus potentially read from borrowed data. + println!("Dropping Foo({}, {:?})", self.0, self.1); + } +} + +fn main() { + let (last_dropped, foo0); + let (foo1, first_dropped); + + last_dropped = ScribbleOnDrop(format!("last")); + first_dropped = ScribbleOnDrop(format!("first")); + foo0 = Foo(0, &last_dropped); // OK + foo1 = Foo(1, &first_dropped); + //~^ ERROR `first_dropped` does not live long enough + + println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1); +} diff --git a/tests/ui/span/issue28498-reject-trait-bound.stderr b/tests/ui/span/issue28498-reject-trait-bound.stderr new file mode 100644 index 000000000..22e4a8205 --- /dev/null +++ b/tests/ui/span/issue28498-reject-trait-bound.stderr @@ -0,0 +1,17 @@ +error[E0597]: `first_dropped` does not live long enough + --> $DIR/issue28498-reject-trait-bound.rs:34:19 + | +LL | foo1 = Foo(1, &first_dropped); + | ^^^^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `first_dropped` dropped here while still borrowed + | borrow might be used here, when `foo1` is dropped and runs the `Drop` code for type `Foo` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/lint-unused-unsafe-thir.rs b/tests/ui/span/lint-unused-unsafe-thir.rs new file mode 100644 index 000000000..adb72c26b --- /dev/null +++ b/tests/ui/span/lint-unused-unsafe-thir.rs @@ -0,0 +1,61 @@ +// FIXME: This file is tracking old lint behavior that's still unchanged in the +// unstable -Zthir-unsafeck implementation. See lint-unused-unsafe.rs for more details. +// +// Exercise the unused_unsafe attribute in some positive and negative cases + +// compile-flags: -Zthir-unsafeck + +#![allow(dead_code)] +#![deny(unused_unsafe)] + + +mod foo { + extern "C" { + pub fn bar(); + } +} + +fn callback<T, F>(_f: F) -> T where F: FnOnce() -> T { panic!() } +unsafe fn unsf() {} + +fn bad1() { unsafe {} } //~ ERROR: unnecessary `unsafe` block +fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad3() { unsafe {} } //~ ERROR: unnecessary `unsafe` block +fn bad4() { unsafe { callback(||{}) } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad5() { unsafe { unsf() } } +fn bad6() { + unsafe { // don't put the warning here + unsafe { //~ ERROR: unnecessary `unsafe` block + unsf() + } + } +} +unsafe fn bad7() { + unsafe { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsf() + } + } +} + +unsafe fn good0() { unsf() } +fn good1() { unsafe { unsf() } } +fn good2() { + /* bug uncovered when implementing warning about unused unsafe blocks. Be + sure that when purity is inherited that the source of the unsafe-ness + is tracked correctly */ + unsafe { + unsafe fn what() -> Vec<String> { panic!() } + + callback(|| { + what(); + }); + } +} + +unsafe fn good3() { foo::bar() } +fn good4() { unsafe { foo::bar() } } + +#[allow(unused_unsafe)] fn allowed() { unsafe {} } + +fn main() {} diff --git a/tests/ui/span/lint-unused-unsafe-thir.stderr b/tests/ui/span/lint-unused-unsafe-thir.stderr new file mode 100644 index 000000000..3bcbb7597 --- /dev/null +++ b/tests/ui/span/lint-unused-unsafe-thir.stderr @@ -0,0 +1,50 @@ +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe-thir.rs:21:13 + | +LL | fn bad1() { unsafe {} } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe-thir.rs:9:9 + | +LL | #![deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe-thir.rs:22:13 + | +LL | fn bad2() { unsafe { bad1() } } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe-thir.rs:23:20 + | +LL | unsafe fn bad3() { unsafe {} } + | ---------------- ^^^^^^ unnecessary `unsafe` block + | | + | because it's nested under this `unsafe` fn + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe-thir.rs:24:13 + | +LL | fn bad4() { unsafe { callback(||{}) } } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe-thir.rs:28:9 + | +LL | unsafe { // don't put the warning here + | ------ because it's nested under this `unsafe` block +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe-thir.rs:35:9 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: aborting due to 6 previous errors + diff --git a/tests/ui/span/lint-unused-unsafe.mir.stderr b/tests/ui/span/lint-unused-unsafe.mir.stderr new file mode 100644 index 000000000..d8412908c --- /dev/null +++ b/tests/ui/span/lint-unused-unsafe.mir.stderr @@ -0,0 +1,1402 @@ +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:26:13 + | +LL | fn bad1() { unsafe {} } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:14:9 + | +LL | #![deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:27:13 + | +LL | fn bad2() { unsafe { bad1() } } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:28:20 + | +LL | unsafe fn bad3() { unsafe {} } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:29:13 + | +LL | fn bad4() { unsafe { callback(||{}) } } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:32:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:39:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:74:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:83:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:84:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:85:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:90:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:100:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:101:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:102:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:112:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:110:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:113:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:114:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:124:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:134:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:135:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:136:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:142:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:153:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:154:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:155:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:166:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:164:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:167:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:168:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:178:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:188:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:189:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:190:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:196:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:207:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:208:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:209:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:220:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:218:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:221:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:222:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:242:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:255:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:268:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:286:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:295:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:296:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:297:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:302:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:312:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:313:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:314:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:324:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:322:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:325:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:326:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:336:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:346:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:347:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:348:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:354:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:365:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:366:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:367:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:378:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:376:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:379:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:380:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:390:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:400:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:401:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:402:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:408:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:419:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:420:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:421:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:432:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:430:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:433:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:434:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:454:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:467:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:480:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:499:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:508:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:509:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:510:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:515:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:525:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsf(); +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:526:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:527:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:537:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:535:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:538:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:539:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:549:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:559:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:560:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:561:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:567:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:578:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsf(); +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:579:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:580:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:591:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:589:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:592:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:593:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:603:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:613:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:614:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:615:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:621:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:632:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsf(); +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:633:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:634:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:645:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:643:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:646:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:647:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:667:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:680:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:693:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:711:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:721:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:722:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:723:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:729:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:740:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:741:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:742:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:753:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:751:24 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:754:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:755:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:765:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:775:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:776:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:777:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:783:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:794:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:795:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:796:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:807:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:805:24 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:808:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:809:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:829:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:842:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:855:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:869:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:879:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:880:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:881:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:887:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:898:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:899:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:900:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:911:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:909:24 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:912:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:913:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:923:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:933:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:934:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:935:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:941:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:952:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:953:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:954:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:965:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:963:24 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:966:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:967:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:987:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1000:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1013:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1059:29 + | +LL | let _ = async { unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1066:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = async { unsf() }; +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1067:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1068:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1073:29 + | +LL | let _ = async { unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1080:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = async { unsf() }; +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1081:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1082:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1092:22 + | +LL | let _x: [(); unsafe { 0 }] = []; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1096:22 + | +LL | let _x: [(); unsafe { unsafe { size() } }] = []; + | ^^^^^^ unnecessary `unsafe` block + +error: aborting due to 174 previous errors + diff --git a/tests/ui/span/lint-unused-unsafe.rs b/tests/ui/span/lint-unused-unsafe.rs new file mode 100644 index 000000000..5d042768b --- /dev/null +++ b/tests/ui/span/lint-unused-unsafe.rs @@ -0,0 +1,1100 @@ +// Exercise the unused_unsafe attribute in some positive and negative cases + + +// edition:2018 + +// revisions: mir + +// FIXME: Adapt -Zthir-unsafeck to behave the same as the mir version after #93678, +// then delete lint-unused-unsafe-thir.rs, and go back to using the settings below +// // revisions: mir thir +// // [thir]compile-flags: -Zthir-unsafeck + +#![allow(dead_code)] +#![deny(unused_unsafe)] + + +mod foo { + extern "C" { + pub fn bar(); + } +} + +fn callback<T, F>(_f: F) -> T where F: FnOnce() -> T { panic!() } +unsafe fn unsf() {} + +fn bad1() { unsafe {} } //~ ERROR: unnecessary `unsafe` block +fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad3() { unsafe {} } //~ ERROR: unnecessary `unsafe` block +fn bad4() { unsafe { callback(||{}) } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad5() { unsafe { unsf() } } +fn bad6() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { // don't put the warning here + unsf() + } + } +} +unsafe fn bad7() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { + unsf() + } + } +} + +unsafe fn good0() { unsf() } +fn good1() { unsafe { unsf() } } +fn good2() { + /* bug uncovered when implementing warning about unused unsafe blocks. Be + sure that when purity is inherited that the source of the unsafe-ness + is tracked correctly */ + unsafe { + unsafe fn what() -> Vec<String> { panic!() } + + callback(|| { + what(); + }); + } +} + +unsafe fn good3() { foo::bar() } +fn good4() { unsafe { foo::bar() } } + +#[allow(unused_unsafe)] fn allowed() { unsafe {} } + +fn main() {} + +mod additional_tests { + unsafe fn unsf() {} + + // some tests + + fn inner_ignored() { + unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + unsafe { + unsf() + } + } + } + + fn multi_level_unused() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + } + } + + fn granularity() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } + unsafe { unsf() } + unsafe { unsf() } + } + } + + fn top_level_used() { + unsafe { + unsf(); + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + + } + + fn top_level_ignored() { + #[allow(unused_unsafe)] + unsafe { + #[deny(unused_unsafe)] + { + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + } + + } + + // same tests in unsafe fn without unsafe_op_in_unsafe_fn allowed + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + unsafe { + unsf() + } + } + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + } + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } + unsafe { unsf() } + unsafe { unsf() } + } + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + unsafe { + unsf(); + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + unsafe { + #[deny(unused_unsafe)] + { + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + } + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + unsafe { + unsf() + } + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } + unsafe { unsf() } + unsafe { unsf() } + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + unsafe { + unsf(); + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + unsafe { + #[deny(unused_unsafe)] + { + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + } + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + unsafe { + unsafe { //~ ERROR: unnecessary `unsafe` block + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + unsf(); + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + unsafe { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + } + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + } +} + +// the same set of tests, with closures everywhere +mod additional_tests_closures { + unsafe fn unsf() {} + + // some tests + + fn inner_ignored() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + fn multi_level_unused() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + fn granularity() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + fn top_level_used() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + fn top_level_ignored() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + + } + + // same tests in unsafe fn without unsafe_op_in_unsafe_fn allowed + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + unsf(); + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + }; + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } +} + +// the same set of tests, with closures everywhere +// and closures on the unsafe fn calls +mod additional_tests_even_more_closures { + unsafe fn unsf() {} + + // some tests + + fn inner_ignored() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + let _ = || unsf(); + }; + }; + } + + fn multi_level_unused() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + fn granularity() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + }; + } + + fn top_level_used() { + let _ = || unsafe { + let _ = || unsf(); + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + fn top_level_ignored() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + } + }; + + } + + // same tests in unsafe fn without unsafe_op_in_unsafe_fn allowed + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + let _ = || unsf(); + }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + let _ = || unsafe { + let _ = || unsf(); + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + let _ = || unsf(); + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + let _ = || unsafe { + let _ = || unsf(); + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = || unsf(); + } + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = || unsf(); + } + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = || unsf(); + } + }; + let _ = || unsf(); + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsf(); + }; + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = || unsf(); + } + }; + } +} + +mod item_likes { + unsafe fn unsf() {} + + struct S; + impl S { + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + unsf(); + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + }; + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + } + + trait T { + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + unsf(); + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + }; + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + } +} + +mod additional_tests_extra { + unsafe fn unsf() {} + + // multiple uses with different `unsafe_op_in_unsafe_fn` in the same closure + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + let _ = || { + unsf(); + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + }; + } + + #[warn(unsafe_op_in_unsafe_fn)] + unsafe fn multiple_unsafe_op_in_unsafe_fn_allows() { + unsafe { + #[allow(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + #[allow(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + } + + async unsafe fn async_blocks() { + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = async { unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; + let _ = async { unsafe { let _ = async { unsf() }; }}; + let _ = async { unsafe { let _ = async { unsf() }; }}; + }}; + let _ = async { unsafe { + let _ = async { unsf() }; + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + }}; + } + #[allow(unsafe_op_in_unsafe_fn)] + { + let _ = async { unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; + let _ = async { unsafe { let _ = async { unsf() }; }}; + let _ = async { unsafe { let _ = async { unsf() }; }}; + }}; + let _ = async { unsafe { + let _ = async { unsf() }; + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + }}; + } + } + + fn used_unsafe_in_const() { + let _x: [(); unsafe { size() }] = []; + } + + fn unused_unsafe_in_const_1() { + let _x: [(); unsafe { 0 }] = []; //~ ERROR: unnecessary `unsafe` block + } + + fn unused_unsafe_in_const_2() { + let _x: [(); unsafe { unsafe { size() } }] = []; //~ ERROR: unnecessary `unsafe` block + } + + const unsafe fn size() -> usize { 0 } +} diff --git a/tests/ui/span/macro-span-replacement.rs b/tests/ui/span/macro-span-replacement.rs new file mode 100644 index 000000000..66973c58d --- /dev/null +++ b/tests/ui/span/macro-span-replacement.rs @@ -0,0 +1,13 @@ +// check-pass + +#![warn(unused)] + +macro_rules! m { + ($a:tt $b:tt) => { + $b $a; //~ WARN struct `S` is never constructed + } +} + +fn main() { + m!(S struct); +} diff --git a/tests/ui/span/macro-span-replacement.stderr b/tests/ui/span/macro-span-replacement.stderr new file mode 100644 index 000000000..5dd563428 --- /dev/null +++ b/tests/ui/span/macro-span-replacement.stderr @@ -0,0 +1,19 @@ +warning: struct `S` is never constructed + --> $DIR/macro-span-replacement.rs:7:12 + | +LL | $b $a; + | ^^ +... +LL | m!(S struct); + | ------------ in this macro invocation + | +note: the lint level is defined here + --> $DIR/macro-span-replacement.rs:3:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(dead_code)]` implied by `#[warn(unused)]` + = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 1 warning emitted + diff --git a/tests/ui/span/macro-ty-params.rs b/tests/ui/span/macro-ty-params.rs new file mode 100644 index 000000000..cf28b0255 --- /dev/null +++ b/tests/ui/span/macro-ty-params.rs @@ -0,0 +1,15 @@ +macro_rules! m { + ($p1: path) => { + #[derive($p1)] struct U; + } +} + +macro_rules! foo { () => () } + +fn main() { + foo::<T>!(); //~ ERROR generic arguments in macro path + foo::<>!(); //~ ERROR generic arguments in macro path + m!(Default<>); + //~^ ERROR unexpected generic arguments in path + //~^^ ERROR generic arguments in macro path +} diff --git a/tests/ui/span/macro-ty-params.stderr b/tests/ui/span/macro-ty-params.stderr new file mode 100644 index 000000000..7023ef8cd --- /dev/null +++ b/tests/ui/span/macro-ty-params.stderr @@ -0,0 +1,26 @@ +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:10:10 + | +LL | foo::<T>!(); + | ^^^ + +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:11:10 + | +LL | foo::<>!(); + | ^^ + +error: unexpected generic arguments in path + --> $DIR/macro-ty-params.rs:12:15 + | +LL | m!(Default<>); + | ^^ + +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:12:15 + | +LL | m!(Default<>); + | ^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/span/method-and-field-eager-resolution.rs b/tests/ui/span/method-and-field-eager-resolution.rs new file mode 100644 index 000000000..a0f0d8810 --- /dev/null +++ b/tests/ui/span/method-and-field-eager-resolution.rs @@ -0,0 +1,15 @@ +// Test that spans get only base in eager type resolution (structurally_resolve_type). + +fn main() { + let mut x = Default::default(); + //~^ ERROR type annotations needed + x.0; + x = 1; +} + +fn foo() { + let mut x = Default::default(); + //~^ ERROR type annotations needed + x[0]; + x = 1; +} diff --git a/tests/ui/span/method-and-field-eager-resolution.stderr b/tests/ui/span/method-and-field-eager-resolution.stderr new file mode 100644 index 000000000..f6efbe40b --- /dev/null +++ b/tests/ui/span/method-and-field-eager-resolution.stderr @@ -0,0 +1,31 @@ +error[E0282]: type annotations needed + --> $DIR/method-and-field-eager-resolution.rs:4:9 + | +LL | let mut x = Default::default(); + | ^^^^^ +LL | +LL | x.0; + | - type must be known at this point + | +help: consider giving `x` an explicit type + | +LL | let mut x: /* Type */ = Default::default(); + | ++++++++++++ + +error[E0282]: type annotations needed + --> $DIR/method-and-field-eager-resolution.rs:11:9 + | +LL | let mut x = Default::default(); + | ^^^^^ +LL | +LL | x[0]; + | - type must be known at this point + | +help: consider giving `x` an explicit type + | +LL | let mut x: /* Type */ = Default::default(); + | ++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/span/missing-unit-argument.rs b/tests/ui/span/missing-unit-argument.rs new file mode 100644 index 000000000..db96ae223 --- /dev/null +++ b/tests/ui/span/missing-unit-argument.rs @@ -0,0 +1,17 @@ +fn foo(():(), ():()) {} +fn bar(():()) {} + +struct S; +impl S { + fn baz(self, (): ()) { } + fn generic<T>(self, _: T) { } +} + +fn main() { + let _: Result<(), String> = Ok(); //~ ERROR this enum variant takes + foo(); //~ ERROR function takes + foo(()); //~ ERROR function takes + bar(); //~ ERROR function takes + S.baz(); //~ ERROR this method takes + S.generic::<()>(); //~ ERROR this method takes +} diff --git a/tests/ui/span/missing-unit-argument.stderr b/tests/ui/span/missing-unit-argument.stderr new file mode 100644 index 000000000..ef4d732b5 --- /dev/null +++ b/tests/ui/span/missing-unit-argument.stderr @@ -0,0 +1,96 @@ +error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied + --> $DIR/missing-unit-argument.rs:11:33 + | +LL | let _: Result<(), String> = Ok(); + | ^^-- an argument of type `()` is missing + | +note: tuple variant defined here + --> $SRC_DIR/core/src/result.rs:LL:COL +help: provide the argument + | +LL | let _: Result<(), String> = Ok(()); + | ~~~~ + +error[E0061]: this function takes 2 arguments but 0 arguments were supplied + --> $DIR/missing-unit-argument.rs:12:5 + | +LL | foo(); + | ^^^-- two arguments of type `()` and `()` are missing + | +note: function defined here + --> $DIR/missing-unit-argument.rs:1:4 + | +LL | fn foo(():(), ():()) {} + | ^^^ ----- ----- +help: provide the arguments + | +LL | foo((), ()); + | ~~~~~~~~ + +error[E0061]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/missing-unit-argument.rs:13:5 + | +LL | foo(()); + | ^^^---- an argument of type `()` is missing + | +note: function defined here + --> $DIR/missing-unit-argument.rs:1:4 + | +LL | fn foo(():(), ():()) {} + | ^^^ ----- ----- +help: provide the argument + | +LL | foo((), ()); + | ~~~~~~~~ + +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/missing-unit-argument.rs:14:5 + | +LL | bar(); + | ^^^-- an argument of type `()` is missing + | +note: function defined here + --> $DIR/missing-unit-argument.rs:2:4 + | +LL | fn bar(():()) {} + | ^^^ ----- +help: provide the argument + | +LL | bar(()); + | ~~~~ + +error[E0061]: this method takes 1 argument but 0 arguments were supplied + --> $DIR/missing-unit-argument.rs:15:7 + | +LL | S.baz(); + | ^^^-- an argument of type `()` is missing + | +note: associated function defined here + --> $DIR/missing-unit-argument.rs:6:8 + | +LL | fn baz(self, (): ()) { } + | ^^^ ------ +help: provide the argument + | +LL | S.baz(()); + | ~~~~ + +error[E0061]: this method takes 1 argument but 0 arguments were supplied + --> $DIR/missing-unit-argument.rs:16:7 + | +LL | S.generic::<()>(); + | ^^^^^^^^^^^^^-- an argument of type `()` is missing + | +note: associated function defined here + --> $DIR/missing-unit-argument.rs:7:8 + | +LL | fn generic<T>(self, _: T) { } + | ^^^^^^^ ---- +help: provide the argument + | +LL | S.generic::<()>(()); + | ~~~~ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/span/move-closure.rs b/tests/ui/span/move-closure.rs new file mode 100644 index 000000000..bdd7951b3 --- /dev/null +++ b/tests/ui/span/move-closure.rs @@ -0,0 +1,6 @@ +// Regression test for issue #24986 +// Make sure that the span of a closure marked `move` begins at the `move` keyword. + +fn main() { + let x: () = move || (); //~ ERROR mismatched types +} diff --git a/tests/ui/span/move-closure.stderr b/tests/ui/span/move-closure.stderr new file mode 100644 index 000000000..dcc607896 --- /dev/null +++ b/tests/ui/span/move-closure.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/move-closure.rs:5:17 + | +LL | let x: () = move || (); + | -- ^^^^^^^^^^ expected `()`, found closure + | | + | expected due to this + | + = note: expected unit type `()` + found closure `[closure@$DIR/move-closure.rs:5:17: 5:24]` +help: use parentheses to call this closure + | +LL | let x: () = (move || ())(); + | + +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/span/multiline-span-E0072.rs b/tests/ui/span/multiline-span-E0072.rs new file mode 100644 index 000000000..728b47d65 --- /dev/null +++ b/tests/ui/span/multiline-span-E0072.rs @@ -0,0 +1,10 @@ +// It should just use the entire body instead of pointing at the next two lines +struct //~ ERROR has infinite size +ListNode +{ + head: u8, + tail: Option<ListNode>, +} + +fn main() { +} diff --git a/tests/ui/span/multiline-span-E0072.stderr b/tests/ui/span/multiline-span-E0072.stderr new file mode 100644 index 000000000..fc2f6e662 --- /dev/null +++ b/tests/ui/span/multiline-span-E0072.stderr @@ -0,0 +1,18 @@ +error[E0072]: recursive type `ListNode` has infinite size + --> $DIR/multiline-span-E0072.rs:2:1 + | +LL | / struct +LL | | ListNode + | |________^ +... +LL | tail: Option<ListNode>, + | -------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | tail: Option<Box<ListNode>>, + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/span/multiline-span-simple.rs b/tests/ui/span/multiline-span-simple.rs new file mode 100644 index 000000000..204a7f6b1 --- /dev/null +++ b/tests/ui/span/multiline-span-simple.rs @@ -0,0 +1,20 @@ +fn foo(a: u32, b: u32) { + a + b; +} + +fn bar(a: u32, b: u32) { + a + b; +} + +fn main() { + let x = 1; + let y = 2; + let z = 3; + foo(1 as u32 + //~ ERROR cannot add `()` to `u32` + + bar(x, + + y), + + z) +} diff --git a/tests/ui/span/multiline-span-simple.stderr b/tests/ui/span/multiline-span-simple.stderr new file mode 100644 index 000000000..b44df962a --- /dev/null +++ b/tests/ui/span/multiline-span-simple.stderr @@ -0,0 +1,16 @@ +error[E0277]: cannot add `()` to `u32` + --> $DIR/multiline-span-simple.rs:13:18 + | +LL | foo(1 as u32 + + | ^ no implementation for `u32 + ()` + | + = help: the trait `Add<()>` is not implemented for `u32` + = help: the following other types implement trait `Add<Rhs>`: + <&'a u32 as Add<u32>> + <&u32 as Add<&u32>> + <u32 as Add<&u32>> + <u32 as Add> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/span/multispan-import-lint.rs b/tests/ui/span/multispan-import-lint.rs new file mode 100644 index 000000000..3ce7f2ce3 --- /dev/null +++ b/tests/ui/span/multispan-import-lint.rs @@ -0,0 +1,10 @@ +// check-pass + +#![warn(unused)] + +use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd}; +//~^ WARN unused imports + +fn main() { + let _ = min(1, 2); +} diff --git a/tests/ui/span/multispan-import-lint.stderr b/tests/ui/span/multispan-import-lint.stderr new file mode 100644 index 000000000..4a955d1b3 --- /dev/null +++ b/tests/ui/span/multispan-import-lint.stderr @@ -0,0 +1,15 @@ +warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd` + --> $DIR/multispan-import-lint.rs:5:16 + | +LL | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd}; + | ^^ ^^^ ^^^^^^^^^ ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/multispan-import-lint.rs:3:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_imports)]` implied by `#[warn(unused)]` + +warning: 1 warning emitted + diff --git a/tests/ui/span/mut-arg-hint.rs b/tests/ui/span/mut-arg-hint.rs new file mode 100644 index 000000000..d7ff1f0de --- /dev/null +++ b/tests/ui/span/mut-arg-hint.rs @@ -0,0 +1,22 @@ +trait B { + fn foo(mut a: &String) { + a.push_str("bar"); //~ ERROR cannot borrow `*a` as mutable, as it is behind a `&` reference + } +} + +pub fn foo<'a>(mut a: &'a String) { + a.push_str("foo"); //~ ERROR cannot borrow `*a` as mutable, as it is behind a `&` reference +} + +struct A {} + +impl A { + pub fn foo(mut a: &String) { + a.push_str("foo"); //~ ERROR cannot borrow `*a` as mutable, as it is behind a `&` reference + } +} + +fn main() { + foo(&"a".to_string()); + A::foo(&"a".to_string()); +} diff --git a/tests/ui/span/mut-arg-hint.stderr b/tests/ui/span/mut-arg-hint.stderr new file mode 100644 index 000000000..96ce4d5bc --- /dev/null +++ b/tests/ui/span/mut-arg-hint.stderr @@ -0,0 +1,36 @@ +error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference + --> $DIR/mut-arg-hint.rs:3:9 + | +LL | a.push_str("bar"); + | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo(mut a: &mut String) { + | ~~~~~~~~~~~ + +error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference + --> $DIR/mut-arg-hint.rs:8:5 + | +LL | a.push_str("foo"); + | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | pub fn foo<'a>(mut a: &'a mut String) { + | ~~~~~~~~~~~~~~ + +error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference + --> $DIR/mut-arg-hint.rs:15:9 + | +LL | a.push_str("foo"); + | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | pub fn foo(mut a: &mut String) { + | ~~~~~~~~~~~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/span/mut-ptr-cant-outlive-ref.rs b/tests/ui/span/mut-ptr-cant-outlive-ref.rs new file mode 100644 index 000000000..b8c752d73 --- /dev/null +++ b/tests/ui/span/mut-ptr-cant-outlive-ref.rs @@ -0,0 +1,15 @@ +use std::cell::RefCell; + +fn main() { + let m = RefCell::new(0); + let p; + { + let b = m.borrow(); + p = &*b; + } + //~^^ ERROR `b` does not live long enough + p.use_ref(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl<T> Fake for T { } diff --git a/tests/ui/span/mut-ptr-cant-outlive-ref.stderr b/tests/ui/span/mut-ptr-cant-outlive-ref.stderr new file mode 100644 index 000000000..4d976a7bb --- /dev/null +++ b/tests/ui/span/mut-ptr-cant-outlive-ref.stderr @@ -0,0 +1,14 @@ +error[E0597]: `b` does not live long enough + --> $DIR/mut-ptr-cant-outlive-ref.rs:8:15 + | +LL | p = &*b; + | ^ borrowed value does not live long enough +LL | } + | - `b` dropped here while still borrowed +LL | +LL | p.use_ref(); + | ----------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/non-existing-module-import.rs b/tests/ui/span/non-existing-module-import.rs new file mode 100644 index 000000000..d2ce7ec4f --- /dev/null +++ b/tests/ui/span/non-existing-module-import.rs @@ -0,0 +1,3 @@ +use std::bar::{foo1, foo2}; //~ ERROR unresolved import + +fn main() {} diff --git a/tests/ui/span/non-existing-module-import.stderr b/tests/ui/span/non-existing-module-import.stderr new file mode 100644 index 000000000..25c099590 --- /dev/null +++ b/tests/ui/span/non-existing-module-import.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `std::bar` + --> $DIR/non-existing-module-import.rs:1:10 + | +LL | use std::bar::{foo1, foo2}; + | ^^^ could not find `bar` in `std` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/span/pub-struct-field.rs b/tests/ui/span/pub-struct-field.rs new file mode 100644 index 000000000..e149b9dbf --- /dev/null +++ b/tests/ui/span/pub-struct-field.rs @@ -0,0 +1,10 @@ +// Regression test for issue #26083 and #35435 +// Test that span for public struct fields start at `pub` + +struct Foo { + bar: u8, + pub bar: u8, //~ ERROR is already declared + pub(crate) bar: u8, //~ ERROR is already declared +} + +fn main() {} diff --git a/tests/ui/span/pub-struct-field.stderr b/tests/ui/span/pub-struct-field.stderr new file mode 100644 index 000000000..065340f44 --- /dev/null +++ b/tests/ui/span/pub-struct-field.stderr @@ -0,0 +1,20 @@ +error[E0124]: field `bar` is already declared + --> $DIR/pub-struct-field.rs:6:5 + | +LL | bar: u8, + | ------- `bar` first declared here +LL | pub bar: u8, + | ^^^^^^^^^^^ field already declared + +error[E0124]: field `bar` is already declared + --> $DIR/pub-struct-field.rs:7:5 + | +LL | bar: u8, + | ------- `bar` first declared here +LL | pub bar: u8, +LL | pub(crate) bar: u8, + | ^^^^^^^^^^^^^^^^^^ field already declared + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0124`. diff --git a/tests/ui/span/range-2.rs b/tests/ui/span/range-2.rs new file mode 100644 index 000000000..c4bb16f44 --- /dev/null +++ b/tests/ui/span/range-2.rs @@ -0,0 +1,15 @@ +// Test range syntax - borrow errors. +#![feature(rustc_attrs)] +pub fn main() { #![rustc_error] // rust-lang/rust#49855 + let r = { + let a = 42; + let b = 42; + &a..&b + }; + //~^^ ERROR `a` does not live long enough + //~| ERROR `b` does not live long enough + r.use_ref(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl<T> Fake for T { } diff --git a/tests/ui/span/range-2.stderr b/tests/ui/span/range-2.stderr new file mode 100644 index 000000000..8ca8156b0 --- /dev/null +++ b/tests/ui/span/range-2.stderr @@ -0,0 +1,25 @@ +error[E0597]: `a` does not live long enough + --> $DIR/range-2.rs:7:9 + | +LL | let r = { + | - borrow later stored here +... +LL | &a..&b + | ^^ borrowed value does not live long enough +LL | }; + | - `a` dropped here while still borrowed + +error[E0597]: `b` does not live long enough + --> $DIR/range-2.rs:7:13 + | +LL | let r = { + | - borrow later stored here +... +LL | &a..&b + | ^^ borrowed value does not live long enough +LL | }; + | - `b` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/recursive-type-field.rs b/tests/ui/span/recursive-type-field.rs new file mode 100644 index 000000000..bd4c43534 --- /dev/null +++ b/tests/ui/span/recursive-type-field.rs @@ -0,0 +1,18 @@ +use std::rc::Rc; + +struct Foo<'a> { //~ ERROR recursive types `Foo` and `Bar` have infinite size + bar: Bar<'a>, + b: Rc<Bar<'a>>, +} + +struct Bar<'a> { + y: (Foo<'a>, Foo<'a>), + z: Option<Bar<'a>>, + a: &'a Foo<'a>, + c: &'a [Bar<'a>], + d: [Bar<'a>; 1], + e: Foo<'a>, + x: Bar<'a>, +} + +fn main() {} diff --git a/tests/ui/span/recursive-type-field.stderr b/tests/ui/span/recursive-type-field.stderr new file mode 100644 index 000000000..10af4c36b --- /dev/null +++ b/tests/ui/span/recursive-type-field.stderr @@ -0,0 +1,27 @@ +error[E0072]: recursive types `Foo` and `Bar` have infinite size + --> $DIR/recursive-type-field.rs:3:1 + | +LL | struct Foo<'a> { + | ^^^^^^^^^^^^^^ +LL | bar: Bar<'a>, + | ------- recursive without indirection +... +LL | struct Bar<'a> { + | ^^^^^^^^^^^^^^ +LL | y: (Foo<'a>, Foo<'a>), + | ------- ------- recursive without indirection + | | + | recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL ~ bar: Box<Bar<'a>>, +LL | b: Rc<Bar<'a>>, + ... +LL | struct Bar<'a> { +LL ~ y: (Box<Foo<'a>>, Box<Foo<'a>>), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.rs b/tests/ui/span/regionck-unboxed-closure-lifetimes.rs new file mode 100644 index 000000000..60ccaa872 --- /dev/null +++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.rs @@ -0,0 +1,16 @@ +#![feature(rustc_attrs)] +use std::ops::FnMut; + +fn main() { #![rustc_error] // rust-lang/rust#49855 + let mut f; + { + let c = 1; + let c_ref = &c; + //~^ ERROR `c` does not live long enough + f = move |a: isize, b: isize| { a + b + *c_ref }; + } + f.use_mut(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl<T> Fake for T { } diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr new file mode 100644 index 000000000..0b985de60 --- /dev/null +++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr @@ -0,0 +1,14 @@ +error[E0597]: `c` does not live long enough + --> $DIR/regionck-unboxed-closure-lifetimes.rs:8:21 + | +LL | let c_ref = &c; + | ^^ borrowed value does not live long enough +... +LL | } + | - `c` dropped here while still borrowed +LL | f.use_mut(); + | ----------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/regions-close-over-borrowed-ref-in-obj.rs b/tests/ui/span/regions-close-over-borrowed-ref-in-obj.rs new file mode 100644 index 000000000..16b4cc258 --- /dev/null +++ b/tests/ui/span/regions-close-over-borrowed-ref-in-obj.rs @@ -0,0 +1,16 @@ +fn id<T>(x: T) -> T { x } + +trait Foo { } + +impl<'a> Foo for &'a isize { } + +fn main() { + + let blah; + + { + let ss: &isize = &id(1); + //~^ ERROR temporary value dropped while borrowed + blah = Box::new(ss) as Box<dyn Foo>; + } +} diff --git a/tests/ui/span/regions-close-over-borrowed-ref-in-obj.stderr b/tests/ui/span/regions-close-over-borrowed-ref-in-obj.stderr new file mode 100644 index 000000000..81e858fa0 --- /dev/null +++ b/tests/ui/span/regions-close-over-borrowed-ref-in-obj.stderr @@ -0,0 +1,16 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/regions-close-over-borrowed-ref-in-obj.rs:12:27 + | +LL | let ss: &isize = &id(1); + | ^^^^^ creates a temporary value which is freed while still in use +... +LL | } + | - temporary value is freed at the end of this statement +LL | } + | - borrow might be used here, when `blah` is dropped and runs the destructor for type `Box<dyn Foo>` + | + = note: consider using a `let` binding to create a longer lived value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/span/regions-close-over-type-parameter-2.rs b/tests/ui/span/regions-close-over-type-parameter-2.rs new file mode 100644 index 000000000..aca3972cb --- /dev/null +++ b/tests/ui/span/regions-close-over-type-parameter-2.rs @@ -0,0 +1,27 @@ +// Test for what happens when a type parameter `A` is closed over into +// an object. This should yield errors unless `A` (and the object) +// both have suitable bounds. + +trait Foo { fn get(&self); } + +impl<A> Foo for A { + fn get(&self) { + } +} + +fn repeater3<'a,A:'a>(v: A) -> Box<dyn Foo + 'a> { + Box::new(v) as Box<dyn Foo+'a> +} + +fn main() { + + // Error results because the type of is inferred to be + // ~Repeat<&'blk isize> where blk is the lifetime of the block below. + + let _ = { + let tmp0 = 3; + let tmp1 = &tmp0; + repeater3(tmp1) + }; + //~^^^ ERROR `tmp0` does not live long enough +} diff --git a/tests/ui/span/regions-close-over-type-parameter-2.stderr b/tests/ui/span/regions-close-over-type-parameter-2.stderr new file mode 100644 index 000000000..2e584d9a8 --- /dev/null +++ b/tests/ui/span/regions-close-over-type-parameter-2.stderr @@ -0,0 +1,13 @@ +error[E0597]: `tmp0` does not live long enough + --> $DIR/regions-close-over-type-parameter-2.rs:23:20 + | +LL | let tmp1 = &tmp0; + | ^^^^^ borrowed value does not live long enough +LL | repeater3(tmp1) + | --------------- borrow later captured here by trait object +LL | }; + | - `tmp0` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/regions-escape-loop-via-variable.rs b/tests/ui/span/regions-escape-loop-via-variable.rs new file mode 100644 index 000000000..ad468896b --- /dev/null +++ b/tests/ui/span/regions-escape-loop-via-variable.rs @@ -0,0 +1,14 @@ +fn main() { + let x = 3; + + // Here, the variable `p` gets inferred to a type with a lifetime + // of the loop body. The regionck then determines that this type + // is invalid. + let mut p = &x; + + loop { + let x = 1 + *p; + p = &x; + } + //~^^ ERROR `x` does not live long enough +} diff --git a/tests/ui/span/regions-escape-loop-via-variable.stderr b/tests/ui/span/regions-escape-loop-via-variable.stderr new file mode 100644 index 000000000..42df66852 --- /dev/null +++ b/tests/ui/span/regions-escape-loop-via-variable.stderr @@ -0,0 +1,13 @@ +error[E0597]: `x` does not live long enough + --> $DIR/regions-escape-loop-via-variable.rs:11:13 + | +LL | let x = 1 + *p; + | -- borrow later used here +LL | p = &x; + | ^^ borrowed value does not live long enough +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/regions-escape-loop-via-vec.rs b/tests/ui/span/regions-escape-loop-via-vec.rs new file mode 100644 index 000000000..1fceb0969 --- /dev/null +++ b/tests/ui/span/regions-escape-loop-via-vec.rs @@ -0,0 +1,13 @@ +// The type of `y` ends up getting inferred to the type of the block. +fn broken() { + let mut x = 3; + let mut _y = vec![&mut x]; + while x < 10 { //~ ERROR cannot use `x` because it was mutably borrowed + let mut z = x; //~ ERROR cannot use `x` because it was mutably borrowed + _y.push(&mut z); + //~^ ERROR `z` does not live long enough + x += 1; //~ ERROR cannot use `x` because it was mutably borrowed + } +} + +fn main() { } diff --git a/tests/ui/span/regions-escape-loop-via-vec.stderr b/tests/ui/span/regions-escape-loop-via-vec.stderr new file mode 100644 index 000000000..2b6493077 --- /dev/null +++ b/tests/ui/span/regions-escape-loop-via-vec.stderr @@ -0,0 +1,50 @@ +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/regions-escape-loop-via-vec.rs:5:11 + | +LL | let mut _y = vec![&mut x]; + | ------ borrow of `x` occurs here +LL | while x < 10 { + | ^ use of borrowed `x` +LL | let mut z = x; +LL | _y.push(&mut z); + | --------------- borrow later used here + +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/regions-escape-loop-via-vec.rs:6:21 + | +LL | let mut _y = vec![&mut x]; + | ------ borrow of `x` occurs here +LL | while x < 10 { +LL | let mut z = x; + | ^ use of borrowed `x` +LL | _y.push(&mut z); + | --------------- borrow later used here + +error[E0597]: `z` does not live long enough + --> $DIR/regions-escape-loop-via-vec.rs:7:17 + | +LL | _y.push(&mut z); + | --------^^^^^^- + | | | + | | borrowed value does not live long enough + | borrow later used here +... +LL | } + | - `z` dropped here while still borrowed + +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/regions-escape-loop-via-vec.rs:9:9 + | +LL | let mut _y = vec![&mut x]; + | ------ borrow of `x` occurs here +... +LL | _y.push(&mut z); + | --------------- borrow later used here +LL | +LL | x += 1; + | ^^^^^^ use of borrowed `x` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0503, E0597. +For more information about an error, try `rustc --explain E0503`. diff --git a/tests/ui/span/regions-infer-borrow-scope-within-loop.rs b/tests/ui/span/regions-infer-borrow-scope-within-loop.rs new file mode 100644 index 000000000..3b20285b1 --- /dev/null +++ b/tests/ui/span/regions-infer-borrow-scope-within-loop.rs @@ -0,0 +1,22 @@ +fn borrow<T>(x: &T) -> &T {x} + +fn foo<C, M>(mut cond: C, mut make_box: M) where + C: FnMut() -> bool, + M: FnMut() -> Box<isize>, +{ + let mut y: &isize; + loop { + let x = make_box(); + + // Here we complain because the resulting region + // of this borrow is the fn body as a whole. + y = borrow(&*x); + //~^ ERROR `*x` does not live long enough + + assert_eq!(*x, *y); + if cond() { break; } + } + assert!(*y != 0); +} + +fn main() {} diff --git a/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr b/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr new file mode 100644 index 000000000..fd67c65c4 --- /dev/null +++ b/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr @@ -0,0 +1,14 @@ +error[E0597]: `*x` does not live long enough + --> $DIR/regions-infer-borrow-scope-within-loop.rs:13:20 + | +LL | y = borrow(&*x); + | ^^^ borrowed value does not live long enough +... +LL | } + | - `*x` dropped here while still borrowed +LL | assert!(*y != 0); + | -- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/send-is-not-static-ensures-scoping.rs b/tests/ui/span/send-is-not-static-ensures-scoping.rs new file mode 100644 index 000000000..2aecc2a7e --- /dev/null +++ b/tests/ui/span/send-is-not-static-ensures-scoping.rs @@ -0,0 +1,26 @@ +struct Guard<'a> { + f: Box<dyn Fn() + Send + 'a>, +} + +fn scoped<'a, F: Fn() + Send + 'a>(f: F) -> Guard<'a> { + Guard { f: Box::new(f) } +} + +impl<'a> Guard<'a> { + fn join(self) {} +} + +fn main() { + let bad = { + let x = 1; + let y = &x; + //~^ ERROR `x` does not live long enough + + scoped(|| { + let _z = y; + //~^ ERROR `y` does not live long enough + }) + }; + + bad.join(); +} diff --git a/tests/ui/span/send-is-not-static-ensures-scoping.stderr b/tests/ui/span/send-is-not-static-ensures-scoping.stderr new file mode 100644 index 000000000..65d10c130 --- /dev/null +++ b/tests/ui/span/send-is-not-static-ensures-scoping.stderr @@ -0,0 +1,29 @@ +error[E0597]: `x` does not live long enough + --> $DIR/send-is-not-static-ensures-scoping.rs:16:17 + | +LL | let bad = { + | --- borrow later stored here +LL | let x = 1; +LL | let y = &x; + | ^^ borrowed value does not live long enough +... +LL | }; + | - `x` dropped here while still borrowed + +error[E0597]: `y` does not live long enough + --> $DIR/send-is-not-static-ensures-scoping.rs:20:22 + | +LL | let bad = { + | --- borrow later stored here +... +LL | scoped(|| { + | -- value captured here +LL | let _z = y; + | ^ borrowed value does not live long enough +... +LL | }; + | - `y` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/send-is-not-static-std-sync-2.rs b/tests/ui/span/send-is-not-static-std-sync-2.rs new file mode 100644 index 000000000..38746d4cb --- /dev/null +++ b/tests/ui/span/send-is-not-static-std-sync-2.rs @@ -0,0 +1,39 @@ +// basic tests to see that certain "obvious" errors are caught by +// these types no longer requiring `'static` (RFC 458) + +#![allow(dead_code)] + +use std::sync::{Mutex, RwLock, mpsc}; + +fn mutex() { + let lock = { + let x = 1; + Mutex::new(&x) + }; + //~^^ ERROR `x` does not live long enough + + let _dangling = *lock.lock().unwrap(); +} + +fn rwlock() { + let lock = { + let x = 1; + RwLock::new(&x) + }; + //~^^ ERROR `x` does not live long enough + let _dangling = *lock.read().unwrap(); +} + +fn channel() { + let (_tx, rx) = { + let x = 1; + let (tx, rx) = mpsc::channel(); + let _ = tx.send(&x); + (tx, rx) + }; + //~^^^ ERROR `x` does not live long enough + + let _dangling = rx.recv(); +} + +fn main() {} diff --git a/tests/ui/span/send-is-not-static-std-sync-2.stderr b/tests/ui/span/send-is-not-static-std-sync-2.stderr new file mode 100644 index 000000000..bcd07e116 --- /dev/null +++ b/tests/ui/span/send-is-not-static-std-sync-2.stderr @@ -0,0 +1,37 @@ +error[E0597]: `x` does not live long enough + --> $DIR/send-is-not-static-std-sync-2.rs:11:20 + | +LL | let lock = { + | ---- borrow later stored here +LL | let x = 1; +LL | Mutex::new(&x) + | ^^ borrowed value does not live long enough +LL | }; + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/send-is-not-static-std-sync-2.rs:21:21 + | +LL | let lock = { + | ---- borrow later stored here +LL | let x = 1; +LL | RwLock::new(&x) + | ^^ borrowed value does not live long enough +LL | }; + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/send-is-not-static-std-sync-2.rs:31:25 + | +LL | let (_tx, rx) = { + | --- borrow later used here +... +LL | let _ = tx.send(&x); + | ^^ borrowed value does not live long enough +LL | (tx, rx) +LL | }; + | - `x` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/send-is-not-static-std-sync.rs b/tests/ui/span/send-is-not-static-std-sync.rs new file mode 100644 index 000000000..f8ab5243c --- /dev/null +++ b/tests/ui/span/send-is-not-static-std-sync.rs @@ -0,0 +1,55 @@ +// basic tests to see that certain "obvious" errors are caught by +// these types no longer requiring `'static` (RFC 458) + +#![allow(dead_code)] + +use std::sync::{Mutex, RwLock, mpsc}; + +fn mutex() { + let x = 1; + let y = Box::new(1); + let lock = Mutex::new(&x); + *lock.lock().unwrap() = &*y; + drop(y); //~ ERROR cannot move out + { + let z = 2; + *lock.lock().unwrap() = &z; + } + //~^^ ERROR `z` does not live long enough + lock.use_ref(); // (Mutex is #[may_dangle] so its dtor does not use `z` => needs explicit use) +} + +fn rwlock() { + let x = 1; + let y = Box::new(1); + let lock = RwLock::new(&x); + *lock.write().unwrap() = &*y; + drop(y); //~ ERROR cannot move out + { + let z = 2; + *lock.write().unwrap() = &z; + } + //~^^ ERROR `z` does not live long enough + lock.use_ref(); // (RwLock is #[may_dangle] so its dtor does not use `z` => needs explicit use) +} + +fn channel() { + let x = 1; + let y = Box::new(1); + let (tx, rx) = mpsc::channel(); + + tx.send(&x).unwrap(); + tx.send(&*y); + drop(y); //~ ERROR cannot move out + { + let z = 2; + tx.send(&z).unwrap(); + } + //~^^ ERROR `z` does not live long enough + // (channels lack #[may_dangle], thus their dtors are implicit uses of `z`) +} + +fn main() {} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl<T> Fake for T { } diff --git a/tests/ui/span/send-is-not-static-std-sync.stderr b/tests/ui/span/send-is-not-static-std-sync.stderr new file mode 100644 index 000000000..5d493a3e4 --- /dev/null +++ b/tests/ui/span/send-is-not-static-std-sync.stderr @@ -0,0 +1,72 @@ +error[E0505]: cannot move out of `y` because it is borrowed + --> $DIR/send-is-not-static-std-sync.rs:13:10 + | +LL | *lock.lock().unwrap() = &*y; + | --- borrow of `*y` occurs here +LL | drop(y); + | ^ move out of `y` occurs here +... +LL | *lock.lock().unwrap() = &z; + | ----------- borrow later used here + +error[E0597]: `z` does not live long enough + --> $DIR/send-is-not-static-std-sync.rs:16:33 + | +LL | *lock.lock().unwrap() = &z; + | ^^ borrowed value does not live long enough +LL | } + | - `z` dropped here while still borrowed +LL | +LL | lock.use_ref(); // (Mutex is #[may_dangle] so its dtor does not use `z` => needs explicit use) + | -------------- borrow later used here + +error[E0505]: cannot move out of `y` because it is borrowed + --> $DIR/send-is-not-static-std-sync.rs:27:10 + | +LL | *lock.write().unwrap() = &*y; + | --- borrow of `*y` occurs here +LL | drop(y); + | ^ move out of `y` occurs here +... +LL | *lock.write().unwrap() = &z; + | ------------ borrow later used here + +error[E0597]: `z` does not live long enough + --> $DIR/send-is-not-static-std-sync.rs:30:34 + | +LL | *lock.write().unwrap() = &z; + | ^^ borrowed value does not live long enough +LL | } + | - `z` dropped here while still borrowed +LL | +LL | lock.use_ref(); // (RwLock is #[may_dangle] so its dtor does not use `z` => needs explicit use) + | -------------- borrow later used here + +error[E0505]: cannot move out of `y` because it is borrowed + --> $DIR/send-is-not-static-std-sync.rs:43:10 + | +LL | tx.send(&*y); + | --- borrow of `*y` occurs here +LL | drop(y); + | ^ move out of `y` occurs here +... +LL | tx.send(&z).unwrap(); + | ----------- borrow later used here + +error[E0597]: `z` does not live long enough + --> $DIR/send-is-not-static-std-sync.rs:46:17 + | +LL | tx.send(&z).unwrap(); + | ^^ borrowed value does not live long enough +LL | } + | - `z` dropped here while still borrowed +... +LL | } + | - borrow might be used here, when `tx` is dropped and runs the `Drop` code for type `Sender` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0505, E0597. +For more information about an error, try `rustc --explain E0505`. diff --git a/tests/ui/span/slice-borrow.rs b/tests/ui/span/slice-borrow.rs new file mode 100644 index 000000000..38cd7acbd --- /dev/null +++ b/tests/ui/span/slice-borrow.rs @@ -0,0 +1,14 @@ +// Test slicing expressions doesn't defeat the borrow checker. + +fn main() { + let y; + { + let x: &[isize] = &vec![1, 2, 3, 4, 5]; + //~^ ERROR temporary value dropped while borrowed + y = &x[1..]; + } + y.use_ref(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl<T> Fake for T { } diff --git a/tests/ui/span/slice-borrow.stderr b/tests/ui/span/slice-borrow.stderr new file mode 100644 index 000000000..b70bf69d6 --- /dev/null +++ b/tests/ui/span/slice-borrow.stderr @@ -0,0 +1,17 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/slice-borrow.rs:6:28 + | +LL | let x: &[isize] = &vec![1, 2, 3, 4, 5]; + | ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use +... +LL | } + | - temporary value is freed at the end of this statement +LL | y.use_ref(); + | ----------- borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + = note: this error originates in the macro `vec` (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 E0716`. diff --git a/tests/ui/span/suggestion-non-ascii.rs b/tests/ui/span/suggestion-non-ascii.rs new file mode 100644 index 000000000..914efd85a --- /dev/null +++ b/tests/ui/span/suggestion-non-ascii.rs @@ -0,0 +1,4 @@ +fn main() { + let tup = (1,); + println!("☃{}", tup[0]); //~ ERROR cannot index into a value of type +} diff --git a/tests/ui/span/suggestion-non-ascii.stderr b/tests/ui/span/suggestion-non-ascii.stderr new file mode 100644 index 000000000..b14632d4e --- /dev/null +++ b/tests/ui/span/suggestion-non-ascii.stderr @@ -0,0 +1,9 @@ +error[E0608]: cannot index into a value of type `({integer},)` + --> $DIR/suggestion-non-ascii.rs:3:21 + | +LL | println!("☃{}", tup[0]); + | ^^^^^^ help: to access tuple elements, use: `tup.0` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0608`. diff --git a/tests/ui/span/transitive-dep-span.rs b/tests/ui/span/transitive-dep-span.rs new file mode 100644 index 000000000..2d46f74ad --- /dev/null +++ b/tests/ui/span/transitive-dep-span.rs @@ -0,0 +1,15 @@ +// Tests that we properly serialize/deserialize spans from transitive dependencies +// (e.g. imported SourceFiles) +// +// The order of these next lines is important, since we need +// transitive_dep_two.rs to be able to reference transitive_dep_three.rs +// +// aux-build: transitive_dep_three.rs +// aux-build: transitive_dep_two.rs +// compile-flags: -Z macro-backtrace + +extern crate transitive_dep_two; + +transitive_dep_two::parse_error!(); //~ ERROR expected one of + +fn main() {} diff --git a/tests/ui/span/transitive-dep-span.stderr b/tests/ui/span/transitive-dep-span.stderr new file mode 100644 index 000000000..4dc3e5721 --- /dev/null +++ b/tests/ui/span/transitive-dep-span.stderr @@ -0,0 +1,18 @@ +error: expected one of `!` or `::`, found `error` + --> $DIR/auxiliary/transitive_dep_three.rs:6:27 + | +LL | macro_rules! parse_error { + | ------------------------ in this expansion of `transitive_dep_two::parse_error!` +LL | () => { parse error } + | ^^^^^ expected one of `!` or `::` + | + ::: $DIR/transitive-dep-span.rs:13:1 + | +LL | transitive_dep_two::parse_error!(); + | ---------------------------------- + | | + | in this macro invocation + | in this macro invocation + +error: aborting due to previous error + diff --git a/tests/ui/span/type-annotations-needed-expr.rs b/tests/ui/span/type-annotations-needed-expr.rs new file mode 100644 index 000000000..f64dab4d7 --- /dev/null +++ b/tests/ui/span/type-annotations-needed-expr.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = (vec![1,2,3]).into_iter().sum() as f64; //~ ERROR E0282 +} diff --git a/tests/ui/span/type-annotations-needed-expr.stderr b/tests/ui/span/type-annotations-needed-expr.stderr new file mode 100644 index 000000000..9dff6c64d --- /dev/null +++ b/tests/ui/span/type-annotations-needed-expr.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/type-annotations-needed-expr.rs:2:39 + | +LL | let _ = (vec![1,2,3]).into_iter().sum() as f64; + | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` + | +help: consider specifying the generic argument + | +LL | let _ = (vec![1,2,3]).into_iter().sum::<S>() as f64; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/span/type-binding.rs b/tests/ui/span/type-binding.rs new file mode 100644 index 000000000..32016e127 --- /dev/null +++ b/tests/ui/span/type-binding.rs @@ -0,0 +1,9 @@ +// Regression test for issue #28158 +// Test the type binding span doesn't include >> + +use std::ops::Deref; + +fn homura<T: Deref<Trget = i32>>(_: T) {} +//~^ ERROR not found + +fn main() {} diff --git a/tests/ui/span/type-binding.stderr b/tests/ui/span/type-binding.stderr new file mode 100644 index 000000000..cb0aefe06 --- /dev/null +++ b/tests/ui/span/type-binding.stderr @@ -0,0 +1,9 @@ +error[E0220]: associated type `Trget` not found for `Deref` + --> $DIR/type-binding.rs:6:20 + | +LL | fn homura<T: Deref<Trget = i32>>(_: T) {} + | ^^^^^ help: there is an associated type with a similar name: `Target` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/span/typo-suggestion.rs b/tests/ui/span/typo-suggestion.rs new file mode 100644 index 000000000..e9d7bc65e --- /dev/null +++ b/tests/ui/span/typo-suggestion.rs @@ -0,0 +1,9 @@ +fn main() { + let foo = 1; + + // `foo` shouldn't be suggested, it is too dissimilar from `bar`. + println!("Hello {}", bar); //~ ERROR cannot find value + + // But this is close enough. + println!("Hello {}", fob); //~ ERROR cannot find value +} diff --git a/tests/ui/span/typo-suggestion.stderr b/tests/ui/span/typo-suggestion.stderr new file mode 100644 index 000000000..61d4e0611 --- /dev/null +++ b/tests/ui/span/typo-suggestion.stderr @@ -0,0 +1,15 @@ +error[E0425]: cannot find value `bar` in this scope + --> $DIR/typo-suggestion.rs:5:26 + | +LL | println!("Hello {}", bar); + | ^^^ not found in this scope + +error[E0425]: cannot find value `fob` in this scope + --> $DIR/typo-suggestion.rs:8:26 + | +LL | println!("Hello {}", fob); + | ^^^ help: a local variable with a similar name exists: `foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/span/unused-warning-point-at-identifier.rs b/tests/ui/span/unused-warning-point-at-identifier.rs new file mode 100644 index 000000000..af4834503 --- /dev/null +++ b/tests/ui/span/unused-warning-point-at-identifier.rs @@ -0,0 +1,30 @@ +// run-pass + +#![warn(unused)] + +enum Enum { //~ WARN enum `Enum` is never used + A, + B, + C, + D, +} + +struct Struct { //~ WARN struct `Struct` is never constructed + a: usize, + b: usize, + c: usize, + d: usize, +} + +fn func() -> usize { //~ WARN function `func` is never used + 3 +} + +fn +func_complete_span() //~ WARN function `func_complete_span` is never used +-> usize +{ + 3 +} + +fn main() {} diff --git a/tests/ui/span/unused-warning-point-at-identifier.stderr b/tests/ui/span/unused-warning-point-at-identifier.stderr new file mode 100644 index 000000000..c2cb56231 --- /dev/null +++ b/tests/ui/span/unused-warning-point-at-identifier.stderr @@ -0,0 +1,33 @@ +warning: enum `Enum` is never used + --> $DIR/unused-warning-point-at-identifier.rs:5:6 + | +LL | enum Enum { + | ^^^^ + | +note: the lint level is defined here + --> $DIR/unused-warning-point-at-identifier.rs:3:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(dead_code)]` implied by `#[warn(unused)]` + +warning: struct `Struct` is never constructed + --> $DIR/unused-warning-point-at-identifier.rs:12:8 + | +LL | struct Struct { + | ^^^^^^ + +warning: function `func` is never used + --> $DIR/unused-warning-point-at-identifier.rs:19:4 + | +LL | fn func() -> usize { + | ^^^^ + +warning: function `func_complete_span` is never used + --> $DIR/unused-warning-point-at-identifier.rs:24:1 + | +LL | func_complete_span() + | ^^^^^^^^^^^^^^^^^^ + +warning: 4 warnings emitted + diff --git a/tests/ui/span/vec-must-not-hide-type-from-dropck.rs b/tests/ui/span/vec-must-not-hide-type-from-dropck.rs new file mode 100644 index 000000000..9bfbfab06 --- /dev/null +++ b/tests/ui/span/vec-must-not-hide-type-from-dropck.rs @@ -0,0 +1,125 @@ +// Checking that `Vec<T>` cannot hide lifetimes within `T` when `T` +// implements `Drop` and might access methods of values that have +// since been deallocated. +// +// In this case, the values in question hold (non-zero) unique-ids +// that zero themselves out when dropped, and are wrapped in another +// type with a destructor that asserts that the ids it references are +// indeed non-zero (i.e., effectively checking that the id's are not +// dropped while there are still any outstanding references). +// +// However, the values in question are also formed into a +// cyclic-structure, ensuring that there is no way for all of the +// conditions above to be satisfied, meaning that if the dropck is +// sound, it should reject this code. + + + +use std::cell::Cell; +use id::Id; + +mod s { + use std::sync::atomic::{AtomicUsize, Ordering}; + + static S_COUNT: AtomicUsize = AtomicUsize::new(0); + + /// generates globally unique count (global across the current + /// process, that is) + pub fn next_count() -> usize { + S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 + } +} + +mod id { + use s; + + /// Id represents a globally unique identifier (global across the + /// current process, that is). When dropped, it automatically + /// clears its `count` field, but leaves `orig_count` untouched, + /// so that if there are subsequent (erroneous) invocations of its + /// method (which is unsound), we can observe it by seeing that + /// the `count` is 0 while the `orig_count` is non-zero. + #[derive(Debug)] + pub struct Id { + orig_count: usize, + count: usize, + } + + impl Id { + /// Creates an `Id` with a globally unique count. + pub fn new() -> Id { + let c = s::next_count(); + println!("building Id {}", c); + Id { orig_count: c, count: c } + } + /// returns the `count` of self; should be non-zero if + /// everything is working. + pub fn count(&self) -> usize { + println!("Id::count on {} returns {}", self.orig_count, self.count); + self.count + } + } + + impl Drop for Id { + fn drop(&mut self) { + println!("dropping Id {}", self.count); + self.count = 0; + } + } +} + +trait HasId { + fn count(&self) -> usize; +} + +#[derive(Debug)] +struct CheckId<T:HasId> { + v: T +} + +#[allow(non_snake_case)] +fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } } + +impl<T:HasId> Drop for CheckId<T> { + fn drop(&mut self) { + assert!(self.v.count() > 0); + } +} + +#[derive(Debug)] +struct C<'a> { + id: Id, + v: Vec<CheckId<Cell<Option<&'a C<'a>>>>>, +} + +impl<'a> HasId for Cell<Option<&'a C<'a>>> { + fn count(&self) -> usize { + match self.get() { + None => 1, + Some(c) => c.id.count(), + } + } +} + +impl<'a> C<'a> { + fn new() -> C<'a> { + C { id: Id::new(), v: Vec::new() } + } +} + +fn f() { + let (mut c1, mut c2); + c1 = C::new(); + c2 = C::new(); + + c1.v.push(CheckId(Cell::new(None))); + c2.v.push(CheckId(Cell::new(None))); + c1.v[0].v.set(Some(&c2)); + //~^ ERROR `c2` does not live long enough + c2.v[0].v.set(Some(&c1)); + //~^ ERROR `c1` does not live long enough +} + +fn main() { + f(); +} diff --git a/tests/ui/span/vec-must-not-hide-type-from-dropck.stderr b/tests/ui/span/vec-must-not-hide-type-from-dropck.stderr new file mode 100644 index 000000000..f87c32d1a --- /dev/null +++ b/tests/ui/span/vec-must-not-hide-type-from-dropck.stderr @@ -0,0 +1,29 @@ +error[E0597]: `c2` does not live long enough + --> $DIR/vec-must-not-hide-type-from-dropck.rs:117:24 + | +LL | c1.v[0].v.set(Some(&c2)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `c2` dropped here while still borrowed + | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `c1` does not live long enough + --> $DIR/vec-must-not-hide-type-from-dropck.rs:119:24 + | +LL | c2.v[0].v.set(Some(&c1)); + | ^^^ borrowed value does not live long enough +LL | +LL | } + | - + | | + | `c1` dropped here while still borrowed + | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/vec_refs_data_with_early_death.rs b/tests/ui/span/vec_refs_data_with_early_death.rs new file mode 100644 index 000000000..c23c52115 --- /dev/null +++ b/tests/ui/span/vec_refs_data_with_early_death.rs @@ -0,0 +1,33 @@ +// This test is a simple example of code that violates the dropck +// rules: it pushes `&x` and `&y` into a bag (with dtor), but the +// referenced data will be dropped before the bag is. + + + + + + + +fn main() { + let mut v = Bag::new(); + + let x: i8 = 3; + let y: i8 = 4; + + v.push(&x); + //~^ ERROR `x` does not live long enough + v.push(&y); + //~^ ERROR `y` does not live long enough + + assert_eq!(v.0, [&3, &4]); +} + +//`Vec<T>` is #[may_dangle] w.r.t. `T`; putting a bag over its head +// forces borrowck to treat dropping the bag as a potential use. +struct Bag<T>(Vec<T>); +impl<T> Drop for Bag<T> { fn drop(&mut self) { } } + +impl<T> Bag<T> { + fn new() -> Self { Bag(Vec::new()) } + fn push(&mut self, t: T) { self.0.push(t); } +} diff --git a/tests/ui/span/vec_refs_data_with_early_death.stderr b/tests/ui/span/vec_refs_data_with_early_death.stderr new file mode 100644 index 000000000..684e78453 --- /dev/null +++ b/tests/ui/span/vec_refs_data_with_early_death.stderr @@ -0,0 +1,31 @@ +error[E0597]: `x` does not live long enough + --> $DIR/vec_refs_data_with_early_death.rs:17:12 + | +LL | v.push(&x); + | ^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `x` dropped here while still borrowed + | borrow might be used here, when `v` is dropped and runs the `Drop` code for type `Bag` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `y` does not live long enough + --> $DIR/vec_refs_data_with_early_death.rs:19:12 + | +LL | v.push(&y); + | ^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `y` dropped here while still borrowed + | borrow might be used here, when `v` is dropped and runs the `Drop` code for type `Bag` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/visibility-ty-params.rs b/tests/ui/span/visibility-ty-params.rs new file mode 100644 index 000000000..d77febe0a --- /dev/null +++ b/tests/ui/span/visibility-ty-params.rs @@ -0,0 +1,13 @@ +macro_rules! m { + ($p: path) => (pub(in $p) struct Z;) +} + +struct S<T>(T); +m!{ S<u8> } //~ ERROR unexpected generic arguments in path + //~| ERROR expected module, found struct `S` + +mod m { + m!{ m<> } //~ ERROR unexpected generic arguments in path +} + +fn main() {} diff --git a/tests/ui/span/visibility-ty-params.stderr b/tests/ui/span/visibility-ty-params.stderr new file mode 100644 index 000000000..067893fd2 --- /dev/null +++ b/tests/ui/span/visibility-ty-params.stderr @@ -0,0 +1,21 @@ +error: unexpected generic arguments in path + --> $DIR/visibility-ty-params.rs:6:6 + | +LL | m!{ S<u8> } + | ^^^^ + +error[E0577]: expected module, found struct `S` + --> $DIR/visibility-ty-params.rs:6:5 + | +LL | m!{ S<u8> } + | ^^^^^ not a module + +error: unexpected generic arguments in path + --> $DIR/visibility-ty-params.rs:10:10 + | +LL | m!{ m<> } + | ^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0577`. diff --git a/tests/ui/span/wf-method-late-bound-regions.rs b/tests/ui/span/wf-method-late-bound-regions.rs new file mode 100644 index 000000000..ca9f73d0a --- /dev/null +++ b/tests/ui/span/wf-method-late-bound-regions.rs @@ -0,0 +1,24 @@ +// A method's receiver must be well-formed, even if it has late-bound regions. +// Because of this, a method's substs being well-formed does not imply that +// the method's implied bounds are met. + +struct Foo<'b>(Option<&'b ()>); + +trait Bar<'b> { + fn xmute<'a>(&'a self, u: &'b u32) -> &'a u32; +} + +impl<'b> Bar<'b> for Foo<'b> { + fn xmute<'a>(&'a self, u: &'b u32) -> &'a u32 { u } +} + +fn main() { + let f = Foo(None); + let f2 = f; + let dangling = { + let pointer = Box::new(42); + f2.xmute(&pointer) + }; + //~^^ ERROR `pointer` does not live long enough + println!("{}", dangling); +} diff --git a/tests/ui/span/wf-method-late-bound-regions.stderr b/tests/ui/span/wf-method-late-bound-regions.stderr new file mode 100644 index 000000000..6b0b00820 --- /dev/null +++ b/tests/ui/span/wf-method-late-bound-regions.stderr @@ -0,0 +1,14 @@ +error[E0597]: `pointer` does not live long enough + --> $DIR/wf-method-late-bound-regions.rs:20:18 + | +LL | let dangling = { + | -------- borrow later stored here +LL | let pointer = Box::new(42); +LL | f2.xmute(&pointer) + | ^^^^^^^^ borrowed value does not live long enough +LL | }; + | - `pointer` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. |