diff options
Diffstat (limited to '')
37 files changed, 1084 insertions, 315 deletions
diff --git a/tests/ui/lint/clashing-extern-fn.stderr b/tests/ui/lint/clashing-extern-fn.stderr index 5d457ba0e..0d269e599 100644 --- a/tests/ui/lint/clashing-extern-fn.stderr +++ b/tests/ui/lint/clashing-extern-fn.stderr @@ -1,11 +1,30 @@ +warning: `extern` block uses type `Option<TransparentNoNiche>`, which is not FFI-safe + --> $DIR/clashing-extern-fn.rs:433:55 + | +LL | fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + = note: `#[warn(improper_ctypes)]` on by default + +warning: `extern` block uses type `Option<UnsafeCell<NonZeroUsize>>`, which is not FFI-safe + --> $DIR/clashing-extern-fn.rs:437:46 + | +LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + warning: `clash` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:14:13 | LL | fn clash(x: u8); - | ---------------- `clash` previously declared here + | --------------- `clash` previously declared here ... LL | fn clash(x: u64); - | ^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(u8)` found `unsafe extern "C" fn(u64)` @@ -18,12 +37,11 @@ LL | #![warn(clashing_extern_declarations)] warning: `extern_link_name` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:52:9 | -LL | / #[link_name = "extern_link_name"] -LL | | fn some_new_name(x: i16); - | |_____________________________- `extern_link_name` previously declared here +LL | #[link_name = "extern_link_name"] + | --------------------------------- `extern_link_name` previously declared here ... -LL | fn extern_link_name(x: u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration +LL | fn extern_link_name(x: u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(i16)` found `unsafe extern "C" fn(u32)` @@ -31,13 +49,11 @@ LL | fn extern_link_name(x: u32); warning: `some_other_extern_link_name` redeclares `some_other_new_name` with a different signature --> $DIR/clashing-extern-fn.rs:55:9 | -LL | fn some_other_new_name(x: i16); - | ------------------------------- `some_other_new_name` previously declared here +LL | fn some_other_new_name(x: i16); + | ------------------------------ `some_other_new_name` previously declared here ... -LL | / #[link_name = "some_other_new_name"] -LL | | -LL | | fn some_other_extern_link_name(x: u32); - | |_______________________________________________^ this signature doesn't match the previous declaration +LL | #[link_name = "some_other_new_name"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(i16)` found `unsafe extern "C" fn(u32)` @@ -45,14 +61,11 @@ LL | | fn some_other_extern_link_name(x: u32); warning: `other_both_names_different` redeclares `link_name_same` with a different signature --> $DIR/clashing-extern-fn.rs:59:9 | -LL | / #[link_name = "link_name_same"] -LL | | fn both_names_different(x: i16); - | |____________________________________- `link_name_same` previously declared here +LL | #[link_name = "link_name_same"] + | ------------------------------- `link_name_same` previously declared here ... -LL | / #[link_name = "link_name_same"] -LL | | -LL | | fn other_both_names_different(x: u32); - | |______________________________________________^ this signature doesn't match the previous declaration +LL | #[link_name = "link_name_same"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(i16)` found `unsafe extern "C" fn(u32)` @@ -61,10 +74,10 @@ warning: `different_mod` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:72:9 | LL | fn different_mod(x: u8); - | ------------------------ `different_mod` previously declared here + | ----------------------- `different_mod` previously declared here ... LL | fn different_mod(x: u64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(u8)` found `unsafe extern "C" fn(u64)` @@ -73,10 +86,10 @@ warning: `variadic_decl` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:82:9 | LL | fn variadic_decl(x: u8, ...); - | ----------------------------- `variadic_decl` previously declared here + | ---------------------------- `variadic_decl` previously declared here ... LL | fn variadic_decl(x: u8); - | ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(u8, ...)` found `unsafe extern "C" fn(u8)` @@ -85,10 +98,10 @@ warning: `weigh_banana` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:142:13 | LL | fn weigh_banana(count: *const Banana) -> u64; - | --------------------------------------------- `weigh_banana` previously declared here + | -------------------------------------------- `weigh_banana` previously declared here ... LL | fn weigh_banana(count: *const Banana) -> u64; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(*const one::Banana) -> u64` found `unsafe extern "C" fn(*const three::Banana) -> u64` @@ -97,10 +110,10 @@ warning: `draw_point` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:171:13 | LL | fn draw_point(p: Point); - | ------------------------ `draw_point` previously declared here + | ----------------------- `draw_point` previously declared here ... LL | fn draw_point(p: Point); - | ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(sameish_members::a::Point)` found `unsafe extern "C" fn(sameish_members::b::Point)` @@ -109,10 +122,10 @@ warning: `origin` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:197:13 | LL | fn origin() -> Point3; - | ---------------------- `origin` previously declared here + | --------------------- `origin` previously declared here ... LL | fn origin() -> Point3; - | ^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> same_sized_members_clash::a::Point3` found `unsafe extern "C" fn() -> same_sized_members_clash::b::Point3` @@ -121,10 +134,10 @@ warning: `transparent_incorrect` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:220:13 | LL | fn transparent_incorrect() -> T; - | -------------------------------- `transparent_incorrect` previously declared here + | ------------------------------- `transparent_incorrect` previously declared here ... LL | fn transparent_incorrect() -> isize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> T` found `unsafe extern "C" fn() -> isize` @@ -133,10 +146,10 @@ warning: `missing_return_type` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:259:13 | LL | fn missing_return_type() -> usize; - | ---------------------------------- `missing_return_type` previously declared here + | --------------------------------- `missing_return_type` previously declared here ... LL | fn missing_return_type(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> usize` found `unsafe extern "C" fn()` @@ -145,10 +158,10 @@ warning: `non_zero_usize` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:277:13 | LL | fn non_zero_usize() -> core::num::NonZeroUsize; - | ----------------------------------------------- `non_zero_usize` previously declared here + | ---------------------------------------------- `non_zero_usize` previously declared here ... LL | fn non_zero_usize() -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> NonZeroUsize` found `unsafe extern "C" fn() -> usize` @@ -157,10 +170,10 @@ warning: `non_null_ptr` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:279:13 | LL | fn non_null_ptr() -> core::ptr::NonNull<usize>; - | ----------------------------------------------- `non_null_ptr` previously declared here + | ---------------------------------------------- `non_null_ptr` previously declared here ... LL | fn non_null_ptr() -> *const usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> NonNull<usize>` found `unsafe extern "C" fn() -> *const usize` @@ -169,10 +182,10 @@ warning: `option_non_zero_usize_incorrect` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:377:13 | LL | fn option_non_zero_usize_incorrect() -> usize; - | ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here + | --------------------------------------------- `option_non_zero_usize_incorrect` previously declared here ... LL | fn option_non_zero_usize_incorrect() -> isize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> usize` found `unsafe extern "C" fn() -> isize` @@ -181,10 +194,10 @@ warning: `option_non_null_ptr_incorrect` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:379:13 | LL | fn option_non_null_ptr_incorrect() -> *const usize; - | --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here + | -------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here ... LL | fn option_non_null_ptr_incorrect() -> *const isize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> *const usize` found `unsafe extern "C" fn() -> *const isize` @@ -193,10 +206,10 @@ warning: `hidden_niche_transparent_no_niche` redeclared with a different signatu --> $DIR/clashing-extern-fn.rs:433:13 | LL | fn hidden_niche_transparent_no_niche() -> usize; - | ------------------------------------------------ `hidden_niche_transparent_no_niche` previously declared here + | ----------------------------------------------- `hidden_niche_transparent_no_niche` previously declared here ... LL | fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> usize` found `unsafe extern "C" fn() -> Option<TransparentNoNiche>` @@ -205,32 +218,13 @@ warning: `hidden_niche_unsafe_cell` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:437:13 | LL | fn hidden_niche_unsafe_cell() -> usize; - | --------------------------------------- `hidden_niche_unsafe_cell` previously declared here + | -------------------------------------- `hidden_niche_unsafe_cell` previously declared here ... LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize>>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> usize` found `unsafe extern "C" fn() -> Option<UnsafeCell<NonZeroUsize>>` -warning: `extern` block uses type `Option<TransparentNoNiche>`, which is not FFI-safe - --> $DIR/clashing-extern-fn.rs:433:55 - | -LL | fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe - | - = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum - = note: enum has no representation hint - = note: `#[warn(improper_ctypes)]` on by default - -warning: `extern` block uses type `Option<UnsafeCell<NonZeroUsize>>`, which is not FFI-safe - --> $DIR/clashing-extern-fn.rs:437:46 - | -LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize>>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe - | - = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum - = note: enum has no representation hint - warning: 19 warnings emitted diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.rs b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.rs new file mode 100644 index 000000000..b71bcd0fa --- /dev/null +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.rs @@ -0,0 +1,19 @@ +// check-pass + +// this test checks that the `dead_code` lint is *NOT* being emited +// for `foo` as `foo` is being used by `main`, and so the `#[expect]` +// is unfulfilled +// +// it also checks that the `dead_code` lint is also *NOT* emited +// for `bar` as it's suppresed by the `#[expect]` on `bar` + +#![feature(lint_reasons)] +#![warn(dead_code)] // to override compiletest + +fn bar() {} + +#[expect(dead_code)] +//~^ WARN this lint expectation is unfulfilled +fn foo() { bar() } + +fn main() { foo() } diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.stderr b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.stderr new file mode 100644 index 000000000..d5c4dabed --- /dev/null +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.stderr @@ -0,0 +1,10 @@ +warning: this lint expectation is unfulfilled + --> $DIR/allow-or-expect-dead_code-114557-2.rs:15:10 + | +LL | #[expect(dead_code)] + | ^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.rs b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.rs new file mode 100644 index 000000000..f8a5d31a0 --- /dev/null +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.rs @@ -0,0 +1,13 @@ +// check-pass + +// this test makes sure that the `unfulfilled_lint_expectations` lint +// is being emited for `foo` as foo is not dead code, it's pub + +#![feature(lint_reasons)] +#![warn(dead_code)] // to override compiletest + +#[expect(dead_code)] +//~^ WARN this lint expectation is unfulfilled +pub fn foo() {} + +fn main() {} diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.stderr b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.stderr new file mode 100644 index 000000000..c954a75b3 --- /dev/null +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.stderr @@ -0,0 +1,10 @@ +warning: this lint expectation is unfulfilled + --> $DIR/allow-or-expect-dead_code-114557-3.rs:9:10 + | +LL | #[expect(dead_code)] + | ^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557.rs b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557.rs new file mode 100644 index 000000000..24fafa3d1 --- /dev/null +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557.rs @@ -0,0 +1,18 @@ +// check-pass +// revisions: allow expect + +// this test checks that no matter if we put #[allow(dead_code)] +// or #[expect(dead_code)], no warning is being emited + +#![feature(lint_reasons)] +#![warn(dead_code)] // to override compiletest + +fn f() {} + +#[cfg_attr(allow, allow(dead_code))] +#[cfg_attr(expect, expect(dead_code))] +fn g() { + f(); +} + +fn main() {} diff --git a/tests/ui/lint/invalid-nan-comparison.stderr b/tests/ui/lint/invalid-nan-comparison.stderr index 054c06d38..f2d55c107 100644 --- a/tests/ui/lint/invalid-nan-comparison.stderr +++ b/tests/ui/lint/invalid-nan-comparison.stderr @@ -5,11 +5,6 @@ LL | const TEST: bool = 5f32 == f32::NAN; | ^^^^^^^^^^^^^^^^ | = note: `#[warn(invalid_nan_comparisons)]` on by default -help: use `f32::is_nan()` or `f64::is_nan()` instead - | -LL - const TEST: bool = 5f32 == f32::NAN; -LL + const TEST: bool = 5f32.is_nan(); - | warning: incorrect NaN comparison, NaN cannot be directly compared to itself --> $DIR/invalid-nan-comparison.rs:14:5 diff --git a/tests/ui/lint/issue-111359.stderr b/tests/ui/lint/issue-111359.stderr index 2296d8413..0aef5007a 100644 --- a/tests/ui/lint/issue-111359.stderr +++ b/tests/ui/lint/issue-111359.stderr @@ -1,26 +1,26 @@ -error: type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation +error: type could implement `Copy`; consider adding `impl Copy` --> $DIR/issue-111359.rs:7:5 | LL | pub struct BarPub; | ^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/issue-111359.rs:1:8 + --> $DIR/issue-111359.rs:2:8 | -LL | #[deny(missing_debug_implementations)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[deny(missing_copy_implementations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: type could implement `Copy`; consider adding `impl Copy` +error: type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation --> $DIR/issue-111359.rs:7:5 | LL | pub struct BarPub; | ^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/issue-111359.rs:2:8 + --> $DIR/issue-111359.rs:1:8 | -LL | #[deny(missing_copy_implementations)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[deny(missing_debug_implementations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/lint/issue-1866.stderr b/tests/ui/lint/issue-1866.stderr index d19a13496..36d323825 100644 --- a/tests/ui/lint/issue-1866.stderr +++ b/tests/ui/lint/issue-1866.stderr @@ -2,10 +2,10 @@ warning: `rust_task_is_unwinding` redeclared with a different signature --> $DIR/issue-1866.rs:23:13 | LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool; - | ------------------------------------------------------------ `rust_task_is_unwinding` previously declared here + | ----------------------------------------------------------- `rust_task_is_unwinding` previously declared here ... LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn(*const usize) -> bool` found `unsafe extern "C" fn(*const bool) -> bool` diff --git a/tests/ui/lint/lint-attr-everywhere-late.stderr b/tests/ui/lint/lint-attr-everywhere-late.stderr index 9587556b0..7fe078068 100644 --- a/tests/ui/lint/lint-attr-everywhere-late.stderr +++ b/tests/ui/lint/lint-attr-everywhere-late.stderr @@ -34,12 +34,6 @@ note: the lint level is defined here LL | #![deny(missing_docs)] | ^^^^^^^^^^^^ -error: missing documentation for a function - --> $DIR/lint-attr-everywhere-late.rs:47:5 - | -LL | pub fn missing_inner() {} - | ^^^^^^^^^^^^^^^^^^^^^^ - error: missing documentation for an associated function --> $DIR/lint-attr-everywhere-late.rs:54:5 | @@ -142,52 +136,6 @@ note: the lint level is defined here LL | #[deny(missing_docs)] | ^^^^^^^^^^^^ -error: missing documentation for a variant - --> $DIR/lint-attr-everywhere-late.rs:112:5 - | -LL | Variant1, - | ^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/lint-attr-everywhere-late.rs:111:12 - | -LL | #[deny(missing_docs)] - | ^^^^^^^^^^^^ - -error: `clashing1` redeclared with a different signature - --> $DIR/lint-attr-everywhere-late.rs:123:5 - | -LL | fn clashing1(); - | --------------- `clashing1` previously declared here -... -LL | fn clashing1(_: i32); - | ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration - | - = note: expected `unsafe extern "C" fn()` - found `unsafe extern "C" fn(i32)` -note: the lint level is defined here - --> $DIR/lint-attr-everywhere-late.rs:122:13 - | -LL | #![deny(clashing_extern_declarations)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: `clashing2` redeclared with a different signature - --> $DIR/lint-attr-everywhere-late.rs:128:5 - | -LL | fn clashing2(); - | --------------- `clashing2` previously declared here -... -LL | fn clashing2(_: i32); - | ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration - | - = note: expected `unsafe extern "C" fn()` - found `unsafe extern "C" fn(i32)` -note: the lint level is defined here - --> $DIR/lint-attr-everywhere-late.rs:127:12 - | -LL | #[deny(clashing_extern_declarations)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped --> $DIR/lint-attr-everywhere-late.rs:93:38 | @@ -230,6 +178,18 @@ note: the lint level is defined here LL | #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000; | ^^^^^^^^^^^^^^^^^^^^ +error: missing documentation for a variant + --> $DIR/lint-attr-everywhere-late.rs:112:5 + | +LL | Variant1, + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:111:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + error: variable `PARAM` should have a snake case name --> $DIR/lint-attr-everywhere-late.rs:131:37 | @@ -436,5 +396,45 @@ note: the lint level is defined here LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^ +error: missing documentation for a function + --> $DIR/lint-attr-everywhere-late.rs:47:5 + | +LL | pub fn missing_inner() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: `clashing1` redeclared with a different signature + --> $DIR/lint-attr-everywhere-late.rs:123:5 + | +LL | fn clashing1(); + | -------------- `clashing1` previously declared here +... +LL | fn clashing1(_: i32); + | ^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn()` + found `unsafe extern "C" fn(i32)` +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:122:13 + | +LL | #![deny(clashing_extern_declarations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `clashing2` redeclared with a different signature + --> $DIR/lint-attr-everywhere-late.rs:128:5 + | +LL | fn clashing2(); + | -------------- `clashing2` previously declared here +... +LL | fn clashing2(_: i32); + | ^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn()` + found `unsafe extern "C" fn(i32)` +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:127:12 + | +LL | #[deny(clashing_extern_declarations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 32 previous errors diff --git a/tests/ui/lint/lint-cap-trait-bounds.rs b/tests/ui/lint/lint-cap-trait-bounds.rs new file mode 100644 index 000000000..d9c28dd0a --- /dev/null +++ b/tests/ui/lint/lint-cap-trait-bounds.rs @@ -0,0 +1,8 @@ +// Regression test for https://github.com/rust-lang/rust/issues/43134 + +// check-pass +// compile-flags: --cap-lints allow + +type Foo<T: Clone> = Option<T>; + +fn main() {} diff --git a/tests/ui/lint/lint-missing-doc.stderr b/tests/ui/lint/lint-missing-doc.stderr index adcc21c44..4e9ee4f27 100644 --- a/tests/ui/lint/lint-missing-doc.stderr +++ b/tests/ui/lint/lint-missing-doc.stderr @@ -113,24 +113,6 @@ LL | pub static BAR4: u32 = 0; | ^^^^^^^^^^^^^^^^^^^^ error: missing documentation for a function - --> $DIR/lint-missing-doc.rs:174:5 - | -LL | pub fn undocumented1() {} - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: missing documentation for a function - --> $DIR/lint-missing-doc.rs:175:5 - | -LL | pub fn undocumented2() {} - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: missing documentation for a function - --> $DIR/lint-missing-doc.rs:181:9 - | -LL | pub fn also_undocumented1() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: missing documentation for a function --> $DIR/lint-missing-doc.rs:196:5 | LL | pub fn extern_fn_undocumented(f: f32) -> f32; @@ -154,5 +136,23 @@ error: missing documentation for a trait alias LL | pub trait T = Sync; | ^^^^^^^^^^^ +error: missing documentation for a function + --> $DIR/lint-missing-doc.rs:174:5 + | +LL | pub fn undocumented1() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a function + --> $DIR/lint-missing-doc.rs:175:5 + | +LL | pub fn undocumented2() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a function + --> $DIR/lint-missing-doc.rs:181:9 + | +LL | pub fn also_undocumented1() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 25 previous errors diff --git a/tests/ui/lint/lint-qualification.fixed b/tests/ui/lint/lint-qualification.fixed new file mode 100644 index 000000000..c14493013 --- /dev/null +++ b/tests/ui/lint/lint-qualification.fixed @@ -0,0 +1,21 @@ +// run-rustfix +#![deny(unused_qualifications)] +#![allow(deprecated)] + +mod foo { + pub fn bar() {} +} + +fn main() { + use foo::bar; + bar(); //~ ERROR: unnecessary qualification + bar(); + + let _ = || -> Result<(), ()> { try!(Ok(())); Ok(()) }; // issue #37345 + + macro_rules! m { () => { + $crate::foo::bar(); // issue #37357 + ::foo::bar(); // issue #38682 + } } + m!(); +} diff --git a/tests/ui/lint/lint-qualification.rs b/tests/ui/lint/lint-qualification.rs index 0cace0ca0..809043035 100644 --- a/tests/ui/lint/lint-qualification.rs +++ b/tests/ui/lint/lint-qualification.rs @@ -1,3 +1,4 @@ +// run-rustfix #![deny(unused_qualifications)] #![allow(deprecated)] diff --git a/tests/ui/lint/lint-qualification.stderr b/tests/ui/lint/lint-qualification.stderr index 149a782d9..90a06bc6c 100644 --- a/tests/ui/lint/lint-qualification.stderr +++ b/tests/ui/lint/lint-qualification.stderr @@ -1,14 +1,19 @@ error: unnecessary qualification - --> $DIR/lint-qualification.rs:10:5 + --> $DIR/lint-qualification.rs:11:5 | LL | foo::bar(); | ^^^^^^^^ | note: the lint level is defined here - --> $DIR/lint-qualification.rs:1:9 + --> $DIR/lint-qualification.rs:2:9 | LL | #![deny(unused_qualifications)] | ^^^^^^^^^^^^^^^^^^^^^ +help: remove the unnecessary path segments + | +LL - foo::bar(); +LL + bar(); + | error: aborting due to previous error diff --git a/tests/ui/lint/lint-struct-necessary.rs b/tests/ui/lint/lint-struct-necessary.rs new file mode 100644 index 000000000..8bc3c1205 --- /dev/null +++ b/tests/ui/lint/lint-struct-necessary.rs @@ -0,0 +1,31 @@ +#![allow(dead_code)] +#![deny(unused_parens)] + +enum State { + Waiting { start_at: u64 } +} +struct Foo {} + +fn main() { + let e = &mut State::Waiting { start_at: 0u64 }; + match (&mut State::Waiting { start_at: 0u64 }) { + _ => {} + } + + match (e) { + //~^ ERROR unnecessary parentheses around `match` scrutinee expression + _ => {} + } + + match &(State::Waiting { start_at: 0u64 }) { + _ => {} + } + + match (State::Waiting { start_at: 0u64 }) { + _ => {} + } + + match (&&Foo {}) { + _ => {} + } +} diff --git a/tests/ui/lint/lint-struct-necessary.stderr b/tests/ui/lint/lint-struct-necessary.stderr new file mode 100644 index 000000000..eb65a9e98 --- /dev/null +++ b/tests/ui/lint/lint-struct-necessary.stderr @@ -0,0 +1,19 @@ +error: unnecessary parentheses around `match` scrutinee expression + --> $DIR/lint-struct-necessary.rs:15:11 + | +LL | match (e) { + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-struct-necessary.rs:2:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - match (e) { +LL + match e { + | + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-unconditional-drop-recursion.rs b/tests/ui/lint/lint-unconditional-drop-recursion.rs new file mode 100644 index 000000000..348cd2801 --- /dev/null +++ b/tests/ui/lint/lint-unconditional-drop-recursion.rs @@ -0,0 +1,38 @@ +// Because drop recursion can only be detected after drop elaboration which +// happens for codegen: +// build-fail + +#![deny(unconditional_recursion)] +#![allow(dead_code)] + +pub struct RecursiveDrop; + +impl Drop for RecursiveDrop { + fn drop(&mut self) { //~ ERROR function cannot return without recursing + let _ = RecursiveDrop; + } +} + +#[derive(Default)] +struct NotRecursiveDrop1; + +impl Drop for NotRecursiveDrop1 { + fn drop(&mut self) { + // Before drop elaboration, the MIR can look like a recursive drop will + // occur. But it will not, since forget() prevents drop() from running. + let taken = std::mem::take(self); + std::mem::forget(taken); + } +} + +struct NotRecursiveDrop2; + +impl Drop for NotRecursiveDrop2 { + fn drop(&mut self) { + // Before drop elaboration, the MIR can look like a recursive drop will + // occur. But it will not, since this will panic. + std::panic::panic_any(NotRecursiveDrop2); + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-unconditional-drop-recursion.stderr b/tests/ui/lint/lint-unconditional-drop-recursion.stderr new file mode 100644 index 000000000..76f954816 --- /dev/null +++ b/tests/ui/lint/lint-unconditional-drop-recursion.stderr @@ -0,0 +1,17 @@ +error: function cannot return without recursing + --> $DIR/lint-unconditional-drop-recursion.rs:11:5 + | +LL | fn drop(&mut self) { + | ^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | let _ = RecursiveDrop; + | - recursive call site + | + = help: a `loop` may express intention better if this is on purpose +note: the lint level is defined here + --> $DIR/lint-unconditional-drop-recursion.rs:5:9 + | +LL | #![deny(unconditional_recursion)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-unconditional-recursion.stderr b/tests/ui/lint/lint-unconditional-recursion.stderr index 9d200a789..d75754bf9 100644 --- a/tests/ui/lint/lint-unconditional-recursion.stderr +++ b/tests/ui/lint/lint-unconditional-recursion.stderr @@ -139,7 +139,7 @@ error: function cannot return without recursing LL | fn index(&self, x: usize) -> &Baz { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing LL | &self[x] - | ------- recursive call site + | --- recursive call site | = help: a `loop` may express intention better if this is on purpose diff --git a/tests/ui/lint/missing-copy-implementations-negative-copy.rs b/tests/ui/lint/missing-copy-implementations-negative-copy.rs new file mode 100644 index 000000000..b29d2209f --- /dev/null +++ b/tests/ui/lint/missing-copy-implementations-negative-copy.rs @@ -0,0 +1,15 @@ +// Regression test for issue #101980. +// Ensure that we don't suggest impl'ing `Copy` for a type if it already impl's `!Copy`. + +// check-pass + +#![feature(negative_impls)] +#![deny(missing_copy_implementations)] + +pub struct Struct { + pub field: i32, +} + +impl !Copy for Struct {} + +fn main() {} diff --git a/tests/ui/lint/missing-doc-private-macro.stderr b/tests/ui/lint/missing-doc-private-macro.stderr index 979b007d0..18c8ad2de 100644 --- a/tests/ui/lint/missing-doc-private-macro.stderr +++ b/tests/ui/lint/missing-doc-private-macro.stderr @@ -1,8 +1,8 @@ error: missing documentation for a macro - --> $DIR/missing-doc-private-macro.rs:31:5 + --> $DIR/missing-doc-private-macro.rs:37:1 | -LL | macro_rules! exported_to_top_level { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub macro top_level_pub_macro { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/missing-doc-private-macro.rs:5:9 @@ -11,10 +11,10 @@ LL | #![deny(missing_docs)] | ^^^^^^^^^^^^ error: missing documentation for a macro - --> $DIR/missing-doc-private-macro.rs:37:1 + --> $DIR/missing-doc-private-macro.rs:31:5 | -LL | pub macro top_level_pub_macro { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | macro_rules! exported_to_top_level { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/lint/noop-method-call.fixed b/tests/ui/lint/noop-method-call.fixed new file mode 100644 index 000000000..eeb80279f --- /dev/null +++ b/tests/ui/lint/noop-method-call.fixed @@ -0,0 +1,51 @@ +// check-pass +// run-rustfix + +#![allow(unused)] + +use std::borrow::Borrow; +use std::ops::Deref; + +struct PlainType<T>(T); + +#[derive(Clone)] +struct CloneType<T>(T); + +fn check(mut encoded: &[u8]) { + let _ = &mut encoded; + //~^ WARN call to `.clone()` on a reference in this situation does nothing + let _ = &encoded; + //~^ WARN call to `.clone()` on a reference in this situation does nothing +} + +fn main() { + let non_clone_type_ref = &PlainType(1u32); + let non_clone_type_ref_clone: &PlainType<u32> = non_clone_type_ref; + //~^ WARN call to `.clone()` on a reference in this situation does nothing + + let clone_type_ref = &CloneType(1u32); + let clone_type_ref_clone: CloneType<u32> = clone_type_ref.clone(); + + + let non_deref_type = &PlainType(1u32); + let non_deref_type_deref: &PlainType<u32> = non_deref_type; + //~^ WARN call to `.deref()` on a reference in this situation does nothing + + let non_borrow_type = &PlainType(1u32); + let non_borrow_type_borrow: &PlainType<u32> = non_borrow_type; + //~^ WARN call to `.borrow()` on a reference in this situation does nothing + + // Borrowing a &&T does not warn since it has collapsed the double reference + let non_borrow_type = &&PlainType(1u32); + let non_borrow_type_borrow: &PlainType<u32> = non_borrow_type.borrow(); +} + +fn generic<T>(non_clone_type: &PlainType<T>) { + non_clone_type; + //~^ WARN call to `.clone()` on a reference in this situation does nothing +} + +fn non_generic(non_clone_type: &PlainType<u32>) { + non_clone_type; + //~^ WARN call to `.clone()` on a reference in this situation does nothing +} diff --git a/tests/ui/lint/noop-method-call.rs b/tests/ui/lint/noop-method-call.rs index dbcf2a513..9569a0dfc 100644 --- a/tests/ui/lint/noop-method-call.rs +++ b/tests/ui/lint/noop-method-call.rs @@ -1,7 +1,7 @@ // check-pass +// run-rustfix #![allow(unused)] -#![warn(noop_method_call)] use std::borrow::Borrow; use std::ops::Deref; @@ -11,45 +11,41 @@ struct PlainType<T>(T); #[derive(Clone)] struct CloneType<T>(T); +fn check(mut encoded: &[u8]) { + let _ = &mut encoded.clone(); + //~^ WARN call to `.clone()` on a reference in this situation does nothing + let _ = &encoded.clone(); + //~^ WARN call to `.clone()` on a reference in this situation does nothing +} + fn main() { let non_clone_type_ref = &PlainType(1u32); let non_clone_type_ref_clone: &PlainType<u32> = non_clone_type_ref.clone(); - //~^ WARNING call to `.clone()` on a reference in this situation does nothing + //~^ WARN call to `.clone()` on a reference in this situation does nothing let clone_type_ref = &CloneType(1u32); let clone_type_ref_clone: CloneType<u32> = clone_type_ref.clone(); - let clone_type_ref = &&CloneType(1u32); - let clone_type_ref_clone: &CloneType<u32> = clone_type_ref.clone(); - //~^ WARNING using `.clone()` on a double reference, which returns `&CloneType<u32>` let non_deref_type = &PlainType(1u32); let non_deref_type_deref: &PlainType<u32> = non_deref_type.deref(); - //~^ WARNING call to `.deref()` on a reference in this situation does nothing - - let non_deref_type = &&PlainType(1u32); - let non_deref_type_deref: &PlainType<u32> = non_deref_type.deref(); - //~^ WARNING using `.deref()` on a double reference, which returns `&PlainType<u32>` + //~^ WARN call to `.deref()` on a reference in this situation does nothing let non_borrow_type = &PlainType(1u32); let non_borrow_type_borrow: &PlainType<u32> = non_borrow_type.borrow(); - //~^ WARNING call to `.borrow()` on a reference in this situation does nothing + //~^ WARN call to `.borrow()` on a reference in this situation does nothing // Borrowing a &&T does not warn since it has collapsed the double reference let non_borrow_type = &&PlainType(1u32); let non_borrow_type_borrow: &PlainType<u32> = non_borrow_type.borrow(); - - let xs = ["a", "b", "c"]; - let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // could use `*x` instead - //~^ WARNING using `.clone()` on a double reference, which returns `&str` } fn generic<T>(non_clone_type: &PlainType<T>) { non_clone_type.clone(); - //~^ WARNING call to `.clone()` on a reference in this situation does nothing + //~^ WARN call to `.clone()` on a reference in this situation does nothing } fn non_generic(non_clone_type: &PlainType<u32>) { non_clone_type.clone(); - //~^ WARNING call to `.clone()` on a reference in this situation does nothing + //~^ WARN call to `.clone()` on a reference in this situation does nothing } diff --git a/tests/ui/lint/noop-method-call.stderr b/tests/ui/lint/noop-method-call.stderr index 37cd1a0fc..aefc2706f 100644 --- a/tests/ui/lint/noop-method-call.stderr +++ b/tests/ui/lint/noop-method-call.stderr @@ -1,67 +1,59 @@ warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:16:71 + --> $DIR/noop-method-call.rs:15:25 | -LL | let non_clone_type_ref_clone: &PlainType<u32> = non_clone_type_ref.clone(); - | ^^^^^^^^ unnecessary method call - | - = note: the type `&PlainType<u32>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed -note: the lint level is defined here - --> $DIR/noop-method-call.rs:4:9 +LL | let _ = &mut encoded.clone(); + | ^^^^^^^^ help: remove this redundant call | -LL | #![warn(noop_method_call)] - | ^^^^^^^^^^^^^^^^ + = note: the type `[u8]` does not implement `Clone`, so calling `clone` on `&[u8]` copies the reference, which does not do anything and can be removed + = note: `#[warn(noop_method_call)]` on by default -warning: using `.clone()` on a double reference, which returns `&CloneType<u32>` instead of cloning the inner type - --> $DIR/noop-method-call.rs:23:63 +warning: call to `.clone()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:17:21 | -LL | let clone_type_ref_clone: &CloneType<u32> = clone_type_ref.clone(); - | ^^^^^^^^ +LL | let _ = &encoded.clone(); + | ^^^^^^^^ help: remove this redundant call | - = note: `#[warn(suspicious_double_ref_op)]` on by default + = note: the type `[u8]` does not implement `Clone`, so calling `clone` on `&[u8]` copies the reference, which does not do anything and can be removed -warning: call to `.deref()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:27:63 +warning: call to `.clone()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:23:71 | -LL | let non_deref_type_deref: &PlainType<u32> = non_deref_type.deref(); - | ^^^^^^^^ unnecessary method call +LL | let non_clone_type_ref_clone: &PlainType<u32> = non_clone_type_ref.clone(); + | ^^^^^^^^ help: remove this redundant call | - = note: the type `&PlainType<u32>` which `deref` is being called on is the same as the type returned from `deref`, so the method call does not do anything and can be removed + = note: the type `PlainType<u32>` does not implement `Clone`, so calling `clone` on `&PlainType<u32>` copies the reference, which does not do anything and can be removed -warning: using `.deref()` on a double reference, which returns `&PlainType<u32>` instead of dereferencing the inner type +warning: call to `.deref()` on a reference in this situation does nothing --> $DIR/noop-method-call.rs:31:63 | LL | let non_deref_type_deref: &PlainType<u32> = non_deref_type.deref(); - | ^^^^^^^^ + | ^^^^^^^^ help: remove this redundant call + | + = note: the type `PlainType<u32>` does not implement `Deref`, so calling `deref` on `&PlainType<u32>` copies the reference, which does not do anything and can be removed warning: call to `.borrow()` on a reference in this situation does nothing --> $DIR/noop-method-call.rs:35:66 | LL | let non_borrow_type_borrow: &PlainType<u32> = non_borrow_type.borrow(); - | ^^^^^^^^^ unnecessary method call - | - = note: the type `&PlainType<u32>` which `borrow` is being called on is the same as the type returned from `borrow`, so the method call does not do anything and can be removed - -warning: using `.clone()` on a double reference, which returns `&str` instead of cloning the inner type - --> $DIR/noop-method-call.rs:43:44 + | ^^^^^^^^^ help: remove this redundant call | -LL | let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // could use `*x` instead - | ^^^^^^^^ + = note: the type `PlainType<u32>` does not implement `Borrow`, so calling `borrow` on `&PlainType<u32>` copies the reference, which does not do anything and can be removed warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:48:19 + --> $DIR/noop-method-call.rs:44:19 | LL | non_clone_type.clone(); - | ^^^^^^^^ unnecessary method call + | ^^^^^^^^ help: remove this redundant call | - = note: the type `&PlainType<T>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed + = note: the type `PlainType<T>` does not implement `Clone`, so calling `clone` on `&PlainType<T>` copies the reference, which does not do anything and can be removed warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:53:19 + --> $DIR/noop-method-call.rs:49:19 | LL | non_clone_type.clone(); - | ^^^^^^^^ unnecessary method call + | ^^^^^^^^ help: remove this redundant call | - = note: the type `&PlainType<u32>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed + = note: the type `PlainType<u32>` does not implement `Clone`, so calling `clone` on `&PlainType<u32>` copies the reference, which does not do anything and can be removed -warning: 8 warnings emitted +warning: 7 warnings emitted diff --git a/tests/ui/lint/ptr_null_checks.rs b/tests/ui/lint/ptr_null_checks.rs new file mode 100644 index 000000000..e677ea309 --- /dev/null +++ b/tests/ui/lint/ptr_null_checks.rs @@ -0,0 +1,76 @@ +// check-pass + +#![feature(ptr_from_ref)] + +use std::ptr; + +extern "C" fn c_fn() {} +fn static_i32() -> &'static i32 { &1 } + +fn main() { + let fn_ptr = main; + + // ------------- Function pointers --------------- + if (fn_ptr as *mut ()).is_null() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *const u8).is_null() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *const ()) == std::ptr::null() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *mut ()) == std::ptr::null_mut() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *const ()) == (0 as *const ()) {} + //~^ WARN function pointers are not nullable + if <*const _>::is_null(fn_ptr as *const ()) {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *mut fn() as *const fn() as *const ()).is_null() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as *mut fn() as *const fn()).cast_mut().is_null() {} + //~^ WARN function pointers are not nullable + if ((fn_ptr as *mut fn()).cast() as *const fn()).cast_mut().is_null() {} + //~^ WARN function pointers are not nullable + if (fn_ptr as fn() as *const ()).is_null() {} + //~^ WARN function pointers are not nullable + if (c_fn as *const fn()).is_null() {} + //~^ WARN function pointers are not nullable + + // ---------------- References ------------------ + if (&mut 8 as *mut i32).is_null() {} + //~^ WARN references are not nullable + if ptr::from_mut(&mut 8).is_null() {} + //~^ WARN references are not nullable + if (&8 as *const i32).is_null() {} + //~^ WARN references are not nullable + if ptr::from_ref(&8).is_null() {} + //~^ WARN references are not nullable + if ptr::from_ref(&8).cast_mut().is_null() {} + //~^ WARN references are not nullable + if (ptr::from_ref(&8).cast_mut() as *mut i32).is_null() {} + //~^ WARN references are not nullable + if (&8 as *const i32) == std::ptr::null() {} + //~^ WARN references are not nullable + let ref_num = &8; + if (ref_num as *const i32) == std::ptr::null() {} + //~^ WARN references are not nullable + if (b"\0" as *const u8).is_null() {} + //~^ WARN references are not nullable + if ("aa" as *const str).is_null() {} + //~^ WARN references are not nullable + if (&[1, 2] as *const i32).is_null() {} + //~^ WARN references are not nullable + if (&mut [1, 2] as *mut i32) == std::ptr::null_mut() {} + //~^ WARN references are not nullable + if (static_i32() as *const i32).is_null() {} + //~^ WARN references are not nullable + if (&*{ static_i32() } as *const i32).is_null() {} + //~^ WARN references are not nullable + + // ---------------------------------------------- + const ZPTR: *const () = 0 as *const _; + const NOT_ZPTR: *const () = 1 as *const _; + + // unlike the uplifted clippy::fn_null_check lint we do + // not lint on them + if (fn_ptr as *const ()) == ZPTR {} + if (fn_ptr as *const ()) == NOT_ZPTR {} +} diff --git a/tests/ui/lint/ptr_null_checks.stderr b/tests/ui/lint/ptr_null_checks.stderr new file mode 100644 index 000000000..3cee1804b --- /dev/null +++ b/tests/ui/lint/ptr_null_checks.stderr @@ -0,0 +1,225 @@ +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:14:8 + | +LL | if (fn_ptr as *mut ()).is_null() {} + | ^------^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `fn() {main}` + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + = note: `#[warn(useless_ptr_null_checks)]` on by default + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:16:8 + | +LL | if (fn_ptr as *const u8).is_null() {} + | ^------^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `fn() {main}` + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:18:8 + | +LL | if (fn_ptr as *const ()) == std::ptr::null() {} + | ^------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `fn() {main}` + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:20:8 + | +LL | if (fn_ptr as *mut ()) == std::ptr::null_mut() {} + | ^------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `fn() {main}` + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:22:8 + | +LL | if (fn_ptr as *const ()) == (0 as *const ()) {} + | ^------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `fn() {main}` + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:24:8 + | +LL | if <*const _>::is_null(fn_ptr as *const ()) {} + | ^^^^^^^^^^^^^^^^^^^^------^^^^^^^^^^^^^^ + | | + | expression has type `fn() {main}` + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:26:8 + | +LL | if (fn_ptr as *mut fn() as *const fn() as *const ()).is_null() {} + | ^------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `fn() {main}` + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:28:8 + | +LL | if (fn_ptr as *mut fn() as *const fn()).cast_mut().is_null() {} + | ^------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `fn() {main}` + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:30:8 + | +LL | if ((fn_ptr as *mut fn()).cast() as *const fn()).cast_mut().is_null() {} + | ^^------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `fn() {main}` + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:32:8 + | +LL | if (fn_ptr as fn() as *const ()).is_null() {} + | ^--------------^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `fn()` + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: function pointers are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:34:8 + | +LL | if (c_fn as *const fn()).is_null() {} + | ^----^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `extern "C" fn() {c_fn}` + | + = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + +warning: references are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:38:8 + | +LL | if (&mut 8 as *mut i32).is_null() {} + | ^------^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `&mut i32` + +warning: references are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:40:8 + | +LL | if ptr::from_mut(&mut 8).is_null() {} + | ^^^^^^^^^^^^^^------^^^^^^^^^^^ + | | + | expression has type `&mut i32` + +warning: references are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:42:8 + | +LL | if (&8 as *const i32).is_null() {} + | ^--^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `&i32` + +warning: references are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:44:8 + | +LL | if ptr::from_ref(&8).is_null() {} + | ^^^^^^^^^^^^^^--^^^^^^^^^^^ + | | + | expression has type `&i32` + +warning: references are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:46:8 + | +LL | if ptr::from_ref(&8).cast_mut().is_null() {} + | ^^^^^^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `&i32` + +warning: references are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:48:8 + | +LL | if (ptr::from_ref(&8).cast_mut() as *mut i32).is_null() {} + | ^^^^^^^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `&i32` + +warning: references are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:50:8 + | +LL | if (&8 as *const i32) == std::ptr::null() {} + | ^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `&i32` + +warning: references are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:53:8 + | +LL | if (ref_num as *const i32) == std::ptr::null() {} + | ^-------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `&i32` + +warning: references are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:55:8 + | +LL | if (b"\0" as *const u8).is_null() {} + | ^-----^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `&[u8; 1]` + +warning: references are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:57:8 + | +LL | if ("aa" as *const str).is_null() {} + | ^----^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `&str` + +warning: references are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:59:8 + | +LL | if (&[1, 2] as *const i32).is_null() {} + | ^-------^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `&[i32; 2]` + +warning: references are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:61:8 + | +LL | if (&mut [1, 2] as *mut i32) == std::ptr::null_mut() {} + | ^-----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `&mut [i32; 2]` + +warning: references are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:63:8 + | +LL | if (static_i32() as *const i32).is_null() {} + | ^------------^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `&i32` + +warning: references are not nullable, so checking them for null will always return false + --> $DIR/ptr_null_checks.rs:65:8 + | +LL | if (&*{ static_i32() } as *const i32).is_null() {} + | ^------------------^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expression has type `&i32` + +warning: 25 warnings emitted + diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs index 996382049..6c38bca3d 100644 --- a/tests/ui/lint/reference_casting.rs +++ b/tests/ui/lint/reference_casting.rs @@ -1,7 +1,6 @@ // check-fail #![feature(ptr_from_ref)] -#![deny(invalid_reference_casting)] extern "C" { // N.B., mutability can be easily incorrect in FFI calls -- as @@ -10,42 +9,97 @@ extern "C" { fn int_ffi(c: *mut i32); } -fn main() { +fn static_u8() -> &'static u8 { + &8 +} + +unsafe fn ref_to_mut() { + let num = &3i32; + + let _num = &mut *(num as *const i32 as *mut i32); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *(num as *const i32).cast_mut(); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *std::ptr::from_ref(num).cast_mut(); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *std::ptr::from_ref({ num }).cast_mut(); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *{ std::ptr::from_ref(num) }.cast_mut(); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *(std::ptr::from_ref({ num }) as *mut i32); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *(num as *const i32).cast::<i32>().cast_mut(); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *(num as *const i32).cast::<i32>().cast_mut().cast_const().cast_mut(); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *(std::ptr::from_ref(static_u8()) as *mut i32); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *std::mem::transmute::<_, *mut i32>(num); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + + let deferred = num as *const i32 as *mut i32; + let _num = &mut *deferred; + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; + let _num = &mut *deferred; + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *(num as *const _ as usize as *mut i32); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + + unsafe fn generic_ref_cast_mut<T>(this: &T) -> &mut T { + &mut *((this as *const _) as *mut _) + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + } +} + +unsafe fn assign_to_ref() { let s = String::from("Hello"); let a = &s; - unsafe { - let num = &3i32; - let mut_num = &mut 3i32; + let num = &3i32; - (*(a as *const _ as *mut String)).push_str(" world"); - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - *(a as *const _ as *mut _) = String::from("Replaced"); - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - *(a as *const _ as *mut String) += " world"; - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - let _num = &mut *(num as *const i32 as *mut i32); - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - let _num = &mut *(num as *const i32).cast_mut(); - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - let _num = *{ num as *const i32 }.cast_mut(); - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - *std::ptr::from_ref(num).cast_mut() += 1; - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - *std::ptr::from_ref({ num }).cast_mut() += 1; - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - *{ std::ptr::from_ref(num) }.cast_mut() += 1; - //~^ ERROR casting `&T` to `&mut T` is undefined behavior - *(std::ptr::from_ref({ num }) as *mut i32) += 1; - //~^ ERROR casting `&T` to `&mut T` is undefined behavior + *(a as *const _ as *mut _) = String::from("Replaced"); + //~^ ERROR assigning to `&T` is undefined behavior + *(a as *const _ as *mut String) += " world"; + //~^ ERROR assigning to `&T` is undefined behavior + *std::ptr::from_ref(num).cast_mut() += 1; + //~^ ERROR assigning to `&T` is undefined behavior + *std::ptr::from_ref({ num }).cast_mut() += 1; + //~^ ERROR assigning to `&T` is undefined behavior + *{ std::ptr::from_ref(num) }.cast_mut() += 1; + //~^ ERROR assigning to `&T` is undefined behavior + *(std::ptr::from_ref({ num }) as *mut i32) += 1; + //~^ ERROR assigning to `&T` is undefined behavior + *std::mem::transmute::<_, *mut i32>(num) += 1; + //~^ ERROR assigning to `&T` is undefined behavior + + let value = num as *const i32 as *mut i32; + *value = 1; + //~^ ERROR assigning to `&T` is undefined behavior + *(num as *const i32).cast::<i32>().cast_mut() = 2; + //~^ ERROR assigning to `&T` is undefined behavior + *(num as *const _ as usize as *mut i32) = 2; + //~^ ERROR assigning to `&T` is undefined behavior - // Shouldn't be warned against - println!("{}", *(num as *const _ as *const i16)); - println!("{}", *(mut_num as *mut _ as *mut i16)); - ffi(a.as_ptr() as *mut _); - int_ffi(num as *const _ as *mut _); - int_ffi(&3 as *const _ as *mut _); - let mut value = 3; - let value: *const i32 = &mut value; - *(value as *const i16 as *mut i16) = 42; + unsafe fn generic_assign_to_ref<T>(this: &T, a: T) { + *(this as *const _ as *mut _) = a; + //~^ ERROR assigning to `&T` is undefined behavior } } + +unsafe fn no_warn() { + let num = &3i32; + let mut_num = &mut 3i32; + let a = &String::from("ffi"); + + *(num as *const i32 as *mut i32); + println!("{}", *(num as *const _ as *const i16)); + println!("{}", *(mut_num as *mut _ as *mut i16)); + ffi(a.as_ptr() as *mut _); + int_ffi(num as *const _ as *mut _); + int_ffi(&3 as *const _ as *mut _); + let mut value = 3; + let value: *const i32 = &mut value; + *(value as *const i16 as *mut i16) = 42; +} + +fn main() {} diff --git a/tests/ui/lint/reference_casting.stderr b/tests/ui/lint/reference_casting.stderr index d5b9bbef6..7ff9b76a8 100644 --- a/tests/ui/lint/reference_casting.stderr +++ b/tests/ui/lint/reference_casting.stderr @@ -1,68 +1,160 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:20:9 + --> $DIR/reference_casting.rs:19:16 | -LL | (*(a as *const _ as *mut String)).push_str(" world"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _num = &mut *(num as *const i32 as *mut i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(invalid_reference_casting)]` on by default + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:21:16 + | +LL | let _num = &mut *(num as *const i32).cast_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:23:16 + | +LL | let _num = &mut *std::ptr::from_ref(num).cast_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:25:16 | -note: the lint level is defined here - --> $DIR/reference_casting.rs:4:9 +LL | let _num = &mut *std::ptr::from_ref({ num }).cast_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:27:16 | -LL | #![deny(invalid_reference_casting)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _num = &mut *{ std::ptr::from_ref(num) }.cast_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:22:9 + --> $DIR/reference_casting.rs:29:16 | -LL | *(a as *const _ as *mut _) = String::from("Replaced"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _num = &mut *(std::ptr::from_ref({ num }) as *mut i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:24:9 + --> $DIR/reference_casting.rs:31:16 | -LL | *(a as *const _ as *mut String) += " world"; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _num = &mut *(num as *const i32).cast::<i32>().cast_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:26:25 + --> $DIR/reference_casting.rs:33:16 | -LL | let _num = &mut *(num as *const i32 as *mut i32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _num = &mut *(num as *const i32).cast::<i32>().cast_mut().cast_const().cast_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:28:25 + --> $DIR/reference_casting.rs:35:16 | -LL | let _num = &mut *(num as *const i32).cast_mut(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _num = &mut *(std::ptr::from_ref(static_u8()) as *mut i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:30:20 + --> $DIR/reference_casting.rs:37:16 | -LL | let _num = *{ num as *const i32 }.cast_mut(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _num = &mut *std::mem::transmute::<_, *mut i32>(num); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:32:9 + --> $DIR/reference_casting.rs:41:16 | -LL | *std::ptr::from_ref(num).cast_mut() += 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let deferred = num as *const i32 as *mut i32; + | ----------------------------- casting happend here +LL | let _num = &mut *deferred; + | ^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:34:9 + --> $DIR/reference_casting.rs:44:16 | -LL | *std::ptr::from_ref({ num }).cast_mut() += 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; + | ---------------------------------------------------------------------------- casting happend here +LL | let _num = &mut *deferred; + | ^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:36:9 + --> $DIR/reference_casting.rs:46:16 | -LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _num = &mut *(num as *const _ as usize as *mut i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:38:9 + --> $DIR/reference_casting.rs:50:9 + | +LL | &mut *((this as *const _) as *mut _) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:60:5 + | +LL | *(a as *const _ as *mut _) = String::from("Replaced"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:62:5 + | +LL | *(a as *const _ as *mut String) += " world"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:64:5 | -LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | *std::ptr::from_ref(num).cast_mut() += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:66:5 + | +LL | *std::ptr::from_ref({ num }).cast_mut() += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:68:5 + | +LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:70:5 + | +LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:72:5 + | +LL | *std::mem::transmute::<_, *mut i32>(num) += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:76:5 + | +LL | let value = num as *const i32 as *mut i32; + | ----------------------------- casting happend here +LL | *value = 1; + | ^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:78:5 + | +LL | *(num as *const i32).cast::<i32>().cast_mut() = 2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:80:5 + | +LL | *(num as *const _ as usize as *mut i32) = 2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:84:9 + | +LL | *(this as *const _ as *mut _) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 10 previous errors +error: aborting due to 25 previous errors diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs index e7da825ae..b2d8a28d3 100644 --- a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs @@ -5,8 +5,8 @@ const s: usize = 42; const s_s: usize = 42; fn main() { - let s = "rust"; //~ ERROR identifier pair considered confusable - let s_s = "rust2"; //~ ERROR identifier pair considered confusable + let s = "rust"; //~ ERROR found both + let s_s = "rust2"; //~ ERROR found both not_affected(); } diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.stderr b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.stderr index e9906c83d..d1920f215 100644 --- a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.stderr +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.stderr @@ -1,11 +1,11 @@ -error: identifier pair considered confusable between `s` and `s` +error: found both `s` and `s` as identifiers, which look alike --> $DIR/lint-confusable-idents.rs:8:9 | LL | const s: usize = 42; - | -- this is where the previous identifier occurred + | -- other identifier used here ... LL | let s = "rust"; - | ^ + | ^ this identifier can be confused with `s` | note: the lint level is defined here --> $DIR/lint-confusable-idents.rs:1:9 @@ -13,14 +13,14 @@ note: the lint level is defined here LL | #![deny(confusable_idents)] | ^^^^^^^^^^^^^^^^^ -error: identifier pair considered confusable between `s_s` and `s_s` +error: found both `s_s` and `s_s` as identifiers, which look alike --> $DIR/lint-confusable-idents.rs:9:9 | LL | const s_s: usize = 42; - | --- this is where the previous identifier occurred + | --- other identifier used here ... LL | let s_s = "rust2"; - | ^^^^^ + | ^^^^^ this identifier can be confused with `s_s` error: aborting due to 2 previous errors diff --git a/tests/ui/lint/suspicious-double-ref-op.rs b/tests/ui/lint/suspicious-double-ref-op.rs index b9bcd31c2..bc8c23c7b 100644 --- a/tests/ui/lint/suspicious-double-ref-op.rs +++ b/tests/ui/lint/suspicious-double-ref-op.rs @@ -1,6 +1,14 @@ #![feature(lazy_cell)] #![deny(suspicious_double_ref_op, noop_method_call)] +use std::borrow::Borrow; +use std::ops::Deref; + +struct PlainType<T>(T); + +#[derive(Clone)] +struct CloneType<T>(T); + pub fn clone_on_double_ref() { let x = vec![1]; let y = &&x; @@ -20,11 +28,16 @@ fn rust_clippy_issue_9272() { println!("{str}") } -fn check(mut encoded: &[u8]) { - let _ = &mut encoded.clone(); - //~^ ERROR call to `.clone()` on a reference in this situation does nothing - let _ = &encoded.clone(); - //~^ ERROR call to `.clone()` on a reference in this situation does nothing -} +fn main() { + let clone_type_ref = &&CloneType(1u32); + let clone_type_ref_clone: &CloneType<u32> = clone_type_ref.clone(); + //~^ ERROR using `.clone()` on a double reference, which returns `&CloneType<u32>` + + let non_deref_type = &&PlainType(1u32); + let non_deref_type_deref: &PlainType<u32> = non_deref_type.deref(); + //~^ ERROR using `.deref()` on a double reference, which returns `&PlainType<u32>` -fn main() {} + let xs = ["a", "b", "c"]; + let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // could use `*x` instead + //~^ ERROR using `.clone()` on a double reference, which returns `&str` +} diff --git a/tests/ui/lint/suspicious-double-ref-op.stderr b/tests/ui/lint/suspicious-double-ref-op.stderr index d15487ca2..f5a71d40f 100644 --- a/tests/ui/lint/suspicious-double-ref-op.stderr +++ b/tests/ui/lint/suspicious-double-ref-op.stderr @@ -1,5 +1,5 @@ error: using `.clone()` on a double reference, which returns `&Vec<i32>` instead of cloning the inner type - --> $DIR/suspicious-double-ref-op.rs:7:23 + --> $DIR/suspicious-double-ref-op.rs:15:23 | LL | let z: &Vec<_> = y.clone(); | ^^^^^^^^ @@ -10,26 +10,23 @@ note: the lint level is defined here LL | #![deny(suspicious_double_ref_op, noop_method_call)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: call to `.clone()` on a reference in this situation does nothing - --> $DIR/suspicious-double-ref-op.rs:24:25 +error: using `.clone()` on a double reference, which returns `&CloneType<u32>` instead of cloning the inner type + --> $DIR/suspicious-double-ref-op.rs:33:63 | -LL | let _ = &mut encoded.clone(); - | ^^^^^^^^ unnecessary method call - | - = note: the type `&[u8]` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed -note: the lint level is defined here - --> $DIR/suspicious-double-ref-op.rs:2:35 - | -LL | #![deny(suspicious_double_ref_op, noop_method_call)] - | ^^^^^^^^^^^^^^^^ +LL | let clone_type_ref_clone: &CloneType<u32> = clone_type_ref.clone(); + | ^^^^^^^^ -error: call to `.clone()` on a reference in this situation does nothing - --> $DIR/suspicious-double-ref-op.rs:26:21 +error: using `.deref()` on a double reference, which returns `&PlainType<u32>` instead of dereferencing the inner type + --> $DIR/suspicious-double-ref-op.rs:37:63 | -LL | let _ = &encoded.clone(); - | ^^^^^^^^ unnecessary method call +LL | let non_deref_type_deref: &PlainType<u32> = non_deref_type.deref(); + | ^^^^^^^^ + +error: using `.clone()` on a double reference, which returns `&str` instead of cloning the inner type + --> $DIR/suspicious-double-ref-op.rs:41:44 | - = note: the type `&[u8]` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed +LL | let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // could use `*x` instead + | ^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/lint/unaligned_references.stderr b/tests/ui/lint/unaligned_references.stderr index 5f9cecadb..d3abc3766 100644 --- a/tests/ui/lint/unaligned_references.stderr +++ b/tests/ui/lint/unaligned_references.stderr @@ -52,7 +52,7 @@ error[E0793]: reference to packed field is unaligned --> $DIR/unaligned_references.rs:40:17 | LL | let _ = good.data.clone(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) diff --git a/tests/ui/lint/unknown-lints/allow-in-other-module.rs b/tests/ui/lint/unknown-lints/allow-in-other-module.rs new file mode 100644 index 000000000..20bf0d7af --- /dev/null +++ b/tests/ui/lint/unknown-lints/allow-in-other-module.rs @@ -0,0 +1,26 @@ +// check-pass + +// Tests that the unknown_lints lint doesn't fire for an unknown lint loaded from a separate file. +// The key part is that the stderr output should be empty. +// Reported in https://github.com/rust-lang/rust/issues/84936 +// Fixed incidentally by https://github.com/rust-lang/rust/pull/97266 + +// This `allow` should apply to submodules, whether they are inline or loaded from a file. +#![allow(unknown_lints)] +#![allow(dead_code)] +// no warning +#![allow(not_a_real_lint)] + +mod other; + +// no warning +#[allow(not_a_real_lint)] +fn m() {} + +mod mm { + // no warning + #[allow(not_a_real_lint)] + fn m() {} +} + +fn main() {} diff --git a/tests/ui/lint/unknown-lints/other.rs b/tests/ui/lint/unknown-lints/other.rs new file mode 100644 index 000000000..a5111c00a --- /dev/null +++ b/tests/ui/lint/unknown-lints/other.rs @@ -0,0 +1,10 @@ +// ignore-test + +// Companion to allow-in-other-module.rs + +// This should not warn. +#![allow(not_a_real_lint)] + +// This should not warn, either. +#[allow(not_a_real_lint)] +fn m() {} diff --git a/tests/ui/lint/unused/const-local-var.rs b/tests/ui/lint/unused/const-local-var.rs new file mode 100644 index 000000000..89ca16fe0 --- /dev/null +++ b/tests/ui/lint/unused/const-local-var.rs @@ -0,0 +1,23 @@ +// regression test for https://github.com/rust-lang/rust/issues/69016 +// check-pass + +#![warn(unused)] +#![deny(warnings)] + +fn _unused1(x: i32) -> i32 { + const F: i32 = 2; + let g = 1; + x * F + g +} + +pub struct Foo {} + +impl Foo { + fn _unused2(x: i32) -> i32 { + const F: i32 = 2; + let g = 1; + x * F + g + } +} + +fn main() {} |