diff options
Diffstat (limited to 'tests/ui/lint')
712 files changed, 32007 insertions, 0 deletions
diff --git a/tests/ui/lint/auxiliary/add-impl.rs b/tests/ui/lint/auxiliary/add-impl.rs new file mode 100644 index 000000000..9d0e3068a --- /dev/null +++ b/tests/ui/lint/auxiliary/add-impl.rs @@ -0,0 +1,22 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(AddImpl)] +// Unnecessary qualification `bar::foo` +// https://github.com/rust-lang/rust/issues/71898 +pub fn derive(input: TokenStream) -> TokenStream { + "impl B { + fn foo(&self) { use bar::foo; bar::foo() } + } + + fn foo() {} + + mod bar { pub fn foo() {} } + ".parse().unwrap() +} diff --git a/tests/ui/lint/auxiliary/external_extern_fn.rs b/tests/ui/lint/auxiliary/external_extern_fn.rs new file mode 100644 index 000000000..c2a8cadc6 --- /dev/null +++ b/tests/ui/lint/auxiliary/external_extern_fn.rs @@ -0,0 +1,3 @@ +extern "C" { + pub fn extern_fn(x: u8); +} diff --git a/tests/ui/lint/auxiliary/inherited_stability.rs b/tests/ui/lint/auxiliary/inherited_stability.rs new file mode 100644 index 000000000..62100e5cc --- /dev/null +++ b/tests/ui/lint/auxiliary/inherited_stability.rs @@ -0,0 +1,47 @@ +#![crate_name="inherited_stability"] +#![crate_type = "lib"] +#![unstable(feature = "unstable_test_feature", issue = "none")] +#![feature(staged_api)] + +pub fn unstable() {} + +#[stable(feature = "rust1", since = "1.0.0")] +pub fn stable() {} + +#[stable(feature = "rust1", since = "1.0.0")] +pub mod stable_mod { + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn unstable() {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stable() {} +} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub mod unstable_mod { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated() {} + + pub fn unstable() {} +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Stable { + #[unstable(feature = "unstable_test_feature", issue = "none")] + fn unstable(&self); + + #[stable(feature = "rust1", since = "1.0.0")] + fn stable(&self); +} + +impl Stable for usize { + fn unstable(&self) {} + fn stable(&self) {} +} + +pub enum Unstable { + UnstableVariant, + #[stable(feature = "rust1", since = "1.0.0")] + StableVariant +} diff --git a/tests/ui/lint/auxiliary/lint_output_format.rs b/tests/ui/lint/auxiliary/lint_output_format.rs new file mode 100644 index 000000000..4e3547250 --- /dev/null +++ b/tests/ui/lint/auxiliary/lint_output_format.rs @@ -0,0 +1,20 @@ +#![crate_name="lint_output_format"] +#![crate_type = "lib"] +#![feature(staged_api)] +#![unstable(feature = "unstable_test_feature", issue = "none")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub fn foo() -> usize { + 20 +} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub fn bar() -> usize { + 40 +} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub fn baz() -> usize { + 30 +} diff --git a/tests/ui/lint/auxiliary/lint_stability.rs b/tests/ui/lint/auxiliary/lint_stability.rs new file mode 100644 index 000000000..99c29dcdd --- /dev/null +++ b/tests/ui/lint/auxiliary/lint_stability.rs @@ -0,0 +1,188 @@ +#![crate_name="lint_stability"] +#![crate_type = "lib"] +#![feature(staged_api)] +#![feature(associated_type_defaults)] +#![stable(feature = "lint_stability", since = "1.0.0")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub fn deprecated() {} +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub fn deprecated_text() {} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "99.99.99", note = "text")] +pub fn deprecated_future() {} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub fn deprecated_unstable() {} +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub fn deprecated_unstable_text() {} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub fn unstable() {} +#[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] +pub fn unstable_text() {} + +#[stable(feature = "rust1", since = "1.0.0")] +pub fn stable() {} +#[stable(feature = "rust1", since = "1.0.0")] +pub fn stable_text() {} + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct MethodTester; + +impl MethodTester { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated(&self) {} + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_unstable_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn method_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn method_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable_text(&self) {} +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait Trait { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated(&self) {} + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_unstable_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + fn trait_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + fn trait_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable_text(&self) {} +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait TraitWithAssociatedTypes { + #[unstable(feature = "unstable_test_feature", issue = "none")] + type TypeUnstable = u8; + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + type TypeDeprecated = u8; +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +impl Trait for MethodTester {} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub trait UnstableTrait { fn dummy(&self) { } } + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub trait DeprecatedTrait { + #[stable(feature = "stable_test_feature", since = "1.0.0")] fn dummy(&self) { } +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedUnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub enum UnstableEnum {} +#[stable(feature = "rust1", since = "1.0.0")] +pub enum StableEnum {} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedUnitStruct; +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedUnstableUnitStruct; +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct UnstableUnitStruct; +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StableUnitStruct; + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub enum Enum { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedVariant, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedUnstableVariant, + #[unstable(feature = "unstable_test_feature", issue = "none")] + UnstableVariant, + + #[stable(feature = "rust1", since = "1.0.0")] + StableVariant, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[macro_export] +macro_rules! macro_test { + () => (deprecated()); +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[macro_export] +macro_rules! macro_test_arg { + ($func:expr) => ($func); +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[macro_export] +macro_rules! macro_test_arg_nested { + ($func:ident) => (macro_test_arg!($func())); +} diff --git a/tests/ui/lint/auxiliary/lint_stability_fields.rs b/tests/ui/lint/auxiliary/lint_stability_fields.rs new file mode 100644 index 000000000..e72a501e1 --- /dev/null +++ b/tests/ui/lint/auxiliary/lint_stability_fields.rs @@ -0,0 +1,66 @@ +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Stable { + pub inherit: u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub override1: u8, + #[deprecated(since = "1.0.0", note = "text")] + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub override2: u8, + #[stable(feature = "rust2", since = "2.0.0")] + pub override3: u8, +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Stable2(#[stable(feature = "rust2", since = "2.0.0")] pub u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] pub u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] pub u8, + pub u8); + +#[stable(feature = "rust1", since = "1.0.0")] +pub enum Stable3 { + Inherit(u8), + InheritOverride(#[stable(feature = "rust2", since = "2.0.0")] u8), + #[stable(feature = "rust2", since = "2.0.0")] + Override1, + #[unstable(feature = "unstable_test_feature", issue = "none")] + Override2, + #[deprecated(since = "1.0.0", note = "text")] + #[unstable(feature = "unstable_test_feature", issue = "none")] + Override3, +} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct Unstable { + pub inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + pub override1: u8, + #[deprecated(since = "1.0.0", note = "text")] + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub override2: u8, +} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct Unstable2(pub u8, + #[stable(feature = "rust1", since = "1.0.0")] pub u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] pub u8); + +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct Deprecated { + pub inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + pub override1: u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub override2: u8, +} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct Deprecated2(pub u8, + #[stable(feature = "rust1", since = "1.0.0")] pub u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] pub u8); diff --git a/tests/ui/lint/auxiliary/lints-in-foreign-macros.rs b/tests/ui/lint/auxiliary/lints-in-foreign-macros.rs new file mode 100644 index 000000000..b969d9dba --- /dev/null +++ b/tests/ui/lint/auxiliary/lints-in-foreign-macros.rs @@ -0,0 +1,14 @@ +#[macro_export] +macro_rules! bar { + () => {use std::string::ToString;} +} + +#[macro_export] +macro_rules! baz { + ($i:item) => ($i) +} + +#[macro_export] +macro_rules! baz2 { + ($($i:tt)*) => ($($i)*) +} diff --git a/tests/ui/lint/auxiliary/stability-cfg2.rs b/tests/ui/lint/auxiliary/stability-cfg2.rs new file mode 100644 index 000000000..c995038e5 --- /dev/null +++ b/tests/ui/lint/auxiliary/stability-cfg2.rs @@ -0,0 +1,5 @@ +// compile-flags:--cfg foo + +#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "none"))] +#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))] +#![feature(staged_api)] diff --git a/tests/ui/lint/auxiliary/stability_cfg1.rs b/tests/ui/lint/auxiliary/stability_cfg1.rs new file mode 100644 index 000000000..2e027cc27 --- /dev/null +++ b/tests/ui/lint/auxiliary/stability_cfg1.rs @@ -0,0 +1,3 @@ +#![cfg_attr(foo, experimental)] +#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))] +#![feature(staged_api)] diff --git a/tests/ui/lint/auxiliary/stability_cfg2.rs b/tests/ui/lint/auxiliary/stability_cfg2.rs new file mode 100644 index 000000000..c995038e5 --- /dev/null +++ b/tests/ui/lint/auxiliary/stability_cfg2.rs @@ -0,0 +1,5 @@ +// compile-flags:--cfg foo + +#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "none"))] +#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))] +#![feature(staged_api)] diff --git a/tests/ui/lint/auxiliary/trivial-cast-ice.rs b/tests/ui/lint/auxiliary/trivial-cast-ice.rs new file mode 100644 index 000000000..ab2332d06 --- /dev/null +++ b/tests/ui/lint/auxiliary/trivial-cast-ice.rs @@ -0,0 +1,7 @@ +#[macro_export] +macro_rules! foo { + () => { + let x: &Option<i32> = &Some(1); + let _y = x as *const Option<i32>; + } +} diff --git a/tests/ui/lint/auxiliary/unaligned_references_external_crate.rs b/tests/ui/lint/auxiliary/unaligned_references_external_crate.rs new file mode 100644 index 000000000..fb486c6b5 --- /dev/null +++ b/tests/ui/lint/auxiliary/unaligned_references_external_crate.rs @@ -0,0 +1,28 @@ +#[macro_export] +macro_rules! mac { + ( + $(#[$attrs:meta])* + pub struct $ident:ident { + $( + $(#[$pin:ident])? + $field_vis:vis $field:ident: $field_ty:ty + ),+ $(,)? + } + ) => { + $(#[$attrs])* + pub struct $ident { + $( + $field_vis $field: $field_ty + ),+ + } + + const _: () = { + #[deny(unaligned_references)] + fn __f(this: &$ident) { + $( + let _ = &this.$field; + )+ + } + }; + }; +} diff --git a/tests/ui/lint/bad-lint-cap.rs b/tests/ui/lint/bad-lint-cap.rs new file mode 100644 index 000000000..e65c8319d --- /dev/null +++ b/tests/ui/lint/bad-lint-cap.rs @@ -0,0 +1,4 @@ +// compile-flags: --cap-lints test +// error-pattern: unknown lint level: `test` + +fn main() {} diff --git a/tests/ui/lint/bad-lint-cap.stderr b/tests/ui/lint/bad-lint-cap.stderr new file mode 100644 index 000000000..f284dbf84 --- /dev/null +++ b/tests/ui/lint/bad-lint-cap.stderr @@ -0,0 +1,2 @@ +error: unknown lint level: `test` + diff --git a/tests/ui/lint/bad-lint-cap2.rs b/tests/ui/lint/bad-lint-cap2.rs new file mode 100644 index 000000000..8bc8aca20 --- /dev/null +++ b/tests/ui/lint/bad-lint-cap2.rs @@ -0,0 +1,8 @@ +// compile-flags: --cap-lints deny + +#![warn(unused)] +#![deny(warnings)] + +use std::option; //~ ERROR + +fn main() {} diff --git a/tests/ui/lint/bad-lint-cap2.stderr b/tests/ui/lint/bad-lint-cap2.stderr new file mode 100644 index 000000000..3f3affe5a --- /dev/null +++ b/tests/ui/lint/bad-lint-cap2.stderr @@ -0,0 +1,15 @@ +error: unused import: `std::option` + --> $DIR/bad-lint-cap2.rs:6:5 + | +LL | use std::option; + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/bad-lint-cap2.rs:4:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]` + +error: aborting due to previous error + diff --git a/tests/ui/lint/bad-lint-cap3.rs b/tests/ui/lint/bad-lint-cap3.rs new file mode 100644 index 000000000..c38105870 --- /dev/null +++ b/tests/ui/lint/bad-lint-cap3.rs @@ -0,0 +1,9 @@ +// check-pass +// compile-flags: --cap-lints warn + +#![warn(unused)] +#![deny(warnings)] + +use std::option; //~ WARN + +fn main() {} diff --git a/tests/ui/lint/bad-lint-cap3.stderr b/tests/ui/lint/bad-lint-cap3.stderr new file mode 100644 index 000000000..0fb65322f --- /dev/null +++ b/tests/ui/lint/bad-lint-cap3.stderr @@ -0,0 +1,15 @@ +warning: unused import: `std::option` + --> $DIR/bad-lint-cap3.rs:7:5 + | +LL | use std::option; + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/bad-lint-cap3.rs:5:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[warn(unused_imports)]` implied by `#[warn(warnings)]` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/bare-trait-objects-path.rs b/tests/ui/lint/bare-trait-objects-path.rs new file mode 100644 index 000000000..0e2294715 --- /dev/null +++ b/tests/ui/lint/bare-trait-objects-path.rs @@ -0,0 +1,26 @@ +#![feature(associated_type_defaults)] + +trait Assoc { + fn func() {} + const CONST: u8 = 0; + type Ty = u8; +} + +trait Dyn {} + +impl Assoc for dyn Dyn {} + +fn main() { + Dyn::func(); + //~^ WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + ::Dyn::func(); + //~^ WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + Dyn::CONST; + //~^ WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + let _: Dyn::Ty; //~ ERROR ambiguous associated type + //~^ WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition +} diff --git a/tests/ui/lint/bare-trait-objects-path.stderr b/tests/ui/lint/bare-trait-objects-path.stderr new file mode 100644 index 000000000..a19f4963c --- /dev/null +++ b/tests/ui/lint/bare-trait-objects-path.stderr @@ -0,0 +1,62 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/bare-trait-objects-path.rs:23:12 + | +LL | let _: Dyn::Ty; + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> + = note: `#[warn(bare_trait_objects)]` on by default +help: use `dyn` + | +LL | let _: <dyn Dyn>::Ty; + | ++++ + + +error[E0223]: ambiguous associated type + --> $DIR/bare-trait-objects-path.rs:23:12 + | +LL | let _: Dyn::Ty; + | ^^^^^^^ help: use the fully-qualified path: `<dyn Dyn as Assoc>::Ty` + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/bare-trait-objects-path.rs:14:5 + | +LL | Dyn::func(); + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | <dyn Dyn>::func(); + | ++++ + + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/bare-trait-objects-path.rs:17:5 + | +LL | ::Dyn::func(); + | ^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | <dyn (::Dyn)>::func(); + | ++++++ ++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/bare-trait-objects-path.rs:20:5 + | +LL | Dyn::CONST; + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | <dyn Dyn>::CONST; + | ++++ + + +error: aborting due to previous error; 4 warnings emitted + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/lint/clashing-extern-fn-recursion.rs b/tests/ui/lint/clashing-extern-fn-recursion.rs new file mode 100644 index 000000000..ab0fd0a2e --- /dev/null +++ b/tests/ui/lint/clashing-extern-fn-recursion.rs @@ -0,0 +1,119 @@ +// check-pass +// +// This tests checks that clashing_extern_declarations handles types that are recursive through a +// pointer or ref argument. See #75512. + +#![crate_type = "lib"] + +mod raw_ptr_recursion { + mod a { + #[repr(C)] + struct Pointy { + pointy: *const Pointy, + } + + extern "C" { + fn run_pointy(pointy: Pointy); + } + } + mod b { + #[repr(C)] + struct Pointy { + pointy: *const Pointy, + } + + extern "C" { + fn run_pointy(pointy: Pointy); + } + } +} + +mod raw_ptr_recursion_once_removed { + mod a { + #[repr(C)] + struct Pointy1 { + pointy_two: *const Pointy2, + } + + #[repr(C)] + struct Pointy2 { + pointy_one: *const Pointy1, + } + + extern "C" { + fn run_pointy2(pointy: Pointy2); + } + } + + mod b { + #[repr(C)] + struct Pointy1 { + pointy_two: *const Pointy2, + } + + #[repr(C)] + struct Pointy2 { + pointy_one: *const Pointy1, + } + + extern "C" { + fn run_pointy2(pointy: Pointy2); + } + } +} + +mod ref_recursion { + mod a { + #[repr(C)] + struct Reffy<'a> { + reffy: &'a Reffy<'a>, + } + + extern "C" { + fn reffy_recursion(reffy: Reffy); + } + } + mod b { + #[repr(C)] + struct Reffy<'a> { + reffy: &'a Reffy<'a>, + } + + extern "C" { + fn reffy_recursion(reffy: Reffy); + } + } +} + +mod ref_recursion_once_removed { + mod a { + #[repr(C)] + struct Reffy1<'a> { + reffy: &'a Reffy2<'a>, + } + + struct Reffy2<'a> { + reffy: &'a Reffy1<'a>, + } + + extern "C" { + #[allow(improper_ctypes)] + fn reffy_once_removed(reffy: Reffy1); + } + } + mod b { + #[repr(C)] + struct Reffy1<'a> { + reffy: &'a Reffy2<'a>, + } + + struct Reffy2<'a> { + reffy: &'a Reffy1<'a>, + } + + extern "C" { + #[allow(improper_ctypes)] + fn reffy_once_removed(reffy: Reffy1); + } + } +} diff --git a/tests/ui/lint/clashing-extern-fn-wasm.rs b/tests/ui/lint/clashing-extern-fn-wasm.rs new file mode 100644 index 000000000..eeb2b8eae --- /dev/null +++ b/tests/ui/lint/clashing-extern-fn-wasm.rs @@ -0,0 +1,21 @@ +// check-pass +#![crate_type = "lib"] + +#[cfg(target_arch = "wasm32")] +mod wasm_non_clash { + mod a { + #[link(wasm_import_module = "a")] + extern "C" { + pub fn foo(); + } + } + + mod b { + #[link(wasm_import_module = "b")] + extern "C" { + pub fn foo() -> usize; + // #79581: These declarations shouldn't clash because foreign fn names are mangled + // on wasm32. + } + } +} diff --git a/tests/ui/lint/clashing-extern-fn.rs b/tests/ui/lint/clashing-extern-fn.rs new file mode 100644 index 000000000..809e06026 --- /dev/null +++ b/tests/ui/lint/clashing-extern-fn.rs @@ -0,0 +1,417 @@ +// check-pass +// aux-build:external_extern_fn.rs +#![crate_type = "lib"] +#![warn(clashing_extern_declarations)] + +mod redeclared_different_signature { + mod a { + extern "C" { + fn clash(x: u8); + } + } + mod b { + extern "C" { + fn clash(x: u64); //~ WARN `clash` redeclared with a different signature + } + } +} + +mod redeclared_same_signature { + mod a { + extern "C" { + fn no_clash(x: u8); + } + } + mod b { + extern "C" { + fn no_clash(x: u8); + } + } +} + +extern crate external_extern_fn; +mod extern_no_clash { + // Should not clash with external_extern_fn::extern_fn. + extern "C" { + fn extern_fn(x: u8); + } +} + +extern "C" { + fn some_other_new_name(x: i16); + + #[link_name = "extern_link_name"] + fn some_new_name(x: i16); + + #[link_name = "link_name_same"] + fn both_names_different(x: i16); +} + +fn link_name_clash() { + extern "C" { + fn extern_link_name(x: u32); + //~^ WARN `extern_link_name` redeclared with a different signature + + #[link_name = "some_other_new_name"] + //~^ WARN `some_other_extern_link_name` redeclares `some_other_new_name` with a different + fn some_other_extern_link_name(x: u32); + + #[link_name = "link_name_same"] + //~^ WARN `other_both_names_different` redeclares `link_name_same` with a different + fn other_both_names_different(x: u32); + } +} + +mod a { + extern "C" { + fn different_mod(x: u8); + } +} +mod b { + extern "C" { + fn different_mod(x: u64); //~ WARN `different_mod` redeclared with a different signature + } +} + +extern "C" { + fn variadic_decl(x: u8, ...); +} + +fn variadic_clash() { + extern "C" { + fn variadic_decl(x: u8); //~ WARN `variadic_decl` redeclared with a different signature + } +} + +#[no_mangle] +fn no_mangle_name(x: u8) {} + +extern "C" { + #[link_name = "unique_link_name"] + fn link_name_specified(x: u8); +} + +fn tricky_no_clash() { + extern "C" { + // Shouldn't warn, because the declaration above actually declares a different symbol (and + // Rust's name resolution rules around shadowing will handle this gracefully). + fn link_name_specified() -> u32; + + // The case of a no_mangle name colliding with an extern decl (see #28179) is related but + // shouldn't be reported by ClashingExternDeclarations, because this is an example of + // unmangled name clash causing bad behaviour in functions with a defined body. + fn no_mangle_name() -> u32; + } +} + +mod banana { + mod one { + #[repr(C)] + struct Banana { + weight: u32, + length: u16, + } + extern "C" { + fn weigh_banana(count: *const Banana) -> u64; + } + } + + mod two { + #[repr(C)] + struct Banana { + weight: u32, + length: u16, + } // note: distinct type + // This should not trigger the lint because two::Banana is structurally equivalent to + // one::Banana. + extern "C" { + fn weigh_banana(count: *const Banana) -> u64; + } + } + + mod three { + // This _should_ trigger the lint, because repr(packed) should generate a struct that has a + // different layout. + #[repr(packed)] + struct Banana { + weight: u32, + length: u16, + } + #[allow(improper_ctypes)] + extern "C" { + fn weigh_banana(count: *const Banana) -> u64; + //~^ WARN `weigh_banana` redeclared with a different signature + } + } +} + +mod sameish_members { + mod a { + #[repr(C)] + struct Point { + x: i16, + y: i16, + } + + extern "C" { + fn draw_point(p: Point); + } + } + mod b { + #[repr(C)] + struct Point { + coordinates: [i16; 2], + } + + // It's possible we are overconservative for this case, as accessing the elements of the + // coordinates array might end up correctly accessing `.x` and `.y`. However, this may not + // always be the case, for every architecture and situation. This is also a really odd + // thing to do anyway. + extern "C" { + fn draw_point(p: Point); + //~^ WARN `draw_point` redeclared with a different signature + } + } +} + +mod same_sized_members_clash { + mod a { + #[repr(C)] + struct Point3 { + x: f32, + y: f32, + z: f32, + } + extern "C" { + fn origin() -> Point3; + } + } + mod b { + #[repr(C)] + struct Point3 { + x: i32, + y: i32, + z: i32, // NOTE: Incorrectly redeclared as i32 + } + extern "C" { + fn origin() -> Point3; //~ WARN `origin` redeclared with a different signature + } + } +} + +mod transparent { + #[repr(transparent)] + struct T(usize); + mod a { + use super::T; + extern "C" { + fn transparent() -> T; + fn transparent_incorrect() -> T; + } + } + + mod b { + extern "C" { + // Shouldn't warn here, because repr(transparent) guarantees that T's layout is the + // same as just the usize. + fn transparent() -> usize; + + // Should warn, because there's a signedness conversion here: + fn transparent_incorrect() -> isize; + //~^ WARN `transparent_incorrect` redeclared with a different signature + } + } +} + +mod missing_return_type { + mod a { + extern "C" { + fn missing_return_type() -> usize; + } + } + + mod b { + extern "C" { + // This should output a warning because we can't assume that the first declaration is + // the correct one -- if this one is the correct one, then calling the usize-returning + // version would allow reads into uninitialised memory. + fn missing_return_type(); + //~^ WARN `missing_return_type` redeclared with a different signature + } + } +} + +mod non_zero_and_non_null { + mod a { + extern "C" { + fn non_zero_usize() -> core::num::NonZeroUsize; + fn non_null_ptr() -> core::ptr::NonNull<usize>; + } + } + mod b { + extern "C" { + // If there's a clash in either of these cases you're either gaining an incorrect + // invariant that the value is non-zero, or you're missing out on that invariant. Both + // cases are warning for, from both a caller-convenience and optimisation perspective. + fn non_zero_usize() -> usize; + //~^ WARN `non_zero_usize` redeclared with a different signature + fn non_null_ptr() -> *const usize; + //~^ WARN `non_null_ptr` redeclared with a different signature + } + } +} + +// See #75739 +mod non_zero_transparent { + mod a1 { + use std::num::NonZeroUsize; + extern "C" { + fn f1() -> NonZeroUsize; + } + } + + mod b1 { + #[repr(transparent)] + struct X(NonZeroUsize); + use std::num::NonZeroUsize; + extern "C" { + fn f1() -> X; + } + } + + mod a2 { + use std::num::NonZeroUsize; + extern "C" { + fn f2() -> NonZeroUsize; + } + } + + mod b2 { + #[repr(transparent)] + struct X1(NonZeroUsize); + + #[repr(transparent)] + struct X(X1); + + use std::num::NonZeroUsize; + extern "C" { + // Same case as above, but with two layers of newtyping. + fn f2() -> X; + } + } + + mod a3 { + #[repr(transparent)] + struct X(core::ptr::NonNull<i32>); + + use std::num::NonZeroUsize; + extern "C" { + fn f3() -> X; + } + } + + mod b3 { + extern "C" { + fn f3() -> core::ptr::NonNull<i32>; + } + } + + mod a4 { + #[repr(transparent)] + enum E { + X(std::num::NonZeroUsize), + } + extern "C" { + fn f4() -> E; + } + } + + mod b4 { + extern "C" { + fn f4() -> std::num::NonZeroUsize; + } + } +} + +mod null_optimised_enums { + mod a { + extern "C" { + fn option_non_zero_usize() -> usize; + fn option_non_zero_isize() -> isize; + fn option_non_null_ptr() -> *const usize; + + fn option_non_zero_usize_incorrect() -> usize; + fn option_non_null_ptr_incorrect() -> *const usize; + } + } + mod b { + extern "C" { + // This should be allowed, because these conversions are guaranteed to be FFI-safe (see + // #60300) + fn option_non_zero_usize() -> Option<core::num::NonZeroUsize>; + fn option_non_zero_isize() -> Option<core::num::NonZeroIsize>; + fn option_non_null_ptr() -> Option<core::ptr::NonNull<usize>>; + + // However, these should be incorrect (note isize instead of usize) + fn option_non_zero_usize_incorrect() -> isize; + //~^ WARN `option_non_zero_usize_incorrect` redeclared with a different signature + fn option_non_null_ptr_incorrect() -> *const isize; + //~^ WARN `option_non_null_ptr_incorrect` redeclared with a different signature + } + } +} + +#[allow(improper_ctypes)] +mod unknown_layout { + mod a { + extern "C" { + pub fn generic(l: Link<u32>); + } + pub struct Link<T> { + pub item: T, + pub next: *const Link<T>, + } + } + + mod b { + extern "C" { + pub fn generic(l: Link<u32>); + } + pub struct Link<T> { + pub item: T, + pub next: *const Link<T>, + } + } +} + +mod hidden_niche { + mod a { + extern "C" { + fn hidden_niche_transparent() -> usize; + fn hidden_niche_transparent_no_niche() -> usize; + fn hidden_niche_unsafe_cell() -> usize; + } + } + mod b { + use std::cell::UnsafeCell; + use std::num::NonZeroUsize; + + #[repr(transparent)] + struct Transparent { x: NonZeroUsize } + + #[repr(transparent)] + struct TransparentNoNiche { y: UnsafeCell<NonZeroUsize> } + + extern "C" { + fn hidden_niche_transparent() -> Option<Transparent>; + + fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>; + //~^ WARN redeclared with a different signature + //~| WARN block uses type `Option<TransparentNoNiche>`, which is not FFI-safe + + fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize>>; + //~^ WARN redeclared with a different signature + //~| WARN block uses type `Option<UnsafeCell<NonZeroUsize>>`, which is not FFI-safe + } + } +} diff --git a/tests/ui/lint/clashing-extern-fn.stderr b/tests/ui/lint/clashing-extern-fn.stderr new file mode 100644 index 000000000..217eed6c9 --- /dev/null +++ b/tests/ui/lint/clashing-extern-fn.stderr @@ -0,0 +1,236 @@ +warning: `clash` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:14:13 + | +LL | fn clash(x: u8); + | ---------------- `clash` previously declared here +... +LL | fn clash(x: u64); + | ^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(u8)` + found `unsafe extern "C" fn(u64)` +note: the lint level is defined here + --> $DIR/clashing-extern-fn.rs:4:9 + | +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 | 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)` + +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 | / #[link_name = "some_other_new_name"] +LL | | +LL | | fn some_other_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)` + +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"] +LL | | +LL | | fn other_both_names_different(x: u32); + | |______________________________________________^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(i16)` + found `unsafe extern "C" fn(u32)` + +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 +... +LL | fn different_mod(x: u64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(u8)` + found `unsafe extern "C" fn(u64)` + +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 +... +LL | fn variadic_decl(x: u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(u8, ...)` + found `unsafe extern "C" fn(u8)` + +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 +... +LL | fn weigh_banana(count: *const Banana) -> u64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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` + +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 +... +LL | fn draw_point(p: Point); + | ^^^^^^^^^^^^^^^^^^^^^^^^ 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)` + +warning: `origin` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:197:13 + | +LL | fn origin() -> Point3; + | ---------------------- `origin` previously declared here +... +LL | fn origin() -> Point3; + | ^^^^^^^^^^^^^^^^^^^^^^ 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` + +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 +... +LL | fn transparent_incorrect() -> isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> T` + found `unsafe extern "C" fn() -> isize` + +warning: `missing_return_type` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:238:13 + | +LL | fn missing_return_type() -> usize; + | ---------------------------------- `missing_return_type` previously declared here +... +LL | fn missing_return_type(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> usize` + found `unsafe extern "C" fn()` + +warning: `non_zero_usize` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:256:13 + | +LL | fn non_zero_usize() -> core::num::NonZeroUsize; + | ----------------------------------------------- `non_zero_usize` previously declared here +... +LL | fn non_zero_usize() -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> NonZeroUsize` + found `unsafe extern "C" fn() -> usize` + +warning: `non_null_ptr` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:258:13 + | +LL | fn non_null_ptr() -> core::ptr::NonNull<usize>; + | ----------------------------------------------- `non_null_ptr` previously declared here +... +LL | fn non_null_ptr() -> *const usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> NonNull<usize>` + found `unsafe extern "C" fn() -> *const usize` + +warning: `option_non_zero_usize_incorrect` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:356:13 + | +LL | fn option_non_zero_usize_incorrect() -> usize; + | ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here +... +LL | fn option_non_zero_usize_incorrect() -> isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> usize` + found `unsafe extern "C" fn() -> isize` + +warning: `option_non_null_ptr_incorrect` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:358:13 + | +LL | fn option_non_null_ptr_incorrect() -> *const usize; + | --------------------------------------------------- `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 + | + = note: expected `unsafe extern "C" fn() -> *const usize` + found `unsafe extern "C" fn() -> *const isize` + +warning: `hidden_niche_transparent_no_niche` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:408:13 + | +LL | fn hidden_niche_transparent_no_niche() -> usize; + | ------------------------------------------------ `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 + | + = note: expected `unsafe extern "C" fn() -> usize` + found `unsafe extern "C" fn() -> Option<TransparentNoNiche>` + +warning: `hidden_niche_unsafe_cell` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:412:13 + | +LL | fn hidden_niche_unsafe_cell() -> usize; + | --------------------------------------- `hidden_niche_unsafe_cell` previously declared here +... +LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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:408: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:412: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/cli-lint-override.forbid_warn.stderr b/tests/ui/lint/cli-lint-override.forbid_warn.stderr new file mode 100644 index 000000000..d1c66a81c --- /dev/null +++ b/tests/ui/lint/cli-lint-override.forbid_warn.stderr @@ -0,0 +1,11 @@ +error: extern declarations without an explicit ABI are deprecated + --> $DIR/cli-lint-override.rs:12:1 + | +LL | extern fn foo() {} + | ^^^^^^^^^^^^^^^ ABI should be specified here + | + = help: the default ABI is C + = note: requested on the command line with `-F missing-abi` + +error: aborting due to previous error + diff --git a/tests/ui/lint/cli-lint-override.force_warn_deny.stderr b/tests/ui/lint/cli-lint-override.force_warn_deny.stderr new file mode 100644 index 000000000..779c24c93 --- /dev/null +++ b/tests/ui/lint/cli-lint-override.force_warn_deny.stderr @@ -0,0 +1,11 @@ +warning: extern declarations without an explicit ABI are deprecated + --> $DIR/cli-lint-override.rs:12:1 + | +LL | extern fn foo() {} + | ^^^^^^^^^^^^^^^ ABI should be specified here + | + = help: the default ABI is C + = note: requested on the command line with `--force-warn missing-abi` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/cli-lint-override.rs b/tests/ui/lint/cli-lint-override.rs new file mode 100644 index 000000000..a0e853fc3 --- /dev/null +++ b/tests/ui/lint/cli-lint-override.rs @@ -0,0 +1,17 @@ +// Tests that subsequent lints specified via the command line override +// each other, except for ForceWarn and Forbid, which cannot be overridden. +// +// revisions: warn_deny forbid_warn force_warn_deny +// +//[warn_deny] compile-flags: --warn missing_abi --deny missing_abi +//[forbid_warn] compile-flags: --warn missing_abi --forbid missing_abi +//[force_warn_deny] compile-flags: --force-warn missing_abi --allow missing_abi +//[force_warn_deny] check-pass + + +extern fn foo() {} +//[warn_deny]~^ ERROR extern declarations without an explicit ABI are deprecated +//[forbid_warn]~^^ ERROR extern declarations without an explicit ABI are deprecated +//[force_warn_deny]~^^^ WARN extern declarations without an explicit ABI are deprecated + +fn main() {} diff --git a/tests/ui/lint/cli-lint-override.warn_deny.stderr b/tests/ui/lint/cli-lint-override.warn_deny.stderr new file mode 100644 index 000000000..f034cfa93 --- /dev/null +++ b/tests/ui/lint/cli-lint-override.warn_deny.stderr @@ -0,0 +1,11 @@ +error: extern declarations without an explicit ABI are deprecated + --> $DIR/cli-lint-override.rs:12:1 + | +LL | extern fn foo() {} + | ^^^^^^^^^^^^^^^ ABI should be specified here + | + = help: the default ABI is C + = note: requested on the command line with `-D missing-abi` + +error: aborting due to previous error + diff --git a/tests/ui/lint/cli-unknown-force-warn.rs b/tests/ui/lint/cli-unknown-force-warn.rs new file mode 100644 index 000000000..f3dea87a6 --- /dev/null +++ b/tests/ui/lint/cli-unknown-force-warn.rs @@ -0,0 +1,7 @@ +// Checks that rustc correctly errors when passed an invalid lint with +// `--force-warn`. This is a regression test for issue #86958. +// +// compile-flags: --force-warn foo-qux +// error-pattern: unknown lint: `foo_qux` + +fn main() {} diff --git a/tests/ui/lint/cli-unknown-force-warn.stderr b/tests/ui/lint/cli-unknown-force-warn.stderr new file mode 100644 index 000000000..9ce9f405a --- /dev/null +++ b/tests/ui/lint/cli-unknown-force-warn.stderr @@ -0,0 +1,11 @@ +error[E0602]: unknown lint: `foo_qux` + | + = note: requested on the command line with `--force-warn foo_qux` + +error[E0602]: unknown lint: `foo_qux` + | + = note: requested on the command line with `--force-warn foo_qux` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/command-line-lint-group-allow.rs b/tests/ui/lint/command-line-lint-group-allow.rs new file mode 100644 index 000000000..21c0df028 --- /dev/null +++ b/tests/ui/lint/command-line-lint-group-allow.rs @@ -0,0 +1,6 @@ +// compile-flags: -A bad-style +// check-pass + +fn main() { + let _InappropriateCamelCasing = true; +} diff --git a/tests/ui/lint/command-line-lint-group-deny.rs b/tests/ui/lint/command-line-lint-group-deny.rs new file mode 100644 index 000000000..da999f33e --- /dev/null +++ b/tests/ui/lint/command-line-lint-group-deny.rs @@ -0,0 +1,5 @@ +// compile-flags: -D bad-style + +fn main() { + let _InappropriateCamelCasing = true; //~ ERROR should have a snake +} diff --git a/tests/ui/lint/command-line-lint-group-deny.stderr b/tests/ui/lint/command-line-lint-group-deny.stderr new file mode 100644 index 000000000..04c3f6f26 --- /dev/null +++ b/tests/ui/lint/command-line-lint-group-deny.stderr @@ -0,0 +1,10 @@ +error: variable `_InappropriateCamelCasing` should have a snake case name + --> $DIR/command-line-lint-group-deny.rs:4:9 + | +LL | let _InappropriateCamelCasing = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `_inappropriate_camel_casing` + | + = note: `-D non-snake-case` implied by `-D bad-style` + +error: aborting due to previous error + diff --git a/tests/ui/lint/command-line-lint-group-forbid.rs b/tests/ui/lint/command-line-lint-group-forbid.rs new file mode 100644 index 000000000..4e5c2aca5 --- /dev/null +++ b/tests/ui/lint/command-line-lint-group-forbid.rs @@ -0,0 +1,5 @@ +// compile-flags: -F bad-style + +fn main() { + let _InappropriateCamelCasing = true; //~ ERROR should have a snake +} diff --git a/tests/ui/lint/command-line-lint-group-forbid.stderr b/tests/ui/lint/command-line-lint-group-forbid.stderr new file mode 100644 index 000000000..736782140 --- /dev/null +++ b/tests/ui/lint/command-line-lint-group-forbid.stderr @@ -0,0 +1,10 @@ +error: variable `_InappropriateCamelCasing` should have a snake case name + --> $DIR/command-line-lint-group-forbid.rs:4:9 + | +LL | let _InappropriateCamelCasing = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `_inappropriate_camel_casing` + | + = note: `-F non-snake-case` implied by `-F bad-style` + +error: aborting due to previous error + diff --git a/tests/ui/lint/command-line-lint-group-warn.rs b/tests/ui/lint/command-line-lint-group-warn.rs new file mode 100644 index 000000000..f4536f9c9 --- /dev/null +++ b/tests/ui/lint/command-line-lint-group-warn.rs @@ -0,0 +1,7 @@ +// compile-flags: -W bad-style +// check-pass + +fn main() { + let _InappropriateCamelCasing = true; + //~^ WARNING should have a snake case name +} diff --git a/tests/ui/lint/command-line-lint-group-warn.stderr b/tests/ui/lint/command-line-lint-group-warn.stderr new file mode 100644 index 000000000..e9c80b4ef --- /dev/null +++ b/tests/ui/lint/command-line-lint-group-warn.stderr @@ -0,0 +1,10 @@ +warning: variable `_InappropriateCamelCasing` should have a snake case name + --> $DIR/command-line-lint-group-warn.rs:5:9 + | +LL | let _InappropriateCamelCasing = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `_inappropriate_camel_casing` + | + = note: `-W non-snake-case` implied by `-W bad-style` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/command-line-register-lint-tool.rs b/tests/ui/lint/command-line-register-lint-tool.rs new file mode 100644 index 000000000..d6e95fd3e --- /dev/null +++ b/tests/ui/lint/command-line-register-lint-tool.rs @@ -0,0 +1,7 @@ +// compile-flags: -A known_tool::foo +// check-pass + +#![feature(register_tool)] +#![register_tool(known_tool)] + +fn main() {} diff --git a/tests/ui/lint/command-line-register-unknown-lint-tool.rs b/tests/ui/lint/command-line-register-unknown-lint-tool.rs new file mode 100644 index 000000000..59fc02000 --- /dev/null +++ b/tests/ui/lint/command-line-register-unknown-lint-tool.rs @@ -0,0 +1,4 @@ +// compile-flags: -A unknown_tool::foo +// error-pattern: unknown lint tool: `unknown_tool` + +fn main() {} diff --git a/tests/ui/lint/command-line-register-unknown-lint-tool.stderr b/tests/ui/lint/command-line-register-unknown-lint-tool.stderr new file mode 100644 index 000000000..c9a2aff21 --- /dev/null +++ b/tests/ui/lint/command-line-register-unknown-lint-tool.stderr @@ -0,0 +1,11 @@ +error[E0602]: unknown lint tool: `unknown_tool` + | + = note: requested on the command line with `-A unknown_tool::foo` + +error[E0602]: unknown lint tool: `unknown_tool` + | + = note: requested on the command line with `-A unknown_tool::foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/crate_level_only_lint.rs b/tests/ui/lint/crate_level_only_lint.rs new file mode 100644 index 000000000..d9673faa2 --- /dev/null +++ b/tests/ui/lint/crate_level_only_lint.rs @@ -0,0 +1,22 @@ +#![deny(uncommon_codepoints, unused_attributes)] + +mod foo { +#![allow(uncommon_codepoints)] +//~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] + +#[allow(uncommon_codepoints)] +//~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +const BAR: f64 = 0.000001; + +} + +#[allow(uncommon_codepoints)] +//~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +fn main() { +} diff --git a/tests/ui/lint/crate_level_only_lint.stderr b/tests/ui/lint/crate_level_only_lint.stderr new file mode 100644 index 000000000..8fb06df2a --- /dev/null +++ b/tests/ui/lint/crate_level_only_lint.stderr @@ -0,0 +1,62 @@ +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:4:10 + | +LL | #![allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/crate_level_only_lint.rs:1:30 + | +LL | #![deny(uncommon_codepoints, unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:9:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:17:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:4:10 + | +LL | #![allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:9:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:17:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:4:10 + | +LL | #![allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:9:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:17:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/dead-code/alias-in-pat.rs b/tests/ui/lint/dead-code/alias-in-pat.rs new file mode 100644 index 000000000..69d455f3b --- /dev/null +++ b/tests/ui/lint/dead-code/alias-in-pat.rs @@ -0,0 +1,10 @@ +// run-pass + +#![deny(dead_code)] + +fn main() { + struct Foo<T> { x: T } + type Bar = Foo<u32>; + let spam = |Bar { x }| x != 0; + println!("{}", spam(Foo { x: 10 })); +} diff --git a/tests/ui/lint/dead-code/anon-const-in-pat.rs b/tests/ui/lint/dead-code/anon-const-in-pat.rs new file mode 100644 index 000000000..d3e39c0de --- /dev/null +++ b/tests/ui/lint/dead-code/anon-const-in-pat.rs @@ -0,0 +1,45 @@ +// check-pass +#![feature(inline_const_pat)] +#![allow(incomplete_features)] +#![deny(dead_code)] + +const fn one() -> i32 { + 1 +} + +const fn two() -> i32 { + 2 +} + +const fn three() -> i32 { + 3 +} + +fn inline_const() { + // rust-lang/rust#78171: dead_code lint triggers even though function is used in const pattern + match 1 { + const { one() } => {} + _ => {} + } +} + +fn inline_const_range() { + match 1 { + 1 ..= const { two() } => {} + _ => {} + } +} + +struct S<const C: i32>; + +fn const_generic_arg() { + match S::<3> { + S::<{three()}> => {} + } +} + +fn main() { + inline_const(); + inline_const_range(); + const_generic_arg(); +} diff --git a/tests/ui/lint/dead-code/associated-type.rs b/tests/ui/lint/dead-code/associated-type.rs new file mode 100644 index 000000000..1cf66e75a --- /dev/null +++ b/tests/ui/lint/dead-code/associated-type.rs @@ -0,0 +1,19 @@ +// run-pass + +#![deny(dead_code)] + +trait Foo { + type Bar; +} + +struct Used; + +struct Ex; + +impl Foo for Ex { + type Bar = Used; +} + +pub fn main() { + let _x = Ex; +} diff --git a/tests/ui/lint/dead-code/basic.rs b/tests/ui/lint/dead-code/basic.rs new file mode 100644 index 000000000..3b8ffd58c --- /dev/null +++ b/tests/ui/lint/dead-code/basic.rs @@ -0,0 +1,15 @@ +#![deny(dead_code)] +#![allow(unreachable_code)] + +fn foo() { //~ ERROR function `foo` is never used + + // none of these should have any dead_code exposed to the user + panic!(); + + panic!("foo"); + + panic!("bar {}", "baz") +} + + +fn main() {} diff --git a/tests/ui/lint/dead-code/basic.stderr b/tests/ui/lint/dead-code/basic.stderr new file mode 100644 index 000000000..7d068cead --- /dev/null +++ b/tests/ui/lint/dead-code/basic.stderr @@ -0,0 +1,14 @@ +error: function `foo` is never used + --> $DIR/basic.rs:4:4 + | +LL | fn foo() { + | ^^^ + | +note: the lint level is defined here + --> $DIR/basic.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/dead-code/closure-bang.rs b/tests/ui/lint/dead-code/closure-bang.rs new file mode 100644 index 000000000..8e8636b11 --- /dev/null +++ b/tests/ui/lint/dead-code/closure-bang.rs @@ -0,0 +1,9 @@ +// ignore-test FIXME(#20574) + +#![deny(unreachable_code)] + +fn main() { + let x = || panic!(); + x(); + println!("Foo bar"); //~ ERROR: unreachable statement +} diff --git a/tests/ui/lint/dead-code/const-and-self.rs b/tests/ui/lint/dead-code/const-and-self.rs new file mode 100644 index 000000000..5c96e4d0e --- /dev/null +++ b/tests/ui/lint/dead-code/const-and-self.rs @@ -0,0 +1,54 @@ +// check-pass + +#![warn(dead_code)] + +const TLC: usize = 4; + +trait Tr { fn doit(&self); } + +impl Tr for [usize; TLC] { + fn doit(&self) { + println!("called 4"); + } +} + +struct X; +struct Y; +struct Z; + +trait Foo<T> { + type Ty; + fn foo() -> Self::Ty; +} + +impl Foo<Y> for X { + type Ty = Z; + fn foo() -> Self::Ty { + unimplemented!() + } +} + +enum E { + A, + B, //~ WARN variants `B` and `C` are never constructed + C, +} + +type F = E; + +impl E { + fn check(&self) -> bool { + match self { + Self::A => true, + Self::B => false, + F::C => false, + } + } +} + +fn main() { + let s = [0,1,2,3]; + s.doit(); + X::foo(); + E::A.check(); +} diff --git a/tests/ui/lint/dead-code/const-and-self.stderr b/tests/ui/lint/dead-code/const-and-self.stderr new file mode 100644 index 000000000..9d1d7d6ec --- /dev/null +++ b/tests/ui/lint/dead-code/const-and-self.stderr @@ -0,0 +1,19 @@ +warning: variants `B` and `C` are never constructed + --> $DIR/const-and-self.rs:33:5 + | +LL | enum E { + | - variants in this enum +LL | A, +LL | B, + | ^ +LL | C, + | ^ + | +note: the lint level is defined here + --> $DIR/const-and-self.rs:3:9 + | +LL | #![warn(dead_code)] + | ^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/dead-code/empty-unused-enum.rs b/tests/ui/lint/dead-code/empty-unused-enum.rs new file mode 100644 index 000000000..864501e94 --- /dev/null +++ b/tests/ui/lint/dead-code/empty-unused-enum.rs @@ -0,0 +1,5 @@ +#![deny(unused)] + +enum E {} //~ ERROR enum `E` is never used + +fn main() {} diff --git a/tests/ui/lint/dead-code/empty-unused-enum.stderr b/tests/ui/lint/dead-code/empty-unused-enum.stderr new file mode 100644 index 000000000..6391f0941 --- /dev/null +++ b/tests/ui/lint/dead-code/empty-unused-enum.stderr @@ -0,0 +1,15 @@ +error: enum `E` is never used + --> $DIR/empty-unused-enum.rs:3:6 + | +LL | enum E {} + | ^ + | +note: the lint level is defined here + --> $DIR/empty-unused-enum.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + +error: aborting due to previous error + diff --git a/tests/ui/lint/dead-code/empty-unused-public-enum.rs b/tests/ui/lint/dead-code/empty-unused-public-enum.rs new file mode 100644 index 000000000..15b04496b --- /dev/null +++ b/tests/ui/lint/dead-code/empty-unused-public-enum.rs @@ -0,0 +1,6 @@ +// build-pass +#![deny(unused)] + +pub enum E {} + +fn main() {} diff --git a/tests/ui/lint/dead-code/enum-variants.rs b/tests/ui/lint/dead-code/enum-variants.rs new file mode 100644 index 000000000..91c97232e --- /dev/null +++ b/tests/ui/lint/dead-code/enum-variants.rs @@ -0,0 +1,14 @@ +// run-pass + +#![deny(dead_code)] + +enum Foo { + A, + B, +} + +pub fn main() { + match Foo::A { + Foo::A | Foo::B => Foo::B + }; +} diff --git a/tests/ui/lint/dead-code/impl-trait.rs b/tests/ui/lint/dead-code/impl-trait.rs new file mode 100644 index 000000000..757b8f83e --- /dev/null +++ b/tests/ui/lint/dead-code/impl-trait.rs @@ -0,0 +1,18 @@ +#![deny(dead_code)] + +trait Trait { + type Type; +} + +impl Trait for () { + type Type = (); +} + +type Used = (); +type Unused = (); //~ ERROR type alias `Unused` is never used + +fn foo() -> impl Trait<Type = Used> {} + +fn main() { + foo(); +} diff --git a/tests/ui/lint/dead-code/impl-trait.stderr b/tests/ui/lint/dead-code/impl-trait.stderr new file mode 100644 index 000000000..e35e13a9e --- /dev/null +++ b/tests/ui/lint/dead-code/impl-trait.stderr @@ -0,0 +1,14 @@ +error: type alias `Unused` is never used + --> $DIR/impl-trait.rs:12:6 + | +LL | type Unused = (); + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/impl-trait.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/dead-code/issue-68408-false-positive.rs b/tests/ui/lint/dead-code/issue-68408-false-positive.rs new file mode 100644 index 000000000..7ee6b5d72 --- /dev/null +++ b/tests/ui/lint/dead-code/issue-68408-false-positive.rs @@ -0,0 +1,22 @@ +// check-pass + +// Make sure we don't have any false positives here. + +#![deny(dead_code)] + +enum X { + A { _a: () }, + B { _b: () }, +} +impl X { + fn a() -> X { + X::A { _a: () } + } + fn b() -> Self { + Self::B { _b: () } + } +} + +fn main() { + let (_, _) = (X::a(), X::b()); +} diff --git a/tests/ui/lint/dead-code/issue-85071-2.rs b/tests/ui/lint/dead-code/issue-85071-2.rs new file mode 100644 index 000000000..f0639931c --- /dev/null +++ b/tests/ui/lint/dead-code/issue-85071-2.rs @@ -0,0 +1,22 @@ +// A slight variation of issue-85071.rs. Here, a method is called instead +// of a function, and the warning is about an unreachable definition +// instead of an unreachable expression. + +// check-pass + +#![warn(unused_variables,unreachable_code)] + +enum Foo {} + +struct S; +impl S { + fn f(&self) -> Foo {todo!()} +} + +fn main() { + let s = S; + let x = s.f(); + //~^ WARNING: unused variable: `x` + let _y = x; + //~^ WARNING: unreachable definition +} diff --git a/tests/ui/lint/dead-code/issue-85071-2.stderr b/tests/ui/lint/dead-code/issue-85071-2.stderr new file mode 100644 index 000000000..5e963183d --- /dev/null +++ b/tests/ui/lint/dead-code/issue-85071-2.stderr @@ -0,0 +1,34 @@ +warning: unreachable definition + --> $DIR/issue-85071-2.rs:20:9 + | +LL | let x = s.f(); + | ----- any code following this expression is unreachable +LL | +LL | let _y = x; + | ^^ unreachable definition + | +note: this expression has type `Foo`, which is uninhabited + --> $DIR/issue-85071-2.rs:18:13 + | +LL | let x = s.f(); + | ^^^^^ +note: the lint level is defined here + --> $DIR/issue-85071-2.rs:7:26 + | +LL | #![warn(unused_variables,unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +warning: unused variable: `x` + --> $DIR/issue-85071-2.rs:18:9 + | +LL | let x = s.f(); + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | +note: the lint level is defined here + --> $DIR/issue-85071-2.rs:7:9 + | +LL | #![warn(unused_variables,unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/dead-code/issue-85071.rs b/tests/ui/lint/dead-code/issue-85071.rs new file mode 100644 index 000000000..d6969321c --- /dev/null +++ b/tests/ui/lint/dead-code/issue-85071.rs @@ -0,0 +1,19 @@ +// Checks that an unreachable code warning is emitted when an expression is +// preceded by an expression with an uninhabited type. Previously, the +// variable liveness analysis was "smarter" than the reachability analysis +// in this regard, which led to confusing "unused variable" warnings +// without an accompanying explanatory "unreachable expression" warning. + +// check-pass + +#![warn(unused_variables,unreachable_code)] + +enum Foo {} +fn f() -> Foo {todo!()} + +fn main() { + let x = f(); + //~^ WARNING: unused variable: `x` + let _ = x; + //~^ WARNING: unreachable expression +} diff --git a/tests/ui/lint/dead-code/issue-85071.stderr b/tests/ui/lint/dead-code/issue-85071.stderr new file mode 100644 index 000000000..721fb8148 --- /dev/null +++ b/tests/ui/lint/dead-code/issue-85071.stderr @@ -0,0 +1,34 @@ +warning: unreachable expression + --> $DIR/issue-85071.rs:17:13 + | +LL | let x = f(); + | --- any code following this expression is unreachable +LL | +LL | let _ = x; + | ^ unreachable expression + | +note: this expression has type `Foo`, which is uninhabited + --> $DIR/issue-85071.rs:15:13 + | +LL | let x = f(); + | ^^^ +note: the lint level is defined here + --> $DIR/issue-85071.rs:9:26 + | +LL | #![warn(unused_variables,unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +warning: unused variable: `x` + --> $DIR/issue-85071.rs:15:9 + | +LL | let x = f(); + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | +note: the lint level is defined here + --> $DIR/issue-85071.rs:9:9 + | +LL | #![warn(unused_variables,unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/dead-code/issue-85255.rs b/tests/ui/lint/dead-code/issue-85255.rs new file mode 100644 index 000000000..043f68137 --- /dev/null +++ b/tests/ui/lint/dead-code/issue-85255.rs @@ -0,0 +1,50 @@ +// Unused `pub` fields in non-`pub` structs should also trigger dead code warnings. +// check-pass + +#![warn(dead_code)] + +struct Foo { + a: i32, //~ WARNING: fields `a` and `b` are never read + pub b: i32, +} + +struct Bar; + +impl Bar { + fn a(&self) -> i32 { 5 } //~ WARNING: associated function `a` is never used + pub fn b(&self) -> i32 { 6 } //~ WARNING: associated function `b` is never used +} + +pub(crate) struct Foo1 { + a: i32, //~ WARNING: fields `a` and `b` are never read + pub b: i32, +} + +pub(crate) struct Bar1; + +impl Bar1 { + fn a(&self) -> i32 { 5 } //~ WARNING: associated function `a` is never used + pub fn b(&self) -> i32 { 6 } //~ WARNING: associated function `b` is never used +} + +pub(crate) struct Foo2 { + a: i32, //~ WARNING: fields `a` and `b` are never read + pub b: i32, +} + +pub(crate) struct Bar2; + +impl Bar2 { + fn a(&self) -> i32 { 5 } //~ WARNING: associated function `a` is never used + pub fn b(&self) -> i32 { 6 } //~ WARNING: associated function `b` is never used +} + + +fn main() { + let _ = Foo { a: 1, b: 2 }; + let _ = Bar; + let _ = Foo1 { a: 1, b: 2 }; + let _ = Bar1; + let _ = Foo2 { a: 1, b: 2 }; + let _ = Bar2; +} diff --git a/tests/ui/lint/dead-code/issue-85255.stderr b/tests/ui/lint/dead-code/issue-85255.stderr new file mode 100644 index 000000000..3497b952f --- /dev/null +++ b/tests/ui/lint/dead-code/issue-85255.stderr @@ -0,0 +1,74 @@ +warning: fields `a` and `b` are never read + --> $DIR/issue-85255.rs:7:5 + | +LL | struct Foo { + | --- fields in this struct +LL | a: i32, + | ^ +LL | pub b: i32, + | ^ + | +note: the lint level is defined here + --> $DIR/issue-85255.rs:4:9 + | +LL | #![warn(dead_code)] + | ^^^^^^^^^ + +warning: fields `a` and `b` are never read + --> $DIR/issue-85255.rs:19:5 + | +LL | pub(crate) struct Foo1 { + | ---- fields in this struct +LL | a: i32, + | ^ +LL | pub b: i32, + | ^ + +warning: fields `a` and `b` are never read + --> $DIR/issue-85255.rs:31:5 + | +LL | pub(crate) struct Foo2 { + | ---- fields in this struct +LL | a: i32, + | ^ +LL | pub b: i32, + | ^ + +warning: associated function `a` is never used + --> $DIR/issue-85255.rs:14:8 + | +LL | fn a(&self) -> i32 { 5 } + | ^ + +warning: associated function `b` is never used + --> $DIR/issue-85255.rs:15:12 + | +LL | pub fn b(&self) -> i32 { 6 } + | ^ + +warning: associated function `a` is never used + --> $DIR/issue-85255.rs:26:8 + | +LL | fn a(&self) -> i32 { 5 } + | ^ + +warning: associated function `b` is never used + --> $DIR/issue-85255.rs:27:12 + | +LL | pub fn b(&self) -> i32 { 6 } + | ^ + +warning: associated function `a` is never used + --> $DIR/issue-85255.rs:38:8 + | +LL | fn a(&self) -> i32 { 5 } + | ^ + +warning: associated function `b` is never used + --> $DIR/issue-85255.rs:39:12 + | +LL | pub fn b(&self) -> i32 { 6 } + | ^ + +warning: 9 warnings emitted + diff --git a/tests/ui/lint/dead-code/leading-underscore.rs b/tests/ui/lint/dead-code/leading-underscore.rs new file mode 100644 index 000000000..d3582961b --- /dev/null +++ b/tests/ui/lint/dead-code/leading-underscore.rs @@ -0,0 +1,31 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![deny(dead_code)] + +static _X: usize = 0; + +fn _foo() {} + +struct _Y { + _z: usize, +} + +enum _Z {} + +impl _Y { + fn _bar() {} +} + +type _A = isize; + +mod _bar { + fn _qux() {} +} + +extern "C" { + #[link_name = "abort"] + fn _abort() -> !; +} + +pub fn main() {} diff --git a/tests/ui/lint/dead-code/lint-dead-code-1.rs b/tests/ui/lint/dead-code/lint-dead-code-1.rs new file mode 100644 index 000000000..8f5a4c41e --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-1.rs @@ -0,0 +1,110 @@ +#![no_std] +#![allow(unused_variables)] +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] +#![deny(dead_code)] + +#![crate_type="lib"] + +pub use foo2::Bar2; + +mod foo { + pub struct Bar; //~ ERROR: struct `Bar` is never constructed +} + +mod foo2 { + pub struct Bar2; +} + +pub static pub_static: isize = 0; +static priv_static: isize = 0; //~ ERROR: static `priv_static` is never used +const used_static: isize = 0; +pub static used_static2: isize = used_static; +const USED_STATIC: isize = 0; +const STATIC_USED_IN_ENUM_DISCRIMINANT: isize = 10; + +pub const pub_const: isize = 0; +const priv_const: isize = 0; //~ ERROR: constant `priv_const` is never used +const used_const: isize = 0; +pub const used_const2: isize = used_const; +const USED_CONST: isize = 1; +const CONST_USED_IN_ENUM_DISCRIMINANT: isize = 11; + +pub type typ = *const UsedStruct4; +pub struct PubStruct; +struct PrivStruct; //~ ERROR: struct `PrivStruct` is never constructed +struct UsedStruct1 { + #[allow(dead_code)] + x: isize +} +struct UsedStruct2(isize); +struct UsedStruct3; +pub struct UsedStruct4; +// this struct is never used directly, but its method is, so we don't want +// to warn it +struct SemiUsedStruct; +impl SemiUsedStruct { + fn la_la_la() {} +} +struct StructUsedAsField; +pub struct StructUsedInEnum; +struct StructUsedInGeneric; +pub struct PubStruct2 { + #[allow(dead_code)] + struct_used_as_field: *const StructUsedAsField +} + +pub enum pub_enum { foo1, bar1 } +pub enum pub_enum2 { a(*const StructUsedInEnum) } +pub enum pub_enum3 { + Foo = STATIC_USED_IN_ENUM_DISCRIMINANT, + Bar = CONST_USED_IN_ENUM_DISCRIMINANT, +} + +enum priv_enum { foo2, bar2 } //~ ERROR: enum `priv_enum` is never used +enum used_enum { + foo3, + bar3 //~ ERROR variant `bar3` is never constructed +} + +fn f<T>() {} + +pub fn pub_fn() { + used_fn(); + let used_struct1 = UsedStruct1 { x: 1 }; + let used_struct2 = UsedStruct2(1); + let used_struct3 = UsedStruct3; + let e = used_enum::foo3; + SemiUsedStruct::la_la_la(); + + let i = 1; + match i { + USED_STATIC => (), + USED_CONST => (), + _ => () + } + f::<StructUsedInGeneric>(); +} +fn priv_fn() { //~ ERROR: function `priv_fn` is never used + let unused_struct = PrivStruct; +} +fn used_fn() {} + +fn foo() { //~ ERROR: function `foo` is never used + bar(); + let unused_enum = priv_enum::foo2; +} + +fn bar() { //~ ERROR: function `bar` is never used + foo(); +} + +fn baz() -> impl Copy { //~ ERROR: function `baz` is never used + "I'm unused, too" +} + +// Code with #[allow(dead_code)] should be marked live (and thus anything it +// calls is marked live) +#[allow(dead_code)] +fn g() { h(); } +fn h() {} diff --git a/tests/ui/lint/dead-code/lint-dead-code-1.stderr b/tests/ui/lint/dead-code/lint-dead-code-1.stderr new file mode 100644 index 000000000..eb728b5b9 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-1.stderr @@ -0,0 +1,71 @@ +error: static `priv_static` is never used + --> $DIR/lint-dead-code-1.rs:20:8 + | +LL | static priv_static: isize = 0; + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-dead-code-1.rs:5:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: constant `priv_const` is never used + --> $DIR/lint-dead-code-1.rs:27:7 + | +LL | const priv_const: isize = 0; + | ^^^^^^^^^^ + +error: struct `PrivStruct` is never constructed + --> $DIR/lint-dead-code-1.rs:35:8 + | +LL | struct PrivStruct; + | ^^^^^^^^^^ + +error: enum `priv_enum` is never used + --> $DIR/lint-dead-code-1.rs:64:6 + | +LL | enum priv_enum { foo2, bar2 } + | ^^^^^^^^^ + +error: variant `bar3` is never constructed + --> $DIR/lint-dead-code-1.rs:67:5 + | +LL | enum used_enum { + | --------- variant in this enum +LL | foo3, +LL | bar3 + | ^^^^ + +error: function `priv_fn` is never used + --> $DIR/lint-dead-code-1.rs:88:4 + | +LL | fn priv_fn() { + | ^^^^^^^ + +error: function `foo` is never used + --> $DIR/lint-dead-code-1.rs:93:4 + | +LL | fn foo() { + | ^^^ + +error: function `bar` is never used + --> $DIR/lint-dead-code-1.rs:98:4 + | +LL | fn bar() { + | ^^^ + +error: function `baz` is never used + --> $DIR/lint-dead-code-1.rs:102:4 + | +LL | fn baz() -> impl Copy { + | ^^^ + +error: struct `Bar` is never constructed + --> $DIR/lint-dead-code-1.rs:12:16 + | +LL | pub struct Bar; + | ^^^ + +error: aborting due to 10 previous errors + diff --git a/tests/ui/lint/dead-code/lint-dead-code-2.rs b/tests/ui/lint/dead-code/lint-dead-code-2.rs new file mode 100644 index 000000000..6bfa4d96f --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-2.rs @@ -0,0 +1,41 @@ +#![allow(unused_variables)] +#![deny(dead_code)] +#![feature(rustc_attrs, start)] + +struct Foo; + +trait Bar { + fn bar1(&self); + fn bar2(&self) { + self.bar1(); + } +} + +impl Bar for Foo { + fn bar1(&self) { + live_fn(); + } +} + +fn live_fn() {} + +fn dead_fn() {} //~ ERROR: function `dead_fn` is never used + +#[rustc_main] +fn dead_fn2() {} //~ ERROR: function `dead_fn2` is never used + +fn used_fn() {} + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + used_fn(); + let foo = Foo; + foo.bar2(); + 0 +} + +// this is not main +fn main() { //~ ERROR: function `main` is never used + dead_fn(); + dead_fn2(); +} diff --git a/tests/ui/lint/dead-code/lint-dead-code-2.stderr b/tests/ui/lint/dead-code/lint-dead-code-2.stderr new file mode 100644 index 000000000..85af553c9 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-2.stderr @@ -0,0 +1,26 @@ +error: function `dead_fn` is never used + --> $DIR/lint-dead-code-2.rs:22:4 + | +LL | fn dead_fn() {} + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-dead-code-2.rs:2:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: function `dead_fn2` is never used + --> $DIR/lint-dead-code-2.rs:25:4 + | +LL | fn dead_fn2() {} + | ^^^^^^^^ + +error: function `main` is never used + --> $DIR/lint-dead-code-2.rs:38:4 + | +LL | fn main() { + | ^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/dead-code/lint-dead-code-3.rs b/tests/ui/lint/dead-code/lint-dead-code-3.rs new file mode 100644 index 000000000..293fcdbc5 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-3.rs @@ -0,0 +1,90 @@ +#![allow(unused_variables)] +#![allow(non_camel_case_types)] +#![allow(clashing_extern_declarations)] +#![deny(dead_code)] + +#![crate_type="lib"] + + +pub use extern_foo as x; +extern "C" { + pub fn extern_foo(); +} + +struct Foo; //~ ERROR: struct `Foo` is never constructed +impl Foo { + fn foo(&self) { //~ ERROR: associated function `foo` is never used + bar() + } +} + +fn bar() { //~ ERROR: function `bar` is never used + fn baz() {} + + Foo.foo(); + baz(); +} + +// no warning +struct Foo2; +impl Foo2 { fn foo2(&self) { bar2() } } +fn bar2() { + fn baz2() {} + + Foo2.foo2(); + baz2(); +} + +pub fn pub_fn() { + let foo2_struct = Foo2; + foo2_struct.foo2(); + + blah::baz(); +} + +mod blah { + // not warned because it's used in the parameter of `free` and return of + // `malloc` below, which are also used. + enum c_void {} + + extern "C" { + fn free(p: *const c_void); + fn malloc(size: usize) -> *const c_void; + } + + pub fn baz() { + unsafe { free(malloc(4)); } + } +} + +enum c_void {} //~ ERROR: enum `c_void` is never used +extern "C" { + fn free(p: *const c_void); //~ ERROR: function `free` is never used +} + +// Check provided method +mod inner { + pub trait Trait { + fn f(&self) { f(); } + } + + impl Trait for isize {} + + fn f() {} +} + +fn anon_const() -> [(); { + fn blah() {} //~ ERROR: function `blah` is never used + 1 +}] { + [(); { + fn blah() {} //~ ERROR: function `blah` is never used + 1 + }] +} + +pub fn foo() { + let a: &dyn inner::Trait = &1_isize; + a.f(); + anon_const(); +} diff --git a/tests/ui/lint/dead-code/lint-dead-code-3.stderr b/tests/ui/lint/dead-code/lint-dead-code-3.stderr new file mode 100644 index 000000000..26fc13bae --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-3.stderr @@ -0,0 +1,50 @@ +error: struct `Foo` is never constructed + --> $DIR/lint-dead-code-3.rs:14:8 + | +LL | struct Foo; + | ^^^ + | +note: the lint level is defined here + --> $DIR/lint-dead-code-3.rs:4:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: function `bar` is never used + --> $DIR/lint-dead-code-3.rs:21:4 + | +LL | fn bar() { + | ^^^ + +error: enum `c_void` is never used + --> $DIR/lint-dead-code-3.rs:60:6 + | +LL | enum c_void {} + | ^^^^^^ + +error: function `blah` is never used + --> $DIR/lint-dead-code-3.rs:77:8 + | +LL | fn blah() {} + | ^^^^ + +error: function `blah` is never used + --> $DIR/lint-dead-code-3.rs:81:12 + | +LL | fn blah() {} + | ^^^^ + +error: associated function `foo` is never used + --> $DIR/lint-dead-code-3.rs:16:8 + | +LL | fn foo(&self) { + | ^^^ + +error: function `free` is never used + --> $DIR/lint-dead-code-3.rs:62:8 + | +LL | fn free(p: *const c_void); + | ^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/lint/dead-code/lint-dead-code-4.rs b/tests/ui/lint/dead-code/lint-dead-code-4.rs new file mode 100644 index 000000000..0fc6c6156 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-4.rs @@ -0,0 +1,83 @@ +#![allow(unused_variables)] +#![allow(non_camel_case_types)] +#![deny(dead_code)] + +struct Foo { + x: usize, + b: bool, //~ ERROR: field `b` is never read +} + +fn field_read(f: Foo) -> usize { + f.x.pow(2) +} + +enum XYZ { + X, //~ ERROR variants `X` and `Y` are never constructed + Y { + a: String, + b: i32, + c: i32, + }, + Z +} + +enum ABC { //~ ERROR enum `ABC` is never used + A, + B { + a: String, + b: i32, + c: i32, + }, + C +} + +// ensure struct variants get warning for their fields +enum IJK { + I, //~ ERROR variants `I` and `K` are never constructed + J { + a: String, + b: i32, //~ ERROR fields `b` and `c` are never read + c: i32, + }, + K + +} + +fn struct_variant_partial_use(b: IJK) -> String { + match b { + IJK::J { a, b: _, .. } => a, + _ => "".to_string() + } +} + +fn field_match_in_patterns(b: XYZ) -> String { + match b { + XYZ::Y { a, b: _, .. } => a, + _ => "".to_string() + } +} + +struct Bar { + x: usize, //~ ERROR: fields `x` and `c` are never read + b: bool, + c: bool, + _guard: () +} + +#[repr(C)] +struct Baz { + x: u32, +} + +fn field_match_in_let(f: Bar) -> bool { + let Bar { b, c: _, .. } = f; + b +} + +fn main() { + field_read(Foo { x: 1, b: false }); + field_match_in_patterns(XYZ::Z); + struct_variant_partial_use(IJK::J { a: "".into(), b: 1, c: -1 }); + field_match_in_let(Bar { x: 42, b: true, c: false, _guard: () }); + let _ = Baz { x: 0 }; +} diff --git a/tests/ui/lint/dead-code/lint-dead-code-4.stderr b/tests/ui/lint/dead-code/lint-dead-code-4.stderr new file mode 100644 index 000000000..668c1dacf --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-4.stderr @@ -0,0 +1,66 @@ +error: field `b` is never read + --> $DIR/lint-dead-code-4.rs:7:5 + | +LL | struct Foo { + | --- field in this struct +LL | x: usize, +LL | b: bool, + | ^ + | +note: the lint level is defined here + --> $DIR/lint-dead-code-4.rs:3:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: variants `X` and `Y` are never constructed + --> $DIR/lint-dead-code-4.rs:15:5 + | +LL | enum XYZ { + | --- variants in this enum +LL | X, + | ^ +LL | Y { + | ^ + +error: enum `ABC` is never used + --> $DIR/lint-dead-code-4.rs:24:6 + | +LL | enum ABC { + | ^^^ + +error: fields `b` and `c` are never read + --> $DIR/lint-dead-code-4.rs:39:9 + | +LL | J { + | - fields in this variant +LL | a: String, +LL | b: i32, + | ^ +LL | c: i32, + | ^ + +error: variants `I` and `K` are never constructed + --> $DIR/lint-dead-code-4.rs:36:5 + | +LL | enum IJK { + | --- variants in this enum +LL | I, + | ^ +... +LL | K + | ^ + +error: fields `x` and `c` are never read + --> $DIR/lint-dead-code-4.rs:61:5 + | +LL | struct Bar { + | --- fields in this struct +LL | x: usize, + | ^ +LL | b: bool, +LL | c: bool, + | ^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/lint/dead-code/lint-dead-code-5.rs b/tests/ui/lint/dead-code/lint-dead-code-5.rs new file mode 100644 index 000000000..ed90fb464 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-5.rs @@ -0,0 +1,50 @@ +#![allow(unused_variables)] +#![deny(dead_code)] + +enum Enum1 { + Variant1(isize), + Variant2 //~ ERROR: variant `Variant2` is never constructed +} + +enum Enum2 { + Variant3(bool), + #[allow(dead_code)] + Variant4(isize), + Variant5 { _x: isize }, //~ ERROR: variants `Variant5` and `Variant6` are never constructed + Variant6(isize), + _Variant7, + Variant8 { _field: bool }, + Variant9, + Variant10(usize) +} + +impl Enum2 { + fn new_variant8() -> Enum2 { + Self::Variant8 { _field: true } + } + + fn new_variant9() -> Enum2 { + Self::Variant9 + } + + fn new_variant10() -> Enum2 { + Self::Variant10(10) + } +} + +enum Enum3 { //~ ERROR: enum `Enum3` is never used + Variant8, + Variant9 +} + +fn main() { + let v = Enum1::Variant1(1); + match v { + Enum1::Variant1(_) => (), + Enum1::Variant2 => () + } + let x = Enum2::Variant3(true); + let _ = Enum2::new_variant8(); + let _ = Enum2::new_variant9(); + let _ = Enum2::new_variant10(); +} diff --git a/tests/ui/lint/dead-code/lint-dead-code-5.stderr b/tests/ui/lint/dead-code/lint-dead-code-5.stderr new file mode 100644 index 000000000..eaf43e453 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-5.stderr @@ -0,0 +1,34 @@ +error: variant `Variant2` is never constructed + --> $DIR/lint-dead-code-5.rs:6:5 + | +LL | enum Enum1 { + | ----- variant in this enum +LL | Variant1(isize), +LL | Variant2 + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-dead-code-5.rs:2:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: variants `Variant5` and `Variant6` are never constructed + --> $DIR/lint-dead-code-5.rs:13:5 + | +LL | enum Enum2 { + | ----- variants in this enum +... +LL | Variant5 { _x: isize }, + | ^^^^^^^^ +LL | Variant6(isize), + | ^^^^^^^^ + +error: enum `Enum3` is never used + --> $DIR/lint-dead-code-5.rs:35:6 + | +LL | enum Enum3 { + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/dead-code/lint-dead-code-6.rs b/tests/ui/lint/dead-code/lint-dead-code-6.rs new file mode 100644 index 000000000..e3074acf1 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-6.rs @@ -0,0 +1,20 @@ +#![deny(dead_code)] + +struct UnusedStruct; //~ ERROR struct `UnusedStruct` is never constructed +impl UnusedStruct { + fn unused_impl_fn_1() { //~ ERROR associated function `unused_impl_fn_1` is never used + println!("blah"); + } + + fn unused_impl_fn_2(var: i32) { //~ ERROR associated function `unused_impl_fn_2` is never used + println!("foo {}", var); + } + + fn unused_impl_fn_3( //~ ERROR associated function `unused_impl_fn_3` is never used + var: i32, + ) { + println!("bar {}", var); + } +} + +fn main() {} diff --git a/tests/ui/lint/dead-code/lint-dead-code-6.stderr b/tests/ui/lint/dead-code/lint-dead-code-6.stderr new file mode 100644 index 000000000..f9d83308a --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-6.stderr @@ -0,0 +1,32 @@ +error: struct `UnusedStruct` is never constructed + --> $DIR/lint-dead-code-6.rs:3:8 + | +LL | struct UnusedStruct; + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-dead-code-6.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: associated function `unused_impl_fn_1` is never used + --> $DIR/lint-dead-code-6.rs:5:8 + | +LL | fn unused_impl_fn_1() { + | ^^^^^^^^^^^^^^^^ + +error: associated function `unused_impl_fn_2` is never used + --> $DIR/lint-dead-code-6.rs:9:8 + | +LL | fn unused_impl_fn_2(var: i32) { + | ^^^^^^^^^^^^^^^^ + +error: associated function `unused_impl_fn_3` is never used + --> $DIR/lint-dead-code-6.rs:13:8 + | +LL | fn unused_impl_fn_3( + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs new file mode 100644 index 000000000..2003e1e29 --- /dev/null +++ b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs @@ -0,0 +1,29 @@ +#![warn(dead_code)] + +struct Bar { + #[allow(dead_code)] + a: usize, + #[forbid(dead_code)] + b: usize, //~ ERROR field `b` is never read + #[deny(dead_code)] + c: usize, //~ ERROR fields `c` and `e` are never read + d: usize, //~ WARN fields `d`, `f`, and `g` are never read + #[deny(dead_code)] + e: usize, + f: usize, + g: usize, + _h: usize, +} + +fn main() { + Bar { + a: 1, + b: 1, + c: 1, + d: 1, + e: 1, + f: 1, + g: 1, + _h: 1, + }; +} diff --git a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr new file mode 100644 index 000000000..0e5c78a71 --- /dev/null +++ b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr @@ -0,0 +1,55 @@ +warning: fields `d`, `f`, and `g` are never read + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:10:5 + | +LL | struct Bar { + | --- fields in this struct +... +LL | d: usize, + | ^ +... +LL | f: usize, + | ^ +LL | g: usize, + | ^ + | +note: the lint level is defined here + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:1:9 + | +LL | #![warn(dead_code)] + | ^^^^^^^^^ + +error: fields `c` and `e` are never read + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:9:5 + | +LL | struct Bar { + | --- fields in this struct +... +LL | c: usize, + | ^ +... +LL | e: usize, + | ^ + | +note: the lint level is defined here + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:8:12 + | +LL | #[deny(dead_code)] + | ^^^^^^^^^ + +error: field `b` is never read + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:7:5 + | +LL | struct Bar { + | --- field in this struct +... +LL | b: usize, + | ^ + | +note: the lint level is defined here + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:6:14 + | +LL | #[forbid(dead_code)] + | ^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/lint/dead-code/newline-span.rs b/tests/ui/lint/dead-code/newline-span.rs new file mode 100644 index 000000000..209c3cd93 --- /dev/null +++ b/tests/ui/lint/dead-code/newline-span.rs @@ -0,0 +1,19 @@ +#![deny(dead_code)] + +fn unused() { //~ error: function `unused` is never used + println!("blah"); +} + +fn unused2(var: i32) { //~ error: function `unused2` is never used + println!("foo {}", var); +} + +fn unused3( //~ error: function `unused3` is never used + var: i32, +) { + println!("bar {}", var); +} + +fn main() { + println!("Hello world!"); +} diff --git a/tests/ui/lint/dead-code/newline-span.stderr b/tests/ui/lint/dead-code/newline-span.stderr new file mode 100644 index 000000000..4eeadccc8 --- /dev/null +++ b/tests/ui/lint/dead-code/newline-span.stderr @@ -0,0 +1,26 @@ +error: function `unused` is never used + --> $DIR/newline-span.rs:3:4 + | +LL | fn unused() { + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/newline-span.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: function `unused2` is never used + --> $DIR/newline-span.rs:7:4 + | +LL | fn unused2(var: i32) { + | ^^^^^^^ + +error: function `unused3` is never used + --> $DIR/newline-span.rs:11:4 + | +LL | fn unused3( + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/dead-code/self-assign.rs b/tests/ui/lint/dead-code/self-assign.rs new file mode 100644 index 000000000..ea7ce98d8 --- /dev/null +++ b/tests/ui/lint/dead-code/self-assign.rs @@ -0,0 +1,52 @@ +// Test that dead code warnings are issued for superfluous assignments of +// fields or variables to themselves (issue #75356). + +// ignore-test FIXME(81658, 83171) + +// check-pass +#![allow(unused_assignments)] +#![warn(dead_code)] + +fn main() { + let mut x = 0; + x = x; + //~^ WARNING: useless assignment of variable of type `i32` to itself + + x = (x); + //~^ WARNING: useless assignment of variable of type `i32` to itself + + x = {x}; + // block expressions don't count as self-assignments + + + struct S<'a> { f: &'a str } + let mut s = S { f: "abc" }; + s = s; + //~^ WARNING: useless assignment of variable of type `S` to itself + + s.f = s.f; + //~^ WARNING: useless assignment of field of type `&str` to itself + + + struct N0 { x: Box<i32> } + struct N1 { n: N0 } + struct N2(N1); + struct N3 { n: N2 }; + let mut n3 = N3 { n: N2(N1 { n: N0 { x: Box::new(42) } }) }; + n3.n.0.n.x = n3.n.0.n.x; + //~^ WARNING: useless assignment of field of type `Box<i32>` to itself + + let mut t = (1, ((2, 3, (4, 5)),)); + t.1.0.2.1 = t.1.0.2.1; + //~^ WARNING: useless assignment of field of type `i32` to itself + + + let mut y = 0; + macro_rules! assign_to_y { + ($cur:expr) => {{ + y = $cur; + }}; + } + assign_to_y!(y); + // self-assignments in macro expansions are not reported either +} diff --git a/tests/ui/lint/dead-code/self-assign.stderr b/tests/ui/lint/dead-code/self-assign.stderr new file mode 100644 index 000000000..bb79c0ec7 --- /dev/null +++ b/tests/ui/lint/dead-code/self-assign.stderr @@ -0,0 +1,44 @@ +warning: useless assignment of variable of type `i32` to itself + --> $DIR/self-assign.rs:10:5 + | +LL | x = x; + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/self-assign.rs:6:9 + | +LL | #![warn(dead_code)] + | ^^^^^^^^^ + +warning: useless assignment of variable of type `i32` to itself + --> $DIR/self-assign.rs:13:5 + | +LL | x = (x); + | ^^^^^^^ + +warning: useless assignment of variable of type `S` to itself + --> $DIR/self-assign.rs:22:5 + | +LL | s = s; + | ^^^^^ + +warning: useless assignment of field of type `&str` to itself + --> $DIR/self-assign.rs:25:5 + | +LL | s.f = s.f; + | ^^^^^^^^^ + +warning: useless assignment of field of type `Box<i32>` to itself + --> $DIR/self-assign.rs:34:5 + | +LL | n3.n.0.n.x = n3.n.0.n.x; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +warning: useless assignment of field of type `i32` to itself + --> $DIR/self-assign.rs:38:5 + | +LL | t.1.0.2.1 = t.1.0.2.1; + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: 6 warnings emitted + diff --git a/tests/ui/lint/dead-code/trait-impl.rs b/tests/ui/lint/dead-code/trait-impl.rs new file mode 100644 index 000000000..92e389a93 --- /dev/null +++ b/tests/ui/lint/dead-code/trait-impl.rs @@ -0,0 +1,19 @@ +// check-pass +#![deny(dead_code)] + +enum Foo { + Bar, +} + +fn main() { + let p = [0; 0]; + p.bar(); +} + +trait Bar { + fn bar(&self) -> usize { + 3 + } +} + +impl Bar for [u32; Foo::Bar as usize] {} diff --git a/tests/ui/lint/dead-code/tuple-struct-field.rs b/tests/ui/lint/dead-code/tuple-struct-field.rs new file mode 100644 index 000000000..14fb30be9 --- /dev/null +++ b/tests/ui/lint/dead-code/tuple-struct-field.rs @@ -0,0 +1,37 @@ +#![deny(unused_tuple_struct_fields)] +//~^ NOTE: the lint level is defined here + +use std::marker::PhantomData; + +const LEN: usize = 4; + +struct SingleUnused(i32, [u8; LEN], String); +//~^ ERROR: field `1` is never read +//~| NOTE: field in this struct +//~| HELP: consider changing the field to be of unit type + +struct MultipleUnused(i32, f32, String, u8); +//~^ ERROR: fields `0`, `1`, `2`, and `3` are never read +//~| NOTE: fields in this struct +//~| HELP: consider changing the fields to be of unit type + +struct GoodUnit(()); + +struct GoodPhantom(PhantomData<i32>); + +struct Void; +struct GoodVoid(Void); + +fn main() { + let w = SingleUnused(42, [0, 1, 2, 3], "abc".to_string()); + let _ = w.0; + let _ = w.2; + + let m = MultipleUnused(42, 3.14, "def".to_string(), 4u8); + + let gu = GoodUnit(()); + let gp = GoodPhantom(PhantomData); + let gv = GoodVoid(Void); + + let _ = (gu, gp, gv, m); +} diff --git a/tests/ui/lint/dead-code/tuple-struct-field.stderr b/tests/ui/lint/dead-code/tuple-struct-field.stderr new file mode 100644 index 000000000..b8ad5cbe4 --- /dev/null +++ b/tests/ui/lint/dead-code/tuple-struct-field.stderr @@ -0,0 +1,33 @@ +error: field `1` is never read + --> $DIR/tuple-struct-field.rs:8:26 + | +LL | struct SingleUnused(i32, [u8; LEN], String); + | ------------ ^^^^^^^^^ + | | + | field in this struct + | +note: the lint level is defined here + --> $DIR/tuple-struct-field.rs:1:9 + | +LL | #![deny(unused_tuple_struct_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field + | +LL | struct SingleUnused(i32, (), String); + | ~~ + +error: fields `0`, `1`, `2`, and `3` are never read + --> $DIR/tuple-struct-field.rs:13:23 + | +LL | struct MultipleUnused(i32, f32, String, u8); + | -------------- ^^^ ^^^ ^^^^^^ ^^ + | | + | fields in this struct + | +help: consider changing the fields to be of unit type to suppress this warning while preserving the field numbering, or remove the fields + | +LL | struct MultipleUnused((), (), (), ()); + | ~~ ~~ ~~ ~~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/dead-code/type-alias.rs b/tests/ui/lint/dead-code/type-alias.rs new file mode 100644 index 000000000..35a7f125d --- /dev/null +++ b/tests/ui/lint/dead-code/type-alias.rs @@ -0,0 +1,10 @@ +#![deny(dead_code)] + +type Used = u8; +type Unused = u8; //~ ERROR type alias `Unused` is never used + +fn id(x: Used) -> Used { x } + +fn main() { + id(0); +} diff --git a/tests/ui/lint/dead-code/type-alias.stderr b/tests/ui/lint/dead-code/type-alias.stderr new file mode 100644 index 000000000..446447d97 --- /dev/null +++ b/tests/ui/lint/dead-code/type-alias.stderr @@ -0,0 +1,14 @@ +error: type alias `Unused` is never used + --> $DIR/type-alias.rs:4:6 + | +LL | type Unused = u8; + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/type-alias.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/dead-code/type-in-foreign.rs b/tests/ui/lint/dead-code/type-in-foreign.rs new file mode 100644 index 000000000..b6c593f31 --- /dev/null +++ b/tests/ui/lint/dead-code/type-in-foreign.rs @@ -0,0 +1,19 @@ +// Verify that we do not warn on types that are used by foreign functions. +// check-pass +#![deny(dead_code)] + +#[repr(C)] +struct Type(u8); + +#[repr(C)] +struct Param(u8); + +extern "C" { + #[allow(dead_code)] + fn hey(t: Param); + + #[allow(dead_code)] + static much: Type; +} + +fn main() {} diff --git a/tests/ui/lint/dead-code/unused-enum.rs b/tests/ui/lint/dead-code/unused-enum.rs new file mode 100644 index 000000000..20df3e1de --- /dev/null +++ b/tests/ui/lint/dead-code/unused-enum.rs @@ -0,0 +1,12 @@ +#![deny(unused)] + +struct F; //~ ERROR struct `F` is never constructed +struct B; //~ ERROR struct `B` is never constructed + +enum E { + //~^ ERROR enum `E` is never used + Foo(F), + Bar(B), +} + +fn main() {} diff --git a/tests/ui/lint/dead-code/unused-enum.stderr b/tests/ui/lint/dead-code/unused-enum.stderr new file mode 100644 index 000000000..d2602dbb3 --- /dev/null +++ b/tests/ui/lint/dead-code/unused-enum.stderr @@ -0,0 +1,27 @@ +error: struct `F` is never constructed + --> $DIR/unused-enum.rs:3:8 + | +LL | struct F; + | ^ + | +note: the lint level is defined here + --> $DIR/unused-enum.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + +error: struct `B` is never constructed + --> $DIR/unused-enum.rs:4:8 + | +LL | struct B; + | ^ + +error: enum `E` is never used + --> $DIR/unused-enum.rs:6:6 + | +LL | enum E { + | ^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/dead-code/unused-struct-variant.rs b/tests/ui/lint/dead-code/unused-struct-variant.rs new file mode 100644 index 000000000..a914e0c33 --- /dev/null +++ b/tests/ui/lint/dead-code/unused-struct-variant.rs @@ -0,0 +1,13 @@ +#![deny(unused)] + +struct F; +struct B; + +enum E { + Foo(F), + Bar(B), //~ ERROR variant `Bar` is never constructed +} + +fn main() { + let _ = E::Foo(F); +} diff --git a/tests/ui/lint/dead-code/unused-struct-variant.stderr b/tests/ui/lint/dead-code/unused-struct-variant.stderr new file mode 100644 index 000000000..d26dd3aff --- /dev/null +++ b/tests/ui/lint/dead-code/unused-struct-variant.stderr @@ -0,0 +1,18 @@ +error: variant `Bar` is never constructed + --> $DIR/unused-struct-variant.rs:8:5 + | +LL | enum E { + | - variant in this enum +LL | Foo(F), +LL | Bar(B), + | ^^^ + | +note: the lint level is defined here + --> $DIR/unused-struct-variant.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + +error: aborting due to previous error + diff --git a/tests/ui/lint/dead-code/unused-variant-pub.rs b/tests/ui/lint/dead-code/unused-variant-pub.rs new file mode 100644 index 000000000..3a9061340 --- /dev/null +++ b/tests/ui/lint/dead-code/unused-variant-pub.rs @@ -0,0 +1,14 @@ +// build-pass +#![deny(unused)] + +pub struct F; +pub struct B; + +pub enum E { + Foo(F), + Bar(B), +} + +fn main() { + let _ = E::Foo(F); +} diff --git a/tests/ui/lint/dead-code/unused-variant.rs b/tests/ui/lint/dead-code/unused-variant.rs new file mode 100644 index 000000000..82108fa9c --- /dev/null +++ b/tests/ui/lint/dead-code/unused-variant.rs @@ -0,0 +1,12 @@ +#![deny(dead_code)] + +#[derive(Clone)] +enum Enum { + Variant1, //~ ERROR: variant `Variant1` is never constructed + Variant2, +} + +fn main() { + let e = Enum::Variant2; + e.clone(); +} diff --git a/tests/ui/lint/dead-code/unused-variant.stderr b/tests/ui/lint/dead-code/unused-variant.stderr new file mode 100644 index 000000000..6029bf268 --- /dev/null +++ b/tests/ui/lint/dead-code/unused-variant.stderr @@ -0,0 +1,17 @@ +error: variant `Variant1` is never constructed + --> $DIR/unused-variant.rs:5:5 + | +LL | enum Enum { + | ---- variant in this enum +LL | Variant1, + | ^^^^^^^^ + | + = note: `Enum` has a derived impl for the trait `Clone`, but this is intentionally ignored during dead code analysis +note: the lint level is defined here + --> $DIR/unused-variant.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/dead-code/with-core-crate.rs b/tests/ui/lint/dead-code/with-core-crate.rs new file mode 100644 index 000000000..0a94b528f --- /dev/null +++ b/tests/ui/lint/dead-code/with-core-crate.rs @@ -0,0 +1,18 @@ +#![deny(dead_code)] +#![allow(unreachable_code)] + +#[macro_use] +extern crate core; + +fn foo() { //~ ERROR function `foo` is never used + + // none of these should have any dead_code exposed to the user + panic!(); + + panic!("foo"); + + panic!("bar {}", "baz") +} + + +fn main() {} diff --git a/tests/ui/lint/dead-code/with-core-crate.stderr b/tests/ui/lint/dead-code/with-core-crate.stderr new file mode 100644 index 000000000..7adcf8848 --- /dev/null +++ b/tests/ui/lint/dead-code/with-core-crate.stderr @@ -0,0 +1,14 @@ +error: function `foo` is never used + --> $DIR/with-core-crate.rs:7:4 + | +LL | fn foo() { + | ^^^ + | +note: the lint level is defined here + --> $DIR/with-core-crate.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/dead-code/with-impl.rs b/tests/ui/lint/dead-code/with-impl.rs new file mode 100644 index 000000000..812fcdd09 --- /dev/null +++ b/tests/ui/lint/dead-code/with-impl.rs @@ -0,0 +1,17 @@ +// run-pass + +#![deny(dead_code)] + +pub struct GenericFoo<T>(#[allow(unused_tuple_struct_fields)] T); + +type Foo = GenericFoo<u32>; + +impl Foo { + fn bar(self) -> u8 { + 0 + } +} + +fn main() { + println!("{}", GenericFoo(0).bar()); +} diff --git a/tests/ui/lint/deny-overflowing-literals.rs b/tests/ui/lint/deny-overflowing-literals.rs new file mode 100644 index 000000000..21c8ba7d6 --- /dev/null +++ b/tests/ui/lint/deny-overflowing-literals.rs @@ -0,0 +1,7 @@ +fn main() { + let x: u8 = 256; + //~^ error: literal out of range for `u8` + + for _ in 0..256u8 {} + //~^ error: range endpoint is out of range for `u8` +} diff --git a/tests/ui/lint/deny-overflowing-literals.stderr b/tests/ui/lint/deny-overflowing-literals.stderr new file mode 100644 index 000000000..beb0ad795 --- /dev/null +++ b/tests/ui/lint/deny-overflowing-literals.stderr @@ -0,0 +1,17 @@ +error: literal out of range for `u8` + --> $DIR/deny-overflowing-literals.rs:2:17 + | +LL | let x: u8 = 256; + | ^^^ + | + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` + = note: `#[deny(overflowing_literals)]` on by default + +error: range endpoint is out of range for `u8` + --> $DIR/deny-overflowing-literals.rs:5:14 + | +LL | for _ in 0..256u8 {} + | ^^^^^^^^ help: use an inclusive range instead: `0..=255u8` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/empty-lint-attributes.rs b/tests/ui/lint/empty-lint-attributes.rs new file mode 100644 index 000000000..9a0ec2533 --- /dev/null +++ b/tests/ui/lint/empty-lint-attributes.rs @@ -0,0 +1,17 @@ +#![feature(lint_reasons)] + +// check-pass + +// Empty (and reason-only) lint attributes are legal—although we may want to +// lint them in the future (Issue #55112). + +#![allow()] +#![warn(reason = "observationalism")] + +#[forbid()] +fn devoir() {} + +#[deny(reason = "ultion")] +fn waldgrave() {} + +fn main() {} diff --git a/tests/ui/lint/enable-unstable-lib-feature.rs b/tests/ui/lint/enable-unstable-lib-feature.rs new file mode 100644 index 000000000..aa6a973d7 --- /dev/null +++ b/tests/ui/lint/enable-unstable-lib-feature.rs @@ -0,0 +1,13 @@ +// Test that enabling an unstable feature disables warnings + +// aux-build:stability-cfg2.rs + +#![feature(unstable_test_feature)] +#![deny(non_snake_case)] // To trigger a hard error + +// Shouldn't generate a warning about unstable features +extern crate stability_cfg2; + +pub fn BOGUS() { } //~ ERROR + +pub fn main() { } diff --git a/tests/ui/lint/enable-unstable-lib-feature.stderr b/tests/ui/lint/enable-unstable-lib-feature.stderr new file mode 100644 index 000000000..bb4e928ad --- /dev/null +++ b/tests/ui/lint/enable-unstable-lib-feature.stderr @@ -0,0 +1,14 @@ +error: function `BOGUS` should have a snake case name + --> $DIR/enable-unstable-lib-feature.rs:11:8 + | +LL | pub fn BOGUS() { } + | ^^^^^ help: convert the identifier to snake case: `bogus` + | +note: the lint level is defined here + --> $DIR/enable-unstable-lib-feature.rs:6:9 + | +LL | #![deny(non_snake_case)] // To trigger a hard error + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/expansion-time-include.rs b/tests/ui/lint/expansion-time-include.rs new file mode 100644 index 000000000..4ea89d5ad --- /dev/null +++ b/tests/ui/lint/expansion-time-include.rs @@ -0,0 +1,4 @@ +// ignore-test auxiliary file for expansion-time.rs + +1 +2 diff --git a/tests/ui/lint/expansion-time.rs b/tests/ui/lint/expansion-time.rs new file mode 100644 index 000000000..f23c7cb0d --- /dev/null +++ b/tests/ui/lint/expansion-time.rs @@ -0,0 +1,33 @@ +// check-pass + +#[warn(meta_variable_misuse)] +macro_rules! foo { + ( $($i:ident)* ) => { $($i)+ }; //~ WARN meta-variable repeats with different Kleene operator +} + +#[warn(missing_fragment_specifier)] +macro_rules! m { ($i) => {} } //~ WARN missing fragment specifier + //~| WARN this was previously accepted + +#[warn(soft_unstable)] +mod benches { + #[bench] //~ WARN use of unstable library feature 'test' + //~| WARN this was previously accepted + fn foo() {} +} + +#[deprecated = "reason"] +macro_rules! deprecated { + () => {} +} + +#[allow(deprecated)] +mod deprecated { + deprecated!(); // No warning +} + +#[warn(incomplete_include)] +fn main() { + // WARN see in the stderr file, the warning points to the included file. + include!("expansion-time-include.rs"); +} diff --git a/tests/ui/lint/expansion-time.stderr b/tests/ui/lint/expansion-time.stderr new file mode 100644 index 000000000..064ee5fad --- /dev/null +++ b/tests/ui/lint/expansion-time.stderr @@ -0,0 +1,56 @@ +warning: meta-variable repeats with different Kleene operator + --> $DIR/expansion-time.rs:5:29 + | +LL | ( $($i:ident)* ) => { $($i)+ }; + | - ^^ - conflicting repetition + | | + | expected repetition + | +note: the lint level is defined here + --> $DIR/expansion-time.rs:3:8 + | +LL | #[warn(meta_variable_misuse)] + | ^^^^^^^^^^^^^^^^^^^^ + +warning: missing fragment specifier + --> $DIR/expansion-time.rs:9:19 + | +LL | macro_rules! m { ($i) => {} } + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107> +note: the lint level is defined here + --> $DIR/expansion-time.rs:8:8 + | +LL | #[warn(missing_fragment_specifier)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable + --> $DIR/expansion-time.rs:14:7 + | +LL | #[bench] + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266> +note: the lint level is defined here + --> $DIR/expansion-time.rs:12:8 + | +LL | #[warn(soft_unstable)] + | ^^^^^^^^^^^^^ + +warning: include macro expected single expression in source + --> $DIR/expansion-time-include.rs:4:1 + | +LL | 2 + | ^ + | +note: the lint level is defined here + --> $DIR/expansion-time.rs:29:8 + | +LL | #[warn(incomplete_include)] + | ^^^^^^^^^^^^^^^^^^ + +warning: 4 warnings emitted + diff --git a/tests/ui/lint/expr_attr_paren_order.rs b/tests/ui/lint/expr_attr_paren_order.rs new file mode 100644 index 000000000..e1ec2e951 --- /dev/null +++ b/tests/ui/lint/expr_attr_paren_order.rs @@ -0,0 +1,22 @@ +#![feature(stmt_expr_attributes)] + +fn main() { + + // Test that attributes on parens get concatenated + // in the expected order in the hir folder. + + #[deny(non_snake_case)] #[allow(non_snake_case)] ( + { + let X = 0; + let _ = X; + } + ); + + #[allow(non_snake_case)] #[deny(non_snake_case)] ( + { + let X = 0; //~ ERROR snake case name + let _ = X; + } + ); + +} diff --git a/tests/ui/lint/expr_attr_paren_order.stderr b/tests/ui/lint/expr_attr_paren_order.stderr new file mode 100644 index 000000000..42beed10c --- /dev/null +++ b/tests/ui/lint/expr_attr_paren_order.stderr @@ -0,0 +1,14 @@ +error: variable `X` should have a snake case name + --> $DIR/expr_attr_paren_order.rs:17:17 + | +LL | let X = 0; + | ^ help: convert the identifier to snake case (notice the capitalization): `x` + | +note: the lint level is defined here + --> $DIR/expr_attr_paren_order.rs:15:37 + | +LL | #[allow(non_snake_case)] #[deny(non_snake_case)] ( + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/fn_must_use.rs b/tests/ui/lint/fn_must_use.rs new file mode 100644 index 000000000..b4e9da0fc --- /dev/null +++ b/tests/ui/lint/fn_must_use.rs @@ -0,0 +1,76 @@ +// check-pass + +#![warn(unused_must_use)] + +#[derive(PartialEq, Eq)] +struct MyStruct { + n: usize, +} + +impl MyStruct { + #[must_use] + fn need_to_use_this_method_value(&self) -> usize { + self.n + } + + #[must_use] + fn need_to_use_this_associated_function_value() -> isize { + -1 + } +} + +trait EvenNature { + #[must_use = "no side effects"] + fn is_even(&self) -> bool; +} + +impl EvenNature for MyStruct { + fn is_even(&self) -> bool { + self.n % 2 == 0 + } +} + +trait Replaceable { + fn replace(&mut self, substitute: usize) -> usize; +} + +impl Replaceable for MyStruct { + // ↓ N.b.: `#[must_use]` attribute on a particular trait implementation + // method won't work; the attribute should be on the method signature in + // the trait's definition. + #[must_use] + fn replace(&mut self, substitute: usize) -> usize { + let previously = self.n; + self.n = substitute; + previously + } +} + +#[must_use = "it's important"] +fn need_to_use_this_value() -> bool { + false +} + +fn main() { + need_to_use_this_value(); //~ WARN unused return value + + let mut m = MyStruct { n: 2 }; + let n = MyStruct { n: 3 }; + + m.need_to_use_this_method_value(); //~ WARN unused return value + m.is_even(); // trait method! + //~^ WARN unused return value + + MyStruct::need_to_use_this_associated_function_value(); + //~^ WARN unused return value + + m.replace(3); // won't warn (annotation needs to be in trait definition) + + // comparison methods are `must_use` + 2.eq(&3); //~ WARN unused return value + m.eq(&n); //~ WARN unused return value + + // lint includes comparison operators + 2 == 3; //~ WARN unused comparison + m == n; //~ WARN unused comparison +} diff --git a/tests/ui/lint/fn_must_use.stderr b/tests/ui/lint/fn_must_use.stderr new file mode 100644 index 000000000..657f23c60 --- /dev/null +++ b/tests/ui/lint/fn_must_use.stderr @@ -0,0 +1,69 @@ +warning: unused return value of `need_to_use_this_value` that must be used + --> $DIR/fn_must_use.rs:55:5 + | +LL | need_to_use_this_value(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: it's important +note: the lint level is defined here + --> $DIR/fn_must_use.rs:3:9 + | +LL | #![warn(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +warning: unused return value of `MyStruct::need_to_use_this_method_value` that must be used + --> $DIR/fn_must_use.rs:60:5 + | +LL | m.need_to_use_this_method_value(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused return value of `EvenNature::is_even` that must be used + --> $DIR/fn_must_use.rs:61:5 + | +LL | m.is_even(); // trait method! + | ^^^^^^^^^^^ + | + = note: no side effects + +warning: unused return value of `MyStruct::need_to_use_this_associated_function_value` that must be used + --> $DIR/fn_must_use.rs:64:5 + | +LL | MyStruct::need_to_use_this_associated_function_value(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused return value of `std::cmp::PartialEq::eq` that must be used + --> $DIR/fn_must_use.rs:70:5 + | +LL | 2.eq(&3); + | ^^^^^^^^ + +warning: unused return value of `std::cmp::PartialEq::eq` that must be used + --> $DIR/fn_must_use.rs:71:5 + | +LL | m.eq(&n); + | ^^^^^^^^ + +warning: unused comparison that must be used + --> $DIR/fn_must_use.rs:74:5 + | +LL | 2 == 3; + | ^^^^^^ the comparison produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = 2 == 3; + | +++++++ + +warning: unused comparison that must be used + --> $DIR/fn_must_use.rs:75:5 + | +LL | m == n; + | ^^^^^^ the comparison produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = m == n; + | +++++++ + +warning: 8 warnings emitted + diff --git a/tests/ui/lint/for_loop_over_fallibles.rs b/tests/ui/lint/for_loop_over_fallibles.rs new file mode 100644 index 000000000..43d71c2e8 --- /dev/null +++ b/tests/ui/lint/for_loop_over_fallibles.rs @@ -0,0 +1,43 @@ +// check-pass + +fn main() { + // Common + for _ in Some(1) {} + //~^ WARN for loop over an `Option`. This is more readably written as an `if let` statement + //~| HELP to check pattern in a loop use `while let` + //~| HELP consider using `if let` to clear intent + for _ in Ok::<_, ()>(1) {} + //~^ WARN for loop over a `Result`. This is more readably written as an `if let` statement + //~| HELP to check pattern in a loop use `while let` + //~| HELP consider using `if let` to clear intent + + // `Iterator::next` specific + for _ in [0; 0].iter().next() {} + //~^ WARN for loop over an `Option`. This is more readably written as an `if let` statement + //~| HELP to iterate over `[0; 0].iter()` remove the call to `next` + //~| HELP consider using `if let` to clear intent + + // `Result<impl Iterator, _>`, but function doesn't return `Result` + for _ in Ok::<_, ()>([0; 0].iter()) {} + //~^ WARN for loop over a `Result`. This is more readably written as an `if let` statement + //~| HELP to check pattern in a loop use `while let` + //~| HELP consider using `if let` to clear intent +} + +fn _returns_result() -> Result<(), ()> { + // `Result<impl Iterator, _>` + for _ in Ok::<_, ()>([0; 0].iter()) {} + //~^ WARN for loop over a `Result`. This is more readably written as an `if let` statement + //~| HELP to check pattern in a loop use `while let` + //~| HELP consider unwrapping the `Result` with `?` to iterate over its contents + //~| HELP consider using `if let` to clear intent + + // `Result<impl IntoIterator>` + for _ in Ok::<_, ()>([0; 0]) {} + //~^ WARN for loop over a `Result`. This is more readably written as an `if let` statement + //~| HELP to check pattern in a loop use `while let` + //~| HELP consider unwrapping the `Result` with `?` to iterate over its contents + //~| HELP consider using `if let` to clear intent + + Ok(()) +} diff --git a/tests/ui/lint/for_loop_over_fallibles.stderr b/tests/ui/lint/for_loop_over_fallibles.stderr new file mode 100644 index 000000000..96efdf85c --- /dev/null +++ b/tests/ui/lint/for_loop_over_fallibles.stderr @@ -0,0 +1,101 @@ +warning: for loop over an `Option`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:5:14 + | +LL | for _ in Some(1) {} + | ^^^^^^^ + | + = note: `#[warn(for_loops_over_fallibles)]` on by default +help: to check pattern in a loop use `while let` + | +LL | while let Some(_) = Some(1) {} + | ~~~~~~~~~~~~~~~ ~~~ +help: consider using `if let` to clear intent + | +LL | if let Some(_) = Some(1) {} + | ~~~~~~~~~~~~ ~~~ + +warning: for loop over a `Result`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:9:14 + | +LL | for _ in Ok::<_, ()>(1) {} + | ^^^^^^^^^^^^^^ + | +help: to check pattern in a loop use `while let` + | +LL | while let Ok(_) = Ok::<_, ()>(1) {} + | ~~~~~~~~~~~~~ ~~~ +help: consider using `if let` to clear intent + | +LL | if let Ok(_) = Ok::<_, ()>(1) {} + | ~~~~~~~~~~ ~~~ + +warning: for loop over an `Option`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:15:14 + | +LL | for _ in [0; 0].iter().next() {} + | ^^^^^^^^^^^^^^^^^^^^ + | +help: to iterate over `[0; 0].iter()` remove the call to `next` + | +LL | for _ in [0; 0].iter().by_ref() {} + | ~~~~~~~~~ +help: consider using `if let` to clear intent + | +LL | if let Some(_) = [0; 0].iter().next() {} + | ~~~~~~~~~~~~ ~~~ + +warning: for loop over a `Result`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:21:14 + | +LL | for _ in Ok::<_, ()>([0; 0].iter()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to check pattern in a loop use `while let` + | +LL | while let Ok(_) = Ok::<_, ()>([0; 0].iter()) {} + | ~~~~~~~~~~~~~ ~~~ +help: consider using `if let` to clear intent + | +LL | if let Ok(_) = Ok::<_, ()>([0; 0].iter()) {} + | ~~~~~~~~~~ ~~~ + +warning: for loop over a `Result`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:29:14 + | +LL | for _ in Ok::<_, ()>([0; 0].iter()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to check pattern in a loop use `while let` + | +LL | while let Ok(_) = Ok::<_, ()>([0; 0].iter()) {} + | ~~~~~~~~~~~~~ ~~~ +help: consider unwrapping the `Result` with `?` to iterate over its contents + | +LL | for _ in Ok::<_, ()>([0; 0].iter())? {} + | + +help: consider using `if let` to clear intent + | +LL | if let Ok(_) = Ok::<_, ()>([0; 0].iter()) {} + | ~~~~~~~~~~ ~~~ + +warning: for loop over a `Result`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:36:14 + | +LL | for _ in Ok::<_, ()>([0; 0]) {} + | ^^^^^^^^^^^^^^^^^^^ + | +help: to check pattern in a loop use `while let` + | +LL | while let Ok(_) = Ok::<_, ()>([0; 0]) {} + | ~~~~~~~~~~~~~ ~~~ +help: consider unwrapping the `Result` with `?` to iterate over its contents + | +LL | for _ in Ok::<_, ()>([0; 0])? {} + | + +help: consider using `if let` to clear intent + | +LL | if let Ok(_) = Ok::<_, ()>([0; 0]) {} + | ~~~~~~~~~~ ~~~ + +warning: 6 warnings emitted + diff --git a/tests/ui/lint/forbid-error-capped.rs b/tests/ui/lint/forbid-error-capped.rs new file mode 100644 index 000000000..b56471a75 --- /dev/null +++ b/tests/ui/lint/forbid-error-capped.rs @@ -0,0 +1,15 @@ +// check-pass +// compile-args: --cap-lints=warn -Fwarnings + +// This checks that the forbid attribute checking is ignored when the forbidden +// lint is capped. + +#![forbid(warnings)] +#![allow(unused)] + +#[allow(unused)] +mod bar { + fn bar() {} +} + +fn main() {} diff --git a/tests/ui/lint/forbid-group-group-1.rs b/tests/ui/lint/forbid-group-group-1.rs new file mode 100644 index 000000000..80f7db4e5 --- /dev/null +++ b/tests/ui/lint/forbid-group-group-1.rs @@ -0,0 +1,13 @@ +// Check what happens when we forbid a smaller group but +// then allow a superset of that group. + +#![forbid(nonstandard_style)] + +// FIXME: Arguably this should be an error, but the WARNINGS group is +// treated in a very special (and rather ad-hoc) way and +// it fails to trigger. +#[allow(warnings)] +fn main() { + let A: (); + //~^ ERROR should have a snake case name +} diff --git a/tests/ui/lint/forbid-group-group-1.stderr b/tests/ui/lint/forbid-group-group-1.stderr new file mode 100644 index 000000000..fd425e5f7 --- /dev/null +++ b/tests/ui/lint/forbid-group-group-1.stderr @@ -0,0 +1,15 @@ +error: variable `A` should have a snake case name + --> $DIR/forbid-group-group-1.rs:11:9 + | +LL | let A: (); + | ^ help: convert the identifier to snake case: `a` + | +note: the lint level is defined here + --> $DIR/forbid-group-group-1.rs:4:11 + | +LL | #![forbid(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ + = note: `#[forbid(non_snake_case)]` implied by `#[forbid(nonstandard_style)]` + +error: aborting due to previous error + diff --git a/tests/ui/lint/forbid-group-group-2.rs b/tests/ui/lint/forbid-group-group-2.rs new file mode 100644 index 000000000..b12fd72da --- /dev/null +++ b/tests/ui/lint/forbid-group-group-2.rs @@ -0,0 +1,26 @@ +// Check what happens when we forbid a bigger group but +// then deny a subset of that group. + +#![forbid(warnings)] +#![deny(forbidden_lint_groups)] + +#[allow(nonstandard_style)] +//~^ ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +fn main() {} diff --git a/tests/ui/lint/forbid-group-group-2.stderr b/tests/ui/lint/forbid-group-group-2.stderr new file mode 100644 index 000000000..b2e2bcea1 --- /dev/null +++ b/tests/ui/lint/forbid-group-group-2.stderr @@ -0,0 +1,115 @@ +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/forbid-group-group-2.rs:5:9 + | +LL | #![deny(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/forbid-group-member.rs b/tests/ui/lint/forbid-group-member.rs new file mode 100644 index 000000000..664edeaa8 --- /dev/null +++ b/tests/ui/lint/forbid-group-member.rs @@ -0,0 +1,17 @@ +// Check what happens when we forbid a group but +// then allow a member of that group. +// +// check-pass + +#![forbid(unused)] + +#[allow(unused_variables)] +//~^ WARNING incompatible with previous forbid +//~| WARNING previously accepted +//~| WARNING incompatible with previous forbid +//~| WARNING previously accepted +//~| WARNING incompatible with previous forbid +//~| WARNING previously accepted +fn main() { + let a: (); +} diff --git a/tests/ui/lint/forbid-group-member.stderr b/tests/ui/lint/forbid-group-member.stderr new file mode 100644 index 000000000..47336d4d8 --- /dev/null +++ b/tests/ui/lint/forbid-group-member.stderr @@ -0,0 +1,39 @@ +warning: allow(unused_variables) incompatible with previous forbid + --> $DIR/forbid-group-member.rs:8:9 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + = note: `#[warn(forbidden_lint_groups)]` on by default + +warning: allow(unused_variables) incompatible with previous forbid + --> $DIR/forbid-group-member.rs:8:9 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +warning: allow(unused_variables) incompatible with previous forbid + --> $DIR/forbid-group-member.rs:8:9 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/forbid-member-group.rs b/tests/ui/lint/forbid-member-group.rs new file mode 100644 index 000000000..e2f76825a --- /dev/null +++ b/tests/ui/lint/forbid-member-group.rs @@ -0,0 +1,11 @@ +// Check what happens when we forbid a member of +// a group but then allow the group. + +#![forbid(unused_variables)] + +#[allow(unused)] +//~^ ERROR incompatible with previous forbid +//~| ERROR incompatible with previous forbid +fn main() { + let a: (); +} diff --git a/tests/ui/lint/forbid-member-group.stderr b/tests/ui/lint/forbid-member-group.stderr new file mode 100644 index 000000000..e65301778 --- /dev/null +++ b/tests/ui/lint/forbid-member-group.stderr @@ -0,0 +1,21 @@ +error[E0453]: allow(unused) incompatible with previous forbid + --> $DIR/forbid-member-group.rs:6:9 + | +LL | #![forbid(unused_variables)] + | ---------------- `forbid` level set here +LL | +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + +error[E0453]: allow(unused) incompatible with previous forbid + --> $DIR/forbid-member-group.rs:6:9 + | +LL | #![forbid(unused_variables)] + | ---------------- `forbid` level set here +LL | +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/force-warn/allow-warnings.rs b/tests/ui/lint/force-warn/allow-warnings.rs new file mode 100644 index 000000000..0199381fc --- /dev/null +++ b/tests/ui/lint/force-warn/allow-warnings.rs @@ -0,0 +1,11 @@ +// --force-warn $LINT causes $LINT (which is warn-by-default) to warn +// despite allowing all warnings in module +// compile-flags: --force-warn dead_code +// check-pass + +#![allow(warnings)] + +fn dead_function() {} +//~^ WARN function `dead_function` is never used + +fn main() {} diff --git a/tests/ui/lint/force-warn/allow-warnings.stderr b/tests/ui/lint/force-warn/allow-warnings.stderr new file mode 100644 index 000000000..4de68a079 --- /dev/null +++ b/tests/ui/lint/force-warn/allow-warnings.stderr @@ -0,0 +1,10 @@ +warning: function `dead_function` is never used + --> $DIR/allow-warnings.rs:8:4 + | +LL | fn dead_function() {} + | ^^^^^^^^^^^^^ + | + = note: requested on the command line with `--force-warn dead-code` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/allowed-by-default-lint.rs b/tests/ui/lint/force-warn/allowed-by-default-lint.rs new file mode 100644 index 000000000..b24ab822d --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-by-default-lint.rs @@ -0,0 +1,12 @@ +// --force-warn $LINT causes $LINT (which is allow-by-default) to warn +// compile-flags: --force-warn elided_lifetimes_in_paths +// check-pass + +struct Foo<'a> { + x: &'a u32, +} + +fn foo(x: &Foo) {} +//~^ WARN hidden lifetime parameters in types are deprecated + +fn main() {} diff --git a/tests/ui/lint/force-warn/allowed-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-by-default-lint.stderr new file mode 100644 index 000000000..ac98b5896 --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-by-default-lint.stderr @@ -0,0 +1,14 @@ +warning: hidden lifetime parameters in types are deprecated + --> $DIR/allowed-by-default-lint.rs:9:12 + | +LL | fn foo(x: &Foo) {} + | ^^^ expected lifetime parameter + | + = note: requested on the command line with `--force-warn elided-lifetimes-in-paths` +help: indicate the anonymous lifetime + | +LL | fn foo(x: &Foo<'_>) {} + | ++++ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs b/tests/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs new file mode 100644 index 000000000..257df13ef --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs @@ -0,0 +1,10 @@ +// --force-warn $LINT causes $LINT (which is deny-by-default) to warn +// despite $LINT being allowed on command line +// compile-flags: -A mutable_transmutes --force-warn mutable_transmutes +// check-pass + +fn main() { + unsafe { + let y = std::mem::transmute::<&i32, &mut i32>(&5); //~WARN: undefined behavior + } +} diff --git a/tests/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr new file mode 100644 index 000000000..6a1fc76e1 --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr @@ -0,0 +1,10 @@ +warning: transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell + --> $DIR/allowed-cli-deny-by-default-lint.rs:8:17 + | +LL | let y = std::mem::transmute::<&i32, &mut i32>(&5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: requested on the command line with `--force-warn mutable-transmutes` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/allowed-deny-by-default-lint.rs b/tests/ui/lint/force-warn/allowed-deny-by-default-lint.rs new file mode 100644 index 000000000..0d4b468c2 --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-deny-by-default-lint.rs @@ -0,0 +1,11 @@ +// --force-warn $LINT causes $LINT (which is deny-by-default) to warn +// despite $LINT being allowed in module +// compile-flags: --force-warn mutable_transmutes +// check-pass + +#![allow(mutable_transmutes)] +fn main() { + unsafe { + let y = std::mem::transmute::<&i32, &mut i32>(&5); //~WARN: undefined behavior + } +} diff --git a/tests/ui/lint/force-warn/allowed-deny-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-deny-by-default-lint.stderr new file mode 100644 index 000000000..9ef53d47e --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-deny-by-default-lint.stderr @@ -0,0 +1,10 @@ +warning: transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell + --> $DIR/allowed-deny-by-default-lint.rs:9:17 + | +LL | let y = std::mem::transmute::<&i32, &mut i32>(&5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: requested on the command line with `--force-warn mutable-transmutes` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs new file mode 100644 index 000000000..631a8cb2f --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs @@ -0,0 +1,18 @@ +// --force-warn $LINT causes $LINT (which is warn-by-default) to warn +// despite $LINT_GROUP (which contains $LINT) being allowed +// compile-flags: --force-warn bare_trait_objects +// check-pass + +#![allow(rust_2018_idioms)] + +pub trait SomeTrait {} + +pub fn function(_x: Box<SomeTrait>) {} +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition + +fn main() {} diff --git a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr new file mode 100644 index 000000000..0f58953a5 --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr @@ -0,0 +1,42 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/allowed-group-warn-by-default-lint.rs:10:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> + = note: requested on the command line with `--force-warn bare-trait-objects` +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/allowed-group-warn-by-default-lint.rs:10:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/allowed-group-warn-by-default-lint.rs:10:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/force-warn/allowed-warn-by-default-lint.rs b/tests/ui/lint/force-warn/allowed-warn-by-default-lint.rs new file mode 100644 index 000000000..06b372867 --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-warn-by-default-lint.rs @@ -0,0 +1,11 @@ +// --force-warn $LINT causes $LINT (which is warn-by-default) to warn +// despite $LINT being allowed in module +// compile-flags: --force-warn dead_code +// check-pass + +#![allow(dead_code)] + +fn dead_function() {} +//~^ WARN function `dead_function` is never used + +fn main() {} diff --git a/tests/ui/lint/force-warn/allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-warn-by-default-lint.stderr new file mode 100644 index 000000000..a6634e212 --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-warn-by-default-lint.stderr @@ -0,0 +1,10 @@ +warning: function `dead_function` is never used + --> $DIR/allowed-warn-by-default-lint.rs:8:4 + | +LL | fn dead_function() {} + | ^^^^^^^^^^^^^ + | + = note: requested on the command line with `--force-warn dead-code` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/cap-lints-allow.rs b/tests/ui/lint/force-warn/cap-lints-allow.rs new file mode 100644 index 000000000..fdba7f410 --- /dev/null +++ b/tests/ui/lint/force-warn/cap-lints-allow.rs @@ -0,0 +1,16 @@ +// --force-warn $LINT casuses $LINT to warn despite --cap-lints +// set to allow +// compile-flags: --cap-lints allow --force-warn bare_trait_objects +// check-pass + +pub trait SomeTrait {} + +pub fn function(_x: Box<SomeTrait>) {} +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition + +fn main() {} diff --git a/tests/ui/lint/force-warn/cap-lints-allow.stderr b/tests/ui/lint/force-warn/cap-lints-allow.stderr new file mode 100644 index 000000000..03a32fa6f --- /dev/null +++ b/tests/ui/lint/force-warn/cap-lints-allow.stderr @@ -0,0 +1,42 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/cap-lints-allow.rs:8:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> + = note: requested on the command line with `--force-warn bare-trait-objects` +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/cap-lints-allow.rs:8:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/cap-lints-allow.rs:8:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.rs b/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.rs new file mode 100644 index 000000000..e65f156bf --- /dev/null +++ b/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.rs @@ -0,0 +1,17 @@ +// --force-warn $LINT_GROUP causes $LINT to warn despite $LINT being +// allowed in module and cap-lints set to warn +// compile-flags: --cap-lints warn --force-warn rust-2021-compatibility +// check-pass +#![allow(ellipsis_inclusive_range_patterns)] + +pub fn f() -> bool { + let x = 123; + match x { + 0...100 => true, + //~^ WARN range patterns are deprecated + //~| WARN this is accepted in the current edition + _ => false, + } +} + +fn main() {} diff --git a/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr new file mode 100644 index 000000000..d1b764b34 --- /dev/null +++ b/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr @@ -0,0 +1,12 @@ +warning: `...` range patterns are deprecated + --> $DIR/cap-lints-warn-allowed-warn-by-default-lint.rs:10:10 + | +LL | 0...100 => true, + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> + = note: `--force-warn ellipsis-inclusive-range-patterns` implied by `--force-warn rust-2021-compatibility` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/deny-by-default-lint.rs b/tests/ui/lint/force-warn/deny-by-default-lint.rs new file mode 100644 index 000000000..c2e9377e9 --- /dev/null +++ b/tests/ui/lint/force-warn/deny-by-default-lint.rs @@ -0,0 +1,9 @@ +// --force-warn $LINT causes $LINT (which is deny-by-default) to warn +// compile-flags: --force-warn mutable_transmutes +// check-pass + +fn main() { + unsafe { + let y = std::mem::transmute::<&i32, &mut i32>(&5); //~WARN: undefined behavior + } +} diff --git a/tests/ui/lint/force-warn/deny-by-default-lint.stderr b/tests/ui/lint/force-warn/deny-by-default-lint.stderr new file mode 100644 index 000000000..c644d0fe7 --- /dev/null +++ b/tests/ui/lint/force-warn/deny-by-default-lint.stderr @@ -0,0 +1,10 @@ +warning: transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell + --> $DIR/deny-by-default-lint.rs:7:17 + | +LL | let y = std::mem::transmute::<&i32, &mut i32>(&5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: requested on the command line with `--force-warn mutable-transmutes` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/lint-group-allow-warnings.rs b/tests/ui/lint/force-warn/lint-group-allow-warnings.rs new file mode 100644 index 000000000..4b95f4d2d --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allow-warnings.rs @@ -0,0 +1,12 @@ +// --force-warn $LINT_GROUP causes $LINT in $LINT_GROUP to warn +// despite all warnings being allowed in module +// warn-by-default lint to warn +// compile-flags: --force-warn nonstandard_style +// check-pass + +#![allow(warnings)] + +pub fn FUNCTION() {} +//~^ WARN function `FUNCTION` should have a snake case name + +fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allow-warnings.stderr b/tests/ui/lint/force-warn/lint-group-allow-warnings.stderr new file mode 100644 index 000000000..dc7b1b7b9 --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allow-warnings.stderr @@ -0,0 +1,10 @@ +warning: function `FUNCTION` should have a snake case name + --> $DIR/lint-group-allow-warnings.rs:9:8 + | +LL | pub fn FUNCTION() {} + | ^^^^^^^^ help: convert the identifier to snake case: `function` + | + = note: `--force-warn non-snake-case` implied by `--force-warn nonstandard-style` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs new file mode 100644 index 000000000..7ad7462dd --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs @@ -0,0 +1,16 @@ +// --force-warn $LINT_GROUP causes $LINT (which is warn-by-default) to warn +// despite $LINT being allowed on command line +// compile-flags: -A bare-trait-objects --force-warn rust-2018-idioms +// check-pass + +pub trait SomeTrait {} + +pub fn function(_x: Box<SomeTrait>) {} +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition + +fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr new file mode 100644 index 000000000..e17630fd3 --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr @@ -0,0 +1,42 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-cli-warn-by-default-lint.rs:8:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> + = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms` +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-cli-warn-by-default-lint.rs:8:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-cli-warn-by-default-lint.rs:8:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs new file mode 100644 index 000000000..ee5a18c38 --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs @@ -0,0 +1,18 @@ +// --force-warn $LINT_GROUP causes $LINT to warn despite +// $LINT_GROUP being allowed in module +// compile-flags: --force-warn rust_2018_idioms +// check-pass + +#![allow(rust_2018_idioms)] + +pub trait SomeTrait {} + +pub fn function(_x: Box<SomeTrait>) {} +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition + +fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr new file mode 100644 index 000000000..72198541a --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr @@ -0,0 +1,42 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-lint-group.rs:10:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> + = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms` +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-lint-group.rs:10:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-lint-group.rs:10:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs new file mode 100644 index 000000000..248aece6f --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs @@ -0,0 +1,18 @@ +// --force-warn $LINT_GROUP causes $LINT (which is warn-by-default) to warn +// despite $LINT being allowed in module +// compile-flags: --force-warn rust-2018-idioms +// check-pass + +#![allow(bare_trait_objects)] + +pub trait SomeTrait {} + +pub fn function(_x: Box<SomeTrait>) {} +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition + +fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr new file mode 100644 index 000000000..52c870ac2 --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr @@ -0,0 +1,42 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-warn-by-default-lint.rs:10:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> + = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms` +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-warn-by-default-lint.rs:10:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-warn-by-default-lint.rs:10:25 + | +LL | pub fn function(_x: Box<SomeTrait>) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +help: use `dyn` + | +LL | pub fn function(_x: Box<dyn SomeTrait>) {} + | +++ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/force-warn/warn-by-default-lint-two-modules.rs b/tests/ui/lint/force-warn/warn-by-default-lint-two-modules.rs new file mode 100644 index 000000000..47a480ad7 --- /dev/null +++ b/tests/ui/lint/force-warn/warn-by-default-lint-two-modules.rs @@ -0,0 +1,18 @@ +// --force-warn $LINT causes $LINT (which is warn-by-default) to warn +// despite being allowed in one submodule (but not the other) +// compile-flags: --force-warn dead_code +// check-pass + +mod one { + #![allow(dead_code)] + + fn dead_function() {} + //~^ WARN function `dead_function` is never used +} + +mod two { + fn dead_function() {} + //~^ WARN function `dead_function` is never used +} + +fn main() {} diff --git a/tests/ui/lint/force-warn/warn-by-default-lint-two-modules.stderr b/tests/ui/lint/force-warn/warn-by-default-lint-two-modules.stderr new file mode 100644 index 000000000..824bcccc0 --- /dev/null +++ b/tests/ui/lint/force-warn/warn-by-default-lint-two-modules.stderr @@ -0,0 +1,16 @@ +warning: function `dead_function` is never used + --> $DIR/warn-by-default-lint-two-modules.rs:9:8 + | +LL | fn dead_function() {} + | ^^^^^^^^^^^^^ + | + = note: requested on the command line with `--force-warn dead-code` + +warning: function `dead_function` is never used + --> $DIR/warn-by-default-lint-two-modules.rs:14:8 + | +LL | fn dead_function() {} + | ^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/force-warn/warnings-lint-group.rs b/tests/ui/lint/force-warn/warnings-lint-group.rs new file mode 100644 index 000000000..d1d4f5602 --- /dev/null +++ b/tests/ui/lint/force-warn/warnings-lint-group.rs @@ -0,0 +1,5 @@ +// --force-warn warnings is an error +// compile-flags: --force-warn warnings +// error-pattern: `warnings` lint group is not supported + +fn main() {} diff --git a/tests/ui/lint/force-warn/warnings-lint-group.stderr b/tests/ui/lint/force-warn/warnings-lint-group.stderr new file mode 100644 index 000000000..1faeed337 --- /dev/null +++ b/tests/ui/lint/force-warn/warnings-lint-group.stderr @@ -0,0 +1,7 @@ +error[E0602]: `warnings` lint group is not supported with ´--force-warn´ + +error[E0602]: `warnings` lint group is not supported with ´--force-warn´ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/function-item-references.rs b/tests/ui/lint/function-item-references.rs new file mode 100644 index 000000000..05213f4ed --- /dev/null +++ b/tests/ui/lint/function-item-references.rs @@ -0,0 +1,169 @@ +// check-pass +#![feature(c_variadic)] +#![warn(function_item_references)] +use std::fmt::Pointer; +use std::fmt::Formatter; + +fn nop() { } +fn foo() -> u32 { 42 } +fn bar(x: u32) -> u32 { x } +fn baz(x: u32, y: u32) -> u32 { x + y } +unsafe fn unsafe_fn() { } +extern "C" fn c_fn() { } +unsafe extern "C" fn unsafe_c_fn() { } +unsafe extern fn variadic(_x: u32, _args: ...) { } +fn take_generic_ref<'a, T>(_x: &'a T) { } +fn take_generic_array<T, const N: usize>(_x: [T; N]) { } +fn multiple_generic<T, U>(_x: T, _y: U) { } +fn multiple_generic_arrays<T, U, const N: usize, const M: usize>(_x: [T; N], _y: [U; M]) { } + +//function references passed to these functions should never lint +fn call_fn(f: &dyn Fn(u32) -> u32, x: u32) { f(x); } +fn parameterized_call_fn<F: Fn(u32) -> u32>(f: &F, x: u32) { f(x); } + +//function references passed to these functions should lint +fn print_ptr<F: Pointer>(f: F) { println!("{:p}", f); } +fn bound_by_ptr_trait<F: Pointer>(_f: F) { } +fn bound_by_ptr_trait_tuple<F: Pointer, G: Pointer>(_t: (F, G)) { } +fn implicit_ptr_trait<F>(f: &F) { println!("{:p}", f); } + +//case found in tinyvec that triggered a compiler error in an earlier version of the lint checker +trait HasItem { + type Item; + fn assoc_item(&self) -> Self::Item; +} +fn _format_assoc_item<T: HasItem>(data: T, f: &mut Formatter) -> std::fmt::Result + where T::Item: Pointer { + //when the arg type bound by `Pointer` is an associated type, we shouldn't attempt to normalize + Pointer::fmt(&data.assoc_item(), f) +} + +//simple test to make sure that calls to `Pointer::fmt` aren't double counted +fn _call_pointer_fmt(f: &mut Formatter) -> std::fmt::Result { + let zst_ref = &foo; + Pointer::fmt(&zst_ref, f) + //~^ WARNING taking a reference to a function item does not give a function pointer +} + +fn main() { + //`let` bindings with function references shouldn't lint + let _ = &foo; + let _ = &mut foo; + + let zst_ref = &foo; + let fn_item = foo; + let indirect_ref = &fn_item; + + let _mut_zst_ref = &mut foo; + let mut mut_fn_item = foo; + let _mut_indirect_ref = &mut mut_fn_item; + + let cast_zst_ptr = &foo as *const _; + let coerced_zst_ptr: *const _ = &foo; + + let _mut_cast_zst_ptr = &mut foo as *mut _; + let _mut_coerced_zst_ptr: *mut _ = &mut foo; + + let _cast_zst_ref = &foo as &dyn Fn() -> u32; + let _coerced_zst_ref: &dyn Fn() -> u32 = &foo; + + let _mut_cast_zst_ref = &mut foo as &mut dyn Fn() -> u32; + let _mut_coerced_zst_ref: &mut dyn Fn() -> u32 = &mut foo; + + //the suggested way to cast to a function pointer + let fn_ptr = foo as fn() -> u32; + + //correct ways to print function pointers + println!("{:p}", foo as fn() -> u32); + println!("{:p}", fn_ptr); + + //potential ways to incorrectly try printing function pointers + println!("{:p}", &foo); + //~^ WARNING taking a reference to a function item does not give a function pointer + print!("{:p}", &foo); + //~^ WARNING taking a reference to a function item does not give a function pointer + format!("{:p}", &foo); + //~^ WARNING taking a reference to a function item does not give a function pointer + + println!("{:p}", &foo as *const _); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", zst_ref); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", cast_zst_ptr); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", coerced_zst_ptr); + //~^ WARNING taking a reference to a function item does not give a function pointer + + println!("{:p}", &fn_item); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", indirect_ref); + //~^ WARNING taking a reference to a function item does not give a function pointer + + println!("{:p}", &nop); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &bar); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &baz); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &unsafe_fn); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &c_fn); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &unsafe_c_fn); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &variadic); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &take_generic_ref::<u32>); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &take_generic_array::<u32, 4>); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &multiple_generic::<u32, f32>); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &multiple_generic_arrays::<u32, f32, 4, 8>); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &std::env::var::<String>); + //~^ WARNING taking a reference to a function item does not give a function pointer + + println!("{:p} {:p} {:p}", &nop, &foo, &bar); + //~^ WARNING taking a reference to a function item does not give a function pointer + //~^^ WARNING taking a reference to a function item does not give a function pointer + //~^^^ WARNING taking a reference to a function item does not give a function pointer + + //using a function reference to call a function shouldn't lint + (&bar)(1); + + //passing a function reference to an arbitrary function shouldn't lint + call_fn(&bar, 1); + parameterized_call_fn(&bar, 1); + std::mem::size_of_val(&foo); + + unsafe { + //potential ways to incorrectly try transmuting function pointers + std::mem::transmute::<_, usize>(&foo); + //~^ WARNING taking a reference to a function item does not give a function pointer + std::mem::transmute::<_, (usize, usize)>((&foo, &bar)); + //~^ WARNING taking a reference to a function item does not give a function pointer + //~^^ WARNING taking a reference to a function item does not give a function pointer + std::mem::transmute::<_, usize>(&take_generic_ref::<u32>); + //~^ WARNING taking a reference to a function item does not give a function pointer + + //the correct way to transmute function pointers + std::mem::transmute::<_, usize>(foo as fn() -> u32); + std::mem::transmute::<_, (usize, usize)>((foo as fn() -> u32, bar as fn(u32) -> u32)); + } + + //function references as arguments required to be bound by std::fmt::Pointer should lint + print_ptr(&bar); + //~^ WARNING taking a reference to a function item does not give a function pointer + bound_by_ptr_trait(&bar); + //~^ WARNING taking a reference to a function item does not give a function pointer + bound_by_ptr_trait_tuple((&foo, &bar)); + //~^ WARNING taking a reference to a function item does not give a function pointer + //~^^ WARNING taking a reference to a function item does not give a function pointer + implicit_ptr_trait(&bar); // ignore + + //correct ways to pass function pointers as arguments bound by std::fmt::Pointer + print_ptr(bar as fn(u32) -> u32); + bound_by_ptr_trait(bar as fn(u32) -> u32); + bound_by_ptr_trait_tuple((foo as fn() -> u32, bar as fn(u32) -> u32)); +} diff --git a/tests/ui/lint/function-item-references.stderr b/tests/ui/lint/function-item-references.stderr new file mode 100644 index 000000000..a9d18bb6a --- /dev/null +++ b/tests/ui/lint/function-item-references.stderr @@ -0,0 +1,206 @@ +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:44:18 + | +LL | Pointer::fmt(&zst_ref, f) + | ^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + | +note: the lint level is defined here + --> $DIR/function-item-references.rs:3:9 + | +LL | #![warn(function_item_references)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:81:22 + | +LL | println!("{:p}", &foo); + | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:83:20 + | +LL | print!("{:p}", &foo); + | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:85:21 + | +LL | format!("{:p}", &foo); + | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:88:22 + | +LL | println!("{:p}", &foo as *const _); + | ^^^^^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:90:22 + | +LL | println!("{:p}", zst_ref); + | ^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:92:22 + | +LL | println!("{:p}", cast_zst_ptr); + | ^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:94:22 + | +LL | println!("{:p}", coerced_zst_ptr); + | ^^^^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:97:22 + | +LL | println!("{:p}", &fn_item); + | ^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:99:22 + | +LL | println!("{:p}", indirect_ref); + | ^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:102:22 + | +LL | println!("{:p}", &nop); + | ^^^^ help: cast `nop` to obtain a function pointer: `nop as fn()` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:104:22 + | +LL | println!("{:p}", &bar); + | ^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:106:22 + | +LL | println!("{:p}", &baz); + | ^^^^ help: cast `baz` to obtain a function pointer: `baz as fn(_, _) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:108:22 + | +LL | println!("{:p}", &unsafe_fn); + | ^^^^^^^^^^ help: cast `unsafe_fn` to obtain a function pointer: `unsafe_fn as unsafe fn()` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:110:22 + | +LL | println!("{:p}", &c_fn); + | ^^^^^ help: cast `c_fn` to obtain a function pointer: `c_fn as extern "C" fn()` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:112:22 + | +LL | println!("{:p}", &unsafe_c_fn); + | ^^^^^^^^^^^^ help: cast `unsafe_c_fn` to obtain a function pointer: `unsafe_c_fn as unsafe extern "C" fn()` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:114:22 + | +LL | println!("{:p}", &variadic); + | ^^^^^^^^^ help: cast `variadic` to obtain a function pointer: `variadic as unsafe extern "C" fn(_, ...)` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:116:22 + | +LL | println!("{:p}", &take_generic_ref::<u32>); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `take_generic_ref` to obtain a function pointer: `take_generic_ref::<u32> as fn(_)` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:118:22 + | +LL | println!("{:p}", &take_generic_array::<u32, 4>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `take_generic_array` to obtain a function pointer: `take_generic_array::<u32, 4> as fn(_)` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:120:22 + | +LL | println!("{:p}", &multiple_generic::<u32, f32>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `multiple_generic` to obtain a function pointer: `multiple_generic::<u32, f32> as fn(_, _)` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:122:22 + | +LL | println!("{:p}", &multiple_generic_arrays::<u32, f32, 4, 8>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `multiple_generic_arrays` to obtain a function pointer: `multiple_generic_arrays::<u32, f32, 4, 8> as fn(_, _)` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:124:22 + | +LL | println!("{:p}", &std::env::var::<String>); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `var` to obtain a function pointer: `var::<String> as fn(_) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:127:32 + | +LL | println!("{:p} {:p} {:p}", &nop, &foo, &bar); + | ^^^^ help: cast `nop` to obtain a function pointer: `nop as fn()` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:127:38 + | +LL | println!("{:p} {:p} {:p}", &nop, &foo, &bar); + | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:127:44 + | +LL | println!("{:p} {:p} {:p}", &nop, &foo, &bar); + | ^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:142:41 + | +LL | std::mem::transmute::<_, usize>(&foo); + | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:144:50 + | +LL | std::mem::transmute::<_, (usize, usize)>((&foo, &bar)); + | ^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:144:50 + | +LL | std::mem::transmute::<_, (usize, usize)>((&foo, &bar)); + | ^^^^^^^^^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:147:41 + | +LL | std::mem::transmute::<_, usize>(&take_generic_ref::<u32>); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `take_generic_ref` to obtain a function pointer: `take_generic_ref::<u32> as fn(_)` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:156:15 + | +LL | print_ptr(&bar); + | ^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:158:24 + | +LL | bound_by_ptr_trait(&bar); + | ^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:160:30 + | +LL | bound_by_ptr_trait_tuple((&foo, &bar)); + | ^^^^^^^^^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:160:30 + | +LL | bound_by_ptr_trait_tuple((&foo, &bar)); + | ^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: 33 warnings emitted + diff --git a/tests/ui/lint/future-incompat-test.rs b/tests/ui/lint/future-incompat-test.rs new file mode 100644 index 000000000..c5f477cc4 --- /dev/null +++ b/tests/ui/lint/future-incompat-test.rs @@ -0,0 +1,10 @@ +// compile-flags: -Zfuture-incompat-test +// check-pass + +// The `-Zfuture-incompat-test flag causes any normal warning to be included +// in the future-incompatible report. The stderr output here should mention +// the future incompatible report (as extracted by compiletest). + +fn main() { + let x = 1; +} diff --git a/tests/ui/lint/future-incompat-test.stderr b/tests/ui/lint/future-incompat-test.stderr new file mode 100644 index 000000000..52674a843 --- /dev/null +++ b/tests/ui/lint/future-incompat-test.stderr @@ -0,0 +1,9 @@ +Future incompatibility report: Future breakage diagnostic: +warning: unused variable: `x` + --> $DIR/future-incompat-test.rs:9:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `-A unused-variables` implied by `-A unused` + diff --git a/tests/ui/lint/inclusive-range-pattern-syntax.fixed b/tests/ui/lint/inclusive-range-pattern-syntax.fixed new file mode 100644 index 000000000..bee5d4ae4 --- /dev/null +++ b/tests/ui/lint/inclusive-range-pattern-syntax.fixed @@ -0,0 +1,21 @@ +// check-pass +// run-rustfix + +#![warn(ellipsis_inclusive_range_patterns)] + +fn main() { + let despondency = 2; + match despondency { + 1..=2 => {} + //~^ WARN `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + _ => {} + } + + match &despondency { + &(1..=2) => {} + //~^ WARN `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + _ => {} + } +} diff --git a/tests/ui/lint/inclusive-range-pattern-syntax.rs b/tests/ui/lint/inclusive-range-pattern-syntax.rs new file mode 100644 index 000000000..d98c10c26 --- /dev/null +++ b/tests/ui/lint/inclusive-range-pattern-syntax.rs @@ -0,0 +1,21 @@ +// check-pass +// run-rustfix + +#![warn(ellipsis_inclusive_range_patterns)] + +fn main() { + let despondency = 2; + match despondency { + 1...2 => {} + //~^ WARN `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + _ => {} + } + + match &despondency { + &1...2 => {} + //~^ WARN `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + _ => {} + } +} diff --git a/tests/ui/lint/inclusive-range-pattern-syntax.stderr b/tests/ui/lint/inclusive-range-pattern-syntax.stderr new file mode 100644 index 000000000..ed9fa0d41 --- /dev/null +++ b/tests/ui/lint/inclusive-range-pattern-syntax.stderr @@ -0,0 +1,25 @@ +warning: `...` range patterns are deprecated + --> $DIR/inclusive-range-pattern-syntax.rs:9:10 + | +LL | 1...2 => {} + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +note: the lint level is defined here + --> $DIR/inclusive-range-pattern-syntax.rs:4:9 + | +LL | #![warn(ellipsis_inclusive_range_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `...` range patterns are deprecated + --> $DIR/inclusive-range-pattern-syntax.rs:16:9 + | +LL | &1...2 => {} + | ^^^^^^ help: use `..=` for an inclusive range: `&(1..=2)` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/inert-attr-macro.rs b/tests/ui/lint/inert-attr-macro.rs new file mode 100644 index 000000000..dc0bb8ac2 --- /dev/null +++ b/tests/ui/lint/inert-attr-macro.rs @@ -0,0 +1,20 @@ +// check-pass + +#![warn(unused)] + +macro_rules! foo { + () => {} +} + +fn main() { + #[inline] foo!(); //~ WARN unused attribute `inline` + + // This does nothing, since `#[allow(warnings)]` is itself + // an inert attribute on a macro call + #[allow(warnings)] #[inline] foo!(); //~ WARN unused attribute `allow` + //~^ WARN unused attribute `inline` + + // This does work, since the attribute is on a parent + // of the macro invocation. + #[allow(warnings)] { #[inline] foo!(); } +} diff --git a/tests/ui/lint/inert-attr-macro.stderr b/tests/ui/lint/inert-attr-macro.stderr new file mode 100644 index 000000000..5ccb4ffe7 --- /dev/null +++ b/tests/ui/lint/inert-attr-macro.stderr @@ -0,0 +1,44 @@ +warning: unused attribute `inline` + --> $DIR/inert-attr-macro.rs:10:5 + | +LL | #[inline] foo!(); + | ^^^^^^^^^ + | +note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo` + --> $DIR/inert-attr-macro.rs:10:15 + | +LL | #[inline] foo!(); + | ^^^ +note: the lint level is defined here + --> $DIR/inert-attr-macro.rs:3:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_attributes)]` implied by `#[warn(unused)]` + +warning: unused attribute `allow` + --> $DIR/inert-attr-macro.rs:14:5 + | +LL | #[allow(warnings)] #[inline] foo!(); + | ^^^^^^^^^^^^^^^^^^ + | +note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `foo` + --> $DIR/inert-attr-macro.rs:14:34 + | +LL | #[allow(warnings)] #[inline] foo!(); + | ^^^ + +warning: unused attribute `inline` + --> $DIR/inert-attr-macro.rs:14:24 + | +LL | #[allow(warnings)] #[inline] foo!(); + | ^^^^^^^^^ + | +note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo` + --> $DIR/inert-attr-macro.rs:14:34 + | +LL | #[allow(warnings)] #[inline] foo!(); + | ^^^ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/inline-trait-and-foreign-items.rs b/tests/ui/lint/inline-trait-and-foreign-items.rs new file mode 100644 index 000000000..13dab7ed9 --- /dev/null +++ b/tests/ui/lint/inline-trait-and-foreign-items.rs @@ -0,0 +1,37 @@ +#![feature(extern_types)] +#![feature(type_alias_impl_trait)] + +#![warn(unused_attributes)] + +trait Trait { + #[inline] //~ WARN `#[inline]` is ignored on constants + //~^ WARN this was previously accepted + const X: u32; + + #[inline] //~ ERROR attribute should be applied to function or closure + type T; + + type U; +} + +impl Trait for () { + #[inline] //~ WARN `#[inline]` is ignored on constants + //~^ WARN this was previously accepted + const X: u32 = 0; + + #[inline] //~ ERROR attribute should be applied to function or closure + type T = Self; + + #[inline] //~ ERROR attribute should be applied to function or closure + type U = impl Trait; //~ ERROR unconstrained opaque type +} + +extern "C" { + #[inline] //~ ERROR attribute should be applied to function or closure + static X: u32; + + #[inline] //~ ERROR attribute should be applied to function or closure + type T; +} + +fn main() {} diff --git a/tests/ui/lint/inline-trait-and-foreign-items.stderr b/tests/ui/lint/inline-trait-and-foreign-items.stderr new file mode 100644 index 000000000..2f1fb4c46 --- /dev/null +++ b/tests/ui/lint/inline-trait-and-foreign-items.stderr @@ -0,0 +1,74 @@ +warning: `#[inline]` is ignored on constants + --> $DIR/inline-trait-and-foreign-items.rs:7:5 + | +LL | #[inline] + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: see issue #65833 <https://github.com/rust-lang/rust/issues/65833> for more information +note: the lint level is defined here + --> $DIR/inline-trait-and-foreign-items.rs:4:9 + | +LL | #![warn(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error[E0518]: attribute should be applied to function or closure + --> $DIR/inline-trait-and-foreign-items.rs:11:5 + | +LL | #[inline] + | ^^^^^^^^^ +LL | type T; + | ------- not a function or closure + +warning: `#[inline]` is ignored on constants + --> $DIR/inline-trait-and-foreign-items.rs:18:5 + | +LL | #[inline] + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: see issue #65833 <https://github.com/rust-lang/rust/issues/65833> for more information + +error[E0518]: attribute should be applied to function or closure + --> $DIR/inline-trait-and-foreign-items.rs:22:5 + | +LL | #[inline] + | ^^^^^^^^^ +LL | type T = Self; + | -------------- not a function or closure + +error[E0518]: attribute should be applied to function or closure + --> $DIR/inline-trait-and-foreign-items.rs:25:5 + | +LL | #[inline] + | ^^^^^^^^^ +LL | type U = impl Trait; + | -------------------- not a function or closure + +error[E0518]: attribute should be applied to function or closure + --> $DIR/inline-trait-and-foreign-items.rs:30:5 + | +LL | #[inline] + | ^^^^^^^^^ +LL | static X: u32; + | -------------- not a function or closure + +error[E0518]: attribute should be applied to function or closure + --> $DIR/inline-trait-and-foreign-items.rs:33:5 + | +LL | #[inline] + | ^^^^^^^^^ +LL | type T; + | ------- not a function or closure + +error: unconstrained opaque type + --> $DIR/inline-trait-and-foreign-items.rs:26:14 + | +LL | type U = impl Trait; + | ^^^^^^^^^^ + | + = note: `U` must be used in combination with a concrete type within the same impl + +error: aborting due to 6 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0518`. diff --git a/tests/ui/lint/invalid_value.rs b/tests/ui/lint/invalid_value.rs new file mode 100644 index 000000000..57d8cbe7c --- /dev/null +++ b/tests/ui/lint/invalid_value.rs @@ -0,0 +1,169 @@ +// This test checks that calling `mem::{uninitialized,zeroed}` with certain types results +// in a lint. + +#![feature(never_type, rustc_attrs)] +#![allow(deprecated)] +#![deny(invalid_value)] + +use std::mem::{self, MaybeUninit}; +use std::ptr::NonNull; +use std::num::NonZeroU32; + +enum Void {} + +struct Ref(&'static i32); +struct RefPair((&'static i32, i32)); + +struct Wrap<T> { wrapped: T } +enum WrapEnum<T> { Wrapped(T) } + +#[rustc_layout_scalar_valid_range_start(0)] +#[rustc_layout_scalar_valid_range_end(128)] +#[repr(transparent)] +pub(crate) struct NonBig(u64); + +/// A two-variant enum, thus needs a tag and may not remain uninitialized. +enum Fruit { + Apple, + Banana, +} + +/// Looks like two variants but really only has one. +enum OneFruit { + Apple(!), + Banana, +} + +enum OneFruitNonZero { + Apple(!), + Banana(NonZeroU32), +} + +enum TwoUninhabited { + A(!), + B(Void), +} + +#[rustc_layout_scalar_valid_range_start(254)] +#[rustc_layout_scalar_valid_range_end(1)] +pub(crate) struct WrapAroundRange(u8); + +#[allow(unused)] +fn generic<T: 'static>() { + unsafe { + let _val: &'static T = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: &'static T = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap<&'static T> = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Wrap<&'static T> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + } +} + +fn main() { + unsafe { + // Things that cannot even be zero. + let _val: ! = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: ! = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: (i32, !) = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: (i32, !) = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Void = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Void = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: &'static i32 = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: &'static i32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Ref = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Ref = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: fn() = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: fn() = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap<fn()> = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Wrap<fn()> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: WrapEnum<fn()> = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: WrapEnum<fn()> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap<(RefPair, i32)> = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: NonNull<i32> = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: NonNull<i32> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: (NonZeroU32, i32) = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: (NonZeroU32, i32) = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: *const dyn Send = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: *const dyn Send = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: [fn(); 2] = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: [fn(); 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: TwoUninhabited = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: TwoUninhabited = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: OneFruitNonZero = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: OneFruitNonZero = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Things that can be zero, but not uninit. + let _val: bool = mem::zeroed(); + let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap<char> = mem::zeroed(); + let _val: Wrap<char> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: NonBig = mem::zeroed(); + let _val: NonBig = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Fruit = mem::zeroed(); + let _val: Fruit = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: [bool; 2] = mem::zeroed(); + let _val: [bool; 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: i32 = mem::zeroed(); + let _val: i32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: f32 = mem::zeroed(); + let _val: f32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: *const () = mem::zeroed(); + let _val: *const () = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: *const [()] = mem::zeroed(); + let _val: *const [()] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: WrapAroundRange = mem::zeroed(); + let _val: WrapAroundRange = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Things where 0 is okay due to rustc implementation details, + // but that are not guaranteed to keep working. + let _val: Result<i32, i32> = mem::zeroed(); + let _val: Result<i32, i32> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Some things that happen to be UB-free due to rustc implementation details, + // but are not guaranteed to keep working. + let _val: OneFruit = mem::zeroed(); + let _val: OneFruit = mem::uninitialized(); + + // Transmute-from-0 + let _val: &'static i32 = mem::transmute(0usize); //~ ERROR: does not permit zero-initialization + let _val: &'static [i32] = mem::transmute((0usize, 0usize)); //~ ERROR: does not permit zero-initialization + let _val: NonZeroU32 = mem::transmute(0); //~ ERROR: does not permit zero-initialization + + // `MaybeUninit` cases + let _val: NonNull<i32> = MaybeUninit::zeroed().assume_init(); //~ ERROR: does not permit zero-initialization + let _val: NonNull<i32> = MaybeUninit::uninit().assume_init(); //~ ERROR: does not permit being left uninitialized + let _val: bool = MaybeUninit::uninit().assume_init(); //~ ERROR: does not permit being left uninitialized + + // Some more types that should work just fine. + let _val: Option<&'static i32> = mem::zeroed(); + let _val: Option<fn()> = mem::zeroed(); + let _val: MaybeUninit<&'static i32> = mem::zeroed(); + let _val: bool = MaybeUninit::zeroed().assume_init(); + let _val: [bool; 0] = MaybeUninit::uninit().assume_init(); + let _val: [!; 0] = MaybeUninit::zeroed().assume_init(); + } +} diff --git a/tests/ui/lint/invalid_value.stderr b/tests/ui/lint/invalid_value.stderr new file mode 100644 index 000000000..48fd4169d --- /dev/null +++ b/tests/ui/lint/invalid_value.stderr @@ -0,0 +1,676 @@ +error: the type `&T` does not permit zero-initialization + --> $DIR/invalid_value.rs:54:32 + | +LL | let _val: &'static T = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null +note: the lint level is defined here + --> $DIR/invalid_value.rs:6:9 + | +LL | #![deny(invalid_value)] + | ^^^^^^^^^^^^^ + +error: the type `&T` does not permit being left uninitialized + --> $DIR/invalid_value.rs:55:32 + | +LL | let _val: &'static T = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `Wrap<&T>` does not permit zero-initialization + --> $DIR/invalid_value.rs:57:38 + | +LL | let _val: Wrap<&'static T> = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `Wrap<&T>` must be non-null +note: because references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap<T> { wrapped: T } + | ^^^^^^^^^^ + +error: the type `Wrap<&T>` does not permit being left uninitialized + --> $DIR/invalid_value.rs:58:38 + | +LL | let _val: Wrap<&'static T> = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `Wrap<&T>` must be non-null +note: because references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap<T> { wrapped: T } + | ^^^^^^^^^^ + +error: the type `!` does not permit zero-initialization + --> $DIR/invalid_value.rs:65:23 + | +LL | let _val: ! = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: the `!` type has no valid value + +error: the type `!` does not permit being left uninitialized + --> $DIR/invalid_value.rs:66:23 + | +LL | let _val: ! = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: the `!` type has no valid value + +error: the type `(i32, !)` does not permit zero-initialization + --> $DIR/invalid_value.rs:68:30 + | +LL | let _val: (i32, !) = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: the `!` type has no valid value + +error: the type `(i32, !)` does not permit being left uninitialized + --> $DIR/invalid_value.rs:69:30 + | +LL | let _val: (i32, !) = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: integers must be initialized + +error: the type `Void` does not permit zero-initialization + --> $DIR/invalid_value.rs:71:26 + | +LL | let _val: Void = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:12:1 + | +LL | enum Void {} + | ^^^^^^^^^ + +error: the type `Void` does not permit being left uninitialized + --> $DIR/invalid_value.rs:72:26 + | +LL | let _val: Void = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:12:1 + | +LL | enum Void {} + | ^^^^^^^^^ + +error: the type `&i32` does not permit zero-initialization + --> $DIR/invalid_value.rs:74:34 + | +LL | let _val: &'static i32 = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `&i32` does not permit being left uninitialized + --> $DIR/invalid_value.rs:75:34 + | +LL | let _val: &'static i32 = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `Ref` does not permit zero-initialization + --> $DIR/invalid_value.rs:77:25 + | +LL | let _val: Ref = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `Ref` must be non-null +note: because references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:14:12 + | +LL | struct Ref(&'static i32); + | ^^^^^^^^^^^^ + +error: the type `Ref` does not permit being left uninitialized + --> $DIR/invalid_value.rs:78:25 + | +LL | let _val: Ref = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `Ref` must be non-null +note: because references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:14:12 + | +LL | struct Ref(&'static i32); + | ^^^^^^^^^^^^ + +error: the type `fn()` does not permit zero-initialization + --> $DIR/invalid_value.rs:80:26 + | +LL | let _val: fn() = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: function pointers must be non-null + +error: the type `fn()` does not permit being left uninitialized + --> $DIR/invalid_value.rs:81:26 + | +LL | let _val: fn() = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: function pointers must be non-null + +error: the type `Wrap<fn()>` does not permit zero-initialization + --> $DIR/invalid_value.rs:83:32 + | +LL | let _val: Wrap<fn()> = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `Wrap<fn()>` must be non-null +note: because function pointers must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap<T> { wrapped: T } + | ^^^^^^^^^^ + +error: the type `Wrap<fn()>` does not permit being left uninitialized + --> $DIR/invalid_value.rs:84:32 + | +LL | let _val: Wrap<fn()> = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `Wrap<fn()>` must be non-null +note: because function pointers must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap<T> { wrapped: T } + | ^^^^^^^^^^ + +error: the type `WrapEnum<fn()>` does not permit zero-initialization + --> $DIR/invalid_value.rs:86:36 + | +LL | let _val: WrapEnum<fn()> = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `WrapEnum<fn()>` must be non-null +note: because function pointers must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:18:28 + | +LL | enum WrapEnum<T> { Wrapped(T) } + | ^ + +error: the type `WrapEnum<fn()>` does not permit being left uninitialized + --> $DIR/invalid_value.rs:87:36 + | +LL | let _val: WrapEnum<fn()> = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `WrapEnum<fn()>` must be non-null +note: because function pointers must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:18:28 + | +LL | enum WrapEnum<T> { Wrapped(T) } + | ^ + +error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization + --> $DIR/invalid_value.rs:89:42 + | +LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | +note: `RefPair` must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap<T> { wrapped: T } + | ^^^^^^^^^^ +note: because references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:15:16 + | +LL | struct RefPair((&'static i32, i32)); + | ^^^^^^^^^^^^^^^^^^^ + +error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized + --> $DIR/invalid_value.rs:90:42 + | +LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | +note: `RefPair` must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap<T> { wrapped: T } + | ^^^^^^^^^^ +note: because references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:15:16 + | +LL | struct RefPair((&'static i32, i32)); + | ^^^^^^^^^^^^^^^^^^^ + +error: the type `NonNull<i32>` does not permit zero-initialization + --> $DIR/invalid_value.rs:92:34 + | +LL | let _val: NonNull<i32> = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `std::ptr::NonNull<i32>` must be non-null + +error: the type `NonNull<i32>` does not permit being left uninitialized + --> $DIR/invalid_value.rs:93:34 + | +LL | let _val: NonNull<i32> = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `std::ptr::NonNull<i32>` must be non-null + = note: raw pointers must be initialized + +error: the type `(NonZeroU32, i32)` does not permit zero-initialization + --> $DIR/invalid_value.rs:95:39 + | +LL | let _val: (NonZeroU32, i32) = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `std::num::NonZeroU32` must be non-null + +error: the type `(NonZeroU32, i32)` does not permit being left uninitialized + --> $DIR/invalid_value.rs:96:39 + | +LL | let _val: (NonZeroU32, i32) = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `std::num::NonZeroU32` must be non-null + = note: integers must be initialized + +error: the type `*const dyn Send` does not permit zero-initialization + --> $DIR/invalid_value.rs:98:37 + | +LL | let _val: *const dyn Send = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: the vtable of a wide raw pointer must be non-null + +error: the type `*const dyn Send` does not permit being left uninitialized + --> $DIR/invalid_value.rs:99:37 + | +LL | let _val: *const dyn Send = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: the vtable of a wide raw pointer must be non-null + +error: the type `[fn(); 2]` does not permit zero-initialization + --> $DIR/invalid_value.rs:101:31 + | +LL | let _val: [fn(); 2] = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: function pointers must be non-null + +error: the type `[fn(); 2]` does not permit being left uninitialized + --> $DIR/invalid_value.rs:102:31 + | +LL | let _val: [fn(); 2] = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: function pointers must be non-null + +error: the type `TwoUninhabited` does not permit zero-initialization + --> $DIR/invalid_value.rs:104:36 + | +LL | let _val: TwoUninhabited = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:42:1 + | +LL | enum TwoUninhabited { + | ^^^^^^^^^^^^^^^^^^^ + +error: the type `TwoUninhabited` does not permit being left uninitialized + --> $DIR/invalid_value.rs:105:36 + | +LL | let _val: TwoUninhabited = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:42:1 + | +LL | enum TwoUninhabited { + | ^^^^^^^^^^^^^^^^^^^ + +error: the type `OneFruitNonZero` does not permit zero-initialization + --> $DIR/invalid_value.rs:107:37 + | +LL | let _val: OneFruitNonZero = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `OneFruitNonZero` must be non-null +note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:39:12 + | +LL | Banana(NonZeroU32), + | ^^^^^^^^^^ + +error: the type `OneFruitNonZero` does not permit being left uninitialized + --> $DIR/invalid_value.rs:108:37 + | +LL | let _val: OneFruitNonZero = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `OneFruitNonZero` must be non-null +note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:39:12 + | +LL | Banana(NonZeroU32), + | ^^^^^^^^^^ + = note: integers must be initialized + +error: the type `bool` does not permit being left uninitialized + --> $DIR/invalid_value.rs:112:26 + | +LL | let _val: bool = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: booleans must be either `true` or `false` + +error: the type `Wrap<char>` does not permit being left uninitialized + --> $DIR/invalid_value.rs:115:32 + | +LL | let _val: Wrap<char> = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `Wrap<char>` must be initialized inside its custom valid range +note: characters must be a valid Unicode codepoint (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap<T> { wrapped: T } + | ^^^^^^^^^^ + +error: the type `NonBig` does not permit being left uninitialized + --> $DIR/invalid_value.rs:118:28 + | +LL | let _val: NonBig = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `NonBig` must be initialized inside its custom valid range +note: integers must be initialized (in this struct field) + --> $DIR/invalid_value.rs:23:26 + | +LL | pub(crate) struct NonBig(u64); + | ^^^ + +error: the type `Fruit` does not permit being left uninitialized + --> $DIR/invalid_value.rs:121:27 + | +LL | let _val: Fruit = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | +note: enums with multiple inhabited variants have to be initialized to a variant + --> $DIR/invalid_value.rs:26:1 + | +LL | enum Fruit { + | ^^^^^^^^^^ + +error: the type `[bool; 2]` does not permit being left uninitialized + --> $DIR/invalid_value.rs:124:31 + | +LL | let _val: [bool; 2] = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: booleans must be either `true` or `false` + +error: the type `i32` does not permit being left uninitialized + --> $DIR/invalid_value.rs:127:25 + | +LL | let _val: i32 = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: integers must be initialized + +error: the type `f32` does not permit being left uninitialized + --> $DIR/invalid_value.rs:130:25 + | +LL | let _val: f32 = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: floats must be initialized + +error: the type `*const ()` does not permit being left uninitialized + --> $DIR/invalid_value.rs:133:31 + | +LL | let _val: *const () = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: raw pointers must be initialized + +error: the type `*const [()]` does not permit being left uninitialized + --> $DIR/invalid_value.rs:136:33 + | +LL | let _val: *const [()] = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: raw pointers must be initialized + +error: the type `WrapAroundRange` does not permit being left uninitialized + --> $DIR/invalid_value.rs:139:37 + | +LL | let _val: WrapAroundRange = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `WrapAroundRange` must be initialized inside its custom valid range +note: integers must be initialized (in this struct field) + --> $DIR/invalid_value.rs:49:35 + | +LL | pub(crate) struct WrapAroundRange(u8); + | ^^ + +error: the type `Result<i32, i32>` does not permit being left uninitialized + --> $DIR/invalid_value.rs:144:38 + | +LL | let _val: Result<i32, i32> = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | +note: enums with multiple inhabited variants have to be initialized to a variant + --> $SRC_DIR/core/src/result.rs:LL:COL + +error: the type `&i32` does not permit zero-initialization + --> $DIR/invalid_value.rs:152:34 + | +LL | let _val: &'static i32 = mem::transmute(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `&[i32]` does not permit zero-initialization + --> $DIR/invalid_value.rs:153:36 + | +LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `NonZeroU32` does not permit zero-initialization + --> $DIR/invalid_value.rs:154:32 + | +LL | let _val: NonZeroU32 = mem::transmute(0); + | ^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `std::num::NonZeroU32` must be non-null + +error: the type `NonNull<i32>` does not permit zero-initialization + --> $DIR/invalid_value.rs:157:34 + | +LL | let _val: NonNull<i32> = MaybeUninit::zeroed().assume_init(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `std::ptr::NonNull<i32>` must be non-null + +error: the type `NonNull<i32>` does not permit being left uninitialized + --> $DIR/invalid_value.rs:158:34 + | +LL | let _val: NonNull<i32> = MaybeUninit::uninit().assume_init(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: `std::ptr::NonNull<i32>` must be non-null + = note: raw pointers must be initialized + +error: the type `bool` does not permit being left uninitialized + --> $DIR/invalid_value.rs:159:26 + | +LL | let _val: bool = MaybeUninit::uninit().assume_init(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done + | + = note: booleans must be either `true` or `false` + +error: aborting due to 51 previous errors + diff --git a/tests/ui/lint/issue-101284.rs b/tests/ui/lint/issue-101284.rs new file mode 100644 index 000000000..1381d4f17 --- /dev/null +++ b/tests/ui/lint/issue-101284.rs @@ -0,0 +1,15 @@ +// check-pass +// edition:2021 +#![deny(rust_2021_compatibility)] + +pub struct Warns { + // `Arc` has significant drop + _significant_drop: std::sync::Arc<()>, + field: String, +} + +pub fn test(w: Warns) { + _ = || drop(w.field); +} + +fn main() {} diff --git a/tests/ui/lint/issue-102705.rs b/tests/ui/lint/issue-102705.rs new file mode 100644 index 000000000..5bcc8950a --- /dev/null +++ b/tests/ui/lint/issue-102705.rs @@ -0,0 +1,22 @@ +// check-pass + +#![allow(opaque_hidden_inferred_bound)] +#![allow(dead_code)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl<R: Duh, F: FnMut() -> R> Trait for F { + type Assoc = R; +} + +fn foo() -> impl Trait<Assoc = impl Send> { + || 42 +} + +fn main() {} diff --git a/tests/ui/lint/issue-103317.fixed b/tests/ui/lint/issue-103317.fixed new file mode 100644 index 000000000..5a987423e --- /dev/null +++ b/tests/ui/lint/issue-103317.fixed @@ -0,0 +1,14 @@ +// check-pass +// run-rustfix + +#[warn(unreachable_pub)] +mod inner { + #[allow(unused)] + pub(crate) enum T { + //~^ WARN unreachable `pub` item + A(u8), + X { a: f32, b: () }, + } +} + +fn main() {} diff --git a/tests/ui/lint/issue-103317.rs b/tests/ui/lint/issue-103317.rs new file mode 100644 index 000000000..c2ba939e1 --- /dev/null +++ b/tests/ui/lint/issue-103317.rs @@ -0,0 +1,14 @@ +// check-pass +// run-rustfix + +#[warn(unreachable_pub)] +mod inner { + #[allow(unused)] + pub enum T { + //~^ WARN unreachable `pub` item + A(u8), + X { a: f32, b: () }, + } +} + +fn main() {} diff --git a/tests/ui/lint/issue-103317.stderr b/tests/ui/lint/issue-103317.stderr new file mode 100644 index 000000000..9c982ddc3 --- /dev/null +++ b/tests/ui/lint/issue-103317.stderr @@ -0,0 +1,17 @@ +warning: unreachable `pub` item + --> $DIR/issue-103317.rs:7:5 + | +LL | pub enum T { + | ---^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates +note: the lint level is defined here + --> $DIR/issue-103317.rs:4:8 + | +LL | #[warn(unreachable_pub)] + | ^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/issue-103435-extra-parentheses.fixed b/tests/ui/lint/issue-103435-extra-parentheses.fixed new file mode 100644 index 000000000..2b01b414b --- /dev/null +++ b/tests/ui/lint/issue-103435-extra-parentheses.fixed @@ -0,0 +1,18 @@ +// run-rustfix +#![deny(unused_parens)] + +fn main() { + if let Some(_) = Some(1) {} + //~^ ERROR unnecessary parentheses around pattern + + for _x in 1..10 {} + //~^ ERROR unnecessary parentheses around pattern + + if 2 == 1 {} + //~^ ERROR unnecessary parentheses around `if` condition + + // reported by parser + for _x in 1..10 {} + //~^ ERROR expected one of + //~| ERROR unexpected parentheses surrounding +} diff --git a/tests/ui/lint/issue-103435-extra-parentheses.rs b/tests/ui/lint/issue-103435-extra-parentheses.rs new file mode 100644 index 000000000..8261610cf --- /dev/null +++ b/tests/ui/lint/issue-103435-extra-parentheses.rs @@ -0,0 +1,18 @@ +// run-rustfix +#![deny(unused_parens)] + +fn main() { + if let(Some(_))= Some(1) {} + //~^ ERROR unnecessary parentheses around pattern + + for(_x)in 1..10 {} + //~^ ERROR unnecessary parentheses around pattern + + if(2 == 1){} + //~^ ERROR unnecessary parentheses around `if` condition + + // reported by parser + for(_x in 1..10){} + //~^ ERROR expected one of + //~| ERROR unexpected parentheses surrounding +} diff --git a/tests/ui/lint/issue-103435-extra-parentheses.stderr b/tests/ui/lint/issue-103435-extra-parentheses.stderr new file mode 100644 index 000000000..29c41c910 --- /dev/null +++ b/tests/ui/lint/issue-103435-extra-parentheses.stderr @@ -0,0 +1,61 @@ +error: expected one of `)`, `,`, `@`, or `|`, found keyword `in` + --> $DIR/issue-103435-extra-parentheses.rs:15:12 + | +LL | for(_x in 1..10){} + | ^^ expected one of `)`, `,`, `@`, or `|` + +error: unexpected parentheses surrounding `for` loop head + --> $DIR/issue-103435-extra-parentheses.rs:15:8 + | +LL | for(_x in 1..10){} + | ^ ^ + | +help: remove parentheses in `for` loop + | +LL - for(_x in 1..10){} +LL + for _x in 1..10 {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-103435-extra-parentheses.rs:5:11 + | +LL | if let(Some(_))= Some(1) {} + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-103435-extra-parentheses.rs:2:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - if let(Some(_))= Some(1) {} +LL + if let Some(_) = Some(1) {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-103435-extra-parentheses.rs:8:8 + | +LL | for(_x)in 1..10 {} + | ^ ^ + | +help: remove these parentheses + | +LL - for(_x)in 1..10 {} +LL + for _x in 1..10 {} + | + +error: unnecessary parentheses around `if` condition + --> $DIR/issue-103435-extra-parentheses.rs:11:7 + | +LL | if(2 == 1){} + | ^ ^ + | +help: remove these parentheses + | +LL - if(2 == 1){} +LL + if 2 == 1 {} + | + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/issue-104392.rs b/tests/ui/lint/issue-104392.rs new file mode 100644 index 000000000..d5608edb4 --- /dev/null +++ b/tests/ui/lint/issue-104392.rs @@ -0,0 +1,11 @@ +fn main() { + { unsafe 92 } //~ ERROR expected `{`, found `92` +} + +fn foo() { + { mod 92 } //~ ERROR expected identifier, found `92` +} + +fn bar() { + { trait 92 } //~ ERROR expected identifier, found `92` +} diff --git a/tests/ui/lint/issue-104392.stderr b/tests/ui/lint/issue-104392.stderr new file mode 100644 index 000000000..8e466439a --- /dev/null +++ b/tests/ui/lint/issue-104392.stderr @@ -0,0 +1,27 @@ +error: expected `{`, found `92` + --> $DIR/issue-104392.rs:2:14 + | +LL | { unsafe 92 } + | ------ ^^ expected `{` + | | + | while parsing this `unsafe` expression + | +help: try placing this code inside a block + | +LL | { unsafe { 92 } } + | + + + +error: expected identifier, found `92` + --> $DIR/issue-104392.rs:6:11 + | +LL | { mod 92 } + | ^^ expected identifier + +error: expected identifier, found `92` + --> $DIR/issue-104392.rs:10:13 + | +LL | { trait 92 } + | ^^ expected identifier + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/issue-104897.rs b/tests/ui/lint/issue-104897.rs new file mode 100644 index 000000000..5fbc658f1 --- /dev/null +++ b/tests/ui/lint/issue-104897.rs @@ -0,0 +1,6 @@ +// error-pattern: this file contains an unclosed delimiter +// error-pattern: this file contains an unclosed delimiter +// error-pattern: this file contains an unclosed delimiter +// error-pattern: format argument must be a string literal + +fn f(){(print!(á diff --git a/tests/ui/lint/issue-104897.stderr b/tests/ui/lint/issue-104897.stderr new file mode 100644 index 000000000..817a93c2f --- /dev/null +++ b/tests/ui/lint/issue-104897.stderr @@ -0,0 +1,43 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-104897.rs:6:18 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-104897.rs:6:18 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-104897.rs:6:18 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: format argument must be a string literal + --> $DIR/issue-104897.rs:6:16 + | +LL | fn f(){(print!(á + | ^ + | +help: you might be missing a string literal to format with + | +LL | fn f(){(print!("{}", á + | +++++ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/issue-108155.rs b/tests/ui/lint/issue-108155.rs new file mode 100644 index 000000000..4ae0cbd92 --- /dev/null +++ b/tests/ui/lint/issue-108155.rs @@ -0,0 +1,15 @@ +// check-pass +// check that `deref_into_dyn_supertrait` doesn't cause ICE by eagerly converting +// a cancelled lint + +#![allow(deref_into_dyn_supertrait)] + +trait Trait {} +impl std::ops::Deref for dyn Trait + Send + Sync { + type Target = dyn Trait; + fn deref(&self) -> &Self::Target { + self + } +} + +fn main() {} diff --git a/tests/ui/lint/issue-14309.rs b/tests/ui/lint/issue-14309.rs new file mode 100644 index 000000000..328a4c982 --- /dev/null +++ b/tests/ui/lint/issue-14309.rs @@ -0,0 +1,39 @@ +#![deny(improper_ctypes)] +#![allow(dead_code)] + +struct A { + x: i32 +} + +#[repr(C, packed)] +struct B { + x: i32, + y: A +} + +#[repr(C)] +struct C { + x: i32 +} + +type A2 = A; +type B2 = B; +type C2 = C; + +#[repr(C)] +struct D { + x: C, + y: A +} + +extern "C" { + fn foo(x: A); //~ ERROR type `A`, which is not FFI-safe + fn bar(x: B); //~ ERROR type `A` + fn baz(x: C); + fn qux(x: A2); //~ ERROR type `A` + fn quux(x: B2); //~ ERROR type `A` + fn corge(x: C2); + fn fred(x: D); //~ ERROR type `A` +} + +fn main() { } diff --git a/tests/ui/lint/issue-14309.stderr b/tests/ui/lint/issue-14309.stderr new file mode 100644 index 000000000..9ce62a6b8 --- /dev/null +++ b/tests/ui/lint/issue-14309.stderr @@ -0,0 +1,77 @@ +error: `extern` block uses type `A`, which is not FFI-safe + --> $DIR/issue-14309.rs:30:15 + | +LL | fn foo(x: A); + | ^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/issue-14309.rs:4:1 + | +LL | struct A { + | ^^^^^^^^ +note: the lint level is defined here + --> $DIR/issue-14309.rs:1:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: `extern` block uses type `A`, which is not FFI-safe + --> $DIR/issue-14309.rs:31:15 + | +LL | fn bar(x: B); + | ^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/issue-14309.rs:4:1 + | +LL | struct A { + | ^^^^^^^^ + +error: `extern` block uses type `A`, which is not FFI-safe + --> $DIR/issue-14309.rs:33:15 + | +LL | fn qux(x: A2); + | ^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/issue-14309.rs:4:1 + | +LL | struct A { + | ^^^^^^^^ + +error: `extern` block uses type `A`, which is not FFI-safe + --> $DIR/issue-14309.rs:34:16 + | +LL | fn quux(x: B2); + | ^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/issue-14309.rs:4:1 + | +LL | struct A { + | ^^^^^^^^ + +error: `extern` block uses type `A`, which is not FFI-safe + --> $DIR/issue-14309.rs:36:16 + | +LL | fn fred(x: D); + | ^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/issue-14309.rs:4:1 + | +LL | struct A { + | ^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/issue-14837.rs b/tests/ui/lint/issue-14837.rs new file mode 100644 index 000000000..a83bc4150 --- /dev/null +++ b/tests/ui/lint/issue-14837.rs @@ -0,0 +1,11 @@ +// check-pass +// pretty-expanded FIXME #23616 + +#[deny(dead_code)] +pub enum Foo { + Bar { + baz: isize + } +} + +fn main() { } diff --git a/tests/ui/lint/issue-17718-const-naming.rs b/tests/ui/lint/issue-17718-const-naming.rs new file mode 100644 index 000000000..d7f0e7276 --- /dev/null +++ b/tests/ui/lint/issue-17718-const-naming.rs @@ -0,0 +1,8 @@ +#![warn(unused)] +#![deny(warnings)] + +const foo: isize = 3; +//~^ ERROR: should have an upper case name +//~^^ ERROR: constant `foo` is never used + +fn main() {} diff --git a/tests/ui/lint/issue-17718-const-naming.stderr b/tests/ui/lint/issue-17718-const-naming.stderr new file mode 100644 index 000000000..7d2aadd5f --- /dev/null +++ b/tests/ui/lint/issue-17718-const-naming.stderr @@ -0,0 +1,23 @@ +error: constant `foo` is never used + --> $DIR/issue-17718-const-naming.rs:4:7 + | +LL | const foo: isize = 3; + | ^^^ + | +note: the lint level is defined here + --> $DIR/issue-17718-const-naming.rs:2:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]` + +error: constant `foo` should have an upper case name + --> $DIR/issue-17718-const-naming.rs:4:7 + | +LL | const foo: isize = 3; + | ^^^ help: convert the identifier to upper case (notice the capitalization): `FOO` + | + = note: `#[deny(non_upper_case_globals)]` implied by `#[deny(warnings)]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/issue-1866.rs b/tests/ui/lint/issue-1866.rs new file mode 100644 index 000000000..caac0c504 --- /dev/null +++ b/tests/ui/lint/issue-1866.rs @@ -0,0 +1,29 @@ +// build-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] +#![warn(clashing_extern_declarations)] + +// pretty-expanded FIXME #23616 + +mod a { + pub type rust_task = usize; + pub mod rustrt { + use super::rust_task; + extern "C" { + pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool; + } + } +} + +mod b { + pub type rust_task = bool; + pub mod rustrt { + use super::rust_task; + extern "C" { + pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool; + //~^ WARN `rust_task_is_unwinding` redeclared with a different signature + } + } +} + +pub fn main() {} diff --git a/tests/ui/lint/issue-1866.stderr b/tests/ui/lint/issue-1866.stderr new file mode 100644 index 000000000..d19a13496 --- /dev/null +++ b/tests/ui/lint/issue-1866.stderr @@ -0,0 +1,19 @@ +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 +... +LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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` +note: the lint level is defined here + --> $DIR/issue-1866.rs:4:9 + | +LL | #![warn(clashing_extern_declarations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/issue-20343.rs b/tests/ui/lint/issue-20343.rs new file mode 100644 index 000000000..000b63984 --- /dev/null +++ b/tests/ui/lint/issue-20343.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(unused_variables)] +// Regression test for Issue #20343. + +// pretty-expanded FIXME #23616 + +#![deny(dead_code)] + +struct B { b: u32 } +struct C; +struct D; + +trait T<A> { fn dummy(&self, a: A) { } } +impl<A> T<A> for () {} + +impl B { + // test for unused code in arguments + fn foo(B { b }: B) -> u32 { b } + + // test for unused code in return type + fn bar() -> C { unsafe { ::std::mem::transmute(()) } } + + // test for unused code in generics + fn baz<A: T<D>>() {} +} + +pub fn main() { + let b = B { b: 3 }; + B::foo(b); + B::bar(); + B::baz::<()>(); +} diff --git a/tests/ui/lint/issue-30302.rs b/tests/ui/lint/issue-30302.rs new file mode 100644 index 000000000..5eccb8cd5 --- /dev/null +++ b/tests/ui/lint/issue-30302.rs @@ -0,0 +1,20 @@ +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(non_snake_case)] +#![deny(unreachable_patterns)] + +enum Stack<T> { + Nil, + Cons(T, Box<Stack<T>>) +} + +fn is_empty<T>(s: Stack<T>) -> bool { + match s { + Nil => true, +//~^ ERROR pattern binding `Nil` is named the same as one of the variants of the type `Stack` + _ => false +//~^ ERROR unreachable pattern + } +} + +fn main() {} diff --git a/tests/ui/lint/issue-30302.stderr b/tests/ui/lint/issue-30302.stderr new file mode 100644 index 000000000..baf6c0d7a --- /dev/null +++ b/tests/ui/lint/issue-30302.stderr @@ -0,0 +1,26 @@ +error[E0170]: pattern binding `Nil` is named the same as one of the variants of the type `Stack` + --> $DIR/issue-30302.rs:13:9 + | +LL | Nil => true, + | ^^^ help: to match on the variant, qualify the path: `Stack::Nil` + | + = note: `#[deny(bindings_with_variant_name)]` on by default + +error: unreachable pattern + --> $DIR/issue-30302.rs:15:9 + | +LL | Nil => true, + | --- matches any value +LL | +LL | _ => false + | ^ unreachable pattern + | +note: the lint level is defined here + --> $DIR/issue-30302.rs:4:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0170`. diff --git a/tests/ui/lint/issue-31924-non-snake-ffi.rs b/tests/ui/lint/issue-31924-non-snake-ffi.rs new file mode 100644 index 000000000..5b9faca49 --- /dev/null +++ b/tests/ui/lint/issue-31924-non-snake-ffi.rs @@ -0,0 +1,15 @@ +// check-pass + +#![deny(non_snake_case)] + +#[no_mangle] +pub extern "C" fn SparklingGenerationForeignFunctionInterface() {} // OK + +pub struct Foo; + +impl Foo { + #[no_mangle] + pub extern "C" fn SparklingGenerationForeignFunctionInterface() {} // OK +} + +fn main() {} diff --git a/tests/ui/lint/issue-34798.rs b/tests/ui/lint/issue-34798.rs new file mode 100644 index 000000000..f0d710123 --- /dev/null +++ b/tests/ui/lint/issue-34798.rs @@ -0,0 +1,25 @@ +// run-pass +#![forbid(improper_ctypes)] +#![allow(dead_code)] + +#[repr(C)] +pub struct Foo { + size: u8, + __value: ::std::marker::PhantomData<i32>, +} + +#[repr(C)] +pub struct ZeroSizeWithPhantomData<T>(::std::marker::PhantomData<T>); + +#[repr(C)] +pub struct Bar { + size: u8, + baz: ZeroSizeWithPhantomData<i32>, +} + +extern "C" { + pub fn bar(_: *mut Foo, _: *mut Bar); +} + +fn main() { +} diff --git a/tests/ui/lint/issue-35075.rs b/tests/ui/lint/issue-35075.rs new file mode 100644 index 000000000..0e54131c2 --- /dev/null +++ b/tests/ui/lint/issue-35075.rs @@ -0,0 +1,9 @@ +struct Bar<T> { + inner: Foo<T> //~ ERROR cannot find type `Foo` in this scope +} + +enum Baz<T> { + Foo(Foo<T>) //~ ERROR cannot find type `Foo` in this scope +} + +fn main() {} diff --git a/tests/ui/lint/issue-35075.stderr b/tests/ui/lint/issue-35075.stderr new file mode 100644 index 000000000..08bdaa728 --- /dev/null +++ b/tests/ui/lint/issue-35075.stderr @@ -0,0 +1,25 @@ +error[E0412]: cannot find type `Foo` in this scope + --> $DIR/issue-35075.rs:2:12 + | +LL | inner: Foo<T> + | ^^^ not found in this scope + | +help: there is an enum variant `Baz::Foo`; try using the variant's enum + | +LL | inner: Baz + | ~~~ + +error[E0412]: cannot find type `Foo` in this scope + --> $DIR/issue-35075.rs:6:9 + | +LL | Foo(Foo<T>) + | ^^^ not found in this scope + | +help: there is an enum variant `Baz::Foo`; try using the variant's enum + | +LL | Foo(Baz) + | ~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs b/tests/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs new file mode 100644 index 000000000..0a951cfa9 --- /dev/null +++ b/tests/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs @@ -0,0 +1,27 @@ +// check-pass + +#![warn(unused_parens)] + +macro_rules! the_worship_the_heart_lifts_above { + ( @as_expr, $e:expr) => { $e }; + ( @generate_fn, $name:tt) => { + #[allow(dead_code)] fn the_moth_for_the_star<'a>() -> Option<&'a str> { + Some(the_worship_the_heart_lifts_above!( @as_expr, $name )) + } + }; + ( $name:ident ) => { the_worship_the_heart_lifts_above!( @generate_fn, (stringify!($name))); } + // ↑ Notably, this does 𝘯𝘰𝘵 warn: we're declining to lint unused parens in + // function/method arguments inside of nested macros because of situations + // like those reported in Issue #47775 +} + +macro_rules! and_the_heavens_reject_not { + () => { + #[allow(dead_code)] fn the_night_for_the_morrow() -> Option<isize> { Some((2)) } + } +} + +the_worship_the_heart_lifts_above!(rah); +and_the_heavens_reject_not!(); + +fn main() {} diff --git a/tests/ui/lint/issue-54099-camel-case-underscore-types.rs b/tests/ui/lint/issue-54099-camel-case-underscore-types.rs new file mode 100644 index 000000000..b2bf87358 --- /dev/null +++ b/tests/ui/lint/issue-54099-camel-case-underscore-types.rs @@ -0,0 +1,14 @@ +// check-pass + +#![forbid(non_camel_case_types)] +#![allow(dead_code)] + +// None of the following types should generate a warning +struct _X {} +struct __X {} +struct __ {} +struct X_ {} +struct X__ {} +struct X___ {} + +fn main() { } diff --git a/tests/ui/lint/issue-57410-1.rs b/tests/ui/lint/issue-57410-1.rs new file mode 100644 index 000000000..d825cb180 --- /dev/null +++ b/tests/ui/lint/issue-57410-1.rs @@ -0,0 +1,18 @@ +// check-pass + +// Originally from #53925. +// Tests that the `unreachable_pub` lint doesn't fire for `pub self::bar::Bar`. + +#![deny(unreachable_pub)] + +mod foo { + mod bar { + pub struct Bar; + } + + pub use self::bar::Bar; +} + +pub use foo::Bar; + +fn main() {} diff --git a/tests/ui/lint/issue-57410.rs b/tests/ui/lint/issue-57410.rs new file mode 100644 index 000000000..0cf4b8068 --- /dev/null +++ b/tests/ui/lint/issue-57410.rs @@ -0,0 +1,17 @@ +// check-pass + +// Tests that the `unreachable_pub` lint doesn't fire for `pub self::imp::f`. + +#![deny(unreachable_pub)] + +mod m { + mod imp { + pub fn f() {} + } + + pub use self::imp::f; +} + +pub use self::m::f; + +fn main() {} diff --git a/tests/ui/lint/issue-63364.rs b/tests/ui/lint/issue-63364.rs new file mode 100644 index 000000000..5223267a6 --- /dev/null +++ b/tests/ui/lint/issue-63364.rs @@ -0,0 +1,10 @@ +fn part(_: u16) -> u32 { + 1 +} + +fn main() { + for n in 100_000.. { + //~^ ERROR: literal out of range for `u16` + let _ = part(n); + } +} diff --git a/tests/ui/lint/issue-63364.stderr b/tests/ui/lint/issue-63364.stderr new file mode 100644 index 000000000..9b5453fa8 --- /dev/null +++ b/tests/ui/lint/issue-63364.stderr @@ -0,0 +1,11 @@ +error: literal out of range for `u16` + --> $DIR/issue-63364.rs:6:14 + | +LL | for n in 100_000.. { + | ^^^^^^^ + | + = note: the literal `100_000` does not fit into the type `u16` whose range is `0..=65535` + = note: `#[deny(overflowing_literals)]` on by default + +error: aborting due to previous error + diff --git a/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs b/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs new file mode 100644 index 000000000..c2b81959f --- /dev/null +++ b/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs @@ -0,0 +1,29 @@ +#![deny(non_snake_case)] +#![allow(unused_variables)] +#![allow(dead_code)] + +enum Foo { + Bad { + lowerCamelCaseName: bool, + //~^ ERROR structure field `lowerCamelCaseName` should have a snake case name + }, + Good { + snake_case_name: bool, + }, +} + +fn main() { + let b = Foo::Bad { lowerCamelCaseName: true }; + + match b { + Foo::Bad { lowerCamelCaseName } => {} + Foo::Good { snake_case_name: lowerCamelCaseBinding } => { } + //~^ ERROR variable `lowerCamelCaseBinding` should have a snake case name + } + + if let Foo::Good { snake_case_name: anotherLowerCamelCaseBinding } = b { } + //~^ ERROR variable `anotherLowerCamelCaseBinding` should have a snake case name + + if let Foo::Bad { lowerCamelCaseName: yetAnotherLowerCamelCaseBinding } = b { } + //~^ ERROR variable `yetAnotherLowerCamelCaseBinding` should have a snake case name +} diff --git a/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr b/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr new file mode 100644 index 000000000..09dc3640f --- /dev/null +++ b/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr @@ -0,0 +1,32 @@ +error: structure field `lowerCamelCaseName` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:7:9 + | +LL | lowerCamelCaseName: bool, + | ^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `lower_camel_case_name` + | +note: the lint level is defined here + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:1:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: variable `lowerCamelCaseBinding` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:20:38 + | +LL | Foo::Good { snake_case_name: lowerCamelCaseBinding } => { } + | ^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `lower_camel_case_binding` + +error: variable `anotherLowerCamelCaseBinding` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:24:41 + | +LL | if let Foo::Good { snake_case_name: anotherLowerCamelCaseBinding } = b { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `another_lower_camel_case_binding` + +error: variable `yetAnotherLowerCamelCaseBinding` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:27:43 + | +LL | if let Foo::Bad { lowerCamelCaseName: yetAnotherLowerCamelCaseBinding } = b { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `yet_another_lower_camel_case_binding` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs new file mode 100644 index 000000000..b4fc33174 --- /dev/null +++ b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs @@ -0,0 +1,50 @@ +// This test is checking that you cannot override a `forbid` by adding in other +// attributes later in the same scope. (We already ensure that you cannot +// override it in nested scopes). + +// If you turn off deduplicate diagnostics (which rustc turns on by default but +// compiletest turns off when it runs ui tests), then the errors are +// (unfortunately) repeated here because the checking is done as we read in the +// errors, and currently that happens two or three different times, depending on +// compiler flags. +// +// I decided avoiding the redundant output was not worth the time in engineering +// effort for bug like this, which 1. end users are unlikely to run into in the +// first place, and 2. they won't see the redundant output anyway. + +// compile-flags: -Z deduplicate-diagnostics=yes + +#![forbid(forbidden_lint_groups)] + +fn forbid_first(num: i32) -> i32 { + #![forbid(unused)] + #![deny(unused)] + //~^ ERROR: deny(unused) incompatible with previous forbid + //~| WARNING being phased out + #![warn(unused)] + #![allow(unused)] + + num * num +} + +fn forbid_last(num: i32) -> i32 { + #![deny(unused)] + #![warn(unused)] + #![allow(unused)] + #![forbid(unused)] + + num * num +} + +fn forbid_multiple(num: i32) -> i32 { + #![forbid(unused)] + #![forbid(unused)] + + num * num +} + +fn main() { + forbid_first(10); + forbid_last(10); + forbid_multiple(10); +} diff --git a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr new file mode 100644 index 000000000..cc44f8aa5 --- /dev/null +++ b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr @@ -0,0 +1,18 @@ +error: deny(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:21:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/issue-79546-fuel-ice.rs b/tests/ui/lint/issue-79546-fuel-ice.rs new file mode 100644 index 000000000..0e9f54088 --- /dev/null +++ b/tests/ui/lint/issue-79546-fuel-ice.rs @@ -0,0 +1,8 @@ +// Regression test for the ICE described in #79546. + +// compile-flags: --cap-lints=allow -Zfuel=issue79546=0 +// check-pass +#![crate_name="issue79546"] + +struct S; +fn main() {} diff --git a/tests/ui/lint/issue-79744.rs b/tests/ui/lint/issue-79744.rs new file mode 100644 index 000000000..e9725a027 --- /dev/null +++ b/tests/ui/lint/issue-79744.rs @@ -0,0 +1,13 @@ +fn main() { + let elem = 6i8; + let e2 = 230; + //~^ ERROR literal out of range for `i8` + //~| HELP consider using the type `u8` instead + + let mut vec = Vec::new(); + + vec.push(e2); + vec.push(elem); + + println!("{:?}", vec); +} diff --git a/tests/ui/lint/issue-79744.stderr b/tests/ui/lint/issue-79744.stderr new file mode 100644 index 000000000..c1b56250d --- /dev/null +++ b/tests/ui/lint/issue-79744.stderr @@ -0,0 +1,12 @@ +error: literal out of range for `i8` + --> $DIR/issue-79744.rs:3:14 + | +LL | let e2 = 230; + | ^^^ + | + = note: the literal `230` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead + = note: `#[deny(overflowing_literals)]` on by default + +error: aborting due to previous error + diff --git a/tests/ui/lint/issue-80988.rs b/tests/ui/lint/issue-80988.rs new file mode 100644 index 000000000..1e116206f --- /dev/null +++ b/tests/ui/lint/issue-80988.rs @@ -0,0 +1,14 @@ +// Regression test for #80988 +// +// check-pass + +#![forbid(warnings)] + +#[deny(warnings)] +//~^ WARNING incompatible with previous forbid +//~| WARNING being phased out +//~| WARNING incompatible with previous forbid +//~| WARNING being phased out +//~| WARNING incompatible with previous forbid +//~| WARNING being phased out +fn main() {} diff --git a/tests/ui/lint/issue-80988.stderr b/tests/ui/lint/issue-80988.stderr new file mode 100644 index 000000000..73e27ffda --- /dev/null +++ b/tests/ui/lint/issue-80988.stderr @@ -0,0 +1,39 @@ +warning: deny(warnings) incompatible with previous forbid + --> $DIR/issue-80988.rs:7:8 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +LL | +LL | #[deny(warnings)] + | ^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + = note: `#[warn(forbidden_lint_groups)]` on by default + +warning: deny(warnings) incompatible with previous forbid + --> $DIR/issue-80988.rs:7:8 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +LL | +LL | #[deny(warnings)] + | ^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +warning: deny(warnings) incompatible with previous forbid + --> $DIR/issue-80988.rs:7:8 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +LL | +LL | #[deny(warnings)] + | ^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/issue-81218.rs b/tests/ui/lint/issue-81218.rs new file mode 100644 index 000000000..f02aa9040 --- /dev/null +++ b/tests/ui/lint/issue-81218.rs @@ -0,0 +1,14 @@ +// Regression test for #81218 +// +// check-pass + +#![forbid(warnings)] + +#[allow(unused_variables)] +fn main() { + // We want to ensure that you don't get an error + // here. The idea is that a derive might generate + // code that would otherwise trigger the "unused variables" + // lint, but it is meant to be suppressed. + let x: (); +} diff --git a/tests/ui/lint/issue-83477.rs b/tests/ui/lint/issue-83477.rs new file mode 100644 index 000000000..4262a2879 --- /dev/null +++ b/tests/ui/lint/issue-83477.rs @@ -0,0 +1,16 @@ +// compile-flags: -Zunstable-options +// check-pass +#![warn(rustc::internal)] + +#[allow(rustc::foo::bar::default_hash_types)] +//~^ WARN unknown lint: `rustc::foo::bar::default_hash_types` +//~| HELP did you mean +//~| SUGGESTION rustc::default_hash_types +#[allow(rustc::foo::default_hash_types)] +//~^ WARN unknown lint: `rustc::foo::default_hash_types` +//~| HELP did you mean +//~| SUGGESTION rustc::default_hash_types +fn main() { + let _ = std::collections::HashMap::<String, String>::new(); + //~^ WARN prefer `FxHashMap` over `HashMap`, it has better performance +} diff --git a/tests/ui/lint/issue-83477.stderr b/tests/ui/lint/issue-83477.stderr new file mode 100644 index 000000000..f824fc09e --- /dev/null +++ b/tests/ui/lint/issue-83477.stderr @@ -0,0 +1,30 @@ +warning: unknown lint: `rustc::foo::bar::default_hash_types` + --> $DIR/issue-83477.rs:5:9 + | +LL | #[allow(rustc::foo::bar::default_hash_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `rustc::default_hash_types` + | + = note: `#[warn(unknown_lints)]` on by default + +warning: unknown lint: `rustc::foo::default_hash_types` + --> $DIR/issue-83477.rs:9:9 + | +LL | #[allow(rustc::foo::default_hash_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `rustc::default_hash_types` + +warning: prefer `FxHashMap` over `HashMap`, it has better performance + --> $DIR/issue-83477.rs:14:13 + | +LL | let _ = std::collections::HashMap::<String, String>::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary +note: the lint level is defined here + --> $DIR/issue-83477.rs:3:9 + | +LL | #![warn(rustc::internal)] + | ^^^^^^^^^^^^^^^ + = note: `#[warn(rustc::default_hash_types)]` implied by `#[warn(rustc::internal)]` + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/issue-86600-lint-twice.rs b/tests/ui/lint/issue-86600-lint-twice.rs new file mode 100644 index 000000000..0e8a837d9 --- /dev/null +++ b/tests/ui/lint/issue-86600-lint-twice.rs @@ -0,0 +1,15 @@ +// Regression test for #86600, where an instance of the +// `illegal_floating_point_literal_pattern` lint was issued twice. + +// check-pass + +fn main() { + let x = 42.0; + + match x { + 5.0 => {} + //~^ WARNING: floating-point types cannot be used in patterns + //~| WARNING: this was previously accepted by the compiler + _ => {} + } +} diff --git a/tests/ui/lint/issue-86600-lint-twice.stderr b/tests/ui/lint/issue-86600-lint-twice.stderr new file mode 100644 index 000000000..5a65c6121 --- /dev/null +++ b/tests/ui/lint/issue-86600-lint-twice.stderr @@ -0,0 +1,12 @@ +warning: floating-point types cannot be used in patterns + --> $DIR/issue-86600-lint-twice.rs:10:9 + | +LL | 5.0 => {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620> + = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/issue-87274-paren-parent.rs b/tests/ui/lint/issue-87274-paren-parent.rs new file mode 100644 index 000000000..0141c5a25 --- /dev/null +++ b/tests/ui/lint/issue-87274-paren-parent.rs @@ -0,0 +1,9 @@ +// check-pass +// Tests that we properly lint at 'paren' expressions + +fn foo() -> Result<(), String> { + (try!(Ok::<u8, String>(1))); //~ WARN use of deprecated macro `try` + Ok(()) +} + +fn main() {} diff --git a/tests/ui/lint/issue-87274-paren-parent.stderr b/tests/ui/lint/issue-87274-paren-parent.stderr new file mode 100644 index 000000000..f06024298 --- /dev/null +++ b/tests/ui/lint/issue-87274-paren-parent.stderr @@ -0,0 +1,10 @@ +warning: use of deprecated macro `try`: use the `?` operator instead + --> $DIR/issue-87274-paren-parent.rs:5:6 + | +LL | (try!(Ok::<u8, String>(1))); + | ^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/issue-89469.rs b/tests/ui/lint/issue-89469.rs new file mode 100644 index 000000000..3a6ab4528 --- /dev/null +++ b/tests/ui/lint/issue-89469.rs @@ -0,0 +1,20 @@ +// Regression test for #89469, where an extra non_snake_case warning was +// reported for a shorthand field binding. + +// check-pass +#![deny(non_snake_case)] + +#[allow(non_snake_case)] +struct Entry { + A: u16, + a: u16 +} + +fn foo() -> Entry {todo!()} + +pub fn f() { + let Entry { A, a } = foo(); + let _ = (A, a); +} + +fn main() {} diff --git a/tests/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs b/tests/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs new file mode 100644 index 000000000..425e2703c --- /dev/null +++ b/tests/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs @@ -0,0 +1,9 @@ +// check-pass +// Allowing the code lint should work without warning and +// the text flow char in the comment should be ignored. + +#![allow(text_direction_codepoint_in_comment)] + +fn main() { + // U+2066 LEFT-TO-RIGHT ISOLATE follows: +} diff --git a/tests/ui/lint/issue-97094.rs b/tests/ui/lint/issue-97094.rs new file mode 100644 index 000000000..22525ca11 --- /dev/null +++ b/tests/ui/lint/issue-97094.rs @@ -0,0 +1,50 @@ +#![deny(warnings)] + +// Ensure that unknown lints inside cfg-attr's are linted for + +#![cfg_attr(all(), allow(nonex_lint_top_level))] +//~^ ERROR unknown lint +#![cfg_attr(all(), allow(bare_trait_object))] +//~^ ERROR has been renamed + +#[cfg_attr(all(), allow(nonex_lint_mod))] +//~^ ERROR unknown lint +mod baz { + #![cfg_attr(all(), allow(nonex_lint_mod_inner))] + //~^ ERROR unknown lint +} + +#[cfg_attr(all(), allow(nonex_lint_fn))] +//~^ ERROR unknown lint +pub fn main() {} + +macro_rules! bar { + ($($t:tt)*) => { + $($t)* + }; +} + +bar!( + #[cfg_attr(all(), allow(nonex_lint_in_macro))] + //~^ ERROR unknown lint + pub fn _bar() {} +); + +// No warning for non-applying cfg +#[cfg_attr(any(), allow(nonex_lint_fn))] +pub fn _foo() {} + +// Allowing unknown lints works if inside cfg_attr +#[cfg_attr(all(), allow(unknown_lints))] +mod bar_allowed { + #[allow(nonex_lint_fn)] + fn _foo() {} +} + +// ... but not if the cfg_attr doesn't evaluate +#[cfg_attr(any(), allow(unknown_lints))] +mod bar_not_allowed { + #[allow(nonex_lint_fn)] + //~^ ERROR unknown lint + fn _foo() {} +} diff --git a/tests/ui/lint/issue-97094.stderr b/tests/ui/lint/issue-97094.stderr new file mode 100644 index 000000000..1a0a3eaf2 --- /dev/null +++ b/tests/ui/lint/issue-97094.stderr @@ -0,0 +1,53 @@ +error: unknown lint: `nonex_lint_top_level` + --> $DIR/issue-97094.rs:5:26 + | +LL | #![cfg_attr(all(), allow(nonex_lint_top_level))] + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-97094.rs:1:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unknown_lints)]` implied by `#[deny(warnings)]` + +error: lint `bare_trait_object` has been renamed to `bare_trait_objects` + --> $DIR/issue-97094.rs:7:26 + | +LL | #![cfg_attr(all(), allow(bare_trait_object))] + | ^^^^^^^^^^^^^^^^^ help: use the new name: `bare_trait_objects` + | + = note: `#[deny(renamed_and_removed_lints)]` implied by `#[deny(warnings)]` + +error: unknown lint: `nonex_lint_mod` + --> $DIR/issue-97094.rs:10:25 + | +LL | #[cfg_attr(all(), allow(nonex_lint_mod))] + | ^^^^^^^^^^^^^^ + +error: unknown lint: `nonex_lint_mod_inner` + --> $DIR/issue-97094.rs:13:30 + | +LL | #![cfg_attr(all(), allow(nonex_lint_mod_inner))] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unknown lint: `nonex_lint_fn` + --> $DIR/issue-97094.rs:17:25 + | +LL | #[cfg_attr(all(), allow(nonex_lint_fn))] + | ^^^^^^^^^^^^^ + +error: unknown lint: `nonex_lint_in_macro` + --> $DIR/issue-97094.rs:28:29 + | +LL | #[cfg_attr(all(), allow(nonex_lint_in_macro))] + | ^^^^^^^^^^^^^^^^^^^ + +error: unknown lint: `nonex_lint_fn` + --> $DIR/issue-97094.rs:47:13 + | +LL | #[allow(nonex_lint_fn)] + | ^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/lint/issue-99387.rs b/tests/ui/lint/issue-99387.rs new file mode 100644 index 000000000..616eb935e --- /dev/null +++ b/tests/ui/lint/issue-99387.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(private_in_public)] + +pub type Successors<'a> = impl Iterator<Item = &'a ()>; + +pub fn f<'a>() -> Successors<'a> { + None.into_iter() +} + +trait Tr { + type Item; +} + +impl<'a> Tr for &'a () { + type Item = Successors<'a>; +} + +pub fn ohno<'a>() -> <&'a () as Tr>::Item { + None.into_iter() +} + +fn main() {} diff --git a/tests/ui/lint/known-tool-in-submodule/root.rs b/tests/ui/lint/known-tool-in-submodule/root.rs new file mode 100644 index 000000000..80806dcbd --- /dev/null +++ b/tests/ui/lint/known-tool-in-submodule/root.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(register_tool)] +#![register_tool(tool)] + +mod submodule; + +fn main() { + submodule::foo(); +} diff --git a/tests/ui/lint/known-tool-in-submodule/submodule.rs b/tests/ui/lint/known-tool-in-submodule/submodule.rs new file mode 100644 index 000000000..bb25e1005 --- /dev/null +++ b/tests/ui/lint/known-tool-in-submodule/submodule.rs @@ -0,0 +1,4 @@ +// ignore-test: not a test + +#[allow(tool::lint)] +pub fn foo() {} diff --git a/tests/ui/lint/let_underscore/let_underscore_drop.rs b/tests/ui/lint/let_underscore/let_underscore_drop.rs new file mode 100644 index 000000000..f298871f1 --- /dev/null +++ b/tests/ui/lint/let_underscore/let_underscore_drop.rs @@ -0,0 +1,14 @@ +// check-pass +#![warn(let_underscore_drop)] + +struct NontrivialDrop; + +impl Drop for NontrivialDrop { + fn drop(&mut self) { + println!("Dropping!"); + } +} + +fn main() { + let _ = NontrivialDrop; //~WARNING non-binding let on a type that implements `Drop` +} diff --git a/tests/ui/lint/let_underscore/let_underscore_drop.stderr b/tests/ui/lint/let_underscore/let_underscore_drop.stderr new file mode 100644 index 000000000..7b7de202e --- /dev/null +++ b/tests/ui/lint/let_underscore/let_underscore_drop.stderr @@ -0,0 +1,22 @@ +warning: non-binding let on a type that implements `Drop` + --> $DIR/let_underscore_drop.rs:13:5 + | +LL | let _ = NontrivialDrop; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/let_underscore_drop.rs:2:9 + | +LL | #![warn(let_underscore_drop)] + | ^^^^^^^^^^^^^^^^^^^ +help: consider binding to an unused variable to avoid immediately dropping the value + | +LL | let _unused = NontrivialDrop; + | ~~~~~~~ +help: consider immediately dropping the value + | +LL | drop(NontrivialDrop); + | ~~~~~ + + +warning: 1 warning emitted + diff --git a/tests/ui/lint/let_underscore/let_underscore_lock.rs b/tests/ui/lint/let_underscore/let_underscore_lock.rs new file mode 100644 index 000000000..7423862cd --- /dev/null +++ b/tests/ui/lint/let_underscore/let_underscore_lock.rs @@ -0,0 +1,7 @@ +// check-fail +use std::sync::{Arc, Mutex}; + +fn main() { + let data = Arc::new(Mutex::new(0)); + let _ = data.lock().unwrap(); //~ERROR non-binding let on a synchronization lock +} diff --git a/tests/ui/lint/let_underscore/let_underscore_lock.stderr b/tests/ui/lint/let_underscore/let_underscore_lock.stderr new file mode 100644 index 000000000..fb58af0a4 --- /dev/null +++ b/tests/ui/lint/let_underscore/let_underscore_lock.stderr @@ -0,0 +1,20 @@ +error: non-binding let on a synchronization lock + --> $DIR/let_underscore_lock.rs:6:9 + | +LL | let _ = data.lock().unwrap(); + | ^ ^^^^^^^^^^^^^^^^^^^^ this binding will immediately drop the value assigned to it + | | + | this lock is not assigned to a binding and is immediately dropped + | + = note: `#[deny(let_underscore_lock)]` on by default +help: consider binding to an unused variable to avoid immediately dropping the value + | +LL | let _unused = data.lock().unwrap(); + | ~~~~~~~ +help: consider immediately dropping the value + | +LL | drop(data.lock().unwrap()); + | ~~~~~ + + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-attr-everywhere-early.rs b/tests/ui/lint/lint-attr-everywhere-early.rs new file mode 100644 index 000000000..fd0c4b43e --- /dev/null +++ b/tests/ui/lint/lint-attr-everywhere-early.rs @@ -0,0 +1,176 @@ +// Tests that lint levels can be set for early lints. +#![allow(non_camel_case_types, unsafe_code, while_true, unused_parens)] + +// The following is a check of the lints used here to verify they do not warn +// when allowed. +fn verify_no_warnings() { + type non_camel_type = i32; // non_camel_case_types + struct NON_CAMEL_IS_ALLOWED; // non_camel_case_types + unsafe {} // unsafe_code + enum Enum { + VARIANT_CAMEL // non_camel_case_types + } + fn generics<foo>() {} // non_camel_case_types + while true {} // while_true + type T = (i32); // unused_parens +} + + +// ################## Types + +#[deny(non_camel_case_types)] +type type_outer = i32; //~ ERROR type `type_outer` should have an upper camel case name + +type BareFnPtr = fn(#[deny(unused_parens)](i32)); //~ ERROR unnecessary parentheses around type +// There aren't any early lints that currently apply to the variadic spot. +// type BareFnPtrVariadic = extern "C" fn(i32, #[deny()]...); + +// ################## Items +#[deny(non_camel_case_types)] +struct ITEM_OUTER; //~ ERROR type `ITEM_OUTER` should have an upper camel case name + +mod module_inner { + #![deny(unsafe_code)] + fn f() { + unsafe {} //~ ERROR usage of an `unsafe` block + } +} + +struct Associated; +impl Associated { + #![deny(unsafe_code)] + + fn inherent_denied_from_inner() { unsafe {} } //~ usage of an `unsafe` block + + #[deny(while_true)] + fn inherent_fn() { while true {} } //~ ERROR denote infinite loops with + + #[deny(while_true)] + const INHERENT_CONST: i32 = {while true {} 1}; //~ ERROR denote infinite loops with +} + +trait trait_inner { //~ ERROR trait `trait_inner` should have an upper camel case name + #![deny(non_camel_case_types)] +} + +trait AssociatedTrait { + #![deny(unsafe_code)] + + fn denied_from_inner() { unsafe {} } //~ ERROR usage of an `unsafe` block + + #[deny(while_true)] + fn assoc_fn() { while true {} } //~ ERROR denote infinite loops with + + #[deny(while_true)] + const ASSOC_CONST: i32 = {while true {} 1}; //~ ERROR denote infinite loops with + + #[deny(non_camel_case_types)] + type assoc_type; //~ ERROR associated type `assoc_type` should have an upper camel case name +} + +impl AssociatedTrait for Associated { + #![deny(unsafe_code)] + + fn denied_from_inner() { unsafe {} } //~ ERROR usage of an `unsafe` block + + #[deny(while_true)] + fn assoc_fn() { while true {} } //~ ERROR denote infinite loops with + + #[deny(while_true)] + const ASSOC_CONST: i32 = {while true {} 1}; //~ ERROR denote infinite loops with + + #[deny(unused_parens)] + type assoc_type = (i32); //~ ERROR unnecessary parentheses around type +} + +struct StructFields { + #[deny(unused_parens)]f1: (i32), //~ ERROR unnecessary parentheses around type +} +struct StructTuple(#[deny(unused_parens)](i32)); //~ ERROR unnecessary parentheses around type + +enum Enum { + #[deny(non_camel_case_types)] + VARIANT_CAMEL, //~ ERROR variant `VARIANT_CAMEL` should have an upper camel case name +} + +extern "C" { + #![deny(unused_parens)] + + fn foreign_denied_from_inner(x: (i32)); //~ ERROR unnecessary parentheses around type +} + +extern "C" { + #[deny(unused_parens)] + fn foreign_denied_from_outer(x: (i32)); //~ ERROR unnecessary parentheses around type +} + +fn function(#[deny(unused_parens)] param: (i32)) {} //~ ERROR unnecessary parentheses around type + +fn generics<#[deny(non_camel_case_types)]foo>() {} //~ ERROR type parameter `foo` should have an upper camel case name + + +// ################## Statements +fn statements() { + #[deny(unused_parens)] + let x = (1); //~ ERROR unnecessary parentheses around assigned value +} + + +// ################## Expressions +fn expressions() { + let closure = |#[deny(unused_parens)] param: (i32)| {}; //~ ERROR unnecessary parentheses around type + + struct Match{f1: i32} + // Strangely unused_parens doesn't fire with {f1: (123)} + let f = Match{#[deny(unused_parens)]f1: {(123)}}; //~ ERROR unnecessary parentheses around block return value + + match f { + #![deny(unsafe_code)] + + #[deny(while_true)] + Match{f1} => { + unsafe {} //~ ERROR usage of an `unsafe` block + while true {} //~ ERROR denote infinite loops with + } + } + + // Statement Block + { + #![deny(unsafe_code)] + unsafe {} //~ ERROR usage of an `unsafe` block + } + let block_tail = { + #[deny(unsafe_code)] + unsafe {} //~ ERROR usage of an `unsafe` block + }; + + // Before expression as a statement. + #[deny(unsafe_code)] + unsafe {}; //~ ERROR usage of an `unsafe` block + + [#[deny(unsafe_code)] unsafe {123}]; //~ ERROR usage of an `unsafe` block + (#[deny(unsafe_code)] unsafe {123},); //~ ERROR usage of an `unsafe` block + fn call(p: i32) {} + call(#[deny(unsafe_code)] unsafe {123}); //~ ERROR usage of an `unsafe` block + struct TupleStruct(i32); + TupleStruct(#[deny(unsafe_code)] unsafe {123}); //~ ERROR usage of an `unsafe` block +} + + +// ################## Patterns +fn patterns() { + struct PatField{f1: i32, f2: i32}; + let f = PatField{f1: 1, f2: 2}; + match f { + PatField { + #[deny(ellipsis_inclusive_range_patterns)] + f1: 0...100, + //~^ ERROR range patterns are deprecated + //~| WARNING this is accepted in the current edition + .. + } => {} + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-attr-everywhere-early.stderr b/tests/ui/lint/lint-attr-everywhere-early.stderr new file mode 100644 index 000000000..d6c6d5fae --- /dev/null +++ b/tests/ui/lint/lint-attr-everywhere-early.stderr @@ -0,0 +1,486 @@ +error: type `type_outer` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:22:6 + | +LL | type type_outer = i32; + | ^^^^^^^^^^ help: convert the identifier to upper camel case: `TypeOuter` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:21:8 + | +LL | #[deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:24:43 + | +LL | type BareFnPtr = fn(#[deny(unused_parens)](i32)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:24:28 + | +LL | type BareFnPtr = fn(#[deny(unused_parens)](i32)); + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - type BareFnPtr = fn(#[deny(unused_parens)](i32)); +LL + type BareFnPtr = fn(#[deny(unused_parens)]i32); + | + +error: type `ITEM_OUTER` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:30:8 + | +LL | struct ITEM_OUTER; + | ^^^^^^^^^^ help: convert the identifier to upper camel case: `ItemOuter` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:29:8 + | +LL | #[deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:35:9 + | +LL | unsafe {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:33:13 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:43:39 + | +LL | fn inherent_denied_from_inner() { unsafe {} } + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:41:13 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:46:24 + | +LL | fn inherent_fn() { while true {} } + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:45:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:49:34 + | +LL | const INHERENT_CONST: i32 = {while true {} 1}; + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:48:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: trait `trait_inner` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:52:7 + | +LL | trait trait_inner { + | ^^^^^^^^^^^ help: convert the identifier to upper camel case: `TraitInner` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:53:13 + | +LL | #![deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:59:30 + | +LL | fn denied_from_inner() { unsafe {} } + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:57:13 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:62:21 + | +LL | fn assoc_fn() { while true {} } + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:61:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:65:31 + | +LL | const ASSOC_CONST: i32 = {while true {} 1}; + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:64:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: associated type `assoc_type` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:68:10 + | +LL | type assoc_type; + | ^^^^^^^^^^ help: convert the identifier to upper camel case: `AssocType` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:67:12 + | +LL | #[deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:74:30 + | +LL | fn denied_from_inner() { unsafe {} } + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:72:13 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:77:21 + | +LL | fn assoc_fn() { while true {} } + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:76:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:80:31 + | +LL | const ASSOC_CONST: i32 = {while true {} 1}; + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:79:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:83:23 + | +LL | type assoc_type = (i32); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:82:12 + | +LL | #[deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - type assoc_type = (i32); +LL + type assoc_type = i32; + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:87:31 + | +LL | #[deny(unused_parens)]f1: (i32), + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:87:12 + | +LL | #[deny(unused_parens)]f1: (i32), + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - #[deny(unused_parens)]f1: (i32), +LL + #[deny(unused_parens)]f1: i32, + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:89:42 + | +LL | struct StructTuple(#[deny(unused_parens)](i32)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:89:27 + | +LL | struct StructTuple(#[deny(unused_parens)](i32)); + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - struct StructTuple(#[deny(unused_parens)](i32)); +LL + struct StructTuple(#[deny(unused_parens)]i32); + | + +error: variant `VARIANT_CAMEL` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:93:5 + | +LL | VARIANT_CAMEL, + | ^^^^^^^^^^^^^ help: convert the identifier to upper camel case: `VariantCamel` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:92:12 + | +LL | #[deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:99:37 + | +LL | fn foreign_denied_from_inner(x: (i32)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:97:13 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - fn foreign_denied_from_inner(x: (i32)); +LL + fn foreign_denied_from_inner(x: i32); + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:104:37 + | +LL | fn foreign_denied_from_outer(x: (i32)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:103:12 + | +LL | #[deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - fn foreign_denied_from_outer(x: (i32)); +LL + fn foreign_denied_from_outer(x: i32); + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:107:43 + | +LL | fn function(#[deny(unused_parens)] param: (i32)) {} + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:107:20 + | +LL | fn function(#[deny(unused_parens)] param: (i32)) {} + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - fn function(#[deny(unused_parens)] param: (i32)) {} +LL + fn function(#[deny(unused_parens)] param: i32) {} + | + +error: type parameter `foo` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:109:42 + | +LL | fn generics<#[deny(non_camel_case_types)]foo>() {} + | ^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:109:20 + | +LL | fn generics<#[deny(non_camel_case_types)]foo>() {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary parentheses around assigned value + --> $DIR/lint-attr-everywhere-early.rs:115:13 + | +LL | let x = (1); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:114:12 + | +LL | #[deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let x = (1); +LL + let x = 1; + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:121:50 + | +LL | let closure = |#[deny(unused_parens)] param: (i32)| {}; + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:121:27 + | +LL | let closure = |#[deny(unused_parens)] param: (i32)| {}; + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let closure = |#[deny(unused_parens)] param: (i32)| {}; +LL + let closure = |#[deny(unused_parens)] param: i32| {}; + | + +error: unnecessary parentheses around block return value + --> $DIR/lint-attr-everywhere-early.rs:125:46 + | +LL | let f = Match{#[deny(unused_parens)]f1: {(123)}}; + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:125:26 + | +LL | let f = Match{#[deny(unused_parens)]f1: {(123)}}; + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let f = Match{#[deny(unused_parens)]f1: {(123)}}; +LL + let f = Match{#[deny(unused_parens)]f1: {123}}; + | + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:132:13 + | +LL | unsafe {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:128:17 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:133:13 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:130:16 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:140:9 + | +LL | unsafe {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:139:17 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:144:9 + | +LL | unsafe {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:143:16 + | +LL | #[deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:149:5 + | +LL | unsafe {}; + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:148:12 + | +LL | #[deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:151:27 + | +LL | [#[deny(unsafe_code)] unsafe {123}]; + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:151:13 + | +LL | [#[deny(unsafe_code)] unsafe {123}]; + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:152:27 + | +LL | (#[deny(unsafe_code)] unsafe {123},); + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:152:13 + | +LL | (#[deny(unsafe_code)] unsafe {123},); + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:154:31 + | +LL | call(#[deny(unsafe_code)] unsafe {123}); + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:154:17 + | +LL | call(#[deny(unsafe_code)] unsafe {123}); + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:156:38 + | +LL | TupleStruct(#[deny(unsafe_code)] unsafe {123}); + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:156:24 + | +LL | TupleStruct(#[deny(unsafe_code)] unsafe {123}); + | ^^^^^^^^^^^ + +error: `...` range patterns are deprecated + --> $DIR/lint-attr-everywhere-early.rs:167:18 + | +LL | f1: 0...100, + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:166:20 + | +LL | #[deny(ellipsis_inclusive_range_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 36 previous errors + diff --git a/tests/ui/lint/lint-attr-everywhere-late.rs b/tests/ui/lint/lint-attr-everywhere-late.rs new file mode 100644 index 000000000..1055157d6 --- /dev/null +++ b/tests/ui/lint/lint-attr-everywhere-late.rs @@ -0,0 +1,197 @@ +// Tests that lint levels can be set for late lints. +#![allow( + non_snake_case, + overflowing_literals, + missing_docs, + dyn_drop, + enum_intrinsics_non_enums, + clashing_extern_declarations +)] + +extern crate core; +use core::mem::{Discriminant, discriminant}; + +// The following is a check of the lints used here to verify they do not warn +// when allowed. +pub fn missing_docs_allowed() {} // missing_docs +fn dyn_drop_allowed(_x: Box<dyn Drop>) {} // dyn_drop +fn verify_no_warnings() { + discriminant::<i32>(&123); // enum_intrinsics_non_enums + let x: u8 = 1000; // overflowing_literals + let NON_SNAKE_CASE = 1; // non_snake_case +} +mod clashing_extern_allowed { + extern "C" { + fn extern_allowed(); + } +} +extern "C" { + fn extern_allowed(_: i32); // clashing_extern_declarations +} + +// ################## Types + +#[deny(missing_docs)] +pub type MissingDocType = i32; //~ ERROR missing documentation for a type alias + +// There aren't any late lints that I can find that can be easily used with types. +// type BareFnPtr = fn(#[deny()]i32); +// type BareFnPtrVariadic = extern "C" fn(i32, #[deny()]...); + +// ################## Items +#[deny(missing_docs)] +pub struct ItemOuter; //~ ERROR missing documentation for a struct + +pub mod module_inner { //~ ERROR missing documentation for a module + #![deny(missing_docs)] + pub fn missing_inner() {} //~ ERROR missing documentation for a function +} + +pub struct Associated; +impl Associated { + #![deny(missing_docs)] + + pub fn inherent_denied_from_inner() {} //~ ERROR missing documentation for an associated function +} + +impl Associated { + #[deny(missing_docs)] + pub fn inherent_fn() {} //~ ERROR missing documentation for an associated function + + #[deny(missing_docs)] + pub const INHERENT_CONST: i32 = 1; //~ ERROR missing documentation for an associated constant +} + +pub trait TraitInner { //~ ERROR missing documentation for a trait + #![deny(missing_docs)] +} + +pub trait AssociatedTraitInner { //~ ERROR missing documentation for a trait + #![deny(missing_docs)] + + fn denied_from_inner() {} //~ ERROR missing documentation for an associated function +} + +pub trait AssociatedTrait { + fn denied_from_inner(_x: Box<dyn Drop>) {} // Used below + + #[deny(missing_docs)] + fn assoc_fn() {} //~ ERROR missing documentation for an associated function + + #[deny(missing_docs)] + const ASSOC_CONST: u8 = 1; //~ ERROR missing documentation for an associated constant + + #[deny(missing_docs)] + type AssocType; //~ ERROR missing documentation for an associated type +} + +struct Foo; + +impl AssociatedTrait for Associated { + #![deny(dyn_drop)] + + fn denied_from_inner(_x: Box<dyn Drop>) {} //~ ERROR types that do not implement `Drop` + + #[deny(enum_intrinsics_non_enums)] + fn assoc_fn() { discriminant::<i32>(&123); } //~ ERROR the return value of + + #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000; //~ ERROR literal out of range + type AssocType = i32; +} + + +// There aren't any late lints that can apply to a field that I can find. +// non_snake_case doesn't work on fields +// struct StructFields { +// #[deny()]f1: i32, +// } +// struct StructTuple(#[deny()]i32); + +pub enum Enum { + #[deny(missing_docs)] + Variant1, //~ ERROR missing documentation for a variant +} + +mod clashing_extern { + extern "C" { + fn clashing1(); + fn clashing2(); + } +} +extern "C" { + #![deny(clashing_extern_declarations)] + fn clashing1(_: i32); //~ ERROR `clashing1` redeclared with a different signature +} + +extern "C" { + #[deny(clashing_extern_declarations)] + fn clashing2(_: i32); //~ ERROR `clashing2` redeclared with a different signature +} + +fn function(#[deny(non_snake_case)] PARAM: i32) {} //~ ERROR variable `PARAM` should have a snake case name +// There aren't any late lints that can apply to generics that I can find. +// fn generics<#[deny()]T>() {} + + +// ################## Statements +fn statements() { + #[deny(enum_intrinsics_non_enums)] + let _ = discriminant::<i32>(&123); //~ ERROR the return value of +} + + +// ################## Expressions +fn expressions() { + let closure = |#[deny(non_snake_case)] PARAM: i32| {}; //~ ERROR variable `PARAM` should have a snake case name + + struct Match{f1: i32} + // I can't find any late lints for patterns. + // let f = Match{#[deny()]f1: 123}; + + let f = Match{f1: 123}; + match f { + #![deny(enum_intrinsics_non_enums)] + Match{f1} => { + discriminant::<i32>(&123); //~ ERROR the return value of + } + } + match f { + #[deny(enum_intrinsics_non_enums)] + Match{f1} => { + discriminant::<i32>(&123); //~ ERROR the return value of + } + } + + // Statement Block + { + #![deny(enum_intrinsics_non_enums)] + discriminant::<i32>(&123); //~ ERROR the return value of + } + let block_tail = { + #[deny(enum_intrinsics_non_enums)] + discriminant::<i32>(&123); //~ ERROR the return value of + }; + + // Before expression as a statement. + #[deny(enum_intrinsics_non_enums)] + discriminant::<i32>(&123); //~ ERROR the return value of + + [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)]; //~ ERROR the return value of + (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),); //~ ERROR the return value of + fn call(p: Discriminant<i32>) {} + call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); //~ ERROR the return value of + struct TupleStruct(Discriminant<i32>); + TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); //~ ERROR the return value of +} + + +// ################## Patterns +fn patterns() { + // There aren't any late lints that I can find that apply to pattern fields. + // + // struct PatField{f1: i32, f2: i32}; + // let f = PatField{f1: 1, f2: 2}; + // let PatField{#[deny()]f1, #[deny()]..} = f; +} + +fn main() {} diff --git a/tests/ui/lint/lint-attr-everywhere-late.stderr b/tests/ui/lint/lint-attr-everywhere-late.stderr new file mode 100644 index 000000000..a69c2e0ef --- /dev/null +++ b/tests/ui/lint/lint-attr-everywhere-late.stderr @@ -0,0 +1,428 @@ +error: missing documentation for a type alias + --> $DIR/lint-attr-everywhere-late.rs:35:1 + | +LL | pub type MissingDocType = i32; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:34:8 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a struct + --> $DIR/lint-attr-everywhere-late.rs:43:1 + | +LL | pub struct ItemOuter; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:42:8 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a module + --> $DIR/lint-attr-everywhere-late.rs:45:1 + | +LL | pub mod module_inner { + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:46:13 + | +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 + | +LL | pub fn inherent_denied_from_inner() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:52:13 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-attr-everywhere-late.rs:59:5 + | +LL | pub fn inherent_fn() {} + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:58:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated constant + --> $DIR/lint-attr-everywhere-late.rs:62:5 + | +LL | pub const INHERENT_CONST: i32 = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:61:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a trait + --> $DIR/lint-attr-everywhere-late.rs:65:1 + | +LL | pub trait TraitInner { + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:66:13 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a trait + --> $DIR/lint-attr-everywhere-late.rs:69:1 + | +LL | pub trait AssociatedTraitInner { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:70:13 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-attr-everywhere-late.rs:72:5 + | +LL | fn denied_from_inner() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-attr-everywhere-late.rs:79:5 + | +LL | fn assoc_fn() {} + | ^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:78:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated constant + --> $DIR/lint-attr-everywhere-late.rs:82:5 + | +LL | const ASSOC_CONST: u8 = 1; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:81:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated type + --> $DIR/lint-attr-everywhere-late.rs:85:5 + | +LL | type AssocType; + | ^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:84:12 + | +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 + | +LL | fn denied_from_inner(_x: Box<dyn Drop>) {} + | ^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:91:13 + | +LL | #![deny(dyn_drop)] + | ^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:96:21 + | +LL | fn assoc_fn() { discriminant::<i32>(&123); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:96:41 + | +LL | fn assoc_fn() { discriminant::<i32>(&123); } + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:95:12 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: literal out of range for `u8` + --> $DIR/lint-attr-everywhere-late.rs:98:59 + | +LL | #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000; + | ^^^^ + | + = note: the literal `1000` does not fit into the type `u8` whose range is `0..=255` +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:98:12 + | +LL | #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000; + | ^^^^^^^^^^^^^^^^^^^^ + +error: variable `PARAM` should have a snake case name + --> $DIR/lint-attr-everywhere-late.rs:131:37 + | +LL | fn function(#[deny(non_snake_case)] PARAM: i32) {} + | ^^^^^ help: convert the identifier to snake case: `param` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:131:20 + | +LL | fn function(#[deny(non_snake_case)] PARAM: i32) {} + | ^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:139:13 + | +LL | let _ = discriminant::<i32>(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:139:33 + | +LL | let _ = discriminant::<i32>(&123); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:138:12 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: variable `PARAM` should have a snake case name + --> $DIR/lint-attr-everywhere-late.rs:145:44 + | +LL | let closure = |#[deny(non_snake_case)] PARAM: i32| {}; + | ^^^^^ help: convert the identifier to snake case: `param` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:145:27 + | +LL | let closure = |#[deny(non_snake_case)] PARAM: i32| {}; + | ^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:155:13 + | +LL | discriminant::<i32>(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:155:33 + | +LL | discriminant::<i32>(&123); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:153:17 + | +LL | #![deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:161:13 + | +LL | discriminant::<i32>(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:161:33 + | +LL | discriminant::<i32>(&123); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:159:16 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:168:9 + | +LL | discriminant::<i32>(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:168:29 + | +LL | discriminant::<i32>(&123); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:167:17 + | +LL | #![deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:172:9 + | +LL | discriminant::<i32>(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:172:29 + | +LL | discriminant::<i32>(&123); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:171:16 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:177:5 + | +LL | discriminant::<i32>(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:177:25 + | +LL | discriminant::<i32>(&123); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:176:12 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:179:41 + | +LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:179:61 + | +LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)]; + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:179:13 + | +LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:180:41 + | +LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:180:61 + | +LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:180:13 + | +LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:182:45 + | +LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:182:65 + | +LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:182:17 + | +LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:184:52 + | +LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:184:72 + | +LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:184:24 + | +LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 31 previous errors + diff --git a/tests/ui/lint/lint-attr-non-item-node.rs b/tests/ui/lint/lint-attr-non-item-node.rs new file mode 100644 index 000000000..3f05e83a7 --- /dev/null +++ b/tests/ui/lint/lint-attr-non-item-node.rs @@ -0,0 +1,9 @@ +// Checks that lint attributes work on non-item AST nodes + +fn main() { + #[deny(unreachable_code)] + loop { + break; + "unreachable"; //~ ERROR unreachable statement + } +} diff --git a/tests/ui/lint/lint-attr-non-item-node.stderr b/tests/ui/lint/lint-attr-non-item-node.stderr new file mode 100644 index 000000000..583579140 --- /dev/null +++ b/tests/ui/lint/lint-attr-non-item-node.stderr @@ -0,0 +1,16 @@ +error: unreachable statement + --> $DIR/lint-attr-non-item-node.rs:7:9 + | +LL | break; + | ----- any code following this expression is unreachable +LL | "unreachable"; + | ^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/lint-attr-non-item-node.rs:4:12 + | +LL | #[deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-cap.rs b/tests/ui/lint/lint-cap.rs new file mode 100644 index 000000000..461b923cc --- /dev/null +++ b/tests/ui/lint/lint-cap.rs @@ -0,0 +1,8 @@ +// run-pass +// compile-flags: --cap-lints allow + +#![deny(warnings)] + +use std::option; + +fn main() {} diff --git a/tests/ui/lint/lint-change-warnings.rs b/tests/ui/lint/lint-change-warnings.rs new file mode 100644 index 000000000..37af3b761 --- /dev/null +++ b/tests/ui/lint/lint-change-warnings.rs @@ -0,0 +1,21 @@ +#![deny(warnings)] +#![allow(dead_code)] + +fn main() { + while true {} //~ ERROR: infinite +} + +#[allow(warnings)] +fn foo() { + while true {} +} + +#[warn(warnings)] +fn bar() { + while true {} //~ WARNING: infinite +} + +#[forbid(warnings)] +fn baz() { + while true {} //~ ERROR: infinite +} diff --git a/tests/ui/lint/lint-change-warnings.stderr b/tests/ui/lint/lint-change-warnings.stderr new file mode 100644 index 000000000..3fd5283aa --- /dev/null +++ b/tests/ui/lint/lint-change-warnings.stderr @@ -0,0 +1,36 @@ +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-change-warnings.rs:5:5 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-change-warnings.rs:1:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(while_true)]` implied by `#[deny(warnings)]` + +warning: denote infinite loops with `loop { ... }` + --> $DIR/lint-change-warnings.rs:15:5 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-change-warnings.rs:20:5 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-change-warnings.rs:18:10 + | +LL | #[forbid(warnings)] + | ^^^^^^^^ + = note: `#[forbid(while_true)]` implied by `#[forbid(warnings)]` + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/lint/lint-const-item-mutation.rs b/tests/ui/lint/lint-const-item-mutation.rs new file mode 100644 index 000000000..4bf5e0a9e --- /dev/null +++ b/tests/ui/lint/lint-const-item-mutation.rs @@ -0,0 +1,66 @@ +// check-pass + +struct MyStruct { + field: bool, + inner_array: [char; 1], + raw_ptr: *mut u8 +} +impl MyStruct { + fn use_mut(&mut self) {} +} + +struct Mutable { + msg: &'static str, +} +impl Drop for Mutable { + fn drop(&mut self) { + println!("{}", self.msg); + } +} + +struct Mutable2 { // this one has drop glue but not a Drop impl + msg: &'static str, + other: String, +} + +const ARRAY: [u8; 1] = [25]; +const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; +const RAW_PTR: *mut u8 = 1 as *mut u8; +const MUTABLE: Mutable = Mutable { msg: "" }; +const MUTABLE2: Mutable2 = Mutable2 { msg: "", other: String::new() }; +const VEC: Vec<i32> = Vec::new(); +const PTR: *mut () = 1 as *mut _; +const PTR_TO_ARRAY: *mut [u32; 4] = 0x12345678 as _; +const ARRAY_OF_PTR: [*mut u32; 1] = [1 as *mut _]; + +fn main() { + ARRAY[0] = 5; //~ WARN attempting to modify + MY_STRUCT.field = false; //~ WARN attempting to modify + MY_STRUCT.inner_array[0] = 'b'; //~ WARN attempting to modify + MY_STRUCT.use_mut(); //~ WARN taking + &mut MY_STRUCT; //~ WARN taking + (&mut MY_STRUCT).use_mut(); //~ WARN taking + + // Test that we don't warn when writing through + // a raw pointer + // This is U.B., but this test is check-pass, + // so this never actually executes + unsafe { + *RAW_PTR = 0; + *MY_STRUCT.raw_ptr = 0; + } + + MUTABLE.msg = "wow"; // no warning, because Drop observes the mutation + MUTABLE2.msg = "wow"; //~ WARN attempting to modify + VEC.push(0); //~ WARN taking a mutable reference to a `const` item + + // Test that we don't warn when converting a raw pointer + // into a mutable reference + unsafe { &mut *PTR }; + + // Test that we don't warn when there's a dereference involved. + // If we ever 'leave' the const via a deference, we're going + // to end up modifying something other than the temporary + unsafe { (*PTR_TO_ARRAY)[0] = 1 }; + unsafe { *ARRAY_OF_PTR[0] = 25; } +} diff --git a/tests/ui/lint/lint-const-item-mutation.stderr b/tests/ui/lint/lint-const-item-mutation.stderr new file mode 100644 index 000000000..747c38b80 --- /dev/null +++ b/tests/ui/lint/lint-const-item-mutation.stderr @@ -0,0 +1,118 @@ +warning: attempting to modify a `const` item + --> $DIR/lint-const-item-mutation.rs:37:5 + | +LL | ARRAY[0] = 5; + | ^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary; the original `const` item will not be modified +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:26:1 + | +LL | const ARRAY: [u8; 1] = [25]; + | ^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(const_item_mutation)]` on by default + +warning: attempting to modify a `const` item + --> $DIR/lint-const-item-mutation.rs:38:5 + | +LL | MY_STRUCT.field = false; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary; the original `const` item will not be modified +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:27:1 + | +LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: attempting to modify a `const` item + --> $DIR/lint-const-item-mutation.rs:39:5 + | +LL | MY_STRUCT.inner_array[0] = 'b'; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary; the original `const` item will not be modified +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:27:1 + | +LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: taking a mutable reference to a `const` item + --> $DIR/lint-const-item-mutation.rs:40:5 + | +LL | MY_STRUCT.use_mut(); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: mutable reference created due to call to this method + --> $DIR/lint-const-item-mutation.rs:9:5 + | +LL | fn use_mut(&mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^ +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:27:1 + | +LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: taking a mutable reference to a `const` item + --> $DIR/lint-const-item-mutation.rs:41:5 + | +LL | &mut MY_STRUCT; + | ^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:27:1 + | +LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: taking a mutable reference to a `const` item + --> $DIR/lint-const-item-mutation.rs:42:5 + | +LL | (&mut MY_STRUCT).use_mut(); + | ^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:27:1 + | +LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: attempting to modify a `const` item + --> $DIR/lint-const-item-mutation.rs:54:5 + | +LL | MUTABLE2.msg = "wow"; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary; the original `const` item will not be modified +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:30:1 + | +LL | const MUTABLE2: Mutable2 = Mutable2 { msg: "", other: String::new() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: taking a mutable reference to a `const` item + --> $DIR/lint-const-item-mutation.rs:55:5 + | +LL | VEC.push(0); + | ^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: mutable reference created due to call to this method + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:31:1 + | +LL | const VEC: Vec<i32> = Vec::new(); + | ^^^^^^^^^^^^^^^^^^^ + +warning: 8 warnings emitted + diff --git a/tests/ui/lint/lint-ctypes-66202.rs b/tests/ui/lint/lint-ctypes-66202.rs new file mode 100644 index 000000000..ebab41d14 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-66202.rs @@ -0,0 +1,17 @@ +// check-pass + +#![deny(improper_ctypes)] + +// This test checks that return types are normalized before being checked for FFI-safety, and that +// transparent newtype wrappers are FFI-safe if the type being wrapped is FFI-safe. + +#[repr(transparent)] +pub struct W<T>(T); + +extern "C" { + pub fn bare() -> (); + pub fn normalize() -> <() as ToOwned>::Owned; + pub fn transparent() -> W<()>; +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73249-1.rs b/tests/ui/lint/lint-ctypes-73249-1.rs new file mode 100644 index 000000000..cf416c3fe --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-1.rs @@ -0,0 +1,21 @@ +// check-pass +#![deny(improper_ctypes)] + +pub trait Foo { + type Assoc: 'static; +} + +impl Foo for () { + type Assoc = u32; +} + +extern "C" { + pub fn lint_me(x: Bar<()>); +} + +#[repr(transparent)] +pub struct Bar<T: Foo> { + value: &'static <T as Foo>::Assoc, +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73249-2.rs b/tests/ui/lint/lint-ctypes-73249-2.rs new file mode 100644 index 000000000..691047c8a --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-2.rs @@ -0,0 +1,29 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Baz {} + +impl Baz for () {} + +type Qux = impl Baz; + +fn assign() -> Qux {} + +pub trait Foo { + type Assoc: 'static; +} + +impl Foo for () { + type Assoc = Qux; +} + +#[repr(transparent)] +pub struct A<T: Foo> { + x: &'static <T as Foo>::Assoc, +} + +extern "C" { + pub fn lint_me() -> A<()>; //~ ERROR: uses type `Qux` +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73249-2.stderr b/tests/ui/lint/lint-ctypes-73249-2.stderr new file mode 100644 index 000000000..8073c33dd --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-2.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `Qux`, which is not FFI-safe + --> $DIR/lint-ctypes-73249-2.rs:26:25 + | +LL | pub fn lint_me() -> A<()>; + | ^^^^^ not FFI-safe + | + = note: opaque types have no C equivalent +note: the lint level is defined here + --> $DIR/lint-ctypes-73249-2.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-ctypes-73249-3.rs b/tests/ui/lint/lint-ctypes-73249-3.rs new file mode 100644 index 000000000..ef8ab7e03 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-3.rs @@ -0,0 +1,23 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Baz {} + +impl Baz for u32 {} + +type Qux = impl Baz; + +fn assign() -> Qux { + 3 +} + +#[repr(C)] +pub struct A { + x: Qux, +} + +extern "C" { + pub fn lint_me() -> A; //~ ERROR: uses type `Qux` +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73249-3.stderr b/tests/ui/lint/lint-ctypes-73249-3.stderr new file mode 100644 index 000000000..c41ce666d --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-3.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `Qux`, which is not FFI-safe + --> $DIR/lint-ctypes-73249-3.rs:20:25 + | +LL | pub fn lint_me() -> A; + | ^ not FFI-safe + | + = note: opaque types have no C equivalent +note: the lint level is defined here + --> $DIR/lint-ctypes-73249-3.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-ctypes-73249-4.rs b/tests/ui/lint/lint-ctypes-73249-4.rs new file mode 100644 index 000000000..6c72bd691 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-4.rs @@ -0,0 +1,24 @@ +// check-pass +#![deny(improper_ctypes)] + +use std::marker::PhantomData; + +trait Foo { + type Assoc; +} + +impl Foo for () { + type Assoc = PhantomData<()>; +} + +#[repr(transparent)] +struct Wow<T> where T: Foo<Assoc = PhantomData<T>> { + x: <T as Foo>::Assoc, + v: u32, +} + +extern "C" { + fn test(v: Wow<()>); +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73249-5.rs b/tests/ui/lint/lint-ctypes-73249-5.rs new file mode 100644 index 000000000..083fb6c5f --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-5.rs @@ -0,0 +1,23 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Baz {} + +impl Baz for u32 {} + +type Qux = impl Baz; + +fn assign() -> Qux { + 3 +} + +#[repr(transparent)] +pub struct A { + x: Qux, +} + +extern "C" { + pub fn lint_me() -> A; //~ ERROR: uses type `Qux` +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73249-5.stderr b/tests/ui/lint/lint-ctypes-73249-5.stderr new file mode 100644 index 000000000..98245c4f1 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-5.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `Qux`, which is not FFI-safe + --> $DIR/lint-ctypes-73249-5.rs:20:25 + | +LL | pub fn lint_me() -> A; + | ^ not FFI-safe + | + = note: opaque types have no C equivalent +note: the lint level is defined here + --> $DIR/lint-ctypes-73249-5.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-ctypes-73249.rs b/tests/ui/lint/lint-ctypes-73249.rs new file mode 100644 index 000000000..5b48fa9b7 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249.rs @@ -0,0 +1,21 @@ +// check-pass +#![deny(improper_ctypes)] + +pub trait Foo { + type Assoc; +} + +impl Foo for () { + type Assoc = u32; +} + +extern "C" { + pub fn lint_me(x: Bar<()>); +} + +#[repr(transparent)] +pub struct Bar<T: Foo> { + value: <T as Foo>::Assoc, +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73251-1.rs b/tests/ui/lint/lint-ctypes-73251-1.rs new file mode 100644 index 000000000..145ba784f --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73251-1.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Baz {} + +impl Baz for u32 {} + +type Qux = impl Baz; + +pub trait Foo { + type Assoc; +} + +impl Foo for u32 { + type Assoc = Qux; +} + +fn assign() -> Qux { + 1 +} + +extern "C" { + pub fn lint_me() -> <u32 as Foo>::Assoc; //~ ERROR: uses type `Qux` +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73251-1.stderr b/tests/ui/lint/lint-ctypes-73251-1.stderr new file mode 100644 index 000000000..9f43576ad --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73251-1.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `Qux`, which is not FFI-safe + --> $DIR/lint-ctypes-73251-1.rs:23:25 + | +LL | pub fn lint_me() -> <u32 as Foo>::Assoc; + | ^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: opaque types have no C equivalent +note: the lint level is defined here + --> $DIR/lint-ctypes-73251-1.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-ctypes-73251-2.rs b/tests/ui/lint/lint-ctypes-73251-2.rs new file mode 100644 index 000000000..df71a9457 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73251-2.rs @@ -0,0 +1,39 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait TraitA { + type Assoc; +} + +impl TraitA for u32 { + type Assoc = u32; +} + +pub trait TraitB { + type Assoc; +} + +impl<T> TraitB for T +where + T: TraitA, +{ + type Assoc = <T as TraitA>::Assoc; +} + +type AliasA = impl TraitA<Assoc = u32>; + +type AliasB = impl TraitB<Assoc = AliasA>; + +fn use_of_a() -> AliasA { + 3 +} + +fn use_of_b() -> AliasB { + 3 +} + +extern "C" { + pub fn lint_me() -> <AliasB as TraitB>::Assoc; //~ ERROR: uses type `AliasA` +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73251-2.stderr b/tests/ui/lint/lint-ctypes-73251-2.stderr new file mode 100644 index 000000000..0b3de379c --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73251-2.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `AliasA`, which is not FFI-safe + --> $DIR/lint-ctypes-73251-2.rs:36:25 + | +LL | pub fn lint_me() -> <AliasB as TraitB>::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: opaque types have no C equivalent +note: the lint level is defined here + --> $DIR/lint-ctypes-73251-2.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-ctypes-73251.rs b/tests/ui/lint/lint-ctypes-73251.rs new file mode 100644 index 000000000..ebc2ca77b --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73251.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Foo { + type Assoc; +} + +impl Foo for () { + type Assoc = u32; +} + +type Bar = impl Foo<Assoc = u32>; + +fn assign() -> Bar {} + +extern "C" { + pub fn lint_me() -> <Bar as Foo>::Assoc; +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73747.rs b/tests/ui/lint/lint-ctypes-73747.rs new file mode 100644 index 000000000..293ffd5c2 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73747.rs @@ -0,0 +1,14 @@ +// check-pass + +#[repr(transparent)] +struct NonNullRawComPtr<T: ComInterface> { + inner: std::ptr::NonNull<<T as ComInterface>::VTable>, +} + +trait ComInterface { + type VTable; +} + +extern "C" fn invoke<T: ComInterface>(_: Option<NonNullRawComPtr<T>>) {} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-enum.rs b/tests/ui/lint/lint-ctypes-enum.rs new file mode 100644 index 000000000..7c2060805 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-enum.rs @@ -0,0 +1,92 @@ +#![feature(transparent_unions)] +#![feature(ptr_internals)] +#![deny(improper_ctypes)] +#![allow(dead_code)] + +use std::num; + +enum Z {} +enum U { + A, +} +enum B { + C, + D, +} +enum T { + E, + F, + G, +} + +#[repr(C)] +enum ReprC { + A, + B, + C, +} + +#[repr(u8)] +enum U8 { + A, + B, + C, +} + +#[repr(isize)] +enum Isize { + A, + B, + C, +} + +#[repr(transparent)] +struct TransparentStruct<T>(T, std::marker::PhantomData<Z>); + +#[repr(transparent)] +enum TransparentEnum<T> { + Variant(T, std::marker::PhantomData<Z>), +} + +#[repr(transparent)] +union TransparentUnion<T: Copy> { + field: T, +} + +struct Rust<T>(T); + +extern "C" { + fn zf(x: Z); + fn uf(x: U); //~ ERROR `extern` block uses type `U` + fn bf(x: B); //~ ERROR `extern` block uses type `B` + fn tf(x: T); //~ ERROR `extern` block uses type `T` + fn repr_c(x: ReprC); + fn repr_u8(x: U8); + fn repr_isize(x: Isize); + fn option_ref(x: Option<&'static u8>); + fn option_fn(x: Option<extern "C" fn()>); + fn nonnull(x: Option<std::ptr::NonNull<u8>>); + fn unique(x: Option<std::ptr::Unique<u8>>); + fn nonzero_u8(x: Option<num::NonZeroU8>); + fn nonzero_u16(x: Option<num::NonZeroU16>); + fn nonzero_u32(x: Option<num::NonZeroU32>); + fn nonzero_u64(x: Option<num::NonZeroU64>); + fn nonzero_u128(x: Option<num::NonZeroU128>); + //~^ ERROR `extern` block uses type `u128` + fn nonzero_usize(x: Option<num::NonZeroUsize>); + fn nonzero_i8(x: Option<num::NonZeroI8>); + fn nonzero_i16(x: Option<num::NonZeroI16>); + fn nonzero_i32(x: Option<num::NonZeroI32>); + fn nonzero_i64(x: Option<num::NonZeroI64>); + fn nonzero_i128(x: Option<num::NonZeroI128>); + //~^ ERROR `extern` block uses type `i128` + fn nonzero_isize(x: Option<num::NonZeroIsize>); + fn transparent_struct(x: Option<TransparentStruct<num::NonZeroU8>>); + fn transparent_enum(x: Option<TransparentEnum<num::NonZeroU8>>); + fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>); + //~^ ERROR `extern` block uses type + fn repr_rust(x: Option<Rust<num::NonZeroU8>>); //~ ERROR `extern` block uses type + fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR `extern` block uses type +} + +pub fn main() {} diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr new file mode 100644 index 000000000..8554e2617 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-enum.stderr @@ -0,0 +1,92 @@ +error: `extern` block uses type `U`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:60:13 + | +LL | fn uf(x: U); + | ^ 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: the type is defined here + --> $DIR/lint-ctypes-enum.rs:9:1 + | +LL | enum U { + | ^^^^^^ +note: the lint level is defined here + --> $DIR/lint-ctypes-enum.rs:3:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: `extern` block uses type `B`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:61:13 + | +LL | fn bf(x: B); + | ^ 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: the type is defined here + --> $DIR/lint-ctypes-enum.rs:12:1 + | +LL | enum B { + | ^^^^^^ + +error: `extern` block uses type `T`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:62:13 + | +LL | fn tf(x: T); + | ^ 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: the type is defined here + --> $DIR/lint-ctypes-enum.rs:16:1 + | +LL | enum T { + | ^^^^^^ + +error: `extern` block uses type `u128`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:74:23 + | +LL | fn nonzero_u128(x: Option<num::NonZeroU128>); + | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:81:23 + | +LL | fn nonzero_i128(x: Option<num::NonZeroI128>); + | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `Option<TransparentUnion<NonZeroU8>>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:86:28 + | +LL | fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Option<Rust<NonZeroU8>>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:88:20 + | +LL | fn repr_rust(x: Option<Rust<num::NonZeroU8>>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), NonZeroI32>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:89:20 + | +LL | fn no_result(x: Result<(), num::NonZeroI32>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: aborting due to 8 previous errors + diff --git a/tests/ui/lint/lint-ctypes-fn.rs b/tests/ui/lint/lint-ctypes-fn.rs new file mode 100644 index 000000000..d3b36a9d5 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-fn.rs @@ -0,0 +1,196 @@ +#![feature(rustc_private)] + +#![allow(private_in_public)] +#![deny(improper_ctypes_definitions)] + +extern crate libc; + +use std::default::Default; +use std::marker::PhantomData; + +trait Trait {} + +trait Mirror { type It: ?Sized; } + +impl<T: ?Sized> Mirror for T { type It = Self; } + +#[repr(C)] +pub struct StructWithProjection(*mut <StructWithProjection as Mirror>::It); + +#[repr(C)] +pub struct StructWithProjectionAndLifetime<'a>( + &'a mut <StructWithProjectionAndLifetime<'a> as Mirror>::It +); + +pub type I32Pair = (i32, i32); + +#[repr(C)] +pub struct ZeroSize; + +pub type RustFn = fn(); + +pub type RustBadRet = extern "C" fn() -> Box<u32>; + +pub type CVoidRet = (); + +pub struct Foo; + +#[repr(transparent)] +pub struct TransparentI128(i128); + +#[repr(transparent)] +pub struct TransparentStr(&'static str); + +#[repr(transparent)] +pub struct TransparentBadFn(RustBadRet); + +#[repr(transparent)] +pub struct TransparentInt(u32); + +#[repr(transparent)] +pub struct TransparentRef<'a>(&'a TransparentInt); + +#[repr(transparent)] +pub struct TransparentLifetime<'a>(*const u8, PhantomData<&'a ()>); + +#[repr(transparent)] +pub struct TransparentUnit<U>(f32, PhantomData<U>); + +#[repr(transparent)] +pub struct TransparentCustomZst(i32, ZeroSize); + +#[repr(C)] +pub struct ZeroSizeWithPhantomData(PhantomData<i32>); + +pub extern "C" fn ptr_type1(size: *const Foo) { } + +pub extern "C" fn ptr_type2(size: *const Foo) { } + +pub extern "C" fn ptr_unit(p: *const ()) { } + +pub extern "C" fn ptr_tuple(p: *const ((),)) { } + +pub extern "C" fn slice_type(p: &[u32]) { } +//~^ ERROR: uses type `[u32]` + +pub extern "C" fn str_type(p: &str) { } +//~^ ERROR: uses type `str` + +pub extern "C" fn box_type(p: Box<u32>) { } + +pub extern "C" fn opt_box_type(p: Option<Box<u32>>) { } + +pub extern "C" fn boxed_slice(p: Box<[u8]>) { } +//~^ ERROR: uses type `Box<[u8]>` + +pub extern "C" fn boxed_string(p: Box<str>) { } +//~^ ERROR: uses type `Box<str>` + +pub extern "C" fn boxed_trait(p: Box<dyn Trait>) { } +//~^ ERROR: uses type `Box<dyn Trait>` + +pub extern "C" fn char_type(p: char) { } +//~^ ERROR uses type `char` + +pub extern "C" fn i128_type(p: i128) { } +//~^ ERROR uses type `i128` + +pub extern "C" fn u128_type(p: u128) { } +//~^ ERROR uses type `u128` + +pub extern "C" fn tuple_type(p: (i32, i32)) { } +//~^ ERROR uses type `(i32, i32)` + +pub extern "C" fn tuple_type2(p: I32Pair) { } +//~^ ERROR uses type `(i32, i32)` + +pub extern "C" fn zero_size(p: ZeroSize) { } +//~^ ERROR uses type `ZeroSize` + +pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { } +//~^ ERROR uses type `ZeroSizeWithPhantomData` + +pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData<bool> { +//~^ ERROR uses type `PhantomData<bool>` + Default::default() +} + +pub extern "C" fn fn_type(p: RustFn) { } +//~^ ERROR uses type `fn()` + +pub extern "C" fn fn_type2(p: fn()) { } +//~^ ERROR uses type `fn()` + +pub extern "C" fn fn_contained(p: RustBadRet) { } + +pub extern "C" fn transparent_i128(p: TransparentI128) { } +//~^ ERROR: uses type `i128` + +pub extern "C" fn transparent_str(p: TransparentStr) { } +//~^ ERROR: uses type `str` + +pub extern "C" fn transparent_fn(p: TransparentBadFn) { } + +pub extern "C" fn good3(fptr: Option<extern "C" fn()>) { } + +pub extern "C" fn good4(aptr: &[u8; 4 as usize]) { } + +pub extern "C" fn good5(s: StructWithProjection) { } + +pub extern "C" fn good6(s: StructWithProjectionAndLifetime) { } + +pub extern "C" fn good7(fptr: extern "C" fn() -> ()) { } + +pub extern "C" fn good8(fptr: extern "C" fn() -> !) { } + +pub extern "C" fn good9() -> () { } + +pub extern "C" fn good10() -> CVoidRet { } + +pub extern "C" fn good11(size: isize) { } + +pub extern "C" fn good12(size: usize) { } + +pub extern "C" fn good13(n: TransparentInt) { } + +pub extern "C" fn good14(p: TransparentRef) { } + +pub extern "C" fn good15(p: TransparentLifetime) { } + +pub extern "C" fn good16(p: TransparentUnit<ZeroSize>) { } + +pub extern "C" fn good17(p: TransparentCustomZst) { } + +#[allow(improper_ctypes_definitions)] +pub extern "C" fn good18(_: &String) { } + +#[cfg(not(target_arch = "wasm32"))] +pub extern "C" fn good1(size: *const libc::c_int) { } + +#[cfg(not(target_arch = "wasm32"))] +pub extern "C" fn good2(size: *const libc::c_uint) { } + +pub extern "C" fn unused_generic1<T>(size: *const Foo) { } + +pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> { +//~^ ERROR uses type `PhantomData<bool>` + Default::default() +} + +pub extern "C" fn used_generic1<T>(x: T) { } + +pub extern "C" fn used_generic2<T>(x: T, size: *const Foo) { } + +pub extern "C" fn used_generic3<T: Default>() -> T { + Default::default() +} + +pub extern "C" fn used_generic4<T>(x: Vec<T>) { } +//~^ ERROR: uses type `Vec<T>` + +pub extern "C" fn used_generic5<T>() -> Vec<T> { +//~^ ERROR: uses type `Vec<T>` + Default::default() +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-fn.stderr b/tests/ui/lint/lint-ctypes-fn.stderr new file mode 100644 index 000000000..a05206bf1 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-fn.stderr @@ -0,0 +1,188 @@ +error: `extern` fn uses type `[u32]`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:73:33 + | +LL | pub extern "C" fn slice_type(p: &[u32]) { } + | ^^^^^^ not FFI-safe + | + = help: consider using a raw pointer instead + = note: slices have no C equivalent +note: the lint level is defined here + --> $DIR/lint-ctypes-fn.rs:4:9 + | +LL | #![deny(improper_ctypes_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `str`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:76:31 + | +LL | pub extern "C" fn str_type(p: &str) { } + | ^^^^ not FFI-safe + | + = help: consider using `*const u8` and a length instead + = note: string slices have no C equivalent + +error: `extern` fn uses type `Box<[u8]>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:83:34 + | +LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { } + | ^^^^^^^^^ not FFI-safe + | + = note: box cannot be represented as a single pointer + +error: `extern` fn uses type `Box<str>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:86:35 + | +LL | pub extern "C" fn boxed_string(p: Box<str>) { } + | ^^^^^^^^ not FFI-safe + | + = note: box cannot be represented as a single pointer + +error: `extern` fn uses type `Box<dyn Trait>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:89:34 + | +LL | pub extern "C" fn boxed_trait(p: Box<dyn Trait>) { } + | ^^^^^^^^^^^^^^ not FFI-safe + | + = note: box cannot be represented as a single pointer + +error: `extern` fn uses type `char`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:92:32 + | +LL | pub extern "C" fn char_type(p: char) { } + | ^^^^ not FFI-safe + | + = help: consider using `u32` or `libc::wchar_t` instead + = note: the `char` type has no C equivalent + +error: `extern` fn uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:95:32 + | +LL | pub extern "C" fn i128_type(p: i128) { } + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` fn uses type `u128`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:98:32 + | +LL | pub extern "C" fn u128_type(p: u128) { } + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:101:33 + | +LL | pub extern "C" fn tuple_type(p: (i32, i32)) { } + | ^^^^^^^^^^ not FFI-safe + | + = help: consider using a struct instead + = note: tuples have unspecified layout + +error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:104:34 + | +LL | pub extern "C" fn tuple_type2(p: I32Pair) { } + | ^^^^^^^ not FFI-safe + | + = help: consider using a struct instead + = note: tuples have unspecified layout + +error: `extern` fn uses type `ZeroSize`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:107:32 + | +LL | pub extern "C" fn zero_size(p: ZeroSize) { } + | ^^^^^^^^ not FFI-safe + | + = help: consider adding a member to this struct + = note: this struct has no fields +note: the type is defined here + --> $DIR/lint-ctypes-fn.rs:28:1 + | +LL | pub struct ZeroSize; + | ^^^^^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `ZeroSizeWithPhantomData`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:110:40 + | +LL | pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { } + | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` +note: the type is defined here + --> $DIR/lint-ctypes-fn.rs:63:1 + | +LL | pub struct ZeroSizeWithPhantomData(PhantomData<i32>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `PhantomData<bool>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:113:51 + | +LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData<bool> { + | ^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` + +error: `extern` fn uses type `fn()`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:118:30 + | +LL | pub extern "C" fn fn_type(p: RustFn) { } + | ^^^^^^ not FFI-safe + | + = help: consider using an `extern fn(...) -> ...` function pointer instead + = note: this function pointer has Rust-specific calling convention + +error: `extern` fn uses type `fn()`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:121:31 + | +LL | pub extern "C" fn fn_type2(p: fn()) { } + | ^^^^ not FFI-safe + | + = help: consider using an `extern fn(...) -> ...` function pointer instead + = note: this function pointer has Rust-specific calling convention + +error: `extern` fn uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:126:39 + | +LL | pub extern "C" fn transparent_i128(p: TransparentI128) { } + | ^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` fn uses type `str`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:129:38 + | +LL | pub extern "C" fn transparent_str(p: TransparentStr) { } + | ^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider using `*const u8` and a length instead + = note: string slices have no C equivalent + +error: `extern` fn uses type `PhantomData<bool>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:175:43 + | +LL | pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> { + | ^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` + +error: `extern` fn uses type `Vec<T>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:188:39 + | +LL | pub extern "C" fn used_generic4<T>(x: Vec<T>) { } + | ^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: `extern` fn uses type `Vec<T>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:191:41 + | +LL | pub extern "C" fn used_generic5<T>() -> Vec<T> { + | ^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: aborting due to 20 previous errors + diff --git a/tests/ui/lint/lint-ctypes.rs b/tests/ui/lint/lint-ctypes.rs new file mode 100644 index 000000000..9165e14b7 --- /dev/null +++ b/tests/ui/lint/lint-ctypes.rs @@ -0,0 +1,118 @@ +#![feature(rustc_private)] + +#![allow(private_in_public)] +#![deny(improper_ctypes)] + +extern crate libc; + +use std::cell::UnsafeCell; +use std::marker::PhantomData; + +trait Bar { } +trait Mirror { type It: ?Sized; } +impl<T: ?Sized> Mirror for T { type It = Self; } +#[repr(C)] +pub struct StructWithProjection(*mut <StructWithProjection as Mirror>::It); +#[repr(C)] +pub struct StructWithProjectionAndLifetime<'a>( + &'a mut <StructWithProjectionAndLifetime<'a> as Mirror>::It +); +pub type I32Pair = (i32, i32); +#[repr(C)] +pub struct ZeroSize; +pub type RustFn = fn(); +pub type RustBadRet = extern "C" fn() -> Box<u32>; +pub type CVoidRet = (); +pub struct Foo; +#[repr(transparent)] +pub struct TransparentI128(i128); +#[repr(transparent)] +pub struct TransparentStr(&'static str); +#[repr(transparent)] +pub struct TransparentBadFn(RustBadRet); +#[repr(transparent)] +pub struct TransparentInt(u32); +#[repr(transparent)] +pub struct TransparentRef<'a>(&'a TransparentInt); +#[repr(transparent)] +pub struct TransparentLifetime<'a>(*const u8, PhantomData<&'a ()>); +#[repr(transparent)] +pub struct TransparentUnit<U>(f32, PhantomData<U>); +#[repr(transparent)] +pub struct TransparentCustomZst(i32, ZeroSize); + +#[repr(C)] +pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>); + +extern "C" { + pub fn ptr_type1(size: *const Foo); //~ ERROR: uses type `Foo` + pub fn ptr_type2(size: *const Foo); //~ ERROR: uses type `Foo` + pub fn ptr_unit(p: *const ()); + pub fn ptr_tuple(p: *const ((),)); //~ ERROR: uses type `((),)` + pub fn slice_type(p: &[u32]); //~ ERROR: uses type `[u32]` + pub fn str_type(p: &str); //~ ERROR: uses type `str` + pub fn box_type(p: Box<u32>); //~ ERROR uses type `Box<u32>` + pub fn opt_box_type(p: Option<Box<u32>>); + //~^ ERROR uses type `Option<Box<u32>>` + pub fn char_type(p: char); //~ ERROR uses type `char` + pub fn i128_type(p: i128); //~ ERROR uses type `i128` + pub fn u128_type(p: u128); //~ ERROR uses type `u128` + pub fn trait_type(p: &dyn Bar); //~ ERROR uses type `dyn Bar` + pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)` + pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)` + pub fn zero_size(p: ZeroSize); //~ ERROR uses type `ZeroSize` + pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); + //~^ ERROR uses type `ZeroSizeWithPhantomData` + pub fn zero_size_phantom_toplevel() + -> ::std::marker::PhantomData<bool>; //~ ERROR uses type `PhantomData<bool>` + pub fn fn_type(p: RustFn); //~ ERROR uses type `fn()` + pub fn fn_type2(p: fn()); //~ ERROR uses type `fn()` + pub fn fn_contained(p: RustBadRet); //~ ERROR: uses type `Box<u32>` + pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128` + pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str` + pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: uses type `Box<u32>` + pub fn raw_array(arr: [u8; 8]); //~ ERROR: uses type `[u8; 8]` + + pub fn no_niche_a(a: Option<UnsafeCell<extern fn()>>); + //~^ ERROR: uses type `Option<UnsafeCell<extern "C" fn()>>` + pub fn no_niche_b(b: Option<UnsafeCell<&i32>>); + //~^ ERROR: uses type `Option<UnsafeCell<&i32>>` + + pub static static_u128_type: u128; //~ ERROR: uses type `u128` + pub static static_u128_array_type: [u128; 16]; //~ ERROR: uses type `u128` + + pub fn good3(fptr: Option<extern "C" fn()>); + pub fn good4(aptr: &[u8; 4 as usize]); + pub fn good5(s: StructWithProjection); + pub fn good6(s: StructWithProjectionAndLifetime); + pub fn good7(fptr: extern "C" fn() -> ()); + pub fn good8(fptr: extern "C" fn() -> !); + pub fn good9() -> (); + pub fn good10() -> CVoidRet; + pub fn good11(size: isize); + pub fn good12(size: usize); + pub fn good13(n: TransparentInt); + pub fn good14(p: TransparentRef); + pub fn good15(p: TransparentLifetime); + pub fn good16(p: TransparentUnit<ZeroSize>); + pub fn good17(p: TransparentCustomZst); + #[allow(improper_ctypes)] + pub fn good18(_: &String); + pub fn good20(arr: *const [u8; 8]); + pub static good21: [u8; 8]; + +} + +#[allow(improper_ctypes)] +extern "C" { + pub fn good19(_: &String); +} + +#[cfg(not(target_arch = "wasm32"))] +extern "C" { + pub fn good1(size: *const libc::c_int); + pub fn good2(size: *const libc::c_uint); +} + +fn main() { +} diff --git a/tests/ui/lint/lint-ctypes.stderr b/tests/ui/lint/lint-ctypes.stderr new file mode 100644 index 000000000..121ad0ce8 --- /dev/null +++ b/tests/ui/lint/lint-ctypes.stderr @@ -0,0 +1,262 @@ +error: `extern` block uses type `Foo`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:48:28 + | +LL | pub fn ptr_type1(size: *const Foo); + | ^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/lint-ctypes.rs:26:1 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/lint-ctypes.rs:4:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: `extern` block uses type `Foo`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:49:28 + | +LL | pub fn ptr_type2(size: *const Foo); + | ^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/lint-ctypes.rs:26:1 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^ + +error: `extern` block uses type `((),)`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:51:25 + | +LL | pub fn ptr_tuple(p: *const ((),)); + | ^^^^^^^^^^^^ not FFI-safe + | + = help: consider using a struct instead + = note: tuples have unspecified layout + +error: `extern` block uses type `[u32]`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:52:26 + | +LL | pub fn slice_type(p: &[u32]); + | ^^^^^^ not FFI-safe + | + = help: consider using a raw pointer instead + = note: slices have no C equivalent + +error: `extern` block uses type `str`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:53:24 + | +LL | pub fn str_type(p: &str); + | ^^^^ not FFI-safe + | + = help: consider using `*const u8` and a length instead + = note: string slices have no C equivalent + +error: `extern` block uses type `Box<u32>`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:54:24 + | +LL | pub fn box_type(p: Box<u32>); + | ^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: `extern` block uses type `Option<Box<u32>>`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:55:28 + | +LL | pub fn opt_box_type(p: Option<Box<u32>>); + | ^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `char`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:57:25 + | +LL | pub fn char_type(p: char); + | ^^^^ not FFI-safe + | + = help: consider using `u32` or `libc::wchar_t` instead + = note: the `char` type has no C equivalent + +error: `extern` block uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:58:25 + | +LL | pub fn i128_type(p: i128); + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `u128`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:59:25 + | +LL | pub fn u128_type(p: u128); + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `dyn Bar`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:60:26 + | +LL | pub fn trait_type(p: &dyn Bar); + | ^^^^^^^^ not FFI-safe + | + = note: trait objects have no C equivalent + +error: `extern` block uses type `(i32, i32)`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:61:26 + | +LL | pub fn tuple_type(p: (i32, i32)); + | ^^^^^^^^^^ not FFI-safe + | + = help: consider using a struct instead + = note: tuples have unspecified layout + +error: `extern` block uses type `(i32, i32)`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:62:27 + | +LL | pub fn tuple_type2(p: I32Pair); + | ^^^^^^^ not FFI-safe + | + = help: consider using a struct instead + = note: tuples have unspecified layout + +error: `extern` block uses type `ZeroSize`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:63:25 + | +LL | pub fn zero_size(p: ZeroSize); + | ^^^^^^^^ not FFI-safe + | + = help: consider adding a member to this struct + = note: this struct has no fields +note: the type is defined here + --> $DIR/lint-ctypes.rs:22:1 + | +LL | pub struct ZeroSize; + | ^^^^^^^^^^^^^^^^^^^ + +error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:64:33 + | +LL | pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); + | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` +note: the type is defined here + --> $DIR/lint-ctypes.rs:45:1 + | +LL | pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `extern` block uses type `PhantomData<bool>`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:67:12 + | +LL | -> ::std::marker::PhantomData<bool>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` + +error: `extern` block uses type `fn()`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:68:23 + | +LL | pub fn fn_type(p: RustFn); + | ^^^^^^ not FFI-safe + | + = help: consider using an `extern fn(...) -> ...` function pointer instead + = note: this function pointer has Rust-specific calling convention + +error: `extern` block uses type `fn()`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:69:24 + | +LL | pub fn fn_type2(p: fn()); + | ^^^^ not FFI-safe + | + = help: consider using an `extern fn(...) -> ...` function pointer instead + = note: this function pointer has Rust-specific calling convention + +error: `extern` block uses type `Box<u32>`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:70:28 + | +LL | pub fn fn_contained(p: RustBadRet); + | ^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: `extern` block uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:71:32 + | +LL | pub fn transparent_i128(p: TransparentI128); + | ^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `str`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:72:31 + | +LL | pub fn transparent_str(p: TransparentStr); + | ^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider using `*const u8` and a length instead + = note: string slices have no C equivalent + +error: `extern` block uses type `Box<u32>`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:73:30 + | +LL | pub fn transparent_fn(p: TransparentBadFn); + | ^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: `extern` block uses type `[u8; 8]`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:74:27 + | +LL | pub fn raw_array(arr: [u8; 8]); + | ^^^^^^^ not FFI-safe + | + = help: consider passing a pointer to the array + = note: passing raw arrays by value is not FFI-safe + +error: `extern` block uses type `Option<UnsafeCell<extern "C" fn()>>`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:76:26 + | +LL | pub fn no_niche_a(a: Option<UnsafeCell<extern fn()>>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Option<UnsafeCell<&i32>>`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:78:26 + | +LL | pub fn no_niche_b(b: Option<UnsafeCell<&i32>>); + | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `u128`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:81:34 + | +LL | pub static static_u128_type: u128; + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `u128`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:82:40 + | +LL | pub static static_u128_array_type: [u128; 16]; + | ^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: aborting due to 27 previous errors + diff --git a/tests/ui/lint/lint-deref-nullptr.rs b/tests/ui/lint/lint-deref-nullptr.rs new file mode 100644 index 000000000..d052dbd9b --- /dev/null +++ b/tests/ui/lint/lint-deref-nullptr.rs @@ -0,0 +1,38 @@ +// test the deref_nullptr lint + +#![deny(deref_nullptr)] + +use std::ptr; + +struct Struct { + field: u8, +} + +fn f() { + unsafe { + let a = 1; + let ub = *(a as *const i32); + let ub = *(0 as *const i32); + //~^ ERROR dereferencing a null pointer + let ub = *ptr::null::<i32>(); + //~^ ERROR dereferencing a null pointer + let ub = *ptr::null_mut::<i32>(); + //~^ ERROR dereferencing a null pointer + let ub = *(ptr::null::<i16>() as *const i32); + //~^ ERROR dereferencing a null pointer + let ub = *(ptr::null::<i16>() as *mut i32 as *mut usize as *const u8); + //~^ ERROR dereferencing a null pointer + let ub = &*ptr::null::<i32>(); + //~^ ERROR dereferencing a null pointer + let ub = &*ptr::null_mut::<i32>(); + //~^ ERROR dereferencing a null pointer + ptr::addr_of!(*ptr::null::<i32>()); + //~^ ERROR dereferencing a null pointer + ptr::addr_of_mut!(*ptr::null_mut::<i32>()); + //~^ ERROR dereferencing a null pointer + let offset = ptr::addr_of!((*ptr::null::<Struct>()).field); + //~^ ERROR dereferencing a null pointer + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-deref-nullptr.stderr b/tests/ui/lint/lint-deref-nullptr.stderr new file mode 100644 index 000000000..c6f432e4e --- /dev/null +++ b/tests/ui/lint/lint-deref-nullptr.stderr @@ -0,0 +1,68 @@ +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:15:18 + | +LL | let ub = *(0 as *const i32); + | ^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + | +note: the lint level is defined here + --> $DIR/lint-deref-nullptr.rs:3:9 + | +LL | #![deny(deref_nullptr)] + | ^^^^^^^^^^^^^ + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:17:18 + | +LL | let ub = *ptr::null::<i32>(); + | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:19:18 + | +LL | let ub = *ptr::null_mut::<i32>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:21:18 + | +LL | let ub = *(ptr::null::<i16>() as *const i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:23:18 + | +LL | let ub = *(ptr::null::<i16>() as *mut i32 as *mut usize as *const u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:25:19 + | +LL | let ub = &*ptr::null::<i32>(); + | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:27:19 + | +LL | let ub = &*ptr::null_mut::<i32>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:29:23 + | +LL | ptr::addr_of!(*ptr::null::<i32>()); + | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:31:27 + | +LL | ptr::addr_of_mut!(*ptr::null_mut::<i32>()); + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:33:36 + | +LL | let offset = ptr::addr_of!((*ptr::null::<Struct>()).field); + | ^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: aborting due to 10 previous errors + diff --git a/tests/ui/lint/lint-directives-on-use-items-issue-10534.rs b/tests/ui/lint/lint-directives-on-use-items-issue-10534.rs new file mode 100644 index 000000000..e5cb0d3df --- /dev/null +++ b/tests/ui/lint/lint-directives-on-use-items-issue-10534.rs @@ -0,0 +1,24 @@ +#![deny(unused_imports)] +#![allow(non_upper_case_globals)] + +// The aim of this test is to ensure that deny/allow/warn directives +// are applied to individual "use" statements instead of silently +// ignored. + +#[allow(dead_code)] +mod a { pub static x: isize = 3; pub static y: isize = 4; } + +mod b { + use a::x; //~ ERROR: unused import + #[allow(unused_imports)] + use a::y; // no error here +} + +#[allow(unused_imports)] +mod c { + use a::x; + #[deny(unused_imports)] + use a::y; //~ ERROR: unused import +} + +fn main() {} diff --git a/tests/ui/lint/lint-directives-on-use-items-issue-10534.stderr b/tests/ui/lint/lint-directives-on-use-items-issue-10534.stderr new file mode 100644 index 000000000..ccb139e0e --- /dev/null +++ b/tests/ui/lint/lint-directives-on-use-items-issue-10534.stderr @@ -0,0 +1,26 @@ +error: unused import: `a::x` + --> $DIR/lint-directives-on-use-items-issue-10534.rs:12:9 + | +LL | use a::x; + | ^^^^ + | +note: the lint level is defined here + --> $DIR/lint-directives-on-use-items-issue-10534.rs:1:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: unused import: `a::y` + --> $DIR/lint-directives-on-use-items-issue-10534.rs:21:9 + | +LL | use a::y; + | ^^^^ + | +note: the lint level is defined here + --> $DIR/lint-directives-on-use-items-issue-10534.rs:20:12 + | +LL | #[deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/lint-enum-intrinsics-non-enums.rs b/tests/ui/lint/lint-enum-intrinsics-non-enums.rs new file mode 100644 index 000000000..8ad337064 --- /dev/null +++ b/tests/ui/lint/lint-enum-intrinsics-non-enums.rs @@ -0,0 +1,67 @@ +// Test the enum_intrinsics_non_enums lint. + +#![feature(variant_count)] + +use std::mem::{discriminant, variant_count}; + +enum SomeEnum { + A, + B, +} + +struct SomeStruct; + +fn generic_discriminant<T>(v: &T) { + discriminant::<T>(v); +} + +fn generic_variant_count<T>() -> usize { + variant_count::<T>() +} + +fn test_discriminant() { + discriminant(&SomeEnum::A); + generic_discriminant(&SomeEnum::B); + + discriminant(&()); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + + discriminant(&&SomeEnum::B); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + + discriminant(&SomeStruct); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + + discriminant(&123u32); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + + discriminant(&&123i8); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type +} + +fn test_variant_count() { + variant_count::<SomeEnum>(); + generic_variant_count::<SomeEnum>(); + + variant_count::<&str>(); + //~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + + variant_count::<*const u8>(); + //~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + + variant_count::<()>(); + //~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + + variant_count::<&SomeEnum>(); + //~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type +} + +fn main() { + test_discriminant(); + test_variant_count(); + + // The lint ignores cases where the type is generic, so these should be + // allowed even though their return values are unspecified + generic_variant_count::<SomeStruct>(); + generic_discriminant::<SomeStruct>(&SomeStruct); +} diff --git a/tests/ui/lint/lint-enum-intrinsics-non-enums.stderr b/tests/ui/lint/lint-enum-intrinsics-non-enums.stderr new file mode 100644 index 000000000..63ed2503c --- /dev/null +++ b/tests/ui/lint/lint-enum-intrinsics-non-enums.stderr @@ -0,0 +1,95 @@ +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:26:5 + | +LL | discriminant(&()); + | ^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `()`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:26:18 + | +LL | discriminant(&()); + | ^^^ + = note: `#[deny(enum_intrinsics_non_enums)]` on by default + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:29:5 + | +LL | discriminant(&&SomeEnum::B); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `&SomeEnum`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:29:18 + | +LL | discriminant(&&SomeEnum::B); + | ^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:32:5 + | +LL | discriminant(&SomeStruct); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `SomeStruct`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:32:18 + | +LL | discriminant(&SomeStruct); + | ^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:35:5 + | +LL | discriminant(&123u32); + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `u32`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:35:18 + | +LL | discriminant(&123u32); + | ^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:38:5 + | +LL | discriminant(&&123i8); + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `&i8`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:38:18 + | +LL | discriminant(&&123i8); + | ^^^^^^^ + +error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:46:5 + | +LL | variant_count::<&str>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `&str`, which is not an enum. + +error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:49:5 + | +LL | variant_count::<*const u8>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `*const u8`, which is not an enum. + +error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:52:5 + | +LL | variant_count::<()>(); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `()`, which is not an enum. + +error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:55:5 + | +LL | variant_count::<&SomeEnum>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `&SomeEnum`, which is not an enum. + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr b/tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr new file mode 100644 index 000000000..3a84c6c1f --- /dev/null +++ b/tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr @@ -0,0 +1,152 @@ +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:18:20 + | +LL | const N: i32 = T::N << 42; + | ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/lint-exceeding-bitshifts.rs:10:9 + | +LL | #![warn(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:22:13 + | +LL | let _ = x << 42; + | ^^^^^^^ attempt to shift left by `42_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:27:15 + | +LL | let n = 1u8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:29:15 + | +LL | let n = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:31:15 + | +LL | let n = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:33:15 + | +LL | let n = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:35:15 + | +LL | let n = 1i8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:37:15 + | +LL | let n = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:39:15 + | +LL | let n = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:41:15 + | +LL | let n = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:44:15 + | +LL | let n = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:46:15 + | +LL | let n = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:48:15 + | +LL | let n = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:50:15 + | +LL | let n = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:52:15 + | +LL | let n = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:54:15 + | +LL | let n = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:56:15 + | +LL | let n = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:58:15 + | +LL | let n = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:62:15 + | +LL | let n = n << 8; + | ^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:64:15 + | +LL | let n = 1u8 << -8; + | ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:69:15 + | +LL | let n = 1u8 << (4+4); + | ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:71:15 + | +LL | let n = 1i64 >> [64][0]; + | ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:77:15 + | +LL | let n = 1_isize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:78:15 + | +LL | let n = 1_usize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +warning: 24 warnings emitted + diff --git a/tests/ui/lint/lint-exceeding-bitshifts.opt.stderr b/tests/ui/lint/lint-exceeding-bitshifts.opt.stderr new file mode 100644 index 000000000..3a84c6c1f --- /dev/null +++ b/tests/ui/lint/lint-exceeding-bitshifts.opt.stderr @@ -0,0 +1,152 @@ +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:18:20 + | +LL | const N: i32 = T::N << 42; + | ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/lint-exceeding-bitshifts.rs:10:9 + | +LL | #![warn(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:22:13 + | +LL | let _ = x << 42; + | ^^^^^^^ attempt to shift left by `42_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:27:15 + | +LL | let n = 1u8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:29:15 + | +LL | let n = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:31:15 + | +LL | let n = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:33:15 + | +LL | let n = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:35:15 + | +LL | let n = 1i8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:37:15 + | +LL | let n = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:39:15 + | +LL | let n = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:41:15 + | +LL | let n = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:44:15 + | +LL | let n = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:46:15 + | +LL | let n = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:48:15 + | +LL | let n = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:50:15 + | +LL | let n = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:52:15 + | +LL | let n = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:54:15 + | +LL | let n = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:56:15 + | +LL | let n = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:58:15 + | +LL | let n = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:62:15 + | +LL | let n = n << 8; + | ^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:64:15 + | +LL | let n = 1u8 << -8; + | ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:69:15 + | +LL | let n = 1u8 << (4+4); + | ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:71:15 + | +LL | let n = 1i64 >> [64][0]; + | ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:77:15 + | +LL | let n = 1_isize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:78:15 + | +LL | let n = 1_usize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +warning: 24 warnings emitted + diff --git a/tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr b/tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr new file mode 100644 index 000000000..3a84c6c1f --- /dev/null +++ b/tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr @@ -0,0 +1,152 @@ +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:18:20 + | +LL | const N: i32 = T::N << 42; + | ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/lint-exceeding-bitshifts.rs:10:9 + | +LL | #![warn(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:22:13 + | +LL | let _ = x << 42; + | ^^^^^^^ attempt to shift left by `42_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:27:15 + | +LL | let n = 1u8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:29:15 + | +LL | let n = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:31:15 + | +LL | let n = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:33:15 + | +LL | let n = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:35:15 + | +LL | let n = 1i8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:37:15 + | +LL | let n = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:39:15 + | +LL | let n = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:41:15 + | +LL | let n = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:44:15 + | +LL | let n = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:46:15 + | +LL | let n = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:48:15 + | +LL | let n = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:50:15 + | +LL | let n = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:52:15 + | +LL | let n = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:54:15 + | +LL | let n = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:56:15 + | +LL | let n = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:58:15 + | +LL | let n = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:62:15 + | +LL | let n = n << 8; + | ^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:64:15 + | +LL | let n = 1u8 << -8; + | ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:69:15 + | +LL | let n = 1u8 << (4+4); + | ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:71:15 + | +LL | let n = 1i64 >> [64][0]; + | ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:77:15 + | +LL | let n = 1_isize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:78:15 + | +LL | let n = 1_usize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +warning: 24 warnings emitted + diff --git a/tests/ui/lint/lint-exceeding-bitshifts.rs b/tests/ui/lint/lint-exceeding-bitshifts.rs new file mode 100644 index 000000000..048c1aff8 --- /dev/null +++ b/tests/ui/lint/lint-exceeding-bitshifts.rs @@ -0,0 +1,79 @@ +// revisions: noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O +// build-pass +// ignore-pass (test emits codegen-time warnings and verifies that they are not errors) +// normalize-stderr-test "shift left by `(64|32)_usize`, which" -> "shift left by `%BITS%`, which" + +#![crate_type="lib"] +#![warn(arithmetic_overflow)] + + +pub trait Foo { + const N: i32; +} + +impl<T: Foo> Foo for Vec<T> { + const N: i32 = T::N << 42; //~ WARN: arithmetic operation will overflow +} + +pub fn foo(x: i32) { + let _ = x << 42; //~ WARN: arithmetic operation will overflow +} + +pub fn main() { + let n = 1u8 << 7; + let n = 1u8 << 8; //~ WARN: arithmetic operation will overflow + let n = 1u16 << 15; + let n = 1u16 << 16; //~ WARN: arithmetic operation will overflow + let n = 1u32 << 31; + let n = 1u32 << 32; //~ WARN: arithmetic operation will overflow + let n = 1u64 << 63; + let n = 1u64 << 64; //~ WARN: arithmetic operation will overflow + let n = 1i8 << 7; + let n = 1i8 << 8; //~ WARN: arithmetic operation will overflow + let n = 1i16 << 15; + let n = 1i16 << 16; //~ WARN: arithmetic operation will overflow + let n = 1i32 << 31; + let n = 1i32 << 32; //~ WARN: arithmetic operation will overflow + let n = 1i64 << 63; + let n = 1i64 << 64; //~ WARN: arithmetic operation will overflow + + let n = 1u8 >> 7; + let n = 1u8 >> 8; //~ WARN: arithmetic operation will overflow + let n = 1u16 >> 15; + let n = 1u16 >> 16; //~ WARN: arithmetic operation will overflow + let n = 1u32 >> 31; + let n = 1u32 >> 32; //~ WARN: arithmetic operation will overflow + let n = 1u64 >> 63; + let n = 1u64 >> 64; //~ WARN: arithmetic operation will overflow + let n = 1i8 >> 7; + let n = 1i8 >> 8; //~ WARN: arithmetic operation will overflow + let n = 1i16 >> 15; + let n = 1i16 >> 16; //~ WARN: arithmetic operation will overflow + let n = 1i32 >> 31; + let n = 1i32 >> 32; //~ WARN: arithmetic operation will overflow + let n = 1i64 >> 63; + let n = 1i64 >> 64; //~ WARN: arithmetic operation will overflow + + let n = 1u8; + let n = n << 7; + let n = n << 8; //~ WARN: arithmetic operation will overflow + + let n = 1u8 << -8; //~ WARN: arithmetic operation will overflow + + let n = 1i8<<(1isize+-1); + + let n = 1u8 << (4+3); + let n = 1u8 << (4+4); //~ WARN: arithmetic operation will overflow + let n = 1i64 >> [63][0]; + let n = 1i64 >> [64][0]; //~ WARN: arithmetic operation will overflow + + #[cfg(target_pointer_width = "32")] + const BITS: usize = 32; + #[cfg(target_pointer_width = "64")] + const BITS: usize = 64; + let n = 1_isize << BITS; //~ WARN: arithmetic operation will overflow + let n = 1_usize << BITS; //~ WARN: arithmetic operation will overflow +} diff --git a/tests/ui/lint/lint-expr-stmt-attrs-for-early-lints.rs b/tests/ui/lint/lint-expr-stmt-attrs-for-early-lints.rs new file mode 100644 index 000000000..07a32904a --- /dev/null +++ b/tests/ui/lint/lint-expr-stmt-attrs-for-early-lints.rs @@ -0,0 +1,14 @@ +// run-pass + +#![feature(stmt_expr_attributes)] +#![deny(unused_parens)] + +// Tests that lint attributes on statements/expressions are +// correctly applied to non-builtin early (AST) lints + +fn main() { + #[allow(unused_parens)] + { + let _ = (9); + } +} diff --git a/tests/ui/lint/lint-ffi-safety-all-phantom.rs b/tests/ui/lint/lint-ffi-safety-all-phantom.rs new file mode 100644 index 000000000..7419d3458 --- /dev/null +++ b/tests/ui/lint/lint-ffi-safety-all-phantom.rs @@ -0,0 +1,22 @@ +// This is a regression test for issue https://github.com/rust-lang/rust/issues/106629. +// It ensures that transparent types where all fields are PhantomData are marked as +// FFI-safe. + +// check-pass + +#[repr(transparent)] +#[derive(Copy, Clone)] +struct MyPhantom(core::marker::PhantomData<u8>); + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Bar { + pub x: i32, + _marker: MyPhantom, +} + +extern "C" { + pub fn foo(bar: *mut Bar); +} + +fn main() {} diff --git a/tests/ui/lint/lint-forbid-attr.rs b/tests/ui/lint/lint-forbid-attr.rs new file mode 100644 index 000000000..6d4cfd834 --- /dev/null +++ b/tests/ui/lint/lint-forbid-attr.rs @@ -0,0 +1,7 @@ +#![forbid(deprecated)] + +#[allow(deprecated)] +//~^ ERROR allow(deprecated) incompatible +//~| ERROR allow(deprecated) incompatible +fn main() { +} diff --git a/tests/ui/lint/lint-forbid-attr.stderr b/tests/ui/lint/lint-forbid-attr.stderr new file mode 100644 index 000000000..5977b9c94 --- /dev/null +++ b/tests/ui/lint/lint-forbid-attr.stderr @@ -0,0 +1,21 @@ +error[E0453]: allow(deprecated) incompatible with previous forbid + --> $DIR/lint-forbid-attr.rs:3:9 + | +LL | #![forbid(deprecated)] + | ---------- `forbid` level set here +LL | +LL | #[allow(deprecated)] + | ^^^^^^^^^^ overruled by previous forbid + +error[E0453]: allow(deprecated) incompatible with previous forbid + --> $DIR/lint-forbid-attr.rs:3:9 + | +LL | #![forbid(deprecated)] + | ---------- `forbid` level set here +LL | +LL | #[allow(deprecated)] + | ^^^^^^^^^^ overruled by previous forbid + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/lint-forbid-cmdline.rs b/tests/ui/lint/lint-forbid-cmdline.rs new file mode 100644 index 000000000..5246ccb57 --- /dev/null +++ b/tests/ui/lint/lint-forbid-cmdline.rs @@ -0,0 +1,6 @@ +// compile-flags: -F deprecated + +#[allow(deprecated)] //~ ERROR allow(deprecated) incompatible + //~| ERROR allow(deprecated) incompatible +fn main() { +} diff --git a/tests/ui/lint/lint-forbid-cmdline.stderr b/tests/ui/lint/lint-forbid-cmdline.stderr new file mode 100644 index 000000000..0a92e58c0 --- /dev/null +++ b/tests/ui/lint/lint-forbid-cmdline.stderr @@ -0,0 +1,19 @@ +error[E0453]: allow(deprecated) incompatible with previous forbid + --> $DIR/lint-forbid-cmdline.rs:3:9 + | +LL | #[allow(deprecated)] + | ^^^^^^^^^^ overruled by previous forbid + | + = note: `forbid` lint level was set on command line + +error[E0453]: allow(deprecated) incompatible with previous forbid + --> $DIR/lint-forbid-cmdline.rs:3:9 + | +LL | #[allow(deprecated)] + | ^^^^^^^^^^ overruled by previous forbid + | + = note: `forbid` lint level was set on command line + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/lint-forbid-internal-unsafe.rs b/tests/ui/lint/lint-forbid-internal-unsafe.rs new file mode 100644 index 000000000..3ee55ba96 --- /dev/null +++ b/tests/ui/lint/lint-forbid-internal-unsafe.rs @@ -0,0 +1,17 @@ +#![forbid(unsafe_code)] +#![feature(allow_internal_unsafe)] + +#[allow_internal_unsafe] +//~^ ERROR: `allow_internal_unsafe` allows defining +macro_rules! evil { + ($e:expr) => { + unsafe { + $e + } + } +} + +fn main() { + println!("{}", evil!(*(0 as *const u8))); + //~^ WARNING dereferencing a null pointer +} diff --git a/tests/ui/lint/lint-forbid-internal-unsafe.stderr b/tests/ui/lint/lint-forbid-internal-unsafe.stderr new file mode 100644 index 000000000..ba425ceb4 --- /dev/null +++ b/tests/ui/lint/lint-forbid-internal-unsafe.stderr @@ -0,0 +1,22 @@ +error: `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site + --> $DIR/lint-forbid-internal-unsafe.rs:4:1 + | +LL | #[allow_internal_unsafe] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-forbid-internal-unsafe.rs:1:11 + | +LL | #![forbid(unsafe_code)] + | ^^^^^^^^^^^ + +warning: dereferencing a null pointer + --> $DIR/lint-forbid-internal-unsafe.rs:15:26 + | +LL | println!("{}", evil!(*(0 as *const u8))); + | ^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + | + = note: `#[warn(deref_nullptr)]` on by default + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/lint/lint-group-nonstandard-style.rs b/tests/ui/lint/lint-group-nonstandard-style.rs new file mode 100644 index 000000000..bd7f327bc --- /dev/null +++ b/tests/ui/lint/lint-group-nonstandard-style.rs @@ -0,0 +1,26 @@ +#![deny(nonstandard_style)] +#![allow(dead_code)] + +fn CamelCase() {} //~ ERROR should have a snake + +#[allow(nonstandard_style)] +mod test { + fn CamelCase() {} + + #[forbid(nonstandard_style)] + mod bad { + fn CamelCase() {} //~ ERROR should have a snake + + static bad: isize = 1; //~ ERROR should have an upper + } + + mod warn { + #![warn(nonstandard_style)] + + fn CamelCase() {} //~ WARN should have a snake + + struct snake_case; //~ WARN should have an upper camel + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-group-nonstandard-style.stderr b/tests/ui/lint/lint-group-nonstandard-style.stderr new file mode 100644 index 000000000..fcd010123 --- /dev/null +++ b/tests/ui/lint/lint-group-nonstandard-style.stderr @@ -0,0 +1,57 @@ +warning: type `snake_case` should have an upper camel case name + --> $DIR/lint-group-nonstandard-style.rs:22:16 + | +LL | struct snake_case; + | ^^^^^^^^^^ help: convert the identifier to upper camel case: `SnakeCase` + | +note: the lint level is defined here + --> $DIR/lint-group-nonstandard-style.rs:18:17 + | +LL | #![warn(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ + = note: `#[warn(non_camel_case_types)]` implied by `#[warn(nonstandard_style)]` + +error: function `CamelCase` should have a snake case name + --> $DIR/lint-group-nonstandard-style.rs:4:4 + | +LL | fn CamelCase() {} + | ^^^^^^^^^ help: convert the identifier to snake case: `camel_case` + | +note: the lint level is defined here + --> $DIR/lint-group-nonstandard-style.rs:1:9 + | +LL | #![deny(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ + = note: `#[deny(non_snake_case)]` implied by `#[deny(nonstandard_style)]` + +error: function `CamelCase` should have a snake case name + --> $DIR/lint-group-nonstandard-style.rs:12:12 + | +LL | fn CamelCase() {} + | ^^^^^^^^^ help: convert the identifier to snake case: `camel_case` + | +note: the lint level is defined here + --> $DIR/lint-group-nonstandard-style.rs:10:14 + | +LL | #[forbid(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ + = note: `#[forbid(non_snake_case)]` implied by `#[forbid(nonstandard_style)]` + +error: static variable `bad` should have an upper case name + --> $DIR/lint-group-nonstandard-style.rs:14:16 + | +LL | static bad: isize = 1; + | ^^^ help: convert the identifier to upper case: `BAD` + | + = note: `#[forbid(non_upper_case_globals)]` implied by `#[forbid(nonstandard_style)]` + +warning: function `CamelCase` should have a snake case name + --> $DIR/lint-group-nonstandard-style.rs:20:12 + | +LL | fn CamelCase() {} + | ^^^^^^^^^ help: convert the identifier to snake case: `camel_case` + | + = note: `#[warn(non_snake_case)]` implied by `#[warn(nonstandard_style)]` + +error: aborting due to 3 previous errors; 2 warnings emitted + diff --git a/tests/ui/lint/lint-impl-fn.rs b/tests/ui/lint/lint-impl-fn.rs new file mode 100644 index 000000000..46874d95c --- /dev/null +++ b/tests/ui/lint/lint-impl-fn.rs @@ -0,0 +1,33 @@ +#![allow(while_true)] +#![allow(dead_code)] + +struct A(isize); + +impl A { + fn foo(&self) { while true {} } + + #[deny(while_true)] + fn bar(&self) { while true {} } //~ ERROR: infinite loops +} + +#[deny(while_true)] +mod foo { + struct B(isize); + + impl B { + fn foo(&self) { while true {} } //~ ERROR: infinite loops + + #[allow(while_true)] + fn bar(&self) { while true {} } + } +} + +#[deny(while_true)] +fn main() { + while true {} //~ ERROR: infinite loops +} + +#[deny(while_true)] +fn bar() { + while cfg!(unix) {} // no error +} diff --git a/tests/ui/lint/lint-impl-fn.stderr b/tests/ui/lint/lint-impl-fn.stderr new file mode 100644 index 000000000..24ec9c7e4 --- /dev/null +++ b/tests/ui/lint/lint-impl-fn.stderr @@ -0,0 +1,38 @@ +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-impl-fn.rs:10:21 + | +LL | fn bar(&self) { while true {} } + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-impl-fn.rs:9:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-impl-fn.rs:18:25 + | +LL | fn foo(&self) { while true {} } + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-impl-fn.rs:13:8 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-impl-fn.rs:27:5 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-impl-fn.rs:25:8 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/lint-incoherent-auto-trait-objects.rs b/tests/ui/lint/lint-incoherent-auto-trait-objects.rs new file mode 100644 index 000000000..d53b51447 --- /dev/null +++ b/tests/ui/lint/lint-incoherent-auto-trait-objects.rs @@ -0,0 +1,19 @@ +trait Foo {} + +impl Foo for dyn Send {} + +impl Foo for dyn Send + Send {} +//~^ ERROR conflicting implementations +//~| hard error + +impl Foo for dyn Send + Sync {} + +impl Foo for dyn Sync + Send {} +//~^ ERROR conflicting implementations +//~| hard error + +impl Foo for dyn Send + Sync + Send {} +//~^ ERROR conflicting implementations +//~| hard error + +fn main() {} diff --git a/tests/ui/lint/lint-incoherent-auto-trait-objects.stderr b/tests/ui/lint/lint-incoherent-auto-trait-objects.stderr new file mode 100644 index 000000000..553ab3869 --- /dev/null +++ b/tests/ui/lint/lint-incoherent-auto-trait-objects.stderr @@ -0,0 +1,81 @@ +error: conflicting implementations of trait `Foo` for type `(dyn Send + 'static)`: (E0119) + --> $DIR/lint-incoherent-auto-trait-objects.rs:5:1 + | +LL | impl Foo for dyn Send {} + | --------------------- first implementation here +LL | +LL | impl Foo for dyn Send + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484> + = note: `#[deny(order_dependent_trait_objects)]` on by default + +error: conflicting implementations of trait `Foo` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/lint-incoherent-auto-trait-objects.rs:11:1 + | +LL | impl Foo for dyn Send + Sync {} + | ---------------------------- first implementation here +LL | +LL | impl Foo for dyn Sync + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484> + +error: conflicting implementations of trait `Foo` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/lint-incoherent-auto-trait-objects.rs:15:1 + | +LL | impl Foo for dyn Sync + Send {} + | ---------------------------- first implementation here +... +LL | impl Foo for dyn Send + Sync + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484> + +error: aborting due to 3 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: conflicting implementations of trait `Foo` for type `(dyn Send + 'static)`: (E0119) + --> $DIR/lint-incoherent-auto-trait-objects.rs:5:1 + | +LL | impl Foo for dyn Send {} + | --------------------- first implementation here +LL | +LL | impl Foo for dyn Send + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484> + = note: `#[deny(order_dependent_trait_objects)]` on by default + +Future breakage diagnostic: +error: conflicting implementations of trait `Foo` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/lint-incoherent-auto-trait-objects.rs:11:1 + | +LL | impl Foo for dyn Send + Sync {} + | ---------------------------- first implementation here +LL | +LL | impl Foo for dyn Sync + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484> + = note: `#[deny(order_dependent_trait_objects)]` on by default + +Future breakage diagnostic: +error: conflicting implementations of trait `Foo` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/lint-incoherent-auto-trait-objects.rs:15:1 + | +LL | impl Foo for dyn Sync + Send {} + | ---------------------------- first implementation here +... +LL | impl Foo for dyn Send + Sync + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484> + = note: `#[deny(order_dependent_trait_objects)]` on by default + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-bool.rs b/tests/ui/lint/lint-invalid-atomic-ordering-bool.rs new file mode 100644 index 000000000..15ceb6195 --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-bool.rs @@ -0,0 +1,28 @@ +// only-x86_64 +use std::sync::atomic::{AtomicBool, Ordering}; + +fn main() { + let x = AtomicBool::new(true); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Allowed store ordering modes + x.store(false, Ordering::Release); + x.store(false, Ordering::SeqCst); + x.store(false, Ordering::Relaxed); + + // Disallowed store ordering modes + x.store(false, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(false, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-bool.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-bool.stderr new file mode 100644 index 000000000..9f38dcb0b --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-bool.stderr @@ -0,0 +1,35 @@ +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-bool.rs:13:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-bool.rs:15:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-bool.rs:24:20 + | +LL | x.store(false, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-bool.rs:26:20 + | +LL | x.store(false, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs b/tests/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs new file mode 100644 index 000000000..63204c725 --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs @@ -0,0 +1,50 @@ +// only-x86_64 +use std::sync::atomic::{AtomicPtr, Ordering}; + +fn main() { + let ptr = &mut 5; + let ptr2 = &mut 10; + // `compare_exchange_weak` testing + let x = AtomicPtr::new(ptr); + + // Allowed ordering combos + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Relaxed); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Acquire); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::SeqCst); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Relaxed); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Acquire); + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::SeqCst); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Release, Ordering::Relaxed); + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::Acquire); + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::SeqCst); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Relaxed); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Acquire); + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::SeqCst); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Relaxed); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Acquire); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::SeqCst); + + // AcqRel is always forbidden as a failure ordering + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Relaxed, Ordering::AcqRel); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::AcqRel); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::AcqRel); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::AcqRel); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::SeqCst, Ordering::AcqRel); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + + // Release is always forbidden as a failure ordering + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Release); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Release); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Release, Ordering::Release); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Release); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Release); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr new file mode 100644 index 000000000..cc075ce9e --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr @@ -0,0 +1,83 @@ +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:28:67 + | +LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Relaxed, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:30:67 + | +LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:32:67 + | +LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:34:66 + | +LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:36:66 + | +LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::SeqCst, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:40:67 + | +LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:42:67 + | +LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:44:67 + | +LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Release, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:46:66 + | +LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:48:66 + | +LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: aborting due to 10 previous errors + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-exchange.rs b/tests/ui/lint/lint-invalid-atomic-ordering-exchange.rs new file mode 100644 index 000000000..488d268ee --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-exchange.rs @@ -0,0 +1,48 @@ +// only-x86_64 +use std::sync::atomic::{AtomicUsize, Ordering}; + +fn main() { + // `compare_exchange` (not weak) testing + let x = AtomicUsize::new(0); + + // Allowed ordering combos + let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Relaxed); + let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Acquire); + let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::SeqCst); + let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Relaxed); + let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Acquire); + let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::SeqCst); + let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Relaxed); + let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Acquire); + let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::SeqCst); + let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Relaxed); + let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Acquire); + let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::SeqCst); + let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Relaxed); + let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Acquire); + let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::SeqCst); + + // AcqRel is always forbidden as a failure ordering + let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::AcqRel); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::AcqRel); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::AcqRel); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::AcqRel); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::AcqRel); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + + // Release is always forbidden as a failure ordering + let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Release); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Release); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Release); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Release); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Release); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-exchange.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-exchange.stderr new file mode 100644 index 000000000..fe6c7e55c --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-exchange.stderr @@ -0,0 +1,83 @@ +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:26:57 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:28:57 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:30:57 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:32:56 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:34:56 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:38:57 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:40:57 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:42:57 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:44:56 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:46:56 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: aborting due to 10 previous errors + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-false-positive.rs b/tests/ui/lint/lint-invalid-atomic-ordering-false-positive.rs new file mode 100644 index 000000000..4fb8605b4 --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-false-positive.rs @@ -0,0 +1,18 @@ +// only-x86_64 +// check-pass +use std::sync::atomic::{AtomicUsize, Ordering}; + +trait Foo { + fn store(self, ordering: Ordering); +} + +impl Foo for AtomicUsize { + fn store(self, _ordering: Ordering) { + AtomicUsize::store(&self, 4, Ordering::SeqCst); + } +} + +fn main() { + let x = AtomicUsize::new(3); + x.store(Ordering::Acquire); +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-fence.rs b/tests/ui/lint/lint-invalid-atomic-ordering-fence.rs new file mode 100644 index 000000000..22034472c --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-fence.rs @@ -0,0 +1,21 @@ +// only-x86_64 +use std::sync::atomic::{compiler_fence, fence, Ordering}; + +fn main() { + // Allowed ordering modes + fence(Ordering::Acquire); + fence(Ordering::Release); + fence(Ordering::AcqRel); + fence(Ordering::SeqCst); + + compiler_fence(Ordering::Acquire); + compiler_fence(Ordering::Release); + compiler_fence(Ordering::AcqRel); + compiler_fence(Ordering::SeqCst); + + // Disallowed ordering modes + fence(Ordering::Relaxed); + //~^ ERROR memory fences cannot have `Relaxed` ordering + compiler_fence(Ordering::Relaxed); + //~^ ERROR memory fences cannot have `Relaxed` ordering +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-fence.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-fence.stderr new file mode 100644 index 000000000..38327d607 --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-fence.stderr @@ -0,0 +1,19 @@ +error: memory fences cannot have `Relaxed` ordering + --> $DIR/lint-invalid-atomic-ordering-fence.rs:17:11 + | +LL | fence(Ordering::Relaxed); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst` + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: memory fences cannot have `Relaxed` ordering + --> $DIR/lint-invalid-atomic-ordering-fence.rs:19:20 + | +LL | compiler_fence(Ordering::Relaxed); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs b/tests/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs new file mode 100644 index 000000000..734b63324 --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs @@ -0,0 +1,49 @@ +// only-x86_64 +use std::sync::atomic::{AtomicIsize, Ordering}; + +fn main() { + // `fetch_update` testing + let x = AtomicIsize::new(0); + + // Allowed ordering combos + let _ = x.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Relaxed, Ordering::Acquire, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Relaxed, Ordering::SeqCst, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Acquire, Ordering::Relaxed, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Acquire, Ordering::Acquire, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Acquire, Ordering::SeqCst, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Release, Ordering::Relaxed, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Release, Ordering::Acquire, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Release, Ordering::SeqCst, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::AcqRel, Ordering::Relaxed, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::AcqRel, Ordering::Acquire, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::AcqRel, Ordering::SeqCst, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::SeqCst, Ordering::Acquire, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |old| Some(old + 1)); + + // AcqRel is always forbidden as a failure ordering + let _ = x.fetch_update(Ordering::Relaxed, Ordering::AcqRel, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::Acquire, Ordering::AcqRel, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::Release, Ordering::AcqRel, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::AcqRel, Ordering::AcqRel, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::SeqCst, Ordering::AcqRel, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + + // Release is always forbidden as a failure ordering + let _ = x.fetch_update(Ordering::Relaxed, Ordering::Release, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::Acquire, Ordering::Release, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::Release, Ordering::Release, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::AcqRel, Ordering::Release, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::SeqCst, Ordering::Release, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr new file mode 100644 index 000000000..33829d68f --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr @@ -0,0 +1,83 @@ +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:26:47 + | +LL | let _ = x.fetch_update(Ordering::Relaxed, Ordering::AcqRel, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:28:47 + | +LL | let _ = x.fetch_update(Ordering::Acquire, Ordering::AcqRel, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:30:47 + | +LL | let _ = x.fetch_update(Ordering::Release, Ordering::AcqRel, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:32:46 + | +LL | let _ = x.fetch_update(Ordering::AcqRel, Ordering::AcqRel, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:34:46 + | +LL | let _ = x.fetch_update(Ordering::SeqCst, Ordering::AcqRel, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:38:47 + | +LL | let _ = x.fetch_update(Ordering::Relaxed, Ordering::Release, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:40:47 + | +LL | let _ = x.fetch_update(Ordering::Acquire, Ordering::Release, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:42:47 + | +LL | let _ = x.fetch_update(Ordering::Release, Ordering::Release, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:44:46 + | +LL | let _ = x.fetch_update(Ordering::AcqRel, Ordering::Release, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:46:46 + | +LL | let _ = x.fetch_update(Ordering::SeqCst, Ordering::Release, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: aborting due to 10 previous errors + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-int.rs b/tests/ui/lint/lint-invalid-atomic-ordering-int.rs new file mode 100644 index 000000000..462c9670f --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-int.rs @@ -0,0 +1,130 @@ +// FIXME: add support for `// only-atomic` to compiletest/header.rs +// only-x86_64 +use std::sync::atomic::{AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, Ordering}; + +fn main() { + // `AtomicI8` test cases + let x = AtomicI8::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicI16` test cases + let x = AtomicI16::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicI32` test cases + let x = AtomicI32::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicI64` test cases + let x = AtomicI64::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicIsize` test cases + let x = AtomicIsize::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-int.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-int.stderr new file mode 100644 index 000000000..36930e2f4 --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-int.stderr @@ -0,0 +1,163 @@ +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:20:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:22:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:26:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:28:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:45:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:47:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:51:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:53:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:70:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:72:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:76:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:78:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:95:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:97:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:101:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:103:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:120:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:122:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:126:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:128:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: aborting due to 20 previous errors + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-ptr.rs b/tests/ui/lint/lint-invalid-atomic-ordering-ptr.rs new file mode 100644 index 000000000..984f7edeb --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-ptr.rs @@ -0,0 +1,30 @@ +// only-x86_64 +use std::sync::atomic::{AtomicPtr, Ordering}; + +fn main() { + let ptr = &mut 5; + let other_ptr = &mut 10; + let x = AtomicPtr::new(ptr); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Allowed store ordering modes + x.store(other_ptr, Ordering::Release); + x.store(other_ptr, Ordering::SeqCst); + x.store(other_ptr, Ordering::Relaxed); + + // Disallowed store ordering modes + x.store(other_ptr, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(other_ptr, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-ptr.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-ptr.stderr new file mode 100644 index 000000000..12f4cad90 --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-ptr.stderr @@ -0,0 +1,35 @@ +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-ptr.rs:15:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-ptr.rs:17:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-ptr.rs:26:24 + | +LL | x.store(other_ptr, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-ptr.rs:28:24 + | +LL | x.store(other_ptr, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-uint.rs b/tests/ui/lint/lint-invalid-atomic-ordering-uint.rs new file mode 100644 index 000000000..80ec3b9ee --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-uint.rs @@ -0,0 +1,129 @@ +// only-x86_64 +use std::sync::atomic::{AtomicU16, AtomicU32, AtomicU64, AtomicU8, AtomicUsize, Ordering}; + +fn main() { + // `AtomicU8` test cases + let x = AtomicU8::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicU16` test cases + let x = AtomicU16::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicU32` test cases + let x = AtomicU32::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicU64` test cases + let x = AtomicU64::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicUsize` test cases + let x = AtomicUsize::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-uint.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-uint.stderr new file mode 100644 index 000000000..d26621f2a --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-uint.stderr @@ -0,0 +1,163 @@ +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:19:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:21:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:25:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:27:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:44:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:46:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:50:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:52:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:69:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:71:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:75:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:77:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:94:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:96:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:100:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:102:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:119:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:121:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:125:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:127:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: aborting due to 20 previous errors + diff --git a/tests/ui/lint/lint-level-macro-def-mod.rs b/tests/ui/lint/lint-level-macro-def-mod.rs new file mode 100644 index 000000000..79f7d1206 --- /dev/null +++ b/tests/ui/lint/lint-level-macro-def-mod.rs @@ -0,0 +1,17 @@ +// This checks that exported macros lint as part of their module of origin, not +// the root module. +// +// check-pass + +//! Top level documentation +#![deny(missing_docs)] + +#[allow(missing_docs)] +mod module { + #[macro_export] + macro_rules! hello { + () => () + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-level-macro-def.rs b/tests/ui/lint/lint-level-macro-def.rs new file mode 100644 index 000000000..720f4b453 --- /dev/null +++ b/tests/ui/lint/lint-level-macro-def.rs @@ -0,0 +1,17 @@ +// Checks that you can set a lint level specficially for a macro definition. +// +// This is a regression test for issue #59306. +// +// check-pass + + +#[deny(missing_docs)] +mod module { + #[allow(missing_docs)] + #[macro_export] + macro_rules! hello { + () => () + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-lowercase-static-const-pattern-rename.rs b/tests/ui/lint/lint-lowercase-static-const-pattern-rename.rs new file mode 100644 index 000000000..d085db43a --- /dev/null +++ b/tests/ui/lint/lint-lowercase-static-const-pattern-rename.rs @@ -0,0 +1,63 @@ +// check-pass +// Issue #7526: lowercase static constants in patterns look like bindings + +// This is similar to lint-lowercase-static-const-pattern.rs, except it +// shows the expected usual workaround (choosing a different name for +// the static definition) and also demonstrates that one can work +// around this problem locally by renaming the constant in the `use` +// form to an uppercase identifier that placates the lint. + +#![deny(non_upper_case_globals)] + +pub const A : isize = 97; + +fn f() { + let r = match (0,0) { + (0, A) => 0, + (x, y) => 1 + x + y, + }; + assert_eq!(r, 1); + let r = match (0,97) { + (0, A) => 0, + (x, y) => 1 + x + y, + }; + assert_eq!(r, 0); +} + +mod m { + #[allow(non_upper_case_globals)] + pub const aha : isize = 7; +} + +fn g() { + use self::m::aha as AHA; + let r = match (0,0) { + (0, AHA) => 0, + (x, y) => 1 + x + y, + }; + assert_eq!(r, 1); + let r = match (0,7) { + (0, AHA) => 0, + (x, y) => 1 + x + y, + }; + assert_eq!(r, 0); +} + +fn h() { + let r = match (0,0) { + (0, self::m::aha) => 0, + (x, y) => 1 + x + y, + }; + assert_eq!(r, 1); + let r = match (0,7) { + (0, self::m::aha) => 0, + (x, y) => 1 + x + y, + }; + assert_eq!(r, 0); +} + +pub fn main () { + f(); + g(); + h(); +} diff --git a/tests/ui/lint/lint-lowercase-static-const-pattern.rs b/tests/ui/lint/lint-lowercase-static-const-pattern.rs new file mode 100644 index 000000000..c2e159eec --- /dev/null +++ b/tests/ui/lint/lint-lowercase-static-const-pattern.rs @@ -0,0 +1,51 @@ +// Issue #7526: lowercase static constants in patterns look like bindings + +#![allow(dead_code)] +#![deny(non_upper_case_globals)] + +#[allow(non_upper_case_globals)] +pub const a : isize = 97; + +fn f() { + let r = match (0,0) { + (0, a) => 0, + //~^ ERROR constant in pattern `a` should have an upper case name + (x, y) => 1 + x + y, + }; + assert_eq!(r, 1); +} + +mod m { + #[allow(non_upper_case_globals)] + pub const aha : isize = 7; +} + +fn g() { + use self::m::aha; + let r = match (0,0) { + (0, aha) => 0, + //~^ ERROR constant in pattern `aha` should have an upper case name + (x, y) => 1 + x + y, + }; + assert_eq!(r, 1); +} + +mod n { + pub const OKAY : isize = 8; +} + +fn h() { + use self::n::OKAY as not_okay; + let r = match (0,0) { + (0, not_okay) => 0, +//~^ ERROR constant in pattern `not_okay` should have an upper case name + (x, y) => 1 + x + y, + }; + assert_eq!(r, 1); +} + +fn main () { + f(); + g(); + h(); +} diff --git a/tests/ui/lint/lint-lowercase-static-const-pattern.stderr b/tests/ui/lint/lint-lowercase-static-const-pattern.stderr new file mode 100644 index 000000000..8780fac05 --- /dev/null +++ b/tests/ui/lint/lint-lowercase-static-const-pattern.stderr @@ -0,0 +1,26 @@ +error: constant in pattern `a` should have an upper case name + --> $DIR/lint-lowercase-static-const-pattern.rs:11:13 + | +LL | (0, a) => 0, + | ^ help: convert the identifier to upper case: `A` + | +note: the lint level is defined here + --> $DIR/lint-lowercase-static-const-pattern.rs:4:9 + | +LL | #![deny(non_upper_case_globals)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: constant in pattern `aha` should have an upper case name + --> $DIR/lint-lowercase-static-const-pattern.rs:26:13 + | +LL | (0, aha) => 0, + | ^^^ help: convert the identifier to upper case: `AHA` + +error: constant in pattern `not_okay` should have an upper case name + --> $DIR/lint-lowercase-static-const-pattern.rs:40:13 + | +LL | (0, not_okay) => 0, + | ^^^^^^^^ help: convert the identifier to upper case: `NOT_OKAY` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/lint-malformed.rs b/tests/ui/lint/lint-malformed.rs new file mode 100644 index 000000000..188e702f9 --- /dev/null +++ b/tests/ui/lint/lint-malformed.rs @@ -0,0 +1,6 @@ +#![deny = "foo"] //~ ERROR malformed `deny` attribute input +#![allow(bar = "baz")] //~ ERROR malformed lint attribute + //~| ERROR malformed lint attribute + //~| ERROR malformed lint attribute + //~| ERROR malformed lint attribute +fn main() { } diff --git a/tests/ui/lint/lint-malformed.stderr b/tests/ui/lint/lint-malformed.stderr new file mode 100644 index 000000000..91b4e509b --- /dev/null +++ b/tests/ui/lint/lint-malformed.stderr @@ -0,0 +1,33 @@ +error[E0452]: malformed lint attribute input + --> $DIR/lint-malformed.rs:2:10 + | +LL | #![allow(bar = "baz")] + | ^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/lint-malformed.rs:2:10 + | +LL | #![allow(bar = "baz")] + | ^^^^^^^^^^^ bad attribute argument + +error: malformed `deny` attribute input + --> $DIR/lint-malformed.rs:1:1 + | +LL | #![deny = "foo"] + | ^^^^^^^^^^^^^^^^ help: must be of the form: `#![deny(lint1, lint2, ..., /*opt*/ reason = "...")]` + +error[E0452]: malformed lint attribute input + --> $DIR/lint-malformed.rs:2:10 + | +LL | #![allow(bar = "baz")] + | ^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/lint-malformed.rs:2:10 + | +LL | #![allow(bar = "baz")] + | ^^^^^^^^^^^ bad attribute argument + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/lint/lint-match-arms.rs b/tests/ui/lint/lint-match-arms.rs new file mode 100644 index 000000000..5c2ccc60e --- /dev/null +++ b/tests/ui/lint/lint-match-arms.rs @@ -0,0 +1,18 @@ +fn deny_on_arm() { + match 0 { + #[deny(unused_variables)] + //~^ NOTE the lint level is defined here + y => (), + //~^ ERROR unused variable + } +} + +#[deny(unused_variables)] +fn allow_on_arm() { + match 0 { + #[allow(unused_variables)] + y => (), // OK + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-match-arms.stderr b/tests/ui/lint/lint-match-arms.stderr new file mode 100644 index 000000000..1bc0e41fd --- /dev/null +++ b/tests/ui/lint/lint-match-arms.stderr @@ -0,0 +1,14 @@ +error: unused variable: `y` + --> $DIR/lint-match-arms.rs:5:9 + | +LL | y => (), + | ^ help: if this is intentional, prefix it with an underscore: `_y` + | +note: the lint level is defined here + --> $DIR/lint-match-arms.rs:3:16 + | +LL | #[deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-misplaced-attr.rs b/tests/ui/lint/lint-misplaced-attr.rs new file mode 100644 index 000000000..d06917ea3 --- /dev/null +++ b/tests/ui/lint/lint-misplaced-attr.rs @@ -0,0 +1,10 @@ +// When denying at the crate level, be sure to not get random warnings from the +// injected intrinsics by the compiler. + +#![deny(unused_attributes)] + +mod a { + #![crate_type = "bin"] //~ ERROR should be in the root module +} + +#[crate_type = "bin"] fn main() {} //~ ERROR should be an inner diff --git a/tests/ui/lint/lint-misplaced-attr.stderr b/tests/ui/lint/lint-misplaced-attr.stderr new file mode 100644 index 000000000..abaf4620e --- /dev/null +++ b/tests/ui/lint/lint-misplaced-attr.stderr @@ -0,0 +1,20 @@ +error: crate-level attribute should be in the root module + --> $DIR/lint-misplaced-attr.rs:7:5 + | +LL | #![crate_type = "bin"] + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-misplaced-attr.rs:4:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/lint-misplaced-attr.rs:10:1 + | +LL | #[crate_type = "bin"] fn main() {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/lint-missing-copy-implementations-allow.rs b/tests/ui/lint/lint-missing-copy-implementations-allow.rs new file mode 100644 index 000000000..051a905ae --- /dev/null +++ b/tests/ui/lint/lint-missing-copy-implementations-allow.rs @@ -0,0 +1,35 @@ +// check-pass +#![deny(missing_copy_implementations)] + +// Don't recommend implementing Copy on something stateful like an iterator. +pub struct MyIterator { + num: u8, +} + +impl Iterator for MyIterator { + type Item = u8; + + fn next(&mut self) -> Option<Self::Item> { + todo!() + } +} + +pub struct Handle { + inner: *mut (), +} + +pub struct Handle2 { + inner: *const (), +} + +pub enum MaybeHandle { + Ptr(*mut ()), +} + +pub union UnionHandle { + ptr: *mut (), +} + +pub struct Array([u8; 2048]); + +fn main() {} diff --git a/tests/ui/lint/lint-missing-copy-implementations.rs b/tests/ui/lint/lint-missing-copy-implementations.rs new file mode 100644 index 000000000..918f40de1 --- /dev/null +++ b/tests/ui/lint/lint-missing-copy-implementations.rs @@ -0,0 +1,15 @@ +// See issue 19712 + +#![deny(missing_copy_implementations)] + +mod inner { + pub struct Foo { //~ ERROR type could implement `Copy`; consider adding `impl Copy` + pub field: i32 + } +} + +pub fn foo() -> inner::Foo { + inner::Foo { field: 42 } +} + +fn main() {} diff --git a/tests/ui/lint/lint-missing-copy-implementations.stderr b/tests/ui/lint/lint-missing-copy-implementations.stderr new file mode 100644 index 000000000..e5f5ce20d --- /dev/null +++ b/tests/ui/lint/lint-missing-copy-implementations.stderr @@ -0,0 +1,16 @@ +error: type could implement `Copy`; consider adding `impl Copy` + --> $DIR/lint-missing-copy-implementations.rs:6:5 + | +LL | / pub struct Foo { +LL | | pub field: i32 +LL | | } + | |_____^ + | +note: the lint level is defined here + --> $DIR/lint-missing-copy-implementations.rs:3:9 + | +LL | #![deny(missing_copy_implementations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-missing-doc.rs b/tests/ui/lint/lint-missing-doc.rs new file mode 100644 index 000000000..229725791 --- /dev/null +++ b/tests/ui/lint/lint-missing-doc.rs @@ -0,0 +1,203 @@ +// When denying at the crate level, be sure to not get random warnings from the +// injected intrinsics by the compiler. +#![deny(missing_docs)] +#![allow(dead_code)] +#![feature(associated_type_defaults, extern_types)] + +//! Some garbage docs for the crate here +#![doc="More garbage"] + +type Typedef = String; +pub type PubTypedef = String; //~ ERROR: missing documentation for a type alias + +struct Foo { + a: isize, + b: isize, +} + +pub struct PubFoo { //~ ERROR: missing documentation for a struct + pub a: isize, //~ ERROR: missing documentation for a struct field + b: isize, +} + +#[allow(missing_docs)] +pub struct PubFoo2 { + pub a: isize, + pub c: isize, +} + +mod module_no_dox {} +pub mod pub_module_no_dox {} //~ ERROR: missing documentation for a module + +/// dox +pub fn foo() {} +pub fn foo2() {} //~ ERROR: missing documentation for a function +fn foo3() {} +#[allow(missing_docs)] pub fn foo4() {} + +/// dox +pub trait A { + /// dox + fn foo(&self); + /// dox + fn foo_with_impl(&self) {} +} + +#[allow(missing_docs)] +trait B { + fn foo(&self); + fn foo_with_impl(&self) {} +} + +pub trait C { //~ ERROR: missing documentation for a trait + fn foo(&self); //~ ERROR: missing documentation for an associated function + fn foo_with_impl(&self) {} //~ ERROR: missing documentation for an associated function +} + +#[allow(missing_docs)] +pub trait D { + fn dummy(&self) { } +} + +/// dox +pub trait E: Sized { + type AssociatedType; //~ ERROR: missing documentation for an associated type + type AssociatedTypeDef = Self; //~ ERROR: missing documentation for an associated type + + /// dox + type DocumentedType; + /// dox + type DocumentedTypeDef = Self; + /// dox + fn dummy(&self) {} +} + +impl Foo { + pub fn foo() {} + fn bar() {} +} + +impl PubFoo { + pub fn foo() {} //~ ERROR: missing documentation for an associated function + /// dox + pub fn foo1() {} + fn foo2() {} + #[allow(missing_docs)] pub fn foo3() {} +} + +#[allow(missing_docs)] +trait F { + fn a(); + fn b(&self); +} + +// should need to redefine documentation for implementations of traits +impl F for Foo { + fn a() {} + fn b(&self) {} +} + +// It sure is nice if doc(hidden) implies allow(missing_docs), and that it +// applies recursively +#[doc(hidden)] +mod a { + pub fn baz() {} + pub mod b { + pub fn baz() {} + } +} + +enum Baz { + BazA { + a: isize, + b: isize + }, + BarB +} + +pub enum PubBaz { //~ ERROR: missing documentation for an enum + PubBazA { //~ ERROR: missing documentation for a variant + a: isize, //~ ERROR: missing documentation for a struct field + }, +} + +/// dox +pub enum PubBaz2 { + /// dox + PubBaz2A { + /// dox + a: isize, + }, +} + +#[allow(missing_docs)] +pub enum PubBaz3 { + PubBaz3A { + b: isize + }, +} + +#[doc(hidden)] +pub fn baz() {} + + +const FOO: u32 = 0; +/// dox +pub const FOO1: u32 = 0; +#[allow(missing_docs)] +pub const FOO2: u32 = 0; +#[doc(hidden)] +pub const FOO3: u32 = 0; +pub const FOO4: u32 = 0; //~ ERROR: missing documentation for a const + + +static BAR: u32 = 0; +/// dox +pub static BAR1: u32 = 0; +#[allow(missing_docs)] +pub static BAR2: u32 = 0; +#[doc(hidden)] +pub static BAR3: u32 = 0; +pub static BAR4: u32 = 0; //~ ERROR: missing documentation for a static + + +mod internal_impl { + /// dox + pub fn documented() {} + pub fn undocumented1() {} //~ ERROR: missing documentation for a function + pub fn undocumented2() {} //~ ERROR: missing documentation for a function + fn undocumented3() {} + /// dox + pub mod globbed { + /// dox + pub fn also_documented() {} + pub fn also_undocumented1() {} //~ ERROR: missing documentation for a function + fn also_undocumented2() {} + } +} +/// dox +pub mod public_interface { + pub use internal_impl::documented as foo; + pub use internal_impl::undocumented1 as bar; + pub use internal_impl::{documented, undocumented2}; + pub use internal_impl::globbed::*; +} + +extern "C" { + /// dox + pub fn extern_fn_documented(f: f32) -> f32; + pub fn extern_fn_undocumented(f: f32) -> f32; + //~^ ERROR: missing documentation for a function + + /// dox + pub static EXTERN_STATIC_DOCUMENTED: u8; + pub static EXTERN_STATIC_UNDOCUMENTED: u8; + //~^ ERROR: missing documentation for a static + + /// dox + pub type ExternTyDocumented; + pub type ExternTyUndocumented; + //~^ ERROR: missing documentation for a foreign type +} + +fn main() {} diff --git a/tests/ui/lint/lint-missing-doc.stderr b/tests/ui/lint/lint-missing-doc.stderr new file mode 100644 index 000000000..d68472d4b --- /dev/null +++ b/tests/ui/lint/lint-missing-doc.stderr @@ -0,0 +1,140 @@ +error: missing documentation for a type alias + --> $DIR/lint-missing-doc.rs:11:1 + | +LL | pub type PubTypedef = String; + | ^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-missing-doc.rs:3:9 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a struct + --> $DIR/lint-missing-doc.rs:18:1 + | +LL | pub struct PubFoo { + | ^^^^^^^^^^^^^^^^^ + +error: missing documentation for a struct field + --> $DIR/lint-missing-doc.rs:19:5 + | +LL | pub a: isize, + | ^^^^^^^^^^^^ + +error: missing documentation for a module + --> $DIR/lint-missing-doc.rs:30:1 + | +LL | pub mod pub_module_no_dox {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a function + --> $DIR/lint-missing-doc.rs:34:1 + | +LL | pub fn foo2() {} + | ^^^^^^^^^^^^^ + +error: missing documentation for a trait + --> $DIR/lint-missing-doc.rs:52:1 + | +LL | pub trait C { + | ^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-missing-doc.rs:53:5 + | +LL | fn foo(&self); + | ^^^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-missing-doc.rs:54:5 + | +LL | fn foo_with_impl(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for an associated type + --> $DIR/lint-missing-doc.rs:64:5 + | +LL | type AssociatedType; + | ^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for an associated type + --> $DIR/lint-missing-doc.rs:65:5 + | +LL | type AssociatedTypeDef = Self; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-missing-doc.rs:81:5 + | +LL | pub fn foo() {} + | ^^^^^^^^^^^^ + +error: missing documentation for an enum + --> $DIR/lint-missing-doc.rs:118:1 + | +LL | pub enum PubBaz { + | ^^^^^^^^^^^^^^^ + +error: missing documentation for a variant + --> $DIR/lint-missing-doc.rs:119:5 + | +LL | PubBazA { + | ^^^^^^^ + +error: missing documentation for a struct field + --> $DIR/lint-missing-doc.rs:120:9 + | +LL | a: isize, + | ^^^^^^^^ + +error: missing documentation for a constant + --> $DIR/lint-missing-doc.rs:151:1 + | +LL | pub const FOO4: u32 = 0; + | ^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a static + --> $DIR/lint-missing-doc.rs:161:1 + | +LL | pub static BAR4: u32 = 0; + | ^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a function + --> $DIR/lint-missing-doc.rs:167:5 + | +LL | pub fn undocumented1() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a function + --> $DIR/lint-missing-doc.rs:168:5 + | +LL | pub fn undocumented2() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a function + --> $DIR/lint-missing-doc.rs:174:9 + | +LL | pub fn also_undocumented1() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a function + --> $DIR/lint-missing-doc.rs:189:5 + | +LL | pub fn extern_fn_undocumented(f: f32) -> f32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a static + --> $DIR/lint-missing-doc.rs:194:5 + | +LL | pub static EXTERN_STATIC_UNDOCUMENTED: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a foreign type + --> $DIR/lint-missing-doc.rs:199:5 + | +LL | pub type ExternTyUndocumented; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 22 previous errors + diff --git a/tests/ui/lint/lint-non-camel-case-types.rs b/tests/ui/lint/lint-non-camel-case-types.rs new file mode 100644 index 000000000..acd5c5df9 --- /dev/null +++ b/tests/ui/lint/lint-non-camel-case-types.rs @@ -0,0 +1,37 @@ +#![forbid(non_camel_case_types)] +#![allow(dead_code)] + +struct ONE_TWO_THREE; +//~^ ERROR type `ONE_TWO_THREE` should have an upper camel case name + +struct foo { //~ ERROR type `foo` should have an upper camel case name + bar: isize, +} + +enum foo2 { //~ ERROR type `foo2` should have an upper camel case name + Bar +} + +struct foo3 { //~ ERROR type `foo3` should have an upper camel case name + bar: isize +} + +type foo4 = isize; //~ ERROR type `foo4` should have an upper camel case name + +enum Foo5 { + bar //~ ERROR variant `bar` should have an upper camel case name +} + +trait foo6 { //~ ERROR trait `foo6` should have an upper camel case name + type foo7; //~ ERROR associated type `foo7` should have an upper camel case name + fn dummy(&self) { } +} + +fn f<ty>(_: ty) {} //~ ERROR type parameter `ty` should have an upper camel case name + +#[repr(C)] +struct foo7 { + bar: isize, +} + +fn main() { } diff --git a/tests/ui/lint/lint-non-camel-case-types.stderr b/tests/ui/lint/lint-non-camel-case-types.stderr new file mode 100644 index 000000000..875380b5d --- /dev/null +++ b/tests/ui/lint/lint-non-camel-case-types.stderr @@ -0,0 +1,62 @@ +error: type `ONE_TWO_THREE` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:4:8 + | +LL | struct ONE_TWO_THREE; + | ^^^^^^^^^^^^^ help: convert the identifier to upper camel case: `OneTwoThree` + | +note: the lint level is defined here + --> $DIR/lint-non-camel-case-types.rs:1:11 + | +LL | #![forbid(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: type `foo` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:7:8 + | +LL | struct foo { + | ^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo` + +error: type `foo2` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:11:6 + | +LL | enum foo2 { + | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo2` + +error: type `foo3` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:15:8 + | +LL | struct foo3 { + | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo3` + +error: type `foo4` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:19:6 + | +LL | type foo4 = isize; + | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo4` + +error: variant `bar` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:22:5 + | +LL | bar + | ^^^ help: convert the identifier to upper camel case: `Bar` + +error: trait `foo6` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:25:7 + | +LL | trait foo6 { + | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo6` + +error: associated type `foo7` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:26:10 + | +LL | type foo7; + | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo7` + +error: type parameter `ty` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:30:6 + | +LL | fn f<ty>(_: ty) {} + | ^^ help: convert the identifier to upper camel case: `Ty` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/lint-non-camel-case-variant.rs b/tests/ui/lint/lint-non-camel-case-variant.rs new file mode 100644 index 000000000..2b1a52f25 --- /dev/null +++ b/tests/ui/lint/lint-non-camel-case-variant.rs @@ -0,0 +1,10 @@ +// check-pass + +#![deny(non_camel_case_types)] + +pub enum Foo { + #[allow(non_camel_case_types)] + bar +} + +fn main() {} diff --git a/tests/ui/lint/lint-non-camel-case-with-trailing-underscores.rs b/tests/ui/lint/lint-non-camel-case-with-trailing-underscores.rs new file mode 100644 index 000000000..b832e4bcd --- /dev/null +++ b/tests/ui/lint/lint-non-camel-case-with-trailing-underscores.rs @@ -0,0 +1,11 @@ +// check-pass + +#![allow(dead_code)] +// This is ok because we often use the trailing underscore to mean 'prime' + +// pretty-expanded FIXME #23616 + +#[forbid(non_camel_case_types)] +type Foo_ = isize; + +pub fn main() { } diff --git a/tests/ui/lint/lint-non-snake-case-crate-2.rs b/tests/ui/lint/lint-non-snake-case-crate-2.rs new file mode 100644 index 000000000..1b763a9d8 --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-crate-2.rs @@ -0,0 +1,6 @@ +// compile-flags: --crate-name NonSnakeCase +// error-pattern: crate `NonSnakeCase` should have a snake case name + +#![deny(non_snake_case)] + +fn main() {} diff --git a/tests/ui/lint/lint-non-snake-case-crate-2.stderr b/tests/ui/lint/lint-non-snake-case-crate-2.stderr new file mode 100644 index 000000000..4b42145bb --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-crate-2.stderr @@ -0,0 +1,11 @@ +error: crate `NonSnakeCase` should have a snake case name + | + = help: convert the identifier to snake case: `non_snake_case` +note: the lint level is defined here + --> $DIR/lint-non-snake-case-crate-2.rs:4:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-non-snake-case-crate.rs b/tests/ui/lint/lint-non-snake-case-crate.rs new file mode 100644 index 000000000..e4e84261a --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-crate.rs @@ -0,0 +1,5 @@ +#![crate_name = "NonSnakeCase"] +//~^ ERROR crate `NonSnakeCase` should have a snake case name +#![deny(non_snake_case)] + +fn main() {} diff --git a/tests/ui/lint/lint-non-snake-case-crate.stderr b/tests/ui/lint/lint-non-snake-case-crate.stderr new file mode 100644 index 000000000..da6b89c1e --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-crate.stderr @@ -0,0 +1,14 @@ +error: crate `NonSnakeCase` should have a snake case name + --> $DIR/lint-non-snake-case-crate.rs:1:18 + | +LL | #![crate_name = "NonSnakeCase"] + | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` + | +note: the lint level is defined here + --> $DIR/lint-non-snake-case-crate.rs:3:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-non-snake-case-functions.rs b/tests/ui/lint/lint-non-snake-case-functions.rs new file mode 100644 index 000000000..fa64a9f98 --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-functions.rs @@ -0,0 +1,44 @@ +#![deny(non_snake_case)] +#![allow(dead_code)] + +struct Foo; + +impl Foo { + fn Foo_Method() {} + //~^ ERROR method `Foo_Method` should have a snake case name + + // Don't allow two underscores in a row + fn foo__method(&self) {} + //~^ ERROR method `foo__method` should have a snake case name + + pub fn xyZ(&mut self) {} + //~^ ERROR method `xyZ` should have a snake case name + + fn render_HTML() {} + //~^ ERROR method `render_HTML` should have a snake case name +} + +trait X { + fn ABC(); + //~^ ERROR trait method `ABC` should have a snake case name + + fn a_b_C(&self) {} + //~^ ERROR trait method `a_b_C` should have a snake case name + + fn something__else(&mut self); + //~^ ERROR trait method `something__else` should have a snake case name +} + +impl X for Foo { + // These errors should be caught at the trait definition not the impl + fn ABC() {} + fn something__else(&mut self) {} +} + +fn Cookie() {} +//~^ ERROR function `Cookie` should have a snake case name + +pub fn bi_S_Cuit() {} +//~^ ERROR function `bi_S_Cuit` should have a snake case name + +fn main() { } diff --git a/tests/ui/lint/lint-non-snake-case-functions.stderr b/tests/ui/lint/lint-non-snake-case-functions.stderr new file mode 100644 index 000000000..f6ac6b99b --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-functions.stderr @@ -0,0 +1,62 @@ +error: method `Foo_Method` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:7:8 + | +LL | fn Foo_Method() {} + | ^^^^^^^^^^ help: convert the identifier to snake case: `foo_method` + | +note: the lint level is defined here + --> $DIR/lint-non-snake-case-functions.rs:1:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: method `foo__method` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:11:8 + | +LL | fn foo__method(&self) {} + | ^^^^^^^^^^^ help: convert the identifier to snake case: `foo_method` + +error: method `xyZ` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:14:12 + | +LL | pub fn xyZ(&mut self) {} + | ^^^ help: convert the identifier to snake case: `xy_z` + +error: method `render_HTML` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:17:8 + | +LL | fn render_HTML() {} + | ^^^^^^^^^^^ help: convert the identifier to snake case: `render_html` + +error: trait method `ABC` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:22:8 + | +LL | fn ABC(); + | ^^^ help: convert the identifier to snake case: `abc` + +error: trait method `a_b_C` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:25:8 + | +LL | fn a_b_C(&self) {} + | ^^^^^ help: convert the identifier to snake case (notice the capitalization): `a_b_c` + +error: trait method `something__else` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:28:8 + | +LL | fn something__else(&mut self); + | ^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `something_else` + +error: function `Cookie` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:38:4 + | +LL | fn Cookie() {} + | ^^^^^^ help: convert the identifier to snake case (notice the capitalization): `cookie` + +error: function `bi_S_Cuit` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:41:8 + | +LL | pub fn bi_S_Cuit() {} + | ^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `bi_s_cuit` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs b/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs new file mode 100644 index 000000000..8cc4f976a --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs @@ -0,0 +1,19 @@ +#![warn(unused)] +#![allow(dead_code)] +#![deny(non_snake_case)] + +mod Impl {} +//~^ ERROR module `Impl` should have a snake case name + +fn While() {} +//~^ ERROR function `While` should have a snake case name + +fn main() { + let Mod: usize = 0; + //~^ ERROR variable `Mod` should have a snake case name + //~^^ WARN unused variable: `Mod` + + let Super: usize = 0; + //~^ ERROR variable `Super` should have a snake case name + //~^^ WARN unused variable: `Super` +} diff --git a/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr b/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr new file mode 100644 index 000000000..2841815ec --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr @@ -0,0 +1,67 @@ +warning: unused variable: `Mod` + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:12:9 + | +LL | let Mod: usize = 0; + | ^^^ help: if this is intentional, prefix it with an underscore: `_Mod` + | +note: the lint level is defined here + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:1:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: unused variable: `Super` + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:16:9 + | +LL | let Super: usize = 0; + | ^^^^^ help: if this is intentional, prefix it with an underscore: `_Super` + +error: module `Impl` should have a snake case name + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:5:5 + | +LL | mod Impl {} + | ^^^^ + | +note: the lint level is defined here + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:3:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ +help: rename the identifier or convert it to a snake case raw identifier + | +LL | mod r#impl {} + | ~~~~~~ + +error: function `While` should have a snake case name + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:8:4 + | +LL | fn While() {} + | ^^^^^ + | +help: rename the identifier or convert it to a snake case raw identifier + | +LL | fn r#while() {} + | ~~~~~~~ + +error: variable `Mod` should have a snake case name + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:12:9 + | +LL | let Mod: usize = 0; + | ^^^ + | +help: rename the identifier or convert it to a snake case raw identifier + | +LL | let r#mod: usize = 0; + | ~~~~~ + +error: variable `Super` should have a snake case name + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:16:9 + | +LL | let Super: usize = 0; + | ^^^^^ help: rename the identifier + | + = note: `super` cannot be used as a raw identifier + +error: aborting due to 4 previous errors; 2 warnings emitted + diff --git a/tests/ui/lint/lint-non-snake-case-lifetimes.rs b/tests/ui/lint/lint-non-snake-case-lifetimes.rs new file mode 100644 index 000000000..de76d2dbe --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-lifetimes.rs @@ -0,0 +1,8 @@ +#![deny(non_snake_case)] +#![allow(dead_code)] + +fn f<'FooBar>( //~ ERROR lifetime `'FooBar` should have a snake case name + _: &'FooBar () +) {} + +fn main() { } diff --git a/tests/ui/lint/lint-non-snake-case-lifetimes.stderr b/tests/ui/lint/lint-non-snake-case-lifetimes.stderr new file mode 100644 index 000000000..d4fe26a43 --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-lifetimes.stderr @@ -0,0 +1,14 @@ +error: lifetime `'FooBar` should have a snake case name + --> $DIR/lint-non-snake-case-lifetimes.rs:4:6 + | +LL | fn f<'FooBar>( + | ^^^^^^^ help: convert the identifier to snake case: `'foo_bar` + | +note: the lint level is defined here + --> $DIR/lint-non-snake-case-lifetimes.rs:1:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-non-snake-case-modules.rs b/tests/ui/lint/lint-non-snake-case-modules.rs new file mode 100644 index 000000000..73f123321 --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-modules.rs @@ -0,0 +1,10 @@ +#![deny(non_snake_case)] +#![allow(dead_code)] + +mod FooBar { //~ ERROR module `FooBar` should have a snake case name + pub struct S; +} + +fn f(_: FooBar::S) { } + +fn main() { } diff --git a/tests/ui/lint/lint-non-snake-case-modules.stderr b/tests/ui/lint/lint-non-snake-case-modules.stderr new file mode 100644 index 000000000..c8b997c87 --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-modules.stderr @@ -0,0 +1,14 @@ +error: module `FooBar` should have a snake case name + --> $DIR/lint-non-snake-case-modules.rs:4:5 + | +LL | mod FooBar { + | ^^^^^^ help: convert the identifier to snake case: `foo_bar` + | +note: the lint level is defined here + --> $DIR/lint-non-snake-case-modules.rs:1:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs b/tests/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs new file mode 100644 index 000000000..9f0c87dca --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs @@ -0,0 +1,11 @@ +// check-pass + +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +#![deny(non_snake_case)] + +// This name is neither upper nor lower case +fn 你好() {} + +fn main() {} diff --git a/tests/ui/lint/lint-non-uppercase-associated-const.rs b/tests/ui/lint/lint-non-uppercase-associated-const.rs new file mode 100644 index 000000000..7b0d93960 --- /dev/null +++ b/tests/ui/lint/lint-non-uppercase-associated-const.rs @@ -0,0 +1,11 @@ +#![deny(non_upper_case_globals)] +#![allow(dead_code)] + +struct Foo; + +impl Foo { + const not_upper: bool = true; +} +//~^^ ERROR associated constant `not_upper` should have an upper case name + +fn main() {} diff --git a/tests/ui/lint/lint-non-uppercase-associated-const.stderr b/tests/ui/lint/lint-non-uppercase-associated-const.stderr new file mode 100644 index 000000000..411ff51aa --- /dev/null +++ b/tests/ui/lint/lint-non-uppercase-associated-const.stderr @@ -0,0 +1,14 @@ +error: associated constant `not_upper` should have an upper case name + --> $DIR/lint-non-uppercase-associated-const.rs:7:11 + | +LL | const not_upper: bool = true; + | ^^^^^^^^^ help: convert the identifier to upper case: `NOT_UPPER` + | +note: the lint level is defined here + --> $DIR/lint-non-uppercase-associated-const.rs:1:9 + | +LL | #![deny(non_upper_case_globals)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-non-uppercase-statics.rs b/tests/ui/lint/lint-non-uppercase-statics.rs new file mode 100644 index 000000000..5bd143032 --- /dev/null +++ b/tests/ui/lint/lint-non-uppercase-statics.rs @@ -0,0 +1,11 @@ +#![forbid(non_upper_case_globals)] +#![allow(dead_code)] + +static foo: isize = 1; //~ ERROR static variable `foo` should have an upper case name + +static mut bar: isize = 1; //~ ERROR static variable `bar` should have an upper case name + +#[no_mangle] +pub static extern_foo: isize = 1; // OK, because #[no_mangle] supersedes the warning + +fn main() { } diff --git a/tests/ui/lint/lint-non-uppercase-statics.stderr b/tests/ui/lint/lint-non-uppercase-statics.stderr new file mode 100644 index 000000000..c6fd0a6e0 --- /dev/null +++ b/tests/ui/lint/lint-non-uppercase-statics.stderr @@ -0,0 +1,20 @@ +error: static variable `foo` should have an upper case name + --> $DIR/lint-non-uppercase-statics.rs:4:8 + | +LL | static foo: isize = 1; + | ^^^ help: convert the identifier to upper case (notice the capitalization): `FOO` + | +note: the lint level is defined here + --> $DIR/lint-non-uppercase-statics.rs:1:11 + | +LL | #![forbid(non_upper_case_globals)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: static variable `bar` should have an upper case name + --> $DIR/lint-non-uppercase-statics.rs:6:12 + | +LL | static mut bar: isize = 1; + | ^^^ help: convert the identifier to upper case: `BAR` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-1.rs b/tests/ui/lint/lint-nonstandard-style-unicode-1.rs new file mode 100644 index 000000000..7c45c0993 --- /dev/null +++ b/tests/ui/lint/lint-nonstandard-style-unicode-1.rs @@ -0,0 +1,49 @@ +#![allow(dead_code)] + +#![forbid(non_camel_case_types)] + +// Some scripts (e.g., hiragana) don't have a concept of +// upper/lowercase + +// 1. non_camel_case_types + +// Can start with non-lowercase letter +struct Θχ; +struct ヒa; + +struct χa; +//~^ ERROR type `χa` should have an upper camel case name + +// If there's already leading or trailing underscores, they get trimmed before checking. +// This is fine: +struct _ヒb; + +// This is not: +struct __χa; +//~^ ERROR type `__χa` should have an upper camel case name + +// Besides this, we cannot have two continuous underscores in the middle. + +struct 对__否; +//~^ ERROR type `对__否` should have an upper camel case name + +struct ヒ__χ; +//~^ ERROR type `ヒ__χ` should have an upper camel case name + +// also cannot have lowercase letter next to an underscore. +// so this triggers the lint: + +struct Hello_你好; +//~^ ERROR type `Hello_你好` should have an upper camel case name + +struct Hello_World; +//~^ ERROR type `Hello_World` should have an upper camel case name + +struct 你_ӟ; +//~^ ERROR type `你_ӟ` should have an upper camel case name + +// and this is ok: + +struct 你_好; + +fn main() {} diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-1.stderr b/tests/ui/lint/lint-nonstandard-style-unicode-1.stderr new file mode 100644 index 000000000..6c2aa225e --- /dev/null +++ b/tests/ui/lint/lint-nonstandard-style-unicode-1.stderr @@ -0,0 +1,50 @@ +error: type `χa` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:14:8 + | +LL | struct χa; + | ^^ help: convert the identifier to upper camel case: `Χa` + | +note: the lint level is defined here + --> $DIR/lint-nonstandard-style-unicode-1.rs:3:11 + | +LL | #![forbid(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: type `__χa` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:22:8 + | +LL | struct __χa; + | ^^^^ help: convert the identifier to upper camel case: `Χa` + +error: type `对__否` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:27:8 + | +LL | struct 对__否; + | ^^^^^^ help: convert the identifier to upper camel case: `对_否` + +error: type `ヒ__χ` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:30:8 + | +LL | struct ヒ__χ; + | ^^^^^ help: convert the identifier to upper camel case: `ヒΧ` + +error: type `Hello_你好` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:36:8 + | +LL | struct Hello_你好; + | ^^^^^^^^^^ help: convert the identifier to upper camel case: `Hello你好` + +error: type `Hello_World` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:39:8 + | +LL | struct Hello_World; + | ^^^^^^^^^^^ help: convert the identifier to upper camel case: `HelloWorld` + +error: type `你_ӟ` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:42:8 + | +LL | struct 你_ӟ; + | ^^^^ help: convert the identifier to upper camel case: `你Ӟ` + +error: aborting due to 7 previous errors + diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-2.rs b/tests/ui/lint/lint-nonstandard-style-unicode-2.rs new file mode 100644 index 000000000..9690be590 --- /dev/null +++ b/tests/ui/lint/lint-nonstandard-style-unicode-2.rs @@ -0,0 +1,29 @@ +#![allow(dead_code)] + +#![forbid(non_snake_case)] + +// Some scripts (e.g., hiragana) don't have a concept of +// upper/lowercase + +// 2. non_snake_case + +// Can only use non-uppercase letters. +// So this works: + +fn 编程() {} + +// but this doesn't: + +fn Ц() {} +//~^ ERROR function `Ц` should have a snake case name + +// besides this, you cannot use continuous underscores in the middle + +fn 分__隔() {} +//~^ ERROR function `分__隔` should have a snake case name + +// but you can use them both at the beginning and at the end. + +fn _______不_连_续_的_存_在_______() {} + +fn main() {} diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-2.stderr b/tests/ui/lint/lint-nonstandard-style-unicode-2.stderr new file mode 100644 index 000000000..8eb0654e0 --- /dev/null +++ b/tests/ui/lint/lint-nonstandard-style-unicode-2.stderr @@ -0,0 +1,20 @@ +error: function `Ц` should have a snake case name + --> $DIR/lint-nonstandard-style-unicode-2.rs:17:4 + | +LL | fn Ц() {} + | ^ help: convert the identifier to snake case: `ц` + | +note: the lint level is defined here + --> $DIR/lint-nonstandard-style-unicode-2.rs:3:11 + | +LL | #![forbid(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: function `分__隔` should have a snake case name + --> $DIR/lint-nonstandard-style-unicode-2.rs:22:4 + | +LL | fn 分__隔() {} + | ^^^^^^ help: convert the identifier to snake case: `分_隔` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-3.rs b/tests/ui/lint/lint-nonstandard-style-unicode-3.rs new file mode 100644 index 000000000..9175be7a0 --- /dev/null +++ b/tests/ui/lint/lint-nonstandard-style-unicode-3.rs @@ -0,0 +1,24 @@ +#![allow(dead_code)] + +#![forbid(non_upper_case_globals)] + +// Some scripts (e.g., hiragana) don't have a concept of +// upper/lowercase + +// 3. non_upper_case_globals + +// Can only use non-lowercase letters. +// So this works: + +static ラ: usize = 0; + +// but this doesn't: + +static τεχ: f32 = 3.14159265; +//~^ ERROR static variable `τεχ` should have an upper case name + +// This has no limit at all on underscore usages. + +static __密__封__线__内__禁__止__答__题__: bool = true; + +fn main() {} diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-3.stderr b/tests/ui/lint/lint-nonstandard-style-unicode-3.stderr new file mode 100644 index 000000000..970e6b838 --- /dev/null +++ b/tests/ui/lint/lint-nonstandard-style-unicode-3.stderr @@ -0,0 +1,14 @@ +error: static variable `τεχ` should have an upper case name + --> $DIR/lint-nonstandard-style-unicode-3.rs:17:8 + | +LL | static τεχ: f32 = 3.14159265; + | ^^^ help: convert the identifier to upper case: `ΤΕΧ` + | +note: the lint level is defined here + --> $DIR/lint-nonstandard-style-unicode-3.rs:3:11 + | +LL | #![forbid(non_upper_case_globals)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-output-format-2.rs b/tests/ui/lint/lint-output-format-2.rs new file mode 100644 index 000000000..985166e09 --- /dev/null +++ b/tests/ui/lint/lint-output-format-2.rs @@ -0,0 +1,15 @@ +// aux-build:lint_output_format.rs + +#![feature(unstable_test_feature)] +// check-pass + +extern crate lint_output_format; +use lint_output_format::{foo, bar}; +//~^ WARNING use of deprecated function `lint_output_format::foo`: text + + +fn main() { + let _x = foo(); + //~^ WARNING use of deprecated function `lint_output_format::foo`: text + let _y = bar(); +} diff --git a/tests/ui/lint/lint-output-format-2.stderr b/tests/ui/lint/lint-output-format-2.stderr new file mode 100644 index 000000000..a36dbd61f --- /dev/null +++ b/tests/ui/lint/lint-output-format-2.stderr @@ -0,0 +1,16 @@ +warning: use of deprecated function `lint_output_format::foo`: text + --> $DIR/lint-output-format-2.rs:7:26 + | +LL | use lint_output_format::{foo, bar}; + | ^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: use of deprecated function `lint_output_format::foo`: text + --> $DIR/lint-output-format-2.rs:12:14 + | +LL | let _x = foo(); + | ^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/lint-output-format.rs b/tests/ui/lint/lint-output-format.rs new file mode 100644 index 000000000..67e8ec8f1 --- /dev/null +++ b/tests/ui/lint/lint-output-format.rs @@ -0,0 +1,13 @@ +// compile-flags: -F unused_features +// aux-build:lint_output_format.rs + +#![allow(deprecated)] + +extern crate lint_output_format; //~ ERROR use of unstable library feature +use lint_output_format::{foo, bar}; //~ ERROR use of unstable library feature +//~| ERROR use of unstable library feature + +fn main() { + let _x = foo(); + let _y = bar(); //~ ERROR use of unstable library feature +} diff --git a/tests/ui/lint/lint-output-format.stderr b/tests/ui/lint/lint-output-format.stderr new file mode 100644 index 000000000..0db79a156 --- /dev/null +++ b/tests/ui/lint/lint-output-format.stderr @@ -0,0 +1,35 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-output-format.rs:6:1 + | +LL | extern crate lint_output_format; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-output-format.rs:7:26 + | +LL | use lint_output_format::{foo, bar}; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-output-format.rs:7:31 + | +LL | use lint_output_format::{foo, bar}; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-output-format.rs:12:14 + | +LL | let _y = bar(); + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/lint-owned-heap-memory.rs b/tests/ui/lint/lint-owned-heap-memory.rs new file mode 100644 index 000000000..af47d5c07 --- /dev/null +++ b/tests/ui/lint/lint-owned-heap-memory.rs @@ -0,0 +1,12 @@ +#![allow(dead_code)] +#![forbid(box_pointers)] + + +struct Foo { + x: Box<isize> //~ ERROR type uses owned +} + +fn main() { + let _x: Foo = Foo { x : Box::new(10) }; + //~^ ERROR type uses owned +} diff --git a/tests/ui/lint/lint-owned-heap-memory.stderr b/tests/ui/lint/lint-owned-heap-memory.stderr new file mode 100644 index 000000000..5ba396970 --- /dev/null +++ b/tests/ui/lint/lint-owned-heap-memory.stderr @@ -0,0 +1,20 @@ +error: type uses owned (Box type) pointers: Box<isize> + --> $DIR/lint-owned-heap-memory.rs:6:5 + | +LL | x: Box<isize> + | ^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-owned-heap-memory.rs:2:11 + | +LL | #![forbid(box_pointers)] + | ^^^^^^^^^^^^ + +error: type uses owned (Box type) pointers: Box<isize> + --> $DIR/lint-owned-heap-memory.rs:10:29 + | +LL | let _x: Foo = Foo { x : Box::new(10) }; + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/lint-pre-expansion-extern-module.rs b/tests/ui/lint/lint-pre-expansion-extern-module.rs new file mode 100644 index 000000000..30e2ed8b7 --- /dev/null +++ b/tests/ui/lint/lint-pre-expansion-extern-module.rs @@ -0,0 +1,7 @@ +// check-pass +// compile-flags: -W rust-2018-compatibility +// error-pattern: `try` is a keyword in the 2018 edition + +fn main() {} + +mod lint_pre_expansion_extern_module_aux; diff --git a/tests/ui/lint/lint-pre-expansion-extern-module.stderr b/tests/ui/lint/lint-pre-expansion-extern-module.stderr new file mode 100644 index 000000000..ce3e8806a --- /dev/null +++ b/tests/ui/lint/lint-pre-expansion-extern-module.stderr @@ -0,0 +1,12 @@ +warning: `try` is a keyword in the 2018 edition + --> $DIR/lint_pre_expansion_extern_module_aux.rs:3:8 + | +LL | pub fn try() {} + | ^^^ help: you can use a raw identifier to stay compatible: `r#try` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716> + = note: `-W keyword-idents` implied by `-W rust-2018-compatibility` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/lint-pub-unreachable-for-nested-glob.rs b/tests/ui/lint/lint-pub-unreachable-for-nested-glob.rs new file mode 100644 index 000000000..2df6d08e7 --- /dev/null +++ b/tests/ui/lint/lint-pub-unreachable-for-nested-glob.rs @@ -0,0 +1,28 @@ +// check-pass + +#![deny(unreachable_pub)] + +pub use self::m1::*; + +mod m1 { + pub use self::m2::*; + + mod m2 { + pub struct Item1; + pub struct Item2; + } +} + + +pub use self::o1::{ Item42, Item24 }; + +mod o1 { + pub use self::o2::{ Item42, Item24 }; + + mod o2 { + pub struct Item42; + pub struct Item24; + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-qualification.rs b/tests/ui/lint/lint-qualification.rs new file mode 100644 index 000000000..0cace0ca0 --- /dev/null +++ b/tests/ui/lint/lint-qualification.rs @@ -0,0 +1,20 @@ +#![deny(unused_qualifications)] +#![allow(deprecated)] + +mod foo { + pub fn bar() {} +} + +fn main() { + use foo::bar; + foo::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.stderr b/tests/ui/lint/lint-qualification.stderr new file mode 100644 index 000000000..149a782d9 --- /dev/null +++ b/tests/ui/lint/lint-qualification.stderr @@ -0,0 +1,14 @@ +error: unnecessary qualification + --> $DIR/lint-qualification.rs:10:5 + | +LL | foo::bar(); + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-qualification.rs:1:9 + | +LL | #![deny(unused_qualifications)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-range-endpoint-overflow.rs b/tests/ui/lint/lint-range-endpoint-overflow.rs new file mode 100644 index 000000000..7034d56aa --- /dev/null +++ b/tests/ui/lint/lint-range-endpoint-overflow.rs @@ -0,0 +1,17 @@ +#![deny(overflowing_literals)] + +fn main() { + let range_a = 0..256; //~ ERROR range endpoint is out of range for `u8` + let range_b = 0..=255; // ok + let range_c = 0..=256; //~ ERROR literal out of range for `u8` + let range_d = 256..5; //~ ERROR literal out of range for `u8` + let range_e = 0..257; //~ ERROR literal out of range for `u8` + let _range_f = 0..256u8; //~ ERROR range endpoint is out of range for `u8` + let _range_g = 0..128i8; //~ ERROR range endpoint is out of range for `i8` + + range_a.collect::<Vec<u8>>(); + range_b.collect::<Vec<u8>>(); + range_c.collect::<Vec<u8>>(); + range_d.collect::<Vec<u8>>(); + range_e.collect::<Vec<u8>>(); +} diff --git a/tests/ui/lint/lint-range-endpoint-overflow.stderr b/tests/ui/lint/lint-range-endpoint-overflow.stderr new file mode 100644 index 000000000..d2df73727 --- /dev/null +++ b/tests/ui/lint/lint-range-endpoint-overflow.stderr @@ -0,0 +1,50 @@ +error: range endpoint is out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:4:19 + | +LL | let range_a = 0..256; + | ^^^^^^ help: use an inclusive range instead: `0..=255` + | +note: the lint level is defined here + --> $DIR/lint-range-endpoint-overflow.rs:1:9 + | +LL | #![deny(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: literal out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:6:23 + | +LL | let range_c = 0..=256; + | ^^^ + | + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` + +error: literal out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:7:19 + | +LL | let range_d = 256..5; + | ^^^ + | + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` + +error: literal out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:8:22 + | +LL | let range_e = 0..257; + | ^^^ + | + = note: the literal `257` does not fit into the type `u8` whose range is `0..=255` + +error: range endpoint is out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:9:20 + | +LL | let _range_f = 0..256u8; + | ^^^^^^^^ help: use an inclusive range instead: `0..=255u8` + +error: range endpoint is out of range for `i8` + --> $DIR/lint-range-endpoint-overflow.rs:10:20 + | +LL | let _range_g = 0..128i8; + | ^^^^^^^^ help: use an inclusive range instead: `0..=127i8` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/lint/lint-removed-allow.rs b/tests/ui/lint/lint-removed-allow.rs new file mode 100644 index 000000000..30ba4f02f --- /dev/null +++ b/tests/ui/lint/lint-removed-allow.rs @@ -0,0 +1,8 @@ +// No warnings about removed lint when +// allow(renamed_and_removed_lints) + +#![allow(renamed_and_removed_lints)] + +#[deny(raw_pointer_derive)] +#[deny(unused_variables)] +fn main() { let unused = (); } //~ ERROR unused diff --git a/tests/ui/lint/lint-removed-allow.stderr b/tests/ui/lint/lint-removed-allow.stderr new file mode 100644 index 000000000..029334c2e --- /dev/null +++ b/tests/ui/lint/lint-removed-allow.stderr @@ -0,0 +1,14 @@ +error: unused variable: `unused` + --> $DIR/lint-removed-allow.rs:8:17 + | +LL | fn main() { let unused = (); } + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/lint-removed-allow.rs:7:8 + | +LL | #[deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-removed-cmdline.rs b/tests/ui/lint/lint-removed-cmdline.rs new file mode 100644 index 000000000..462beabb9 --- /dev/null +++ b/tests/ui/lint/lint-removed-cmdline.rs @@ -0,0 +1,12 @@ +// The raw_pointer_derived lint warns about its removal +// cc #30346 + +// compile-flags:-D raw_pointer_derive + +// error-pattern:lint `raw_pointer_derive` has been removed +// error-pattern:requested on the command line with `-D raw_pointer_derive` + +#![warn(unused)] + +#[deny(warnings)] +fn main() { let unused = (); } diff --git a/tests/ui/lint/lint-removed-cmdline.stderr b/tests/ui/lint/lint-removed-cmdline.stderr new file mode 100644 index 000000000..9be532ef2 --- /dev/null +++ b/tests/ui/lint/lint-removed-cmdline.stderr @@ -0,0 +1,27 @@ +warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok + | + = note: requested on the command line with `-D raw_pointer_derive` + +warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok + | + = note: requested on the command line with `-D raw_pointer_derive` + +warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok + | + = note: requested on the command line with `-D raw_pointer_derive` + +error: unused variable: `unused` + --> $DIR/lint-removed-cmdline.rs:12:17 + | +LL | fn main() { let unused = (); } + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/lint-removed-cmdline.rs:11:8 + | +LL | #[deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]` + +error: aborting due to previous error; 3 warnings emitted + diff --git a/tests/ui/lint/lint-removed.rs b/tests/ui/lint/lint-removed.rs new file mode 100644 index 000000000..92f4372c2 --- /dev/null +++ b/tests/ui/lint/lint-removed.rs @@ -0,0 +1,8 @@ +// The raw_pointer_derived lint was removed, but is now reported by +// the renamed_and_removed_lints lint, which means it's a warning by +// default, and allowed in cargo dependency builds. +// cc #30346 + +#[deny(raw_pointer_derive)] //~ WARN `raw_pointer_derive` has been removed +#[deny(unused_variables)] +fn main() { let unused = (); } //~ ERROR unused diff --git a/tests/ui/lint/lint-removed.stderr b/tests/ui/lint/lint-removed.stderr new file mode 100644 index 000000000..dc0515b84 --- /dev/null +++ b/tests/ui/lint/lint-removed.stderr @@ -0,0 +1,22 @@ +warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok + --> $DIR/lint-removed.rs:6:8 + | +LL | #[deny(raw_pointer_derive)] + | ^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(renamed_and_removed_lints)]` on by default + +error: unused variable: `unused` + --> $DIR/lint-removed.rs:8:17 + | +LL | fn main() { let unused = (); } + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/lint-removed.rs:7:8 + | +LL | #[deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/lint/lint-renamed-allow.rs b/tests/ui/lint/lint-renamed-allow.rs new file mode 100644 index 000000000..9cf6f329c --- /dev/null +++ b/tests/ui/lint/lint-renamed-allow.rs @@ -0,0 +1,8 @@ +// No warnings about renamed lint when +// allow(renamed_and_removed_lints) + +#![allow(renamed_and_removed_lints)] + +#[deny(single_use_lifetime)] +#[deny(unused)] +fn main() { let unused = (); } //~ ERROR unused diff --git a/tests/ui/lint/lint-renamed-allow.stderr b/tests/ui/lint/lint-renamed-allow.stderr new file mode 100644 index 000000000..46f6a10de --- /dev/null +++ b/tests/ui/lint/lint-renamed-allow.stderr @@ -0,0 +1,15 @@ +error: unused variable: `unused` + --> $DIR/lint-renamed-allow.rs:8:17 + | +LL | fn main() { let unused = (); } + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/lint-renamed-allow.rs:7:8 + | +LL | #[deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-renamed-cmdline.rs b/tests/ui/lint/lint-renamed-cmdline.rs new file mode 100644 index 000000000..c873771e3 --- /dev/null +++ b/tests/ui/lint/lint-renamed-cmdline.rs @@ -0,0 +1,8 @@ +// compile-flags:-D bare_trait_object + +// error-pattern:lint `bare_trait_object` has been renamed to `bare_trait_objects` +// error-pattern:requested on the command line with `-D bare_trait_object` +// error-pattern:unused + +#[deny(unused)] +fn main() { let unused = (); } diff --git a/tests/ui/lint/lint-renamed-cmdline.stderr b/tests/ui/lint/lint-renamed-cmdline.stderr new file mode 100644 index 000000000..8dfd61ac9 --- /dev/null +++ b/tests/ui/lint/lint-renamed-cmdline.stderr @@ -0,0 +1,27 @@ +warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` + | + = note: requested on the command line with `-D bare_trait_object` + +warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` + | + = note: requested on the command line with `-D bare_trait_object` + +warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` + | + = note: requested on the command line with `-D bare_trait_object` + +error: unused variable: `unused` + --> $DIR/lint-renamed-cmdline.rs:8:17 + | +LL | fn main() { let unused = (); } + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/lint-renamed-cmdline.rs:7:8 + | +LL | #[deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: aborting due to previous error; 3 warnings emitted + diff --git a/tests/ui/lint/lint-renamed.rs b/tests/ui/lint/lint-renamed.rs new file mode 100644 index 000000000..ca3299430 --- /dev/null +++ b/tests/ui/lint/lint-renamed.rs @@ -0,0 +1,4 @@ +#[deny(bare_trait_object)] +//~^ WARN lint `bare_trait_object` has been renamed to `bare_trait_objects` +#[deny(unused)] +fn main() { let unused = (); } //~ ERROR unused diff --git a/tests/ui/lint/lint-renamed.stderr b/tests/ui/lint/lint-renamed.stderr new file mode 100644 index 000000000..984254571 --- /dev/null +++ b/tests/ui/lint/lint-renamed.stderr @@ -0,0 +1,23 @@ +warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` + --> $DIR/lint-renamed.rs:1:8 + | +LL | #[deny(bare_trait_object)] + | ^^^^^^^^^^^^^^^^^ help: use the new name: `bare_trait_objects` + | + = note: `#[warn(renamed_and_removed_lints)]` on by default + +error: unused variable: `unused` + --> $DIR/lint-renamed.rs:4:17 + | +LL | fn main() { let unused = (); } + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/lint-renamed.rs:3:8 + | +LL | #[deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/lint/lint-shorthand-field.fixed b/tests/ui/lint/lint-shorthand-field.fixed new file mode 100644 index 000000000..7cd5717bc --- /dev/null +++ b/tests/ui/lint/lint-shorthand-field.fixed @@ -0,0 +1,70 @@ +// run-rustfix + +#![allow(nonstandard_style, unused_variables, unused_mut)] +#![deny(non_shorthand_field_patterns)] + +struct Foo { + x: isize, + y: isize, +} + +fn main() { + { + let Foo { + x, //~ ERROR the `x:` in this pattern is redundant + ref y, //~ ERROR the `y:` in this pattern is redundant + } = Foo { x: 0, y: 0 }; + + let Foo { + x, + ref y, + } = Foo { x: 0, y: 0 }; + } + + { + const x: isize = 1; + + match (Foo { x: 1, y: 1 }) { + Foo { x: x, ..} => {}, + _ => {}, + } + } + + { + struct Bar { + x: x, + } + + struct x; + + match (Bar { x: x }) { + Bar { x: x } => {}, + } + } + + { + struct Bar { + x: Foo, + } + + enum Foo { x } + + match (Bar { x: Foo::x }) { + Bar { x: Foo::x } => {}, + } + } + + { + struct Baz { + x: isize, + y: isize, + z: isize, + } + + let Baz { + mut x, //~ ERROR the `x:` in this pattern is redundant + ref y, //~ ERROR the `y:` in this pattern is redundant + ref mut z, //~ ERROR the `z:` in this pattern is redundant + } = Baz { x: 0, y: 0, z: 0 }; + } +} diff --git a/tests/ui/lint/lint-shorthand-field.rs b/tests/ui/lint/lint-shorthand-field.rs new file mode 100644 index 000000000..22de9c325 --- /dev/null +++ b/tests/ui/lint/lint-shorthand-field.rs @@ -0,0 +1,70 @@ +// run-rustfix + +#![allow(nonstandard_style, unused_variables, unused_mut)] +#![deny(non_shorthand_field_patterns)] + +struct Foo { + x: isize, + y: isize, +} + +fn main() { + { + let Foo { + x: x, //~ ERROR the `x:` in this pattern is redundant + y: ref y, //~ ERROR the `y:` in this pattern is redundant + } = Foo { x: 0, y: 0 }; + + let Foo { + x, + ref y, + } = Foo { x: 0, y: 0 }; + } + + { + const x: isize = 1; + + match (Foo { x: 1, y: 1 }) { + Foo { x: x, ..} => {}, + _ => {}, + } + } + + { + struct Bar { + x: x, + } + + struct x; + + match (Bar { x: x }) { + Bar { x: x } => {}, + } + } + + { + struct Bar { + x: Foo, + } + + enum Foo { x } + + match (Bar { x: Foo::x }) { + Bar { x: Foo::x } => {}, + } + } + + { + struct Baz { + x: isize, + y: isize, + z: isize, + } + + let Baz { + x: mut x, //~ ERROR the `x:` in this pattern is redundant + y: ref y, //~ ERROR the `y:` in this pattern is redundant + z: ref mut z, //~ ERROR the `z:` in this pattern is redundant + } = Baz { x: 0, y: 0, z: 0 }; + } +} diff --git a/tests/ui/lint/lint-shorthand-field.stderr b/tests/ui/lint/lint-shorthand-field.stderr new file mode 100644 index 000000000..2d1ca30f9 --- /dev/null +++ b/tests/ui/lint/lint-shorthand-field.stderr @@ -0,0 +1,38 @@ +error: the `x:` in this pattern is redundant + --> $DIR/lint-shorthand-field.rs:14:13 + | +LL | x: x, + | ^^^^ help: use shorthand field pattern: `x` + | +note: the lint level is defined here + --> $DIR/lint-shorthand-field.rs:4:9 + | +LL | #![deny(non_shorthand_field_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `y:` in this pattern is redundant + --> $DIR/lint-shorthand-field.rs:15:13 + | +LL | y: ref y, + | ^^^^^^^^ help: use shorthand field pattern: `ref y` + +error: the `x:` in this pattern is redundant + --> $DIR/lint-shorthand-field.rs:65:13 + | +LL | x: mut x, + | ^^^^^^^^ help: use shorthand field pattern: `mut x` + +error: the `y:` in this pattern is redundant + --> $DIR/lint-shorthand-field.rs:66:13 + | +LL | y: ref y, + | ^^^^^^^^ help: use shorthand field pattern: `ref y` + +error: the `z:` in this pattern is redundant + --> $DIR/lint-shorthand-field.rs:67:13 + | +LL | z: ref mut z, + | ^^^^^^^^^^^^ help: use shorthand field pattern: `ref mut z` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/lint-stability-2.rs b/tests/ui/lint/lint-stability-2.rs new file mode 100644 index 000000000..94a8d08c8 --- /dev/null +++ b/tests/ui/lint/lint-stability-2.rs @@ -0,0 +1,413 @@ +// aux-build:lint_stability.rs +// aux-build:stability_cfg1.rs + +#![allow(deprecated)] +#![allow(dead_code)] +#![feature(staged_api)] + +#![stable(feature = "rust1", since = "1.0.0")] + +#[macro_use] +extern crate lint_stability; + +mod cross_crate { + extern crate stability_cfg1; + + use lint_stability::*; + + fn test() { + type Foo = MethodTester; + let foo = MethodTester; + + deprecated(); + foo.method_deprecated(); + Foo::method_deprecated(&foo); + <Foo>::method_deprecated(&foo); + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + <Foo>::trait_deprecated(&foo); + <Foo as Trait>::trait_deprecated(&foo); + + deprecated_text(); + foo.method_deprecated_text(); + Foo::method_deprecated_text(&foo); + <Foo>::method_deprecated_text(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + <Foo>::trait_deprecated_text(&foo); + <Foo as Trait>::trait_deprecated_text(&foo); + + foo.method_deprecated_unstable(); + //~^ ERROR use of unstable library feature + Foo::method_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + <Foo>::method_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + foo.trait_deprecated_unstable(); + //~^ ERROR use of unstable library feature + <Foo>::trait_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + + foo.method_deprecated_unstable_text(); + //~^ ERROR use of unstable library feature + Foo::method_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + <Foo>::method_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + foo.trait_deprecated_unstable_text(); + //~^ ERROR use of unstable library feature + <Foo>::trait_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + + foo.method_unstable(); //~ ERROR use of unstable library feature + Foo::method_unstable(&foo); //~ ERROR use of unstable library feature + <Foo>::method_unstable(&foo); //~ ERROR use of unstable library feature + foo.trait_unstable(); //~ ERROR use of unstable library feature + <Foo>::trait_unstable(&foo); //~ ERROR use of unstable library feature + + foo.method_unstable_text(); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + Foo::method_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + <Foo>::method_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + foo.trait_unstable_text(); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + <Foo>::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + + stable(); + foo.method_stable(); + Foo::method_stable(&foo); + <Foo>::method_stable(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + <Foo>::trait_stable(&foo); + <Foo as Trait>::trait_stable(&foo); + + stable_text(); + foo.method_stable_text(); + Foo::method_stable_text(&foo); + <Foo>::method_stable_text(&foo); + foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + <Foo>::trait_stable_text(&foo); + <Foo as Trait>::trait_stable_text(&foo); + + struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated); + + let _ = DeprecatedStruct { + i: 0 + }; + let _ = StableStruct { i: 0 }; + + let _ = DeprecatedUnitStruct; + let _ = StableUnitStruct; + + let _ = Enum::DeprecatedVariant; + let _ = Enum::StableVariant; + + let _ = DeprecatedTupleStruct (1); + let _ = StableTupleStruct (1); + + // At the moment, the lint checker only checks stability in + // in the arguments of macros. + // Eventually, we will want to lint the contents of the + // macro in the module *defining* it. Also, stability levels + // on macros themselves are not yet linted. + macro_test_arg!(deprecated_text()); + macro_test_arg!(macro_test_arg!(deprecated_text())); + } + + fn test_method_param<Foo: Trait>(foo: Foo) { + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + <Foo>::trait_deprecated(&foo); + <Foo as Trait>::trait_deprecated(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + <Foo>::trait_deprecated_text(&foo); + <Foo as Trait>::trait_deprecated_text(&foo); + foo.trait_deprecated_unstable(); + //~^ ERROR use of unstable library feature + <Foo>::trait_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + foo.trait_deprecated_unstable_text(); + //~^ ERROR use of unstable library feature + <Foo>::trait_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + foo.trait_unstable(); //~ ERROR use of unstable library feature + <Foo>::trait_unstable(&foo); //~ ERROR use of unstable library feature + foo.trait_unstable_text(); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + <Foo>::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + foo.trait_stable(); + Trait::trait_stable(&foo); + <Foo>::trait_stable(&foo); + <Foo as Trait>::trait_stable(&foo); + } + + fn test_method_object(foo: &dyn Trait) { + foo.trait_deprecated(); + foo.trait_deprecated_text(); + foo.trait_deprecated_unstable(); + //~^ ERROR use of unstable library feature + foo.trait_deprecated_unstable_text(); + //~^ ERROR use of unstable library feature + foo.trait_unstable(); //~ ERROR use of unstable library feature + foo.trait_unstable_text(); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + foo.trait_stable(); + } + + struct S; + + impl DeprecatedTrait for S {} + trait LocalTrait2 : DeprecatedTrait { } +} + +mod this_crate { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated() {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated_text() {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn unstable() {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn unstable_text() {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stable() {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stable_text() {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub struct MethodTester; + + impl MethodTester { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn method_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn method_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable_text(&self) {} + } + + pub trait Trait { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + fn trait_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + fn trait_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable_text(&self) {} + } + + impl Trait for MethodTester {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedUnitStruct; + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableUnitStruct; + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableUnitStruct; + + pub enum Enum { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedVariant, + #[unstable(feature = "unstable_test_feature", issue = "none")] + UnstableVariant, + + #[stable(feature = "rust1", since = "1.0.0")] + StableVariant, + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedTupleStruct(isize); + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableTupleStruct(isize); + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableTupleStruct(isize); + + fn test() { + // Only the deprecated cases of the following should generate + // errors, because other stability attributes now have meaning + // only *across* crates, not within a single crate. + + type Foo = MethodTester; + let foo = MethodTester; + + deprecated(); + foo.method_deprecated(); + Foo::method_deprecated(&foo); + <Foo>::method_deprecated(&foo); + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + <Foo>::trait_deprecated(&foo); + <Foo as Trait>::trait_deprecated(&foo); + + deprecated_text(); + foo.method_deprecated_text(); + Foo::method_deprecated_text(&foo); + <Foo>::method_deprecated_text(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + <Foo>::trait_deprecated_text(&foo); + <Foo as Trait>::trait_deprecated_text(&foo); + + unstable(); + foo.method_unstable(); + Foo::method_unstable(&foo); + <Foo>::method_unstable(&foo); + foo.trait_unstable(); + Trait::trait_unstable(&foo); + <Foo>::trait_unstable(&foo); + <Foo as Trait>::trait_unstable(&foo); + + unstable_text(); + foo.method_unstable_text(); + Foo::method_unstable_text(&foo); + <Foo>::method_unstable_text(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + <Foo>::trait_unstable_text(&foo); + <Foo as Trait>::trait_unstable_text(&foo); + + stable(); + foo.method_stable(); + Foo::method_stable(&foo); + <Foo>::method_stable(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + <Foo>::trait_stable(&foo); + <Foo as Trait>::trait_stable(&foo); + + stable_text(); + foo.method_stable_text(); + Foo::method_stable_text(&foo); + <Foo>::method_stable_text(&foo); + foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + <Foo>::trait_stable_text(&foo); + <Foo as Trait>::trait_stable_text(&foo); + + let _ = DeprecatedStruct { + i: 0 + }; + let _ = UnstableStruct { i: 0 }; + let _ = StableStruct { i: 0 }; + + let _ = DeprecatedUnitStruct; + let _ = UnstableUnitStruct; + let _ = StableUnitStruct; + + let _ = Enum::DeprecatedVariant; + let _ = Enum::UnstableVariant; + let _ = Enum::StableVariant; + + let _ = DeprecatedTupleStruct (1); + let _ = UnstableTupleStruct (1); + let _ = StableTupleStruct (1); + } + + fn test_method_param<Foo: Trait>(foo: Foo) { + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + <Foo>::trait_deprecated(&foo); + <Foo as Trait>::trait_deprecated(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + <Foo>::trait_deprecated_text(&foo); + <Foo as Trait>::trait_deprecated_text(&foo); + foo.trait_unstable(); + Trait::trait_unstable(&foo); + <Foo>::trait_unstable(&foo); + <Foo as Trait>::trait_unstable(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + <Foo>::trait_unstable_text(&foo); + <Foo as Trait>::trait_unstable_text(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + <Foo>::trait_stable(&foo); + <Foo as Trait>::trait_stable(&foo); + } + + fn test_method_object(foo: &dyn Trait) { + foo.trait_deprecated(); + foo.trait_deprecated_text(); + foo.trait_unstable(); + foo.trait_unstable_text(); + foo.trait_stable(); + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn test_fn_body() { + fn fn_in_body() {} + fn_in_body(); + } + + impl MethodTester { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn test_method_body(&self) { + fn fn_in_body() {} + fn_in_body(); + } + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub trait DeprecatedTrait { + fn dummy(&self) { } + } + + struct S; + + impl DeprecatedTrait for S { } + + trait LocalTrait : DeprecatedTrait { } +} + +fn main() {} diff --git a/tests/ui/lint/lint-stability-2.stderr b/tests/ui/lint/lint-stability-2.stderr new file mode 100644 index 000000000..5b7537fa2 --- /dev/null +++ b/tests/ui/lint/lint-stability-2.stderr @@ -0,0 +1,259 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:40:13 + | +LL | foo.method_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:42:9 + | +LL | Foo::method_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:44:9 + | +LL | <Foo>::method_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:46:13 + | +LL | foo.trait_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:48:9 + | +LL | <Foo>::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:51:13 + | +LL | foo.method_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:53:9 + | +LL | Foo::method_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:55:9 + | +LL | <Foo>::method_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:57:13 + | +LL | foo.trait_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:59:9 + | +LL | <Foo>::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:62:13 + | +LL | foo.method_unstable(); + | ^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:63:9 + | +LL | Foo::method_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:64:9 + | +LL | <Foo>::method_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:65:13 + | +LL | foo.trait_unstable(); + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:66:9 + | +LL | <Foo>::trait_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:68:13 + | +LL | foo.method_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:70:9 + | +LL | Foo::method_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:72:9 + | +LL | <Foo>::method_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:74:13 + | +LL | foo.trait_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:76:9 + | +LL | <Foo>::trait_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:131:13 + | +LL | foo.trait_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:133:9 + | +LL | <Foo>::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:135:13 + | +LL | foo.trait_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:137:9 + | +LL | <Foo>::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:139:13 + | +LL | foo.trait_unstable(); + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:140:9 + | +LL | <Foo>::trait_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:141:13 + | +LL | foo.trait_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:143:9 + | +LL | <Foo>::trait_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:154:13 + | +LL | foo.trait_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:156:13 + | +LL | foo.trait_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:158:13 + | +LL | foo.trait_unstable(); + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:159:13 + | +LL | foo.trait_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to 32 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/lint-stability-deprecated.rs b/tests/ui/lint/lint-stability-deprecated.rs new file mode 100644 index 000000000..74c35083e --- /dev/null +++ b/tests/ui/lint/lint-stability-deprecated.rs @@ -0,0 +1,464 @@ +// check-pass +// aux-build:lint_stability.rs +// aux-build:inherited_stability.rs +// aux-build:stability_cfg1.rs +// aux-build:stability-cfg2.rs +#![warn(deprecated)] +#![feature(staged_api, unstable_test_feature)] + +#![stable(feature = "rust1", since = "1.0.0")] + +#[macro_use] +extern crate lint_stability; + +mod cross_crate { + extern crate stability_cfg1; + extern crate stability_cfg2; + + use lint_stability::*; + + fn test() { + type Foo = MethodTester; + let foo = MethodTester; + + deprecated(); //~ WARN use of deprecated function `lint_stability::deprecated` + foo.method_deprecated(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated` + Foo::method_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated` + <Foo>::method_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated` + foo.trait_deprecated(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + + deprecated_text(); //~ WARN use of deprecated function `lint_stability::deprecated_text`: text + foo.method_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text + Foo::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text + <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text + foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + + deprecated_unstable(); //~ WARN use of deprecated function `lint_stability::deprecated_unstable` + foo.method_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable` + Foo::method_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable` + <Foo>::method_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable` + foo.trait_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + + deprecated_unstable_text(); //~ WARN use of deprecated function `lint_stability::deprecated_unstable_text`: text + foo.method_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text + Foo::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text + <Foo>::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text + foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + + unstable(); + foo.method_unstable(); + Foo::method_unstable(&foo); + <Foo>::method_unstable(&foo); + foo.trait_unstable(); + Trait::trait_unstable(&foo); + <Foo>::trait_unstable(&foo); + <Foo as Trait>::trait_unstable(&foo); + + unstable_text(); + foo.method_unstable_text(); + Foo::method_unstable_text(&foo); + <Foo>::method_unstable_text(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + <Foo>::trait_unstable_text(&foo); + <Foo as Trait>::trait_unstable_text(&foo); + + stable(); + foo.method_stable(); + Foo::method_stable(&foo); + <Foo>::method_stable(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + <Foo>::trait_stable(&foo); + <Foo as Trait>::trait_stable(&foo); + + stable_text(); + foo.method_stable_text(); + Foo::method_stable_text(&foo); + <Foo>::method_stable_text(&foo); + foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + <Foo>::trait_stable_text(&foo); + <Foo as Trait>::trait_stable_text(&foo); + + struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable); + struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated); + //~^ WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + type A = dyn TraitWithAssociatedTypes< + TypeUnstable = u8, + TypeDeprecated = u16, + //~^ WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` + //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` + //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` + >; + + let _ = DeprecatedStruct { //~ WARN use of deprecated struct `lint_stability::DeprecatedStruct` + i: 0 //~ WARN use of deprecated field `lint_stability::DeprecatedStruct::i` + }; + let _ = DeprecatedUnstableStruct { + //~^ WARN use of deprecated struct `lint_stability::DeprecatedUnstableStruct` + i: 0 //~ WARN use of deprecated field `lint_stability::DeprecatedUnstableStruct::i` + }; + let _ = UnstableStruct { i: 0 }; + let _ = StableStruct { i: 0 }; + + let _ = DeprecatedUnitStruct; //~ WARN use of deprecated unit struct `lint_stability::DeprecatedUnitStruct` + let _ = DeprecatedUnstableUnitStruct; //~ WARN use of deprecated unit struct `lint_stability::DeprecatedUnstableUnitStruct` + let _ = UnstableUnitStruct; + let _ = StableUnitStruct; + + let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated unit variant `lint_stability::Enum::DeprecatedVariant` + let _ = Enum::DeprecatedUnstableVariant; //~ WARN use of deprecated unit variant `lint_stability::Enum::DeprecatedUnstableVariant` + let _ = Enum::UnstableVariant; + let _ = Enum::StableVariant; + + let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated tuple struct `lint_stability::DeprecatedTupleStruct` + let _ = DeprecatedUnstableTupleStruct (1); //~ WARN use of deprecated tuple struct `lint_stability::DeprecatedUnstableTupleStruct` + let _ = UnstableTupleStruct (1); + let _ = StableTupleStruct (1); + + // At the moment, the lint checker only checks stability + // in the arguments of macros. + // Eventually, we will want to lint the contents of the + // macro in the module *defining* it. Also, stability levels + // on macros themselves are not yet linted. + macro_test_arg!(deprecated_text()); //~ WARN use of deprecated function `lint_stability::deprecated_text`: text + macro_test_arg!(deprecated_unstable_text()); //~ WARN use of deprecated function `lint_stability::deprecated_unstable_text`: text + macro_test_arg!(macro_test_arg!(deprecated_text())); //~ WARN use of deprecated function `lint_stability::deprecated_text`: text + } + + fn test_method_param<Foo: Trait>(foo: Foo) { + foo.trait_deprecated(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + foo.trait_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + foo.trait_unstable(); + Trait::trait_unstable(&foo); + <Foo>::trait_unstable(&foo); + <Foo as Trait>::trait_unstable(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + <Foo>::trait_unstable_text(&foo); + <Foo as Trait>::trait_unstable_text(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + <Foo>::trait_stable(&foo); + <Foo as Trait>::trait_stable(&foo); + } + + fn test_method_object(foo: &dyn Trait) { + foo.trait_deprecated(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + foo.trait_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + foo.trait_unstable(); + foo.trait_unstable_text(); + foo.trait_stable(); + } + + struct S; + + impl UnstableTrait for S { } + impl DeprecatedTrait for S {} //~ WARN use of deprecated trait `lint_stability::DeprecatedTrait`: text + trait LocalTrait : UnstableTrait { } + trait LocalTrait2 : DeprecatedTrait { } //~ WARN use of deprecated trait `lint_stability::DeprecatedTrait`: text + + impl Trait for S { + fn trait_stable(&self) {} + fn trait_unstable(&self) {} + } +} + +mod inheritance { + extern crate inherited_stability; + use self::inherited_stability::*; + + fn test_inheritance() { + unstable(); + stable(); + + stable_mod::unstable(); + stable_mod::stable(); + + unstable_mod::deprecated(); //~ WARN use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text + unstable_mod::unstable(); + + let _ = Unstable::UnstableVariant; + let _ = Unstable::StableVariant; + + let x: usize = 0; + x.unstable(); + x.stable(); + } +} + +mod this_crate { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated() {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated_text() {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn unstable() {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn unstable_text() {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stable() {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stable_text() {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub struct MethodTester; + + impl MethodTester { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn method_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn method_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable_text(&self) {} + } + + pub trait Trait { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + fn trait_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + fn trait_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable_text(&self) {} + } + + impl Trait for MethodTester {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedUnitStruct; + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableUnitStruct; + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableUnitStruct; + + pub enum Enum { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedVariant, + #[unstable(feature = "unstable_test_feature", issue = "none")] + UnstableVariant, + + #[stable(feature = "rust1", since = "1.0.0")] + StableVariant, + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedTupleStruct(isize); + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableTupleStruct(isize); + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableTupleStruct(isize); + + fn test() { + // Only the deprecated cases of the following should generate + // errors, because other stability attributes now have meaning + // only *across* crates, not within a single crate. + + type Foo = MethodTester; + let foo = MethodTester; + + deprecated(); //~ WARN use of deprecated function `this_crate::deprecated` + foo.method_deprecated(); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated` + Foo::method_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated` + <Foo>::method_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated` + foo.trait_deprecated(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + + deprecated_text(); //~ WARN use of deprecated function `this_crate::deprecated_text`: text + foo.method_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + Foo::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + + unstable(); + foo.method_unstable(); + Foo::method_unstable(&foo); + <Foo>::method_unstable(&foo); + foo.trait_unstable(); + Trait::trait_unstable(&foo); + <Foo>::trait_unstable(&foo); + <Foo as Trait>::trait_unstable(&foo); + + unstable_text(); + foo.method_unstable_text(); + Foo::method_unstable_text(&foo); + <Foo>::method_unstable_text(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + <Foo>::trait_unstable_text(&foo); + <Foo as Trait>::trait_unstable_text(&foo); + + stable(); + foo.method_stable(); + Foo::method_stable(&foo); + <Foo>::method_stable(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + <Foo>::trait_stable(&foo); + <Foo as Trait>::trait_stable(&foo); + + stable_text(); + foo.method_stable_text(); + Foo::method_stable_text(&foo); + <Foo>::method_stable_text(&foo); + foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + <Foo>::trait_stable_text(&foo); + <Foo as Trait>::trait_stable_text(&foo); + + let _ = DeprecatedStruct { + //~^ WARN use of deprecated struct `this_crate::DeprecatedStruct` + i: 0 //~ WARN use of deprecated field `this_crate::DeprecatedStruct::i` + }; + let _ = UnstableStruct { i: 0 }; + let _ = StableStruct { i: 0 }; + + let _ = DeprecatedUnitStruct; //~ WARN use of deprecated unit struct `this_crate::DeprecatedUnitStruct` + let _ = UnstableUnitStruct; + let _ = StableUnitStruct; + + let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated unit variant `this_crate::Enum::DeprecatedVariant` + let _ = Enum::UnstableVariant; + let _ = Enum::StableVariant; + + let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated tuple struct `this_crate::DeprecatedTupleStruct` + let _ = UnstableTupleStruct (1); + let _ = StableTupleStruct (1); + } + + fn test_method_param<Foo: Trait>(foo: Foo) { + foo.trait_deprecated(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + foo.trait_unstable(); + Trait::trait_unstable(&foo); + <Foo>::trait_unstable(&foo); + <Foo as Trait>::trait_unstable(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + <Foo>::trait_unstable_text(&foo); + <Foo as Trait>::trait_unstable_text(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + <Foo>::trait_stable(&foo); + <Foo as Trait>::trait_stable(&foo); + } + + fn test_method_object(foo: &dyn Trait) { + foo.trait_deprecated(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + foo.trait_unstable(); + foo.trait_unstable_text(); + foo.trait_stable(); + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn test_fn_body() { + fn fn_in_body() {} + fn_in_body(); //~ WARN use of deprecated function `this_crate::test_fn_body::fn_in_body`: text + } + + impl MethodTester { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn test_method_body(&self) { + fn fn_in_body() {} + fn_in_body(); //~ WARN use of deprecated function `this_crate::MethodTester::test_method_body::fn_in_body`: text + } + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub trait DeprecatedTrait { + fn dummy(&self) { } + } + + struct S; + + impl DeprecatedTrait for S { } //~ WARN use of deprecated trait `this_crate::DeprecatedTrait` + + trait LocalTrait : DeprecatedTrait { } //~ WARN use of deprecated trait `this_crate::DeprecatedTrait` +} + +fn main() {} diff --git a/tests/ui/lint/lint-stability-deprecated.stderr b/tests/ui/lint/lint-stability-deprecated.stderr new file mode 100644 index 000000000..9f1e7b281 --- /dev/null +++ b/tests/ui/lint/lint-stability-deprecated.stderr @@ -0,0 +1,656 @@ +warning: use of deprecated function `lint_stability::deprecated`: text + --> $DIR/lint-stability-deprecated.rs:24:9 + | +LL | deprecated(); + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-stability-deprecated.rs:6:9 + | +LL | #![warn(deprecated)] + | ^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:29:16 + | +LL | Trait::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:31:25 + | +LL | <Foo as Trait>::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `lint_stability::deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:33:9 + | +LL | deprecated_text(); + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:38:16 + | +LL | ... Trait::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:40:25 + | +LL | ... <Foo as Trait>::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `lint_stability::deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:42:9 + | +LL | deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:47:16 + | +LL | ... Trait::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:49:25 + | +LL | ... <Foo as Trait>::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:51:9 + | +LL | deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:56:16 + | +LL | ... Trait::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:58:25 + | +LL | ... <Foo as Trait>::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated struct `lint_stability::DeprecatedStruct`: text + --> $DIR/lint-stability-deprecated.rs:108:17 + | +LL | let _ = DeprecatedStruct { + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated struct `lint_stability::DeprecatedUnstableStruct`: text + --> $DIR/lint-stability-deprecated.rs:111:17 + | +LL | let _ = DeprecatedUnstableStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated unit struct `lint_stability::DeprecatedUnitStruct`: text + --> $DIR/lint-stability-deprecated.rs:118:17 + | +LL | let _ = DeprecatedUnitStruct; + | ^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated unit struct `lint_stability::DeprecatedUnstableUnitStruct`: text + --> $DIR/lint-stability-deprecated.rs:119:17 + | +LL | let _ = DeprecatedUnstableUnitStruct; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated unit variant `lint_stability::Enum::DeprecatedVariant`: text + --> $DIR/lint-stability-deprecated.rs:123:23 + | +LL | let _ = Enum::DeprecatedVariant; + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated unit variant `lint_stability::Enum::DeprecatedUnstableVariant`: text + --> $DIR/lint-stability-deprecated.rs:124:23 + | +LL | let _ = Enum::DeprecatedUnstableVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated tuple struct `lint_stability::DeprecatedTupleStruct`: text + --> $DIR/lint-stability-deprecated.rs:128:17 + | +LL | let _ = DeprecatedTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated tuple struct `lint_stability::DeprecatedUnstableTupleStruct`: text + --> $DIR/lint-stability-deprecated.rs:129:17 + | +LL | let _ = DeprecatedUnstableTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `lint_stability::deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:138:25 + | +LL | macro_test_arg!(deprecated_text()); + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:139:25 + | +LL | macro_test_arg!(deprecated_unstable_text()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `lint_stability::deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:140:41 + | +LL | macro_test_arg!(macro_test_arg!(deprecated_text())); + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:145:16 + | +LL | Trait::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:147:25 + | +LL | <Foo as Trait>::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:149:16 + | +LL | ... Trait::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:151:25 + | +LL | ... <Foo as Trait>::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:153:16 + | +LL | ... Trait::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:155:25 + | +LL | ... <Foo as Trait>::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:157:16 + | +LL | ... Trait::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:159:25 + | +LL | ... <Foo as Trait>::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text + --> $DIR/lint-stability-deprecated.rs:187:10 + | +LL | impl DeprecatedTrait for S {} + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text + --> $DIR/lint-stability-deprecated.rs:189:25 + | +LL | trait LocalTrait2 : DeprecatedTrait { } + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text + --> $DIR/lint-stability-deprecated.rs:208:23 + | +LL | unstable_mod::deprecated(); + | ^^^^^^^^^^ + +warning: use of deprecated function `this_crate::deprecated`: text + --> $DIR/lint-stability-deprecated.rs:330:9 + | +LL | deprecated(); + | ^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:335:16 + | +LL | Trait::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:337:25 + | +LL | <Foo as Trait>::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `this_crate::deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:339:9 + | +LL | deprecated_text(); + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:344:16 + | +LL | Trait::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:346:25 + | +LL | ... <Foo as Trait>::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated struct `this_crate::DeprecatedStruct`: text + --> $DIR/lint-stability-deprecated.rs:384:17 + | +LL | let _ = DeprecatedStruct { + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated unit struct `this_crate::DeprecatedUnitStruct`: text + --> $DIR/lint-stability-deprecated.rs:391:17 + | +LL | let _ = DeprecatedUnitStruct; + | ^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text + --> $DIR/lint-stability-deprecated.rs:395:23 + | +LL | let _ = Enum::DeprecatedVariant; + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text + --> $DIR/lint-stability-deprecated.rs:399:17 + | +LL | let _ = DeprecatedTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:406:16 + | +LL | Trait::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:408:25 + | +LL | <Foo as Trait>::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:410:16 + | +LL | Trait::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:412:25 + | +LL | ... <Foo as Trait>::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `this_crate::test_fn_body::fn_in_body`: text + --> $DIR/lint-stability-deprecated.rs:439:9 + | +LL | fn_in_body(); + | ^^^^^^^^^^ + +warning: use of deprecated trait `this_crate::DeprecatedTrait`: text + --> $DIR/lint-stability-deprecated.rs:459:10 + | +LL | impl DeprecatedTrait for S { } + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated trait `this_crate::DeprecatedTrait`: text + --> $DIR/lint-stability-deprecated.rs:461:24 + | +LL | trait LocalTrait : DeprecatedTrait { } + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated function `this_crate::MethodTester::test_method_body::fn_in_body`: text + --> $DIR/lint-stability-deprecated.rs:447:13 + | +LL | fn_in_body(); + | ^^^^^^^^^^ + +warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + --> $DIR/lint-stability-deprecated.rs:97:48 + | +LL | struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + --> $DIR/lint-stability-deprecated.rs:102:13 + | +LL | TypeDeprecated = u16, + | ^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:25:13 + | +LL | foo.method_deprecated(); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:26:14 + | +LL | Foo::method_deprecated(&foo); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:27:16 + | +LL | <Foo>::method_deprecated(&foo); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:28:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:30:16 + | +LL | <Foo>::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:34:13 + | +LL | ... foo.method_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:35:14 + | +LL | ... Foo::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:36:16 + | +LL | ... <Foo>::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:37:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:39:16 + | +LL | ... <Foo>::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:43:13 + | +LL | ... foo.method_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:44:14 + | +LL | ... Foo::method_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:45:16 + | +LL | ... <Foo>::method_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:46:13 + | +LL | foo.trait_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:48:16 + | +LL | ... <Foo>::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:52:13 + | +LL | ... foo.method_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:53:14 + | +LL | ... Foo::method_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:54:16 + | +LL | ... <Foo>::method_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:55:13 + | +LL | ... foo.trait_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:57:16 + | +LL | ... <Foo>::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated field `lint_stability::DeprecatedStruct::i`: text + --> $DIR/lint-stability-deprecated.rs:109:13 + | +LL | i: 0 + | ^^^^ + +warning: use of deprecated field `lint_stability::DeprecatedUnstableStruct::i`: text + --> $DIR/lint-stability-deprecated.rs:113:13 + | +LL | i: 0 + | ^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:144:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:146:16 + | +LL | <Foo>::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:148:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:150:16 + | +LL | ... <Foo>::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:152:13 + | +LL | foo.trait_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:154:16 + | +LL | ... <Foo>::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:156:13 + | +LL | ... foo.trait_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:158:16 + | +LL | ... <Foo>::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:175:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:176:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:177:13 + | +LL | foo.trait_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:178:13 + | +LL | ... foo.trait_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:331:13 + | +LL | foo.method_deprecated(); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:332:14 + | +LL | Foo::method_deprecated(&foo); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:333:16 + | +LL | <Foo>::method_deprecated(&foo); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:334:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:336:16 + | +LL | <Foo>::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:340:13 + | +LL | ... foo.method_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:341:14 + | +LL | ... Foo::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:342:16 + | +LL | ... <Foo>::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:343:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:345:16 + | +LL | <Foo>::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated field `this_crate::DeprecatedStruct::i`: text + --> $DIR/lint-stability-deprecated.rs:386:13 + | +LL | i: 0 + | ^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:405:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:407:16 + | +LL | <Foo>::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:409:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:411:16 + | +LL | <Foo>::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:428:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:429:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + --> $DIR/lint-stability-deprecated.rs:97:48 + | +LL | struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + --> $DIR/lint-stability-deprecated.rs:102:13 + | +LL | TypeDeprecated = u16, + | ^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + --> $DIR/lint-stability-deprecated.rs:102:13 + | +LL | TypeDeprecated = u16, + | ^^^^^^^^^^^^^^^^^^^^ + +warning: 108 warnings emitted + diff --git a/tests/ui/lint/lint-stability-fields-deprecated.rs b/tests/ui/lint/lint-stability-fields-deprecated.rs new file mode 100644 index 000000000..a5511966d --- /dev/null +++ b/tests/ui/lint/lint-stability-fields-deprecated.rs @@ -0,0 +1,344 @@ +// aux-build:lint_stability_fields.rs + +#![deny(deprecated)] +#![allow(dead_code)] +#![feature(staged_api, unstable_test_feature)] + +#![stable(feature = "rust1", since = "1.0.0")] + +mod cross_crate { + extern crate lint_stability_fields; + + use self::lint_stability_fields::*; + + pub fn foo() { + let x = Stable { + inherit: 1, + override1: 2, + override2: 3, + //~^ ERROR use of deprecated field + override3: 4, + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + //~^ ERROR use of deprecated field + let _ = x.override3; + + let Stable { + inherit: _, + override1: _, + override2: _, + //~^ ERROR use of deprecated field + override3: _, + } = x; + // all fine + let Stable { .. } = x; + + let x = Stable2(1, 2, 3, 4); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + //~^ ERROR use of deprecated field + let _ = x.3; + + let Stable2(_, + _, + _, + //~^ ERROR use of deprecated field + _) + = x; + // all fine + let Stable2(..) = x; + + + let x = Unstable { + inherit: 1, + override1: 2, + override2: 3, + //~^ ERROR use of deprecated field + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + //~^ ERROR use of deprecated field + + let Unstable { + inherit: _, + override1: _, + override2: _ + //~^ ERROR use of deprecated field + } = x; + + let Unstable + // the patterns are all fine: + { .. } = x; + + + let x = Unstable2(1, 2, 3); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + //~^ ERROR use of deprecated field + + let Unstable2 + (_, + _, + _) + //~^ ERROR use of deprecated field + = x; + let Unstable2 + // the patterns are all fine: + (..) = x; + + + let x = Deprecated { + //~^ ERROR use of deprecated struct + inherit: 1, + //~^ ERROR use of deprecated field + override1: 2, + //~^ ERROR use of deprecated field + override2: 3, + //~^ ERROR use of deprecated field + }; + + let _ = x.inherit; + //~^ ERROR use of deprecated field + let _ = x.override1; + //~^ ERROR use of deprecated field + let _ = x.override2; + //~^ ERROR use of deprecated field + + let Deprecated { + //~^ ERROR use of deprecated struct + inherit: _, + //~^ ERROR use of deprecated field + override1: _, + //~^ ERROR use of deprecated field + override2: _ + //~^ ERROR use of deprecated field + } = x; + + let Deprecated + //~^ ERROR use of deprecated struct + // the patterns are all fine: + { .. } = x; + + let x = Deprecated2(1, 2, 3); + //~^ ERROR use of deprecated tuple struct + + let _ = x.0; + //~^ ERROR use of deprecated field + let _ = x.1; + //~^ ERROR use of deprecated field + let _ = x.2; + //~^ ERROR use of deprecated field + + let Deprecated2 + //~^ ERROR use of deprecated tuple struct + (_, + //~^ ERROR use of deprecated field + _, + //~^ ERROR use of deprecated field + _) + //~^ ERROR use of deprecated field + = x; + let Deprecated2 + //~^ ERROR use of deprecated tuple struct + // the patterns are all fine: + (..) = x; + } +} + +mod this_crate { + #[stable(feature = "rust1", since = "1.0.0")] + struct Stable { + inherit: u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + override1: u8, + #[deprecated(since = "1.0.0", note = "text")] + #[unstable(feature = "unstable_test_feature", issue = "none")] + override2: u8, + } + + #[stable(feature = "rust1", since = "1.0.0")] + struct Stable2(u8, + #[stable(feature = "rust1", since = "1.0.0")] u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] u8); + + #[unstable(feature = "unstable_test_feature", issue = "none")] + struct Unstable { + inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + override1: u8, + #[deprecated(since = "1.0.0", note = "text")] + #[unstable(feature = "unstable_test_feature", issue = "none")] + override2: u8, + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + struct Unstable2(u8, + #[stable(feature = "rust1", since = "1.0.0")] u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] u8); + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + struct Deprecated { + inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + override1: u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + override2: u8, + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + struct Deprecated2(u8, + #[stable(feature = "rust1", since = "1.0.0")] u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] u8); + + pub fn foo() { + let x = Stable { + inherit: 1, + override1: 2, + override2: 3, + //~^ ERROR use of deprecated field + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + //~^ ERROR use of deprecated field + + let Stable { + inherit: _, + override1: _, + override2: _ + //~^ ERROR use of deprecated field + } = x; + // all fine + let Stable { .. } = x; + + let x = Stable2(1, 2, 3); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + //~^ ERROR use of deprecated field + + let Stable2(_, + _, + _) + //~^ ERROR use of deprecated field + = x; + // all fine + let Stable2(..) = x; + + + let x = Unstable { + inherit: 1, + override1: 2, + override2: 3, + //~^ ERROR use of deprecated field + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + //~^ ERROR use of deprecated field + + let Unstable { + inherit: _, + override1: _, + override2: _ + //~^ ERROR use of deprecated field + } = x; + + let Unstable + // the patterns are all fine: + { .. } = x; + + + let x = Unstable2(1, 2, 3); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + //~^ ERROR use of deprecated field + + let Unstable2 + (_, + _, + _) + //~^ ERROR use of deprecated field + = x; + let Unstable2 + // the patterns are all fine: + (..) = x; + + + let x = Deprecated { + //~^ ERROR use of deprecated struct + inherit: 1, + //~^ ERROR use of deprecated field + override1: 2, + //~^ ERROR use of deprecated field + override2: 3, + //~^ ERROR use of deprecated field + }; + + let _ = x.inherit; + //~^ ERROR use of deprecated field + let _ = x.override1; + //~^ ERROR use of deprecated field + let _ = x.override2; + //~^ ERROR use of deprecated field + + let Deprecated { + //~^ ERROR use of deprecated struct + inherit: _, + //~^ ERROR use of deprecated field + override1: _, + //~^ ERROR use of deprecated field + override2: _ + //~^ ERROR use of deprecated field + } = x; + + let Deprecated + //~^ ERROR use of deprecated struct + // the patterns are all fine: + { .. } = x; + + let x = Deprecated2(1, 2, 3); + //~^ ERROR use of deprecated tuple struct + + let _ = x.0; + //~^ ERROR use of deprecated field + let _ = x.1; + //~^ ERROR use of deprecated field + let _ = x.2; + //~^ ERROR use of deprecated field + + let Deprecated2 + //~^ ERROR use of deprecated tuple struct + (_, + //~^ ERROR use of deprecated field + _, + //~^ ERROR use of deprecated field + _) + //~^ ERROR use of deprecated field + = x; + let Deprecated2 + //~^ ERROR use of deprecated tuple struct + // the patterns are all fine: + (..) = x; + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-stability-fields-deprecated.stderr b/tests/ui/lint/lint-stability-fields-deprecated.stderr new file mode 100644 index 000000000..2d8326020 --- /dev/null +++ b/tests/ui/lint/lint-stability-fields-deprecated.stderr @@ -0,0 +1,380 @@ +error: use of deprecated struct `cross_crate::lint_stability_fields::Deprecated`: text + --> $DIR/lint-stability-fields-deprecated.rs:99:17 + | +LL | let x = Deprecated { + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-stability-fields-deprecated.rs:3:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ + +error: use of deprecated struct `cross_crate::lint_stability_fields::Deprecated`: text + --> $DIR/lint-stability-fields-deprecated.rs:116:13 + | +LL | let Deprecated { + | ^^^^^^^^^^ + +error: use of deprecated struct `cross_crate::lint_stability_fields::Deprecated`: text + --> $DIR/lint-stability-fields-deprecated.rs:126:13 + | +LL | let Deprecated + | ^^^^^^^^^^ + +error: use of deprecated tuple struct `cross_crate::lint_stability_fields::Deprecated2`: text + --> $DIR/lint-stability-fields-deprecated.rs:131:17 + | +LL | let x = Deprecated2(1, 2, 3); + | ^^^^^^^^^^^ + +error: use of deprecated tuple struct `cross_crate::lint_stability_fields::Deprecated2`: text + --> $DIR/lint-stability-fields-deprecated.rs:141:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + +error: use of deprecated tuple struct `cross_crate::lint_stability_fields::Deprecated2`: text + --> $DIR/lint-stability-fields-deprecated.rs:150:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + +error: use of deprecated struct `this_crate::Deprecated`: text + --> $DIR/lint-stability-fields-deprecated.rs:286:17 + | +LL | let x = Deprecated { + | ^^^^^^^^^^ + +error: use of deprecated struct `this_crate::Deprecated`: text + --> $DIR/lint-stability-fields-deprecated.rs:303:13 + | +LL | let Deprecated { + | ^^^^^^^^^^ + +error: use of deprecated struct `this_crate::Deprecated`: text + --> $DIR/lint-stability-fields-deprecated.rs:313:13 + | +LL | let Deprecated + | ^^^^^^^^^^ + +error: use of deprecated tuple struct `this_crate::Deprecated2`: text + --> $DIR/lint-stability-fields-deprecated.rs:318:17 + | +LL | let x = Deprecated2(1, 2, 3); + | ^^^^^^^^^^^ + +error: use of deprecated tuple struct `this_crate::Deprecated2`: text + --> $DIR/lint-stability-fields-deprecated.rs:328:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + +error: use of deprecated tuple struct `this_crate::Deprecated2`: text + --> $DIR/lint-stability-fields-deprecated.rs:337:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Stable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:18:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Stable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:25:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Stable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:32:13 + | +LL | override2: _, + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Stable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:43:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Stable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:49:20 + | +LL | _, + | ^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Unstable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:60:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Unstable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:66:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Unstable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:72:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Unstable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:85:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Unstable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:91:14 + | +LL | _) + | ^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::inherit`: text + --> $DIR/lint-stability-fields-deprecated.rs:101:13 + | +LL | inherit: 1, + | ^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override1`: text + --> $DIR/lint-stability-fields-deprecated.rs:103:13 + | +LL | override1: 2, + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:105:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::inherit`: text + --> $DIR/lint-stability-fields-deprecated.rs:109:17 + | +LL | let _ = x.inherit; + | ^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override1`: text + --> $DIR/lint-stability-fields-deprecated.rs:111:17 + | +LL | let _ = x.override1; + | ^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:113:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::inherit`: text + --> $DIR/lint-stability-fields-deprecated.rs:118:13 + | +LL | inherit: _, + | ^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override1`: text + --> $DIR/lint-stability-fields-deprecated.rs:120:13 + | +LL | override1: _, + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:122:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::0`: text + --> $DIR/lint-stability-fields-deprecated.rs:134:17 + | +LL | let _ = x.0; + | ^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::1`: text + --> $DIR/lint-stability-fields-deprecated.rs:136:17 + | +LL | let _ = x.1; + | ^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:138:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::0`: text + --> $DIR/lint-stability-fields-deprecated.rs:143:14 + | +LL | (_, + | ^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::1`: text + --> $DIR/lint-stability-fields-deprecated.rs:145:14 + | +LL | _, + | ^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:147:14 + | +LL | _) + | ^ + +error: use of deprecated field `this_crate::Stable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:210:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Stable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:216:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Stable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:222:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Stable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:232:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `this_crate::Stable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:237:20 + | +LL | _) + | ^ + +error: use of deprecated field `this_crate::Unstable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:247:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Unstable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:253:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Unstable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:259:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Unstable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:272:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `this_crate::Unstable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:278:14 + | +LL | _) + | ^ + +error: use of deprecated field `this_crate::Deprecated::inherit`: text + --> $DIR/lint-stability-fields-deprecated.rs:288:13 + | +LL | inherit: 1, + | ^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::override1`: text + --> $DIR/lint-stability-fields-deprecated.rs:290:13 + | +LL | override1: 2, + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:292:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::inherit`: text + --> $DIR/lint-stability-fields-deprecated.rs:296:17 + | +LL | let _ = x.inherit; + | ^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::override1`: text + --> $DIR/lint-stability-fields-deprecated.rs:298:17 + | +LL | let _ = x.override1; + | ^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:300:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::inherit`: text + --> $DIR/lint-stability-fields-deprecated.rs:305:13 + | +LL | inherit: _, + | ^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::override1`: text + --> $DIR/lint-stability-fields-deprecated.rs:307:13 + | +LL | override1: _, + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:309:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated2::0`: text + --> $DIR/lint-stability-fields-deprecated.rs:321:17 + | +LL | let _ = x.0; + | ^^^ + +error: use of deprecated field `this_crate::Deprecated2::1`: text + --> $DIR/lint-stability-fields-deprecated.rs:323:17 + | +LL | let _ = x.1; + | ^^^ + +error: use of deprecated field `this_crate::Deprecated2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:325:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `this_crate::Deprecated2::0`: text + --> $DIR/lint-stability-fields-deprecated.rs:330:14 + | +LL | (_, + | ^ + +error: use of deprecated field `this_crate::Deprecated2::1`: text + --> $DIR/lint-stability-fields-deprecated.rs:332:14 + | +LL | _, + | ^ + +error: use of deprecated field `this_crate::Deprecated2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:334:14 + | +LL | _) + | ^ + +error: aborting due to 62 previous errors + diff --git a/tests/ui/lint/lint-stability-fields.rs b/tests/ui/lint/lint-stability-fields.rs new file mode 100644 index 000000000..51990b6ee --- /dev/null +++ b/tests/ui/lint/lint-stability-fields.rs @@ -0,0 +1,293 @@ +// aux-build:lint_stability_fields.rs +#![allow(deprecated)] +#![allow(dead_code)] +#![feature(staged_api)] + +#![stable(feature = "rust1", since = "1.0.0")] + +mod cross_crate { + extern crate lint_stability_fields; + + mod reexport { + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::lint_stability_fields::*; + } + + use self::lint_stability_fields::*; + + pub fn foo() { + let x = Stable { + inherit: 1, + override1: 2, //~ ERROR use of unstable + override2: 3, //~ ERROR use of unstable + override3: 4, + }; + + let _ = x.inherit; + let _ = x.override1; //~ ERROR use of unstable + let _ = x.override2; //~ ERROR use of unstable + let _ = x.override3; + + let Stable { + inherit: _, + override1: _, //~ ERROR use of unstable + override2: _, //~ ERROR use of unstable + override3: _ + } = x; + // all fine + let Stable { .. } = x; + + let x = Stable2(1, 2, 3, 4); + + let _ = x.0; + let _ = x.1; //~ ERROR use of unstable + let _ = x.2; //~ ERROR use of unstable + let _ = x.3; + + let Stable2(_, + _, //~ ERROR use of unstable + _, //~ ERROR use of unstable + _) + = x; + // all fine + let Stable2(..) = x; + + + let x = Unstable { //~ ERROR use of unstable + inherit: 1, //~ ERROR use of unstable + override1: 2, + override2: 3, //~ ERROR use of unstable + }; + + let _ = x.inherit; //~ ERROR use of unstable + let _ = x.override1; + let _ = x.override2; //~ ERROR use of unstable + + let Unstable { //~ ERROR use of unstable + inherit: _, //~ ERROR use of unstable + override1: _, + override2: _ //~ ERROR use of unstable + } = x; + + let Unstable //~ ERROR use of unstable + // the patterns are all fine: + { .. } = x; + + // Unstable items are still unstable even when used through a stable "pub use". + let x = reexport::Unstable2(1, 2, 3); //~ ERROR use of unstable + + let x = Unstable2(1, 2, 3); //~ ERROR use of unstable + + let _ = x.0; //~ ERROR use of unstable + let _ = x.1; + let _ = x.2; //~ ERROR use of unstable + + let Unstable2 //~ ERROR use of unstable + (_, //~ ERROR use of unstable + _, + _) //~ ERROR use of unstable + = x; + let Unstable2 //~ ERROR use of unstable + // the patterns are all fine: + (..) = x; + + + let x = Deprecated { //~ ERROR use of unstable + inherit: 1, //~ ERROR use of unstable + override1: 2, + override2: 3, //~ ERROR use of unstable + }; + + let _ = x.inherit; //~ ERROR use of unstable + let _ = x.override1; + let _ = x.override2; //~ ERROR use of unstable + + let Deprecated { //~ ERROR use of unstable + inherit: _, //~ ERROR use of unstable + override1: _, + override2: _ //~ ERROR use of unstable + } = x; + + let Deprecated //~ ERROR use of unstable + // the patterns are all fine: + { .. } = x; + + let x = Deprecated2(1, 2, 3); //~ ERROR use of unstable + + let _ = x.0; //~ ERROR use of unstable + let _ = x.1; + let _ = x.2; //~ ERROR use of unstable + + let Deprecated2 //~ ERROR use of unstable + (_, //~ ERROR use of unstable + _, + _) //~ ERROR use of unstable + = x; + let Deprecated2 //~ ERROR use of unstable + // the patterns are all fine: + (..) = x; + } +} + +mod this_crate { + #[stable(feature = "rust1", since = "1.0.0")] + struct Stable { + inherit: u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + override1: u8, + #[deprecated(since = "1.0.0", note = "text")] + #[unstable(feature = "unstable_test_feature", issue = "none")] + override2: u8, + #[stable(feature = "rust2", since = "2.0.0")] + override3: u8, + } + + #[stable(feature = "rust1", since = "1.0.0")] + struct Stable2(u8, + #[stable(feature = "rust2", since = "2.0.0")] u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] u8); + + #[unstable(feature = "unstable_test_feature", issue = "none")] + struct Unstable { + inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + override1: u8, + #[deprecated(since = "1.0.0", note = "text")] + #[unstable(feature = "unstable_test_feature", issue = "none")] + override2: u8, + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + struct Unstable2(u8, + #[stable(feature = "rust1", since = "1.0.0")] u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] u8); + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + struct Deprecated { + inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + override1: u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + override2: u8, + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + struct Deprecated2(u8, + #[stable(feature = "rust1", since = "1.0.0")] u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] u8); + + pub fn foo() { + let x = Stable { + inherit: 1, + override1: 2, + override2: 3, + override3: 4, + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + let _ = x.override3; + + let Stable { + inherit: _, + override1: _, + override2: _, + override3: _ + } = x; + // all fine + let Stable { .. } = x; + + let x = Stable2(1, 2, 3); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + + let Stable2(_, + _, + _) + = x; + // all fine + let Stable2(..) = x; + + + let x = Unstable { + inherit: 1, + override1: 2, + override2: 3, + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + + let Unstable { + inherit: _, + override1: _, + override2: _ + } = x; + + let Unstable + // the patterns are all fine: + { .. } = x; + + + let x = Unstable2(1, 2, 3); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + + let Unstable2 + (_, + _, + _) + = x; + let Unstable2 + // the patterns are all fine: + (..) = x; + + + let x = Deprecated { + inherit: 1, + override1: 2, + override2: 3, + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + + let Deprecated { + inherit: _, + override1: _, + override2: _ + } = x; + + let Deprecated + // the patterns are all fine: + { .. } = x; + + let x = Deprecated2(1, 2, 3); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + + let Deprecated2 + (_, + _, + _) + = x; + let Deprecated2 + // the patterns are all fine: + (..) = x; + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-stability-fields.stderr b/tests/ui/lint/lint-stability-fields.stderr new file mode 100644 index 000000000..3d2e73c1e --- /dev/null +++ b/tests/ui/lint/lint-stability-fields.stderr @@ -0,0 +1,347 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:56:17 + | +LL | let x = Unstable { + | ^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:66:13 + | +LL | let Unstable { + | ^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:72:13 + | +LL | let Unstable + | ^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:77:17 + | +LL | let x = reexport::Unstable2(1, 2, 3); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:79:17 + | +LL | let x = Unstable2(1, 2, 3); + | ^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:85:13 + | +LL | let Unstable2 + | ^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:90:13 + | +LL | let Unstable2 + | ^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:95:17 + | +LL | let x = Deprecated { + | ^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:105:13 + | +LL | let Deprecated { + | ^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:111:13 + | +LL | let Deprecated + | ^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:115:17 + | +LL | let x = Deprecated2(1, 2, 3); + | ^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:121:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:126:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:21:13 + | +LL | override1: 2, + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:22:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:27:17 + | +LL | let _ = x.override1; + | ^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:28:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:33:13 + | +LL | override1: _, + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:34:13 + | +LL | override2: _, + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:43:17 + | +LL | let _ = x.1; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:44:17 + | +LL | let _ = x.2; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:48:20 + | +LL | _, + | ^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:49:20 + | +LL | _, + | ^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:57:13 + | +LL | inherit: 1, + | ^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:59:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:62:17 + | +LL | let _ = x.inherit; + | ^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:64:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:67:13 + | +LL | inherit: _, + | ^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:69:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:81:17 + | +LL | let _ = x.0; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:83:17 + | +LL | let _ = x.2; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:86:14 + | +LL | (_, + | ^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:88:14 + | +LL | _) + | ^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:96:13 + | +LL | inherit: 1, + | ^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:98:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:101:17 + | +LL | let _ = x.inherit; + | ^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:103:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:106:13 + | +LL | inherit: _, + | ^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:108:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:117:17 + | +LL | let _ = x.0; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:119:17 + | +LL | let _ = x.2; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:122:14 + | +LL | (_, + | ^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:124:14 + | +LL | _) + | ^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to 43 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/lint-stability.rs b/tests/ui/lint/lint-stability.rs new file mode 100644 index 000000000..d0f0e9f80 --- /dev/null +++ b/tests/ui/lint/lint-stability.rs @@ -0,0 +1,454 @@ +// aux-build:lint_stability.rs +// aux-build:inherited_stability.rs +// aux-build:stability_cfg1.rs +// aux-build:stability-cfg2.rs + +#![allow(deprecated)] +#![allow(dead_code)] +#![feature(staged_api)] + +#![stable(feature = "rust1", since = "1.0.0")] + +#[macro_use] +extern crate lint_stability; + +mod cross_crate { + extern crate stability_cfg1; + extern crate stability_cfg2; //~ ERROR use of unstable library feature + + use lint_stability::*; + + fn test() { + type Foo = MethodTester; + let foo = MethodTester; + + deprecated(); + foo.method_deprecated(); + Foo::method_deprecated(&foo); + <Foo>::method_deprecated(&foo); + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + <Foo>::trait_deprecated(&foo); + <Foo as Trait>::trait_deprecated(&foo); + + deprecated_text(); + foo.method_deprecated_text(); + Foo::method_deprecated_text(&foo); + <Foo>::method_deprecated_text(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + <Foo>::trait_deprecated_text(&foo); + <Foo as Trait>::trait_deprecated_text(&foo); + + deprecated_future(); // Fine; no error. + + deprecated_unstable(); + //~^ ERROR use of unstable library feature + Trait::trait_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + <Foo as Trait>::trait_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + + deprecated_unstable_text(); + //~^ ERROR use of unstable library feature + Trait::trait_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + <Foo as Trait>::trait_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + + unstable(); //~ ERROR use of unstable library feature + Trait::trait_unstable(&foo); //~ ERROR use of unstable library feature + <Foo as Trait>::trait_unstable(&foo); //~ ERROR use of unstable library feature + + unstable_text(); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + Trait::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + <Foo as Trait>::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + + stable(); + foo.method_stable(); + Foo::method_stable(&foo); + <Foo>::method_stable(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + <Foo>::trait_stable(&foo); + <Foo as Trait>::trait_stable(&foo); + + stable_text(); + foo.method_stable_text(); + Foo::method_stable_text(&foo); + <Foo>::method_stable_text(&foo); + foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + <Foo>::trait_stable_text(&foo); + <Foo as Trait>::trait_stable_text(&foo); + + struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable); + //~^ ERROR use of unstable library feature + struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated); + type A = dyn TraitWithAssociatedTypes< + TypeUnstable = u8, //~ ERROR use of unstable library feature + TypeDeprecated = u16, + >; + + let _ = DeprecatedStruct { + i: 0 + }; + let _ = DeprecatedUnstableStruct { + //~^ ERROR use of unstable library feature + i: 0 + }; + let _ = UnstableStruct { i: 0 }; //~ ERROR use of unstable library feature + let _ = StableStruct { i: 0 }; + + let _ = DeprecatedUnitStruct; + let _ = DeprecatedUnstableUnitStruct; + //~^ ERROR use of unstable library feature + let _ = UnstableUnitStruct; //~ ERROR use of unstable library feature + let _ = StableUnitStruct; + + let _ = Enum::DeprecatedVariant; + let _ = Enum::DeprecatedUnstableVariant; + //~^ ERROR use of unstable library feature + let _ = Enum::UnstableVariant; //~ ERROR use of unstable library feature + let _ = Enum::StableVariant; + + let _ = DeprecatedTupleStruct (1); + let _ = DeprecatedUnstableTupleStruct (1); + //~^ ERROR use of unstable library feature + let _ = UnstableTupleStruct (1); //~ ERROR use of unstable library feature + let _ = StableTupleStruct (1); + + // At the moment, the lint checker only checks stability in + // in the arguments of macros. + // Eventually, we will want to lint the contents of the + // macro in the module *defining* it. Also, stability levels + // on macros themselves are not yet linted. + macro_test_arg!(deprecated_text()); + macro_test_arg!(deprecated_unstable_text()); + //~^ ERROR use of unstable library feature + macro_test_arg!(macro_test_arg!(deprecated_text())); + } + + fn test_method_param<Foo: Trait>(foo: Foo) { + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + <Foo>::trait_deprecated(&foo); + <Foo as Trait>::trait_deprecated(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + <Foo>::trait_deprecated_text(&foo); + <Foo as Trait>::trait_deprecated_text(&foo); + Trait::trait_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + <Foo as Trait>::trait_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + Trait::trait_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + <Foo as Trait>::trait_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + Trait::trait_unstable(&foo); //~ ERROR use of unstable library feature + <Foo as Trait>::trait_unstable(&foo); //~ ERROR use of unstable library feature + Trait::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + <Foo as Trait>::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + foo.trait_stable(); + Trait::trait_stable(&foo); + <Foo>::trait_stable(&foo); + <Foo as Trait>::trait_stable(&foo); + } + + fn test_method_object(foo: &dyn Trait) { + foo.trait_deprecated(); + foo.trait_deprecated_text(); + foo.trait_stable(); + } + + struct S; + + impl UnstableTrait for S { } //~ ERROR use of unstable library feature + impl DeprecatedTrait for S {} + trait LocalTrait : UnstableTrait { } //~ ERROR use of unstable library feature + trait LocalTrait2 : DeprecatedTrait { } + + impl Trait for S { + fn trait_stable(&self) {} + fn trait_unstable(&self) {} //~ ERROR use of unstable library feature + } +} + +mod inheritance { + extern crate inherited_stability; //~ ERROR use of unstable library feature + use self::inherited_stability::*; //~ ERROR use of unstable library feature + + fn test_inheritance() { + unstable(); //~ ERROR use of unstable library feature + stable(); + + stable_mod::unstable(); //~ ERROR use of unstable library feature + stable_mod::stable(); + + unstable_mod::deprecated(); //~ ERROR use of unstable library feature + unstable_mod::unstable(); //~ ERROR use of unstable library feature + + let _ = Unstable::UnstableVariant; //~ ERROR use of unstable library feature + let _ = Unstable::StableVariant; //~ ERROR use of unstable library feature + + let x: usize = 0; + x.stable(); + } +} + +mod this_crate { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated() {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated_text() {} + + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "99.99.99", note = "text")] + pub fn deprecated_future() {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn unstable() {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn unstable_text() {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stable() {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stable_text() {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub struct MethodTester; + + impl MethodTester { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn method_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn method_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable_text(&self) {} + } + + pub trait Trait { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + fn trait_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + fn trait_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable_text(&self) {} + } + + impl Trait for MethodTester {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedUnitStruct; + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableUnitStruct; + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableUnitStruct; + + pub enum Enum { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedVariant, + #[unstable(feature = "unstable_test_feature", issue = "none")] + UnstableVariant, + + #[stable(feature = "rust1", since = "1.0.0")] + StableVariant, + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedTupleStruct(isize); + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableTupleStruct(isize); + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableTupleStruct(isize); + + fn test() { + // Only the deprecated cases of the following should generate + // errors, because other stability attributes now have meaning + // only *across* crates, not within a single crate. + + type Foo = MethodTester; + let foo = MethodTester; + + deprecated(); + foo.method_deprecated(); + Foo::method_deprecated(&foo); + <Foo>::method_deprecated(&foo); + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + <Foo>::trait_deprecated(&foo); + <Foo as Trait>::trait_deprecated(&foo); + + deprecated_text(); + foo.method_deprecated_text(); + Foo::method_deprecated_text(&foo); + <Foo>::method_deprecated_text(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + <Foo>::trait_deprecated_text(&foo); + <Foo as Trait>::trait_deprecated_text(&foo); + + deprecated_future(); + + unstable(); + foo.method_unstable(); + Foo::method_unstable(&foo); + <Foo>::method_unstable(&foo); + foo.trait_unstable(); + Trait::trait_unstable(&foo); + <Foo>::trait_unstable(&foo); + <Foo as Trait>::trait_unstable(&foo); + + unstable_text(); + foo.method_unstable_text(); + Foo::method_unstable_text(&foo); + <Foo>::method_unstable_text(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + <Foo>::trait_unstable_text(&foo); + <Foo as Trait>::trait_unstable_text(&foo); + + stable(); + foo.method_stable(); + Foo::method_stable(&foo); + <Foo>::method_stable(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + <Foo>::trait_stable(&foo); + <Foo as Trait>::trait_stable(&foo); + + stable_text(); + foo.method_stable_text(); + Foo::method_stable_text(&foo); + <Foo>::method_stable_text(&foo); + foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + <Foo>::trait_stable_text(&foo); + <Foo as Trait>::trait_stable_text(&foo); + + let _ = DeprecatedStruct { + i: 0 + }; + let _ = UnstableStruct { i: 0 }; + let _ = StableStruct { i: 0 }; + + let _ = DeprecatedUnitStruct; + let _ = UnstableUnitStruct; + let _ = StableUnitStruct; + + let _ = Enum::DeprecatedVariant; + let _ = Enum::UnstableVariant; + let _ = Enum::StableVariant; + + let _ = DeprecatedTupleStruct (1); + let _ = UnstableTupleStruct (1); + let _ = StableTupleStruct (1); + } + + fn test_method_param<Foo: Trait>(foo: Foo) { + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + <Foo>::trait_deprecated(&foo); + <Foo as Trait>::trait_deprecated(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + <Foo>::trait_deprecated_text(&foo); + <Foo as Trait>::trait_deprecated_text(&foo); + foo.trait_unstable(); + Trait::trait_unstable(&foo); + <Foo>::trait_unstable(&foo); + <Foo as Trait>::trait_unstable(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + <Foo>::trait_unstable_text(&foo); + <Foo as Trait>::trait_unstable_text(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + <Foo>::trait_stable(&foo); + <Foo as Trait>::trait_stable(&foo); + } + + fn test_method_object(foo: &dyn Trait) { + foo.trait_deprecated(); + foo.trait_deprecated_text(); + foo.trait_unstable(); + foo.trait_unstable_text(); + foo.trait_stable(); + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn test_fn_body() { + fn fn_in_body() {} + fn_in_body(); + } + + impl MethodTester { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn test_method_body(&self) { + fn fn_in_body() {} + fn_in_body(); + } + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub trait DeprecatedTrait { + fn dummy(&self) { } + } + + struct S; + + impl DeprecatedTrait for S { } + + trait LocalTrait : DeprecatedTrait { } +} + +fn main() {} diff --git a/tests/ui/lint/lint-stability.stderr b/tests/ui/lint/lint-stability.stderr new file mode 100644 index 000000000..bd1a57dc4 --- /dev/null +++ b/tests/ui/lint/lint-stability.stderr @@ -0,0 +1,347 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:17:5 + | +LL | extern crate stability_cfg2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:45:9 + | +LL | deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:47:9 + | +LL | Trait::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:49:9 + | +LL | <Foo as Trait>::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:52:9 + | +LL | deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:54:9 + | +LL | Trait::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:56:9 + | +LL | <Foo as Trait>::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:59:9 + | +LL | unstable(); + | ^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:60:9 + | +LL | Trait::trait_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:61:9 + | +LL | <Foo as Trait>::trait_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability.rs:63:9 + | +LL | unstable_text(); + | ^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability.rs:65:9 + | +LL | Trait::trait_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability.rs:67:9 + | +LL | <Foo as Trait>::trait_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:99:17 + | +LL | let _ = DeprecatedUnstableStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:103:17 + | +LL | let _ = UnstableStruct { i: 0 }; + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:107:17 + | +LL | let _ = DeprecatedUnstableUnitStruct; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:109:17 + | +LL | let _ = UnstableUnitStruct; + | ^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:113:17 + | +LL | let _ = Enum::DeprecatedUnstableVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:115:17 + | +LL | let _ = Enum::UnstableVariant; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:119:17 + | +LL | let _ = DeprecatedUnstableTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:121:17 + | +LL | let _ = UnstableTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:130:25 + | +LL | macro_test_arg!(deprecated_unstable_text()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:144:9 + | +LL | Trait::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:146:9 + | +LL | <Foo as Trait>::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:148:9 + | +LL | Trait::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:150:9 + | +LL | <Foo as Trait>::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:152:9 + | +LL | Trait::trait_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:153:9 + | +LL | <Foo as Trait>::trait_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability.rs:154:9 + | +LL | Trait::trait_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability.rs:156:9 + | +LL | <Foo as Trait>::trait_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:172:10 + | +LL | impl UnstableTrait for S { } + | ^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:174:24 + | +LL | trait LocalTrait : UnstableTrait { } + | ^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:179:9 + | +LL | fn trait_unstable(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:184:5 + | +LL | extern crate inherited_stability; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:185:9 + | +LL | use self::inherited_stability::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:188:9 + | +LL | unstable(); + | ^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:191:9 + | +LL | stable_mod::unstable(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:194:9 + | +LL | unstable_mod::deprecated(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:195:9 + | +LL | unstable_mod::unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:197:17 + | +LL | let _ = Unstable::UnstableVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:198:17 + | +LL | let _ = Unstable::StableVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:88:48 + | +LL | struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable); + | ^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:92:13 + | +LL | TypeUnstable = u8, + | ^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to 43 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/lint-stability2.rs b/tests/ui/lint/lint-stability2.rs new file mode 100644 index 000000000..9ae23dac6 --- /dev/null +++ b/tests/ui/lint/lint-stability2.rs @@ -0,0 +1,13 @@ +// aux-build:lint_stability.rs +// error-pattern: use of deprecated function + +#![deny(deprecated)] + +#[macro_use] +extern crate lint_stability; + +use lint_stability::*; + +fn main() { + macro_test!(); +} diff --git a/tests/ui/lint/lint-stability2.stderr b/tests/ui/lint/lint-stability2.stderr new file mode 100644 index 000000000..51bdf84a3 --- /dev/null +++ b/tests/ui/lint/lint-stability2.stderr @@ -0,0 +1,15 @@ +error: use of deprecated function `lint_stability::deprecated`: text + --> $DIR/lint-stability2.rs:12:5 + | +LL | macro_test!(); + | ^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-stability2.rs:4:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ + = note: this error originates in the macro `macro_test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-stability3.rs b/tests/ui/lint/lint-stability3.rs new file mode 100644 index 000000000..4452846ec --- /dev/null +++ b/tests/ui/lint/lint-stability3.rs @@ -0,0 +1,14 @@ +// aux-build:lint_stability.rs +// error-pattern: use of deprecated function + +#![deny(deprecated)] +#![allow(warnings)] + +#[macro_use] +extern crate lint_stability; + +use lint_stability::*; + +fn main() { + macro_test_arg_nested!(deprecated_text); +} diff --git a/tests/ui/lint/lint-stability3.stderr b/tests/ui/lint/lint-stability3.stderr new file mode 100644 index 000000000..3bbb60dd3 --- /dev/null +++ b/tests/ui/lint/lint-stability3.stderr @@ -0,0 +1,14 @@ +error: use of deprecated function `lint_stability::deprecated_text`: text + --> $DIR/lint-stability3.rs:13:28 + | +LL | macro_test_arg_nested!(deprecated_text); + | ^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-stability3.rs:4:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-strict-provenance-fuzzy-casts.rs b/tests/ui/lint/lint-strict-provenance-fuzzy-casts.rs new file mode 100644 index 000000000..d2d72a68f --- /dev/null +++ b/tests/ui/lint/lint-strict-provenance-fuzzy-casts.rs @@ -0,0 +1,7 @@ +#![feature(strict_provenance)] +#![deny(fuzzy_provenance_casts)] + +fn main() { + let dangling = 16_usize as *const u8; + //~^ ERROR strict provenance disallows casting integer `usize` to pointer `*const u8` +} diff --git a/tests/ui/lint/lint-strict-provenance-fuzzy-casts.stderr b/tests/ui/lint/lint-strict-provenance-fuzzy-casts.stderr new file mode 100644 index 000000000..383623b48 --- /dev/null +++ b/tests/ui/lint/lint-strict-provenance-fuzzy-casts.stderr @@ -0,0 +1,19 @@ +error: strict provenance disallows casting integer `usize` to pointer `*const u8` + --> $DIR/lint-strict-provenance-fuzzy-casts.rs:5:20 + | +LL | let dangling = 16_usize as *const u8; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::from_exposed_addr()` instead +note: the lint level is defined here + --> $DIR/lint-strict-provenance-fuzzy-casts.rs:2:9 + | +LL | #![deny(fuzzy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^ +help: use `.with_addr()` to adjust a valid pointer in the same allocation, to this address + | +LL | let dangling = (...).with_addr(16_usize); + | ++++++++++++++++ ~ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-strict-provenance-lossy-casts.rs b/tests/ui/lint/lint-strict-provenance-lossy-casts.rs new file mode 100644 index 000000000..9799a0537 --- /dev/null +++ b/tests/ui/lint/lint-strict-provenance-lossy-casts.rs @@ -0,0 +1,18 @@ +#![feature(strict_provenance)] +#![deny(lossy_provenance_casts)] + +fn main() { + let x: u8 = 37; + let addr: usize = &x as *const u8 as usize; + //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize` + + let addr_32bit = &x as *const u8 as u32; + //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` + + // don't add unnecessary parens in the suggestion + let ptr = &x as *const u8; + let ptr_addr = ptr as usize; + //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize` + let ptr_addr_32bit = ptr as u32; + //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` +} diff --git a/tests/ui/lint/lint-strict-provenance-lossy-casts.stderr b/tests/ui/lint/lint-strict-provenance-lossy-casts.stderr new file mode 100644 index 000000000..aa151fe2d --- /dev/null +++ b/tests/ui/lint/lint-strict-provenance-lossy-casts.stderr @@ -0,0 +1,51 @@ +error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize` + --> $DIR/lint-strict-provenance-lossy-casts.rs:6:23 + | +LL | let addr: usize = &x as *const u8 as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead +note: the lint level is defined here + --> $DIR/lint-strict-provenance-lossy-casts.rs:2:9 + | +LL | #![deny(lossy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^ +help: use `.addr()` to obtain the address of a pointer + | +LL | let addr: usize = (&x as *const u8).addr(); + | + ~~~~~~~~ + +error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` + --> $DIR/lint-strict-provenance-lossy-casts.rs:9:22 + | +LL | let addr_32bit = &x as *const u8 as u32; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead +help: use `.addr()` to obtain the address of a pointer + | +LL | let addr_32bit = (&x as *const u8).addr() as u32; + | + ~~~~~~~~~~~~~~~ + +error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize` + --> $DIR/lint-strict-provenance-lossy-casts.rs:14:20 + | +LL | let ptr_addr = ptr as usize; + | ^^^--------- + | | + | help: use `.addr()` to obtain the address of a pointer: `.addr()` + | + = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead + +error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` + --> $DIR/lint-strict-provenance-lossy-casts.rs:16:26 + | +LL | let ptr_addr_32bit = ptr as u32; + | ^^^------- + | | + | help: use `.addr()` to obtain the address of a pointer: `.addr() as u32` + | + = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/lint-temporary-cstring-as-param.rs b/tests/ui/lint/lint-temporary-cstring-as-param.rs new file mode 100644 index 000000000..9f5805367 --- /dev/null +++ b/tests/ui/lint/lint-temporary-cstring-as-param.rs @@ -0,0 +1,11 @@ +#![deny(temporary_cstring_as_ptr)] + +use std::ffi::CString; +use std::os::raw::c_char; + +fn some_function(data: *const c_char) {} + +fn main() { + some_function(CString::new("").unwrap().as_ptr()); + //~^ ERROR getting the inner pointer of a temporary `CString` +} diff --git a/tests/ui/lint/lint-temporary-cstring-as-param.stderr b/tests/ui/lint/lint-temporary-cstring-as-param.stderr new file mode 100644 index 000000000..838b3bc13 --- /dev/null +++ b/tests/ui/lint/lint-temporary-cstring-as-param.stderr @@ -0,0 +1,18 @@ +error: getting the inner pointer of a temporary `CString` + --> $DIR/lint-temporary-cstring-as-param.rs:9:45 + | +LL | some_function(CString::new("").unwrap().as_ptr()); + | ------------------------- ^^^^^^ this pointer will be invalid + | | + | this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime + | + = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: for more information, see https://doc.rust-lang.org/reference/destructors.html +note: the lint level is defined here + --> $DIR/lint-temporary-cstring-as-param.rs:1:9 + | +LL | #![deny(temporary_cstring_as_ptr)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-temporary-cstring-as-ptr.rs b/tests/ui/lint/lint-temporary-cstring-as-ptr.rs new file mode 100644 index 000000000..7aa4f2e1e --- /dev/null +++ b/tests/ui/lint/lint-temporary-cstring-as-ptr.rs @@ -0,0 +1,9 @@ +// this program is not technically incorrect, but is an obscure enough style to be worth linting +#![deny(temporary_cstring_as_ptr)] + +use std::ffi::CString; + +fn main() { + let s = CString::new("some text").unwrap().as_ptr(); + //~^ ERROR getting the inner pointer of a temporary `CString` +} diff --git a/tests/ui/lint/lint-temporary-cstring-as-ptr.stderr b/tests/ui/lint/lint-temporary-cstring-as-ptr.stderr new file mode 100644 index 000000000..79ef57dd1 --- /dev/null +++ b/tests/ui/lint/lint-temporary-cstring-as-ptr.stderr @@ -0,0 +1,18 @@ +error: getting the inner pointer of a temporary `CString` + --> $DIR/lint-temporary-cstring-as-ptr.rs:7:48 + | +LL | let s = CString::new("some text").unwrap().as_ptr(); + | ---------------------------------- ^^^^^^ this pointer will be invalid + | | + | this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime + | + = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: for more information, see https://doc.rust-lang.org/reference/destructors.html +note: the lint level is defined here + --> $DIR/lint-temporary-cstring-as-ptr.rs:2:9 + | +LL | #![deny(temporary_cstring_as_ptr)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-type-limits.rs b/tests/ui/lint/lint-type-limits.rs new file mode 100644 index 000000000..2b140f869 --- /dev/null +++ b/tests/ui/lint/lint-type-limits.rs @@ -0,0 +1,27 @@ +#![allow(dead_code)] + +// compile-flags: -D unused-comparisons +fn main() { } + +fn foo() { + let mut i = 100_usize; + while i >= 0 { //~ ERROR comparison is useless due to type limits + i -= 1; + } +} + +fn bar() -> i8 { + return 123; +} + +fn bleh() { + let u = 42u8; + let _ = u > 255; //~ ERROR comparison is useless due to type limits + let _ = 255 < u; //~ ERROR comparison is useless due to type limits + let _ = u < 0; //~ ERROR comparison is useless due to type limits + let _ = 0 > u; //~ ERROR comparison is useless due to type limits + let _ = u <= 255; //~ ERROR comparison is useless due to type limits + let _ = 255 >= u; //~ ERROR comparison is useless due to type limits + let _ = u >= 0; //~ ERROR comparison is useless due to type limits + let _ = 0 <= u; //~ ERROR comparison is useless due to type limits +} diff --git a/tests/ui/lint/lint-type-limits.stderr b/tests/ui/lint/lint-type-limits.stderr new file mode 100644 index 000000000..71a2b3bfd --- /dev/null +++ b/tests/ui/lint/lint-type-limits.stderr @@ -0,0 +1,58 @@ +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:8:11 + | +LL | while i >= 0 { + | ^^^^^^ + | + = note: requested on the command line with `-D unused-comparisons` + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:19:13 + | +LL | let _ = u > 255; + | ^^^^^^^ + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:20:13 + | +LL | let _ = 255 < u; + | ^^^^^^^ + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:21:13 + | +LL | let _ = u < 0; + | ^^^^^ + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:22:13 + | +LL | let _ = 0 > u; + | ^^^^^ + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:23:13 + | +LL | let _ = u <= 255; + | ^^^^^^^^ + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:24:13 + | +LL | let _ = 255 >= u; + | ^^^^^^^^ + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:25:13 + | +LL | let _ = u >= 0; + | ^^^^^^ + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:26:13 + | +LL | let _ = 0 <= u; + | ^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/lint-type-limits2.rs b/tests/ui/lint/lint-type-limits2.rs new file mode 100644 index 000000000..3f90119cd --- /dev/null +++ b/tests/ui/lint/lint-type-limits2.rs @@ -0,0 +1,15 @@ +#![allow(dead_code)] +#![warn(overflowing_literals)] + +// compile-flags: -D unused-comparisons +fn main() { } + + +fn bar() -> i8 { + return 123; +} + +fn baz() -> bool { + 128 > bar() //~ ERROR comparison is useless due to type limits + //~| WARN literal out of range for `i8` +} diff --git a/tests/ui/lint/lint-type-limits2.stderr b/tests/ui/lint/lint-type-limits2.stderr new file mode 100644 index 000000000..b3420ad8a --- /dev/null +++ b/tests/ui/lint/lint-type-limits2.stderr @@ -0,0 +1,24 @@ +error: comparison is useless due to type limits + --> $DIR/lint-type-limits2.rs:13:5 + | +LL | 128 > bar() + | ^^^^^^^^^^^ + | + = note: requested on the command line with `-D unused-comparisons` + +warning: literal out of range for `i8` + --> $DIR/lint-type-limits2.rs:13:5 + | +LL | 128 > bar() + | ^^^ + | + = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead +note: the lint level is defined here + --> $DIR/lint-type-limits2.rs:2:9 + | +LL | #![warn(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/lint/lint-type-limits3.rs b/tests/ui/lint/lint-type-limits3.rs new file mode 100644 index 000000000..ceecf9ab3 --- /dev/null +++ b/tests/ui/lint/lint-type-limits3.rs @@ -0,0 +1,13 @@ +#![allow(dead_code)] +#![warn(overflowing_literals)] + +// compile-flags: -D unused-comparisons +fn main() { } + +fn qux() { + let mut i = 1i8; + while 200 != i { //~ ERROR comparison is useless due to type limits + //~| WARN literal out of range for `i8` + i += 1; + } +} diff --git a/tests/ui/lint/lint-type-limits3.stderr b/tests/ui/lint/lint-type-limits3.stderr new file mode 100644 index 000000000..db46e7ae7 --- /dev/null +++ b/tests/ui/lint/lint-type-limits3.stderr @@ -0,0 +1,24 @@ +error: comparison is useless due to type limits + --> $DIR/lint-type-limits3.rs:9:11 + | +LL | while 200 != i { + | ^^^^^^^^ + | + = note: requested on the command line with `-D unused-comparisons` + +warning: literal out of range for `i8` + --> $DIR/lint-type-limits3.rs:9:11 + | +LL | while 200 != i { + | ^^^ + | + = note: the literal `200` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead +note: the lint level is defined here + --> $DIR/lint-type-limits3.rs:2:9 + | +LL | #![warn(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/lint/lint-type-overflow.rs b/tests/ui/lint/lint-type-overflow.rs new file mode 100644 index 000000000..9672da6d3 --- /dev/null +++ b/tests/ui/lint/lint-type-overflow.rs @@ -0,0 +1,45 @@ +#![deny(overflowing_literals)] + +fn test(x: i8) { + println!("x {}", x); +} + +#[allow(unused_variables)] +fn main() { + let x1: u8 = 255; // should be OK + let x1: u8 = 256; //~ error: literal out of range for `u8` + + let x1 = 255_u8; // should be OK + let x1 = 256_u8; //~ error: literal out of range for `u8` + + let x2: i8 = -128; // should be OK + let x1: i8 = 128; //~ error: literal out of range for `i8` + + let x3: i8 = -129; //~ error: literal out of range for `i8` + let x3: i8 = -(129); //~ error: literal out of range for `i8` + let x3: i8 = -{129}; //~ error: literal out of range for `i8` + + test(1000); //~ error: literal out of range for `i8` + + let x = 128_i8; //~ error: literal out of range for `i8` + let x = 127_i8; + let x = -128_i8; + let x = -(128_i8); + let x = -129_i8; //~ error: literal out of range for `i8` + + let x: i32 = 2147483647; // should be OK + let x = 2147483647_i32; // should be OK + let x: i32 = 2147483648; //~ error: literal out of range for `i32` + let x = 2147483648_i32; //~ error: literal out of range for `i32` + let x: i32 = -2147483648; // should be OK + let x = -2147483648_i32; // should be OK + let x: i32 = -2147483649; //~ error: literal out of range for `i32` + let x = -2147483649_i32; //~ error: literal out of range for `i32` + let x = 2147483648; //~ error: literal out of range for `i32` + + let x = 9223372036854775808_i64; //~ error: literal out of range for `i64` + let x = -9223372036854775808_i64; // should be OK + let x = 18446744073709551615_i64; //~ error: literal out of range for `i64` + let x: i64 = -9223372036854775809; //~ error: literal out of range for `i64` + let x = -9223372036854775809_i64; //~ error: literal out of range for `i64` +} diff --git a/tests/ui/lint/lint-type-overflow.stderr b/tests/ui/lint/lint-type-overflow.stderr new file mode 100644 index 000000000..48d8228b8 --- /dev/null +++ b/tests/ui/lint/lint-type-overflow.stderr @@ -0,0 +1,167 @@ +error: literal out of range for `u8` + --> $DIR/lint-type-overflow.rs:10:18 + | +LL | let x1: u8 = 256; + | ^^^ + | + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` +note: the lint level is defined here + --> $DIR/lint-type-overflow.rs:1:9 + | +LL | #![deny(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: literal out of range for `u8` + --> $DIR/lint-type-overflow.rs:13:14 + | +LL | let x1 = 256_u8; + | ^^^^^^ + | + = note: the literal `256_u8` does not fit into the type `u8` whose range is `0..=255` + +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:16:18 + | +LL | let x1: i8 = 128; + | ^^^ + | + = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead + +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:18:19 + | +LL | let x3: i8 = -129; + | ^^^ + | + = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `i16` instead + +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:19:19 + | +LL | let x3: i8 = -(129); + | ^^^^^ + | + = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `i16` instead + +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:20:20 + | +LL | let x3: i8 = -{129}; + | ^^^ + | + = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead + +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:22:10 + | +LL | test(1000); + | ^^^^ + | + = note: the literal `1000` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `i16` instead + +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:24:13 + | +LL | let x = 128_i8; + | ^^^^^^ + | + = note: the literal `128_i8` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead + +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:28:14 + | +LL | let x = -129_i8; + | ^^^^^^ + | + = note: the literal `129_i8` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `i16` instead + +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:32:18 + | +LL | let x: i32 = 2147483648; + | ^^^^^^^^^^ + | + = note: the literal `2147483648` does not fit into the type `i32` whose range is `-2147483648..=2147483647` + = help: consider using the type `u32` instead + +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:33:13 + | +LL | let x = 2147483648_i32; + | ^^^^^^^^^^^^^^ + | + = note: the literal `2147483648_i32` does not fit into the type `i32` whose range is `-2147483648..=2147483647` + = help: consider using the type `u32` instead + +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:36:19 + | +LL | let x: i32 = -2147483649; + | ^^^^^^^^^^ + | + = note: the literal `2147483649` does not fit into the type `i32` whose range is `-2147483648..=2147483647` + = help: consider using the type `i64` instead + +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:37:14 + | +LL | let x = -2147483649_i32; + | ^^^^^^^^^^^^^^ + | + = note: the literal `2147483649_i32` does not fit into the type `i32` whose range is `-2147483648..=2147483647` + = help: consider using the type `i64` instead + +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:38:13 + | +LL | let x = 2147483648; + | ^^^^^^^^^^ + | + = note: the literal `2147483648` does not fit into the type `i32` whose range is `-2147483648..=2147483647` + = help: consider using the type `u32` instead + +error: literal out of range for `i64` + --> $DIR/lint-type-overflow.rs:40:13 + | +LL | let x = 9223372036854775808_i64; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775808_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` + = help: consider using the type `u64` instead + +error: literal out of range for `i64` + --> $DIR/lint-type-overflow.rs:42:13 + | +LL | let x = 18446744073709551615_i64; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `18446744073709551615_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` + = help: consider using the type `u64` instead + +error: literal out of range for `i64` + --> $DIR/lint-type-overflow.rs:43:19 + | +LL | let x: i64 = -9223372036854775809; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775809` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` + = help: consider using the type `i128` instead + +error: literal out of range for `i64` + --> $DIR/lint-type-overflow.rs:44:14 + | +LL | let x = -9223372036854775809_i64; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775809_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` + = help: consider using the type `i128` instead + +error: aborting due to 18 previous errors + diff --git a/tests/ui/lint/lint-type-overflow2.rs b/tests/ui/lint/lint-type-overflow2.rs new file mode 100644 index 000000000..9b1eb510b --- /dev/null +++ b/tests/ui/lint/lint-type-overflow2.rs @@ -0,0 +1,12 @@ +// compile-flags: -O + +#![deny(overflowing_literals)] + +fn main() { + let x2: i8 = --128; //~ ERROR literal out of range for `i8` + + let x = -3.40282357e+38_f32; //~ ERROR literal out of range for `f32` + let x = 3.40282357e+38_f32; //~ ERROR literal out of range for `f32` + let x = -1.7976931348623159e+308_f64; //~ ERROR literal out of range for `f64` + let x = 1.7976931348623159e+308_f64; //~ ERROR literal out of range for `f64` +} diff --git a/tests/ui/lint/lint-type-overflow2.stderr b/tests/ui/lint/lint-type-overflow2.stderr new file mode 100644 index 000000000..eb593d062 --- /dev/null +++ b/tests/ui/lint/lint-type-overflow2.stderr @@ -0,0 +1,48 @@ +error: literal out of range for `i8` + --> $DIR/lint-type-overflow2.rs:6:20 + | +LL | let x2: i8 = --128; + | ^^^ + | + = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead +note: the lint level is defined here + --> $DIR/lint-type-overflow2.rs:3:9 + | +LL | #![deny(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: literal out of range for `f32` + --> $DIR/lint-type-overflow2.rs:8:14 + | +LL | let x = -3.40282357e+38_f32; + | ^^^^^^^^^^^^^^^^^^ + | + = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY` + +error: literal out of range for `f32` + --> $DIR/lint-type-overflow2.rs:9:14 + | +LL | let x = 3.40282357e+38_f32; + | ^^^^^^^^^^^^^^^^^^ + | + = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY` + +error: literal out of range for `f64` + --> $DIR/lint-type-overflow2.rs:10:14 + | +LL | let x = -1.7976931348623159e+308_f64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY` + +error: literal out of range for `f64` + --> $DIR/lint-type-overflow2.rs:11:14 + | +LL | let x = 1.7976931348623159e+308_f64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/lint-unconditional-recursion.rs b/tests/ui/lint/lint-unconditional-recursion.rs new file mode 100644 index 000000000..ad052d36f --- /dev/null +++ b/tests/ui/lint/lint-unconditional-recursion.rs @@ -0,0 +1,194 @@ +#![deny(unconditional_recursion)] + +#![allow(dead_code)] +fn foo() { //~ ERROR function cannot return without recursing + foo(); +} + +fn bar() { + if true { + bar() + } +} + +fn baz() { //~ ERROR function cannot return without recursing + if true { + baz() + } else { + baz() + } +} + +fn qux() { + loop {} +} + +fn quz() -> bool { //~ ERROR function cannot return without recursing + if true { + while quz() {} + true + } else { + loop { quz(); } + } +} + +// Trait method calls. +trait Foo { + fn bar(&self) { //~ ERROR function cannot return without recursing + self.bar() + } +} + +impl Foo for Box<dyn Foo + 'static> { + fn bar(&self) { //~ ERROR function cannot return without recursing + loop { + self.bar() + } + } +} + +// Trait method call with integer fallback after method resolution. +impl Foo for i32 { + fn bar(&self) { //~ ERROR function cannot return without recursing + 0.bar() + } +} + +impl Foo for u32 { + fn bar(&self) { + 0.bar() + } +} + +// Trait method calls via paths. +trait Foo2 { + fn bar(&self) { //~ ERROR function cannot return without recursing + Foo2::bar(self) + } +} + +impl Foo2 for Box<dyn Foo2 + 'static> { + fn bar(&self) { //~ ERROR function cannot return without recursing + loop { + Foo2::bar(self) + } + } +} + +struct Baz; +impl Baz { + // Inherent method call. + fn qux(&self) { //~ ERROR function cannot return without recursing + self.qux(); + } + + // Inherent method call via path. + fn as_ref(&self) -> &Self { //~ ERROR function cannot return without recursing + Baz::as_ref(self) + } +} + +// Trait method calls to impls via paths. +impl Default for Baz { + fn default() -> Baz { //~ ERROR function cannot return without recursing + let x = Default::default(); + x + } +} + +// Overloaded operators. +impl std::ops::Deref for Baz { + type Target = (); + fn deref(&self) -> &() { //~ ERROR function cannot return without recursing + &**self + } +} + +impl std::ops::Index<usize> for Baz { + type Output = Baz; + fn index(&self, x: usize) -> &Baz { //~ ERROR function cannot return without recursing + &self[x] + } +} + +// Overloaded autoderef. +struct Quux; +impl std::ops::Deref for Quux { + type Target = Baz; + fn deref(&self) -> &Baz { //~ ERROR function cannot return without recursing + self.as_ref() + } +} + +fn all_fine() { + let _f = all_fine; +} + +// issue 26333 +trait Bar { + fn method<T: Bar>(&self, x: &T) { + x.method(x) + } +} + +// Do not trigger on functions that may diverge instead of self-recursing (#54444) + +pub fn loops(x: bool) { + if x { + loops(x); + } else { + loop {} + } +} + +pub fn panics(x: bool) { + if x { + panics(!x); + } else { + panic!("panics"); + } +} + +pub fn unreachable1() { + panic!(); + unreachable1(); // WARN unreachable statement +} + +pub fn unreachable2() { + loop {} + unreachable2(); // WARN unreachable statement +} + +pub fn drop_and_replace(mut a: Option<String>) { //~ ERROR function cannot return without recursing + a = None; + drop_and_replace(a); +} + +// Calls are assumed to return normally. +pub fn call() -> String { //~ ERROR function cannot return without recursing + let s = String::new(); + call(); + s +} + +// Arithmetic operations are assumed not to overflow. +pub fn overflow_check(a: i32, b: i32) { //~ ERROR function cannot return without recursing + let _ = a + b; + overflow_check(a, b); +} + +pub struct Point { + pub x: f32, + pub y: f32, +} + +impl Default for Point { + fn default() -> Self { //~ ERROR function cannot return without recursing + Point { + x: Default::default(), + ..Default::default() + } + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-unconditional-recursion.stderr b/tests/ui/lint/lint-unconditional-recursion.stderr new file mode 100644 index 000000000..9d200a789 --- /dev/null +++ b/tests/ui/lint/lint-unconditional-recursion.stderr @@ -0,0 +1,201 @@ +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:4:1 + | +LL | fn foo() { + | ^^^^^^^^ cannot return without recursing +LL | foo(); + | ----- 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-recursion.rs:1:9 + | +LL | #![deny(unconditional_recursion)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:14:1 + | +LL | fn baz() { + | ^^^^^^^^ cannot return without recursing +LL | if true { +LL | baz() + | ----- recursive call site +LL | } else { +LL | baz() + | ----- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:26:1 + | +LL | fn quz() -> bool { + | ^^^^^^^^^^^^^^^^ cannot return without recursing +LL | if true { +LL | while quz() {} + | ----- recursive call site +... +LL | loop { quz(); } + | ----- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:37:5 + | +LL | fn bar(&self) { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | self.bar() + | ---------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:43:5 + | +LL | fn bar(&self) { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | loop { +LL | self.bar() + | ---------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:52:5 + | +LL | fn bar(&self) { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | 0.bar() + | ------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:65:5 + | +LL | fn bar(&self) { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | Foo2::bar(self) + | --------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:71:5 + | +LL | fn bar(&self) { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | loop { +LL | Foo2::bar(self) + | --------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:81:5 + | +LL | fn qux(&self) { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | self.qux(); + | ---------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:86:5 + | +LL | fn as_ref(&self) -> &Self { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | Baz::as_ref(self) + | ----------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:93:5 + | +LL | fn default() -> Baz { + | ^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | let x = Default::default(); + | ------------------ recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:102:5 + | +LL | fn deref(&self) -> &() { + | ^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | &**self + | ------ recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:109:5 + | +LL | fn index(&self, x: usize) -> &Baz { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | &self[x] + | ------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:118:5 + | +LL | fn deref(&self) -> &Baz { + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | self.as_ref() + | ------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:162:1 + | +LL | pub fn drop_and_replace(mut a: Option<String>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | a = None; +LL | drop_and_replace(a); + | ------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:168:1 + | +LL | pub fn call() -> String { + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | let s = String::new(); +LL | call(); + | ------ recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:175:1 + | +LL | pub fn overflow_check(a: i32, b: i32) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | let _ = a + b; +LL | overflow_check(a, b); + | -------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:186:5 + | +LL | fn default() -> Self { + | ^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +... +LL | ..Default::default() + | ------------------ recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: aborting due to 18 previous errors + diff --git a/tests/ui/lint/lint-unexported-no-mangle.rs b/tests/ui/lint/lint-unexported-no-mangle.rs new file mode 100644 index 000000000..f260fc323 --- /dev/null +++ b/tests/ui/lint/lint-unexported-no-mangle.rs @@ -0,0 +1,29 @@ +// compile-flags:-F private_no_mangle_fns -F no_mangle_const_items -F private_no_mangle_statics + +#[no_mangle] +fn foo() { +} + +#[allow(dead_code)] +#[no_mangle] +const FOO: u64 = 1; //~ ERROR const items should never be `#[no_mangle]` + +#[no_mangle] +pub const PUB_FOO: u64 = 1; //~ ERROR const items should never be `#[no_mangle]` + +#[no_mangle] +pub fn bar() { +} + +#[no_mangle] +pub static BAR: u64 = 1; + +#[allow(dead_code)] +#[no_mangle] +static PRIVATE_BAR: u64 = 1; + + +fn main() { + foo(); + bar(); +} diff --git a/tests/ui/lint/lint-unexported-no-mangle.stderr b/tests/ui/lint/lint-unexported-no-mangle.stderr new file mode 100644 index 000000000..a11ee769c --- /dev/null +++ b/tests/ui/lint/lint-unexported-no-mangle.stderr @@ -0,0 +1,44 @@ +warning: lint `private_no_mangle_fns` has been removed: no longer a warning, `#[no_mangle]` functions always exported + | + = note: requested on the command line with `-F private_no_mangle_fns` + +warning: lint `private_no_mangle_statics` has been removed: no longer a warning, `#[no_mangle]` statics always exported + | + = note: requested on the command line with `-F private_no_mangle_statics` + +warning: lint `private_no_mangle_fns` has been removed: no longer a warning, `#[no_mangle]` functions always exported + | + = note: requested on the command line with `-F private_no_mangle_fns` + +warning: lint `private_no_mangle_statics` has been removed: no longer a warning, `#[no_mangle]` statics always exported + | + = note: requested on the command line with `-F private_no_mangle_statics` + +warning: lint `private_no_mangle_fns` has been removed: no longer a warning, `#[no_mangle]` functions always exported + | + = note: requested on the command line with `-F private_no_mangle_fns` + +warning: lint `private_no_mangle_statics` has been removed: no longer a warning, `#[no_mangle]` statics always exported + | + = note: requested on the command line with `-F private_no_mangle_statics` + +error: const items should never be `#[no_mangle]` + --> $DIR/lint-unexported-no-mangle.rs:9:1 + | +LL | const FOO: u64 = 1; + | -----^^^^^^^^^^^^^^ + | | + | help: try a static value: `pub static` + | + = note: requested on the command line with `-F no-mangle-const-items` + +error: const items should never be `#[no_mangle]` + --> $DIR/lint-unexported-no-mangle.rs:12:1 + | +LL | pub const PUB_FOO: u64 = 1; + | ---------^^^^^^^^^^^^^^^^^^ + | | + | help: try a static value: `pub static` + +error: aborting due to 2 previous errors; 6 warnings emitted + diff --git a/tests/ui/lint/lint-unknown-feature-default.rs b/tests/ui/lint/lint-unknown-feature-default.rs new file mode 100644 index 000000000..84a2e5a4b --- /dev/null +++ b/tests/ui/lint/lint-unknown-feature-default.rs @@ -0,0 +1,9 @@ +// check-pass + +// Tests the default for the unused_features lint + +#![allow(stable_features)] +// FIXME(#44232) we should warn that this isn't used. +#![feature(rust1)] + +fn main() {} diff --git a/tests/ui/lint/lint-unknown-feature.rs b/tests/ui/lint/lint-unknown-feature.rs new file mode 100644 index 000000000..1af8d4ff8 --- /dev/null +++ b/tests/ui/lint/lint-unknown-feature.rs @@ -0,0 +1,9 @@ +// check-pass + +#![warn(unused_features)] + +#![allow(stable_features)] +// FIXME(#44232) we should warn that this isn't used. +#![feature(rust1)] + +fn main() {} diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.rs b/tests/ui/lint/lint-unknown-lint-cmdline.rs new file mode 100644 index 000000000..7f3f55fba --- /dev/null +++ b/tests/ui/lint/lint-unknown-lint-cmdline.rs @@ -0,0 +1,9 @@ +// compile-flags:-D bogus -D dead_cod + +// error-pattern:unknown lint: `bogus` +// error-pattern:requested on the command line with `-D bogus` +// error-pattern:unknown lint: `dead_cod` +// error-pattern:requested on the command line with `-D dead_cod` +// error-pattern:did you mean: `dead_code` + +fn main() { } diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.stderr b/tests/ui/lint/lint-unknown-lint-cmdline.stderr new file mode 100644 index 000000000..3855d5527 --- /dev/null +++ b/tests/ui/lint/lint-unknown-lint-cmdline.stderr @@ -0,0 +1,21 @@ +error[E0602]: unknown lint: `bogus` + | + = note: requested on the command line with `-D bogus` + +error[E0602]: unknown lint: `dead_cod` + | + = help: did you mean: `dead_code` + = note: requested on the command line with `-D dead_cod` + +error[E0602]: unknown lint: `bogus` + | + = note: requested on the command line with `-D bogus` + +error[E0602]: unknown lint: `dead_cod` + | + = help: did you mean: `dead_code` + = note: requested on the command line with `-D dead_cod` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/lint-unknown-lint.rs b/tests/ui/lint/lint-unknown-lint.rs new file mode 100644 index 000000000..2d842d514 --- /dev/null +++ b/tests/ui/lint/lint-unknown-lint.rs @@ -0,0 +1,13 @@ +#![deny(unknown_lints)] + +#![allow(not_a_real_lint)] //~ ERROR unknown lint + +#![deny(dead_cod)] //~ ERROR unknown lint + //~| HELP did you mean + //~| SUGGESTION dead_code + +#![deny(rust_2018_idiots)] //~ ERROR unknown lint + //~| HELP did you mean + //~| SUGGESTION rust_2018_idioms + +fn main() {} diff --git a/tests/ui/lint/lint-unknown-lint.stderr b/tests/ui/lint/lint-unknown-lint.stderr new file mode 100644 index 000000000..0cb6b4957 --- /dev/null +++ b/tests/ui/lint/lint-unknown-lint.stderr @@ -0,0 +1,26 @@ +error: unknown lint: `not_a_real_lint` + --> $DIR/lint-unknown-lint.rs:3:10 + | +LL | #![allow(not_a_real_lint)] + | ^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-unknown-lint.rs:1:9 + | +LL | #![deny(unknown_lints)] + | ^^^^^^^^^^^^^ + +error: unknown lint: `dead_cod` + --> $DIR/lint-unknown-lint.rs:5:9 + | +LL | #![deny(dead_cod)] + | ^^^^^^^^ help: did you mean: `dead_code` + +error: unknown lint: `rust_2018_idiots` + --> $DIR/lint-unknown-lint.rs:9:9 + | +LL | #![deny(rust_2018_idiots)] + | ^^^^^^^^^^^^^^^^ help: did you mean: `rust_2018_idioms` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/lint-unnecessary-import-braces.rs b/tests/ui/lint/lint-unnecessary-import-braces.rs new file mode 100644 index 000000000..9a3398a87 --- /dev/null +++ b/tests/ui/lint/lint-unnecessary-import-braces.rs @@ -0,0 +1,11 @@ +#![deny(unused_import_braces)] + +use test::{A}; //~ ERROR braces around A is unnecessary + +mod test { + use test::{self}; // OK + use test::{self as rename}; // OK + pub struct A; +} + +fn main() {} diff --git a/tests/ui/lint/lint-unnecessary-import-braces.stderr b/tests/ui/lint/lint-unnecessary-import-braces.stderr new file mode 100644 index 000000000..2d289404d --- /dev/null +++ b/tests/ui/lint/lint-unnecessary-import-braces.stderr @@ -0,0 +1,14 @@ +error: braces around A is unnecessary + --> $DIR/lint-unnecessary-import-braces.rs:3:1 + | +LL | use test::{A}; + | ^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-unnecessary-import-braces.rs:1:9 + | +LL | #![deny(unused_import_braces)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-unnecessary-parens.fixed b/tests/ui/lint/lint-unnecessary-parens.fixed new file mode 100644 index 000000000..9c144324f --- /dev/null +++ b/tests/ui/lint/lint-unnecessary-parens.fixed @@ -0,0 +1,81 @@ +// run-rustfix + +#![deny(unused_parens)] +#![allow(while_true)] // for rustfix + +#[derive(Eq, PartialEq)] +struct X { y: bool } +impl X { + fn foo(&self, conjunct: bool) -> bool { self.y && conjunct } +} + +fn foo() -> isize { + return 1; //~ ERROR unnecessary parentheses around `return` value +} +fn bar(y: bool) -> X { + return X { y }; //~ ERROR unnecessary parentheses around `return` value +} + +pub fn unused_parens_around_return_type() -> u32 { //~ ERROR unnecessary parentheses around type + panic!() +} + +pub fn unused_parens_around_block_return() -> u32 { + let _foo = { + 5 //~ ERROR unnecessary parentheses around block return value + }; + 5 //~ ERROR unnecessary parentheses around block return value +} + +pub trait Trait { + fn test(&self); +} + +pub fn passes_unused_parens_lint() -> &'static (dyn Trait) { + panic!() +} + +macro_rules! baz { + ($($foo:expr),+) => { + ($($foo),*) + } +} + +pub const CONST_ITEM: usize = 10; //~ ERROR unnecessary parentheses around assigned value +pub static STATIC_ITEM: usize = 10; //~ ERROR unnecessary parentheses around assigned value + +fn main() { + foo(); + bar(true); //~ ERROR unnecessary parentheses around function argument + + if true {} //~ ERROR unnecessary parentheses around `if` condition + while true {} //~ ERROR unnecessary parentheses around `while` condition + match true { //~ ERROR unnecessary parentheses around `match` scrutinee expression + _ => {} + } + if let 1 = 1 {} //~ ERROR unnecessary parentheses around `let` scrutinee expression + while let 1 = 2 {} //~ ERROR unnecessary parentheses around `let` scrutinee expression + let v = X { y: false }; + // struct lits needs parens, so these shouldn't warn. + if (v == X { y: true }) {} + if (X { y: true } == v) {} + if (X { y: false }.y) {} + // this shouldn't warn, because the parens are necessary to disambiguate let chains + if let true = (true && false) {} + + while (X { y: false }.foo(true)) {} + while (true | X { y: false }.y) {} + + match (X { y: false }) { + _ => {} + } + + X { y: false }.foo(true); //~ ERROR unnecessary parentheses around method argument + + let mut _a = 0; //~ ERROR unnecessary parentheses around assigned value + _a = 0; //~ ERROR unnecessary parentheses around assigned value + _a += 1; //~ ERROR unnecessary parentheses around assigned value + + let _a = baz!(3, 4); + let _b = baz!(3); +} diff --git a/tests/ui/lint/lint-unnecessary-parens.rs b/tests/ui/lint/lint-unnecessary-parens.rs new file mode 100644 index 000000000..4fd9cabb3 --- /dev/null +++ b/tests/ui/lint/lint-unnecessary-parens.rs @@ -0,0 +1,81 @@ +// run-rustfix + +#![deny(unused_parens)] +#![allow(while_true)] // for rustfix + +#[derive(Eq, PartialEq)] +struct X { y: bool } +impl X { + fn foo(&self, conjunct: bool) -> bool { self.y && conjunct } +} + +fn foo() -> isize { + return (1); //~ ERROR unnecessary parentheses around `return` value +} +fn bar(y: bool) -> X { + return (X { y }); //~ ERROR unnecessary parentheses around `return` value +} + +pub fn unused_parens_around_return_type() -> (u32) { //~ ERROR unnecessary parentheses around type + panic!() +} + +pub fn unused_parens_around_block_return() -> u32 { + let _foo = { + (5) //~ ERROR unnecessary parentheses around block return value + }; + (5) //~ ERROR unnecessary parentheses around block return value +} + +pub trait Trait { + fn test(&self); +} + +pub fn passes_unused_parens_lint() -> &'static (dyn Trait) { + panic!() +} + +macro_rules! baz { + ($($foo:expr),+) => { + ($($foo),*) + } +} + +pub const CONST_ITEM: usize = (10); //~ ERROR unnecessary parentheses around assigned value +pub static STATIC_ITEM: usize = (10); //~ ERROR unnecessary parentheses around assigned value + +fn main() { + foo(); + bar((true)); //~ ERROR unnecessary parentheses around function argument + + if (true) {} //~ ERROR unnecessary parentheses around `if` condition + while (true) {} //~ ERROR unnecessary parentheses around `while` condition + match (true) { //~ ERROR unnecessary parentheses around `match` scrutinee expression + _ => {} + } + if let 1 = (1) {} //~ ERROR unnecessary parentheses around `let` scrutinee expression + while let 1 = (2) {} //~ ERROR unnecessary parentheses around `let` scrutinee expression + let v = X { y: false }; + // struct lits needs parens, so these shouldn't warn. + if (v == X { y: true }) {} + if (X { y: true } == v) {} + if (X { y: false }.y) {} + // this shouldn't warn, because the parens are necessary to disambiguate let chains + if let true = (true && false) {} + + while (X { y: false }.foo(true)) {} + while (true | X { y: false }.y) {} + + match (X { y: false }) { + _ => {} + } + + X { y: false }.foo((true)); //~ ERROR unnecessary parentheses around method argument + + let mut _a = (0); //~ ERROR unnecessary parentheses around assigned value + _a = (0); //~ ERROR unnecessary parentheses around assigned value + _a += (1); //~ ERROR unnecessary parentheses around assigned value + + let _a = baz!(3, 4); + let _b = baz!(3); +} diff --git a/tests/ui/lint/lint-unnecessary-parens.stderr b/tests/ui/lint/lint-unnecessary-parens.stderr new file mode 100644 index 000000000..e13620f06 --- /dev/null +++ b/tests/ui/lint/lint-unnecessary-parens.stderr @@ -0,0 +1,211 @@ +error: unnecessary parentheses around `return` value + --> $DIR/lint-unnecessary-parens.rs:13:12 + | +LL | return (1); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-unnecessary-parens.rs:3:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - return (1); +LL + return 1; + | + +error: unnecessary parentheses around `return` value + --> $DIR/lint-unnecessary-parens.rs:16:12 + | +LL | return (X { y }); + | ^ ^ + | +help: remove these parentheses + | +LL - return (X { y }); +LL + return X { y }; + | + +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:19:46 + | +LL | pub fn unused_parens_around_return_type() -> (u32) { + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn unused_parens_around_return_type() -> (u32) { +LL + pub fn unused_parens_around_return_type() -> u32 { + | + +error: unnecessary parentheses around block return value + --> $DIR/lint-unnecessary-parens.rs:25:9 + | +LL | (5) + | ^ ^ + | +help: remove these parentheses + | +LL - (5) +LL + 5 + | + +error: unnecessary parentheses around block return value + --> $DIR/lint-unnecessary-parens.rs:27:5 + | +LL | (5) + | ^ ^ + | +help: remove these parentheses + | +LL - (5) +LL + 5 + | + +error: unnecessary parentheses around assigned value + --> $DIR/lint-unnecessary-parens.rs:44:31 + | +LL | pub const CONST_ITEM: usize = (10); + | ^ ^ + | +help: remove these parentheses + | +LL - pub const CONST_ITEM: usize = (10); +LL + pub const CONST_ITEM: usize = 10; + | + +error: unnecessary parentheses around assigned value + --> $DIR/lint-unnecessary-parens.rs:45:33 + | +LL | pub static STATIC_ITEM: usize = (10); + | ^ ^ + | +help: remove these parentheses + | +LL - pub static STATIC_ITEM: usize = (10); +LL + pub static STATIC_ITEM: usize = 10; + | + +error: unnecessary parentheses around function argument + --> $DIR/lint-unnecessary-parens.rs:49:9 + | +LL | bar((true)); + | ^ ^ + | +help: remove these parentheses + | +LL - bar((true)); +LL + bar(true); + | + +error: unnecessary parentheses around `if` condition + --> $DIR/lint-unnecessary-parens.rs:51:8 + | +LL | if (true) {} + | ^ ^ + | +help: remove these parentheses + | +LL - if (true) {} +LL + if true {} + | + +error: unnecessary parentheses around `while` condition + --> $DIR/lint-unnecessary-parens.rs:52:11 + | +LL | while (true) {} + | ^ ^ + | +help: remove these parentheses + | +LL - while (true) {} +LL + while true {} + | + +error: unnecessary parentheses around `match` scrutinee expression + --> $DIR/lint-unnecessary-parens.rs:53:11 + | +LL | match (true) { + | ^ ^ + | +help: remove these parentheses + | +LL - match (true) { +LL + match true { + | + +error: unnecessary parentheses around `let` scrutinee expression + --> $DIR/lint-unnecessary-parens.rs:56:16 + | +LL | if let 1 = (1) {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let 1 = (1) {} +LL + if let 1 = 1 {} + | + +error: unnecessary parentheses around `let` scrutinee expression + --> $DIR/lint-unnecessary-parens.rs:57:19 + | +LL | while let 1 = (2) {} + | ^ ^ + | +help: remove these parentheses + | +LL - while let 1 = (2) {} +LL + while let 1 = 2 {} + | + +error: unnecessary parentheses around method argument + --> $DIR/lint-unnecessary-parens.rs:73:24 + | +LL | X { y: false }.foo((true)); + | ^ ^ + | +help: remove these parentheses + | +LL - X { y: false }.foo((true)); +LL + X { y: false }.foo(true); + | + +error: unnecessary parentheses around assigned value + --> $DIR/lint-unnecessary-parens.rs:75:18 + | +LL | let mut _a = (0); + | ^ ^ + | +help: remove these parentheses + | +LL - let mut _a = (0); +LL + let mut _a = 0; + | + +error: unnecessary parentheses around assigned value + --> $DIR/lint-unnecessary-parens.rs:76:10 + | +LL | _a = (0); + | ^ ^ + | +help: remove these parentheses + | +LL - _a = (0); +LL + _a = 0; + | + +error: unnecessary parentheses around assigned value + --> $DIR/lint-unnecessary-parens.rs:77:11 + | +LL | _a += (1); + | ^ ^ + | +help: remove these parentheses + | +LL - _a += (1); +LL + _a += 1; + | + +error: aborting due to 17 previous errors + diff --git a/tests/ui/lint/lint-unsafe-code.rs b/tests/ui/lint/lint-unsafe-code.rs new file mode 100644 index 000000000..b72e4c3a9 --- /dev/null +++ b/tests/ui/lint/lint-unsafe-code.rs @@ -0,0 +1,130 @@ +#![allow(unused_unsafe)] +#![allow(dead_code)] +#![deny(unsafe_code)] + +struct Bar; +struct Bar2; +struct Bar3; + +#[allow(unsafe_code)] +mod allowed_unsafe { + fn allowed() { unsafe {} } + unsafe fn also_allowed() {} + unsafe trait AllowedUnsafe { } + unsafe impl AllowedUnsafe for super::Bar {} + #[no_mangle] fn allowed2() {} + #[export_name = "foo"] fn allowed3() {} +} + +macro_rules! unsafe_in_macro { + () => {{ + #[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` function + #[no_mangle] static FOO: u32 = 5; //~ ERROR: declaration of a `no_mangle` static + #[export_name = "bar"] fn bar() {} + //~^ ERROR: declaration of a function with `export_name` + #[export_name = "BAR"] static BAR: u32 = 5; + //~^ ERROR: declaration of a static with `export_name` + unsafe {} //~ ERROR: usage of an `unsafe` block + }} +} + +#[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` function +#[no_mangle] static FOO: u32 = 5; //~ ERROR: declaration of a `no_mangle` static + +trait AssocFnTrait { + fn foo(); +} + +struct AssocFnFoo; + +impl AssocFnFoo { + #[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` method +} + +impl AssocFnTrait for AssocFnFoo { + #[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` method +} + +#[export_name = "bar"] fn bar() {} //~ ERROR: declaration of a function with `export_name` +#[export_name = "BAR"] static BAR: u32 = 5; //~ ERROR: declaration of a static with `export_name` + +#[link_section = ".example_section"] fn uwu() {} //~ ERROR: declaration of a function with `link_section` +#[link_section = ".example_section"] static UWU: u32 = 5; //~ ERROR: declaration of a static with `link_section` + +struct AssocFnBar; + +impl AssocFnBar { + #[export_name = "bar"] fn bar() {} //~ ERROR: declaration of a method with `export_name` +} + +impl AssocFnTrait for AssocFnBar { + #[export_name = "bar"] fn foo() {} //~ ERROR: declaration of a method with `export_name` +} + +unsafe fn baz() {} //~ ERROR: declaration of an `unsafe` function +unsafe trait Foo {} //~ ERROR: declaration of an `unsafe` trait +unsafe impl Foo for Bar {} //~ ERROR: implementation of an `unsafe` trait + +trait Baz { + unsafe fn baz(&self); //~ ERROR: declaration of an `unsafe` method + unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method + unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +impl Baz for Bar { + unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method + unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method +} + + +#[allow(unsafe_code)] +trait A { + unsafe fn allowed_unsafe(&self); + unsafe fn allowed_unsafe_provided(&self) {} +} + +#[allow(unsafe_code)] +impl Baz for Bar2 { + unsafe fn baz(&self) {} + unsafe fn provided_override(&self) {} +} + +impl Baz for Bar3 { + #[allow(unsafe_code)] + unsafe fn baz(&self) {} + unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +#[allow(unsafe_code)] +unsafe trait B { + fn dummy(&self) {} +} + +trait C { + #[allow(unsafe_code)] + unsafe fn baz(&self); + unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +impl C for Bar { + #[allow(unsafe_code)] + unsafe fn baz(&self) {} + unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +impl C for Bar2 { + unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +trait D { + #[allow(unsafe_code)] + unsafe fn unsafe_provided(&self) {} +} + +impl D for Bar {} + +fn main() { + unsafe {} //~ ERROR: usage of an `unsafe` block + + unsafe_in_macro!() +} diff --git a/tests/ui/lint/lint-unsafe-code.stderr b/tests/ui/lint/lint-unsafe-code.stderr new file mode 100644 index 000000000..037f0a832 --- /dev/null +++ b/tests/ui/lint/lint-unsafe-code.stderr @@ -0,0 +1,224 @@ +error: declaration of a `no_mangle` function + --> $DIR/lint-unsafe-code.rs:31:1 + | +LL | #[no_mangle] fn foo() {} + | ^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them +note: the lint level is defined here + --> $DIR/lint-unsafe-code.rs:3:9 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: declaration of a `no_mangle` static + --> $DIR/lint-unsafe-code.rs:32:1 + | +LL | #[no_mangle] static FOO: u32 = 5; + | ^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: declaration of a `no_mangle` method + --> $DIR/lint-unsafe-code.rs:41:5 + | +LL | #[no_mangle] fn foo() {} + | ^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: declaration of a `no_mangle` method + --> $DIR/lint-unsafe-code.rs:45:5 + | +LL | #[no_mangle] fn foo() {} + | ^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: declaration of a function with `export_name` + --> $DIR/lint-unsafe-code.rs:48:1 + | +LL | #[export_name = "bar"] fn bar() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: declaration of a static with `export_name` + --> $DIR/lint-unsafe-code.rs:49:1 + | +LL | #[export_name = "BAR"] static BAR: u32 = 5; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: declaration of a function with `link_section` + --> $DIR/lint-unsafe-code.rs:51:1 + | +LL | #[link_section = ".example_section"] fn uwu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them + +error: declaration of a static with `link_section` + --> $DIR/lint-unsafe-code.rs:52:1 + | +LL | #[link_section = ".example_section"] static UWU: u32 = 5; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them + +error: declaration of a method with `export_name` + --> $DIR/lint-unsafe-code.rs:57:5 + | +LL | #[export_name = "bar"] fn bar() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: declaration of a method with `export_name` + --> $DIR/lint-unsafe-code.rs:61:5 + | +LL | #[export_name = "bar"] fn foo() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: declaration of an `unsafe` function + --> $DIR/lint-unsafe-code.rs:64:1 + | +LL | unsafe fn baz() {} + | ^^^^^^^^^^^^^^^^^^ + +error: declaration of an `unsafe` trait + --> $DIR/lint-unsafe-code.rs:65:1 + | +LL | unsafe trait Foo {} + | ^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` trait + --> $DIR/lint-unsafe-code.rs:66:1 + | +LL | unsafe impl Foo for Bar {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: declaration of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:69:5 + | +LL | unsafe fn baz(&self); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:70:5 + | +LL | unsafe fn provided(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:71:5 + | +LL | unsafe fn provided_override(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:75:5 + | +LL | unsafe fn baz(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:76:5 + | +LL | unsafe fn provided_override(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:95:5 + | +LL | unsafe fn provided_override(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:106:5 + | +LL | unsafe fn provided(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:112:5 + | +LL | unsafe fn provided(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:116:5 + | +LL | unsafe fn baz(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-unsafe-code.rs:127:5 + | +LL | unsafe {} + | ^^^^^^^^^ + +error: declaration of a `no_mangle` function + --> $DIR/lint-unsafe-code.rs:21:9 + | +LL | #[no_mangle] fn foo() {} + | ^^^^^^^^^^^^ +... +LL | unsafe_in_macro!() + | ------------------ in this macro invocation + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: declaration of a `no_mangle` static + --> $DIR/lint-unsafe-code.rs:22:9 + | +LL | #[no_mangle] static FOO: u32 = 5; + | ^^^^^^^^^^^^ +... +LL | unsafe_in_macro!() + | ------------------ in this macro invocation + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: declaration of a function with `export_name` + --> $DIR/lint-unsafe-code.rs:23:9 + | +LL | #[export_name = "bar"] fn bar() {} + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | unsafe_in_macro!() + | ------------------ in this macro invocation + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: declaration of a static with `export_name` + --> $DIR/lint-unsafe-code.rs:25:9 + | +LL | #[export_name = "BAR"] static BAR: u32 = 5; + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | unsafe_in_macro!() + | ------------------ in this macro invocation + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of an `unsafe` block + --> $DIR/lint-unsafe-code.rs:27:9 + | +LL | unsafe {} + | ^^^^^^^^^ +... +LL | unsafe_in_macro!() + | ------------------ in this macro invocation + | + = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 28 previous errors + diff --git a/tests/ui/lint/lint-uppercase-variables.rs b/tests/ui/lint/lint-uppercase-variables.rs new file mode 100644 index 000000000..59dba536f --- /dev/null +++ b/tests/ui/lint/lint-uppercase-variables.rs @@ -0,0 +1,41 @@ +#![warn(unused)] +#![allow(dead_code)] +#![deny(non_snake_case)] + +mod foo { + pub enum Foo { Foo } +} + +struct Something { + X: usize //~ ERROR structure field `X` should have a snake case name +} + +fn test(Xx: usize) { //~ ERROR variable `Xx` should have a snake case name + println!("{}", Xx); +} + +fn main() { + let Test: usize = 0; //~ ERROR variable `Test` should have a snake case name + println!("{}", Test); + + match foo::Foo::Foo { + Foo => {} + //~^ ERROR variable `Foo` should have a snake case name + //~^^ ERROR `Foo` is named the same as one of the variants of the type `foo::Foo` + //~^^^ WARN unused variable: `Foo` + } + + let Foo = foo::Foo::Foo; + //~^ ERROR variable `Foo` should have a snake case name + //~^^ ERROR `Foo` is named the same as one of the variants of the type `foo::Foo` + //~^^^ WARN unused variable: `Foo` + + fn in_param(Foo: foo::Foo) {} + //~^ ERROR variable `Foo` should have a snake case name + //~^^ ERROR `Foo` is named the same as one of the variants of the type `foo::Foo` + //~^^^ WARN unused variable: `Foo` + + test(1); + + let _ = Something { X: 0 }; +} diff --git a/tests/ui/lint/lint-uppercase-variables.stderr b/tests/ui/lint/lint-uppercase-variables.stderr new file mode 100644 index 000000000..42ec9364b --- /dev/null +++ b/tests/ui/lint/lint-uppercase-variables.stderr @@ -0,0 +1,90 @@ +error[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo` + --> $DIR/lint-uppercase-variables.rs:22:9 + | +LL | Foo => {} + | ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo` + | + = note: `#[deny(bindings_with_variant_name)]` on by default + +error[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo` + --> $DIR/lint-uppercase-variables.rs:28:9 + | +LL | let Foo = foo::Foo::Foo; + | ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo` + +error[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo` + --> $DIR/lint-uppercase-variables.rs:33:17 + | +LL | fn in_param(Foo: foo::Foo) {} + | ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo` + +warning: unused variable: `Foo` + --> $DIR/lint-uppercase-variables.rs:22:9 + | +LL | Foo => {} + | ^^^ help: if this is intentional, prefix it with an underscore: `_Foo` + | +note: the lint level is defined here + --> $DIR/lint-uppercase-variables.rs:1:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: unused variable: `Foo` + --> $DIR/lint-uppercase-variables.rs:28:9 + | +LL | let Foo = foo::Foo::Foo; + | ^^^ help: if this is intentional, prefix it with an underscore: `_Foo` + +warning: unused variable: `Foo` + --> $DIR/lint-uppercase-variables.rs:33:17 + | +LL | fn in_param(Foo: foo::Foo) {} + | ^^^ help: if this is intentional, prefix it with an underscore: `_Foo` + +error: structure field `X` should have a snake case name + --> $DIR/lint-uppercase-variables.rs:10:5 + | +LL | X: usize + | ^ help: convert the identifier to snake case (notice the capitalization): `x` + | +note: the lint level is defined here + --> $DIR/lint-uppercase-variables.rs:3:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: variable `Xx` should have a snake case name + --> $DIR/lint-uppercase-variables.rs:13:9 + | +LL | fn test(Xx: usize) { + | ^^ help: convert the identifier to snake case (notice the capitalization): `xx` + +error: variable `Test` should have a snake case name + --> $DIR/lint-uppercase-variables.rs:18:9 + | +LL | let Test: usize = 0; + | ^^^^ help: convert the identifier to snake case: `test` + +error: variable `Foo` should have a snake case name + --> $DIR/lint-uppercase-variables.rs:22:9 + | +LL | Foo => {} + | ^^^ help: convert the identifier to snake case (notice the capitalization): `foo` + +error: variable `Foo` should have a snake case name + --> $DIR/lint-uppercase-variables.rs:28:9 + | +LL | let Foo = foo::Foo::Foo; + | ^^^ help: convert the identifier to snake case (notice the capitalization): `foo` + +error: variable `Foo` should have a snake case name + --> $DIR/lint-uppercase-variables.rs:33:17 + | +LL | fn in_param(Foo: foo::Foo) {} + | ^^^ help: convert the identifier to snake case (notice the capitalization): `foo` + +error: aborting due to 9 previous errors; 3 warnings emitted + +For more information about this error, try `rustc --explain E0170`. diff --git a/tests/ui/lint/lint_pre_expansion_extern_module_aux.rs b/tests/ui/lint/lint_pre_expansion_extern_module_aux.rs new file mode 100644 index 000000000..71dec40ea --- /dev/null +++ b/tests/ui/lint/lint_pre_expansion_extern_module_aux.rs @@ -0,0 +1,3 @@ +// ignore-test: not a test + +pub fn try() {} diff --git a/tests/ui/lint/lints-in-foreign-macros.rs b/tests/ui/lint/lints-in-foreign-macros.rs new file mode 100644 index 000000000..1e8b6788a --- /dev/null +++ b/tests/ui/lint/lints-in-foreign-macros.rs @@ -0,0 +1,21 @@ +// aux-build:lints-in-foreign-macros.rs +// check-pass + +#![warn(unused_imports)] //~ missing documentation for the crate [missing_docs] +#![warn(missing_docs)] + +#[macro_use] +extern crate lints_in_foreign_macros; + +macro_rules! foo { + () => {use std::string::ToString;} //~ WARN: unused import +} + +mod a { foo!(); } +mod b { bar!(); } +mod c { baz!(use std::string::ToString;); } //~ WARN: unused import +mod d { baz2!(use std::string::ToString;); } //~ WARN: unused import +baz!(pub fn undocumented() {}); //~ WARN: missing documentation for a function +baz2!(pub fn undocumented2() {}); //~ WARN: missing documentation for a function + +fn main() {} diff --git a/tests/ui/lint/lints-in-foreign-macros.stderr b/tests/ui/lint/lints-in-foreign-macros.stderr new file mode 100644 index 000000000..f20e16287 --- /dev/null +++ b/tests/ui/lint/lints-in-foreign-macros.stderr @@ -0,0 +1,60 @@ +warning: unused import: `std::string::ToString` + --> $DIR/lints-in-foreign-macros.rs:11:16 + | +LL | () => {use std::string::ToString;} + | ^^^^^^^^^^^^^^^^^^^^^ +... +LL | mod a { foo!(); } + | ------ in this macro invocation + | +note: the lint level is defined here + --> $DIR/lints-in-foreign-macros.rs:4:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unused import: `std::string::ToString` + --> $DIR/lints-in-foreign-macros.rs:16:18 + | +LL | mod c { baz!(use std::string::ToString;); } + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: unused import: `std::string::ToString` + --> $DIR/lints-in-foreign-macros.rs:17:19 + | +LL | mod d { baz2!(use std::string::ToString;); } + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: missing documentation for the crate + --> $DIR/lints-in-foreign-macros.rs:4:1 + | +LL | / #![warn(unused_imports)] +LL | | #![warn(missing_docs)] +LL | | +LL | | #[macro_use] +... | +LL | | +LL | | fn main() {} + | |____________^ + | +note: the lint level is defined here + --> $DIR/lints-in-foreign-macros.rs:5:9 + | +LL | #![warn(missing_docs)] + | ^^^^^^^^^^^^ + +warning: missing documentation for a function + --> $DIR/lints-in-foreign-macros.rs:18:6 + | +LL | baz!(pub fn undocumented() {}); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: missing documentation for a function + --> $DIR/lints-in-foreign-macros.rs:19:7 + | +LL | baz2!(pub fn undocumented2() {}); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: 6 warnings emitted + diff --git a/tests/ui/lint/missing-doc-private-macro.rs b/tests/ui/lint/missing-doc-private-macro.rs new file mode 100644 index 000000000..0d4332ed0 --- /dev/null +++ b/tests/ui/lint/missing-doc-private-macro.rs @@ -0,0 +1,43 @@ +// Checks that undocumented private macros will not generate `missing_docs` +// lints, but public ones will. +// +// This is a regression test for issue #57569 +#![deny(missing_docs)] +#![feature(decl_macro)] +//! Empty documentation. + +macro new_style_private_macro { + () => () +} + +pub(crate) macro new_style_crate_macro { + () => () +} + +macro_rules! old_style_private_macro { + () => () +} + +mod submodule { + pub macro new_style_macro_in_private_module { + () => () + } + + macro_rules! old_style_mod_private_macro { + () => () + } + + #[macro_export] + macro_rules! exported_to_top_level { + //~^ ERROR missing documentation for a macro + () => () + } +} + +pub macro top_level_pub_macro { + //~^ ERROR missing documentation for a macro + () => () +} + +/// Empty documentation. +pub fn main() {} diff --git a/tests/ui/lint/missing-doc-private-macro.stderr b/tests/ui/lint/missing-doc-private-macro.stderr new file mode 100644 index 000000000..979b007d0 --- /dev/null +++ b/tests/ui/lint/missing-doc-private-macro.stderr @@ -0,0 +1,20 @@ +error: missing documentation for a macro + --> $DIR/missing-doc-private-macro.rs:31:5 + | +LL | macro_rules! exported_to_top_level { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/missing-doc-private-macro.rs:5:9 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a macro + --> $DIR/missing-doc-private-macro.rs:37:1 + | +LL | pub macro top_level_pub_macro { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/must_not_suspend/boxed.rs b/tests/ui/lint/must_not_suspend/boxed.rs new file mode 100644 index 000000000..1f823fc55 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/boxed.rs @@ -0,0 +1,25 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + i: i64 +} + + +fn bar() -> Box<Umm> { + Box::new(Umm { + i: 1 + }) +} + +async fn other() {} + +pub async fn uhoh() { + let _guard = bar(); //~ ERROR boxed `Umm` held across + other().await; +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/boxed.stderr b/tests/ui/lint/must_not_suspend/boxed.stderr new file mode 100644 index 000000000..9efc7b069 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/boxed.stderr @@ -0,0 +1,26 @@ +error: boxed `Umm` held across a suspend point, but should not be + --> $DIR/boxed.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +LL | other().await; + | ------ the value is held across this suspend point + | +note: You gotta use Umm's, ya know? + --> $DIR/boxed.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/boxed.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +note: the lint level is defined here + --> $DIR/boxed.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/dedup.rs b/tests/ui/lint/must_not_suspend/dedup.rs new file mode 100644 index 000000000..81a08579b --- /dev/null +++ b/tests/ui/lint/must_not_suspend/dedup.rs @@ -0,0 +1,20 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] +struct No {} + +async fn shushspend() {} + +async fn wheeee<T>(t: T) { + shushspend().await; + drop(t); +} + +async fn yes() { + wheeee(&No {}).await; //~ ERROR `No` held across +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/dedup.stderr b/tests/ui/lint/must_not_suspend/dedup.stderr new file mode 100644 index 000000000..f8978ba57 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/dedup.stderr @@ -0,0 +1,19 @@ +error: `No` held across a suspend point, but should not be + --> $DIR/dedup.rs:16:13 + | +LL | wheeee(&No {}).await; + | ^^^^^ ------ the value is held across this suspend point + | +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/dedup.rs:16:13 + | +LL | wheeee(&No {}).await; + | ^^^^^ +note: the lint level is defined here + --> $DIR/dedup.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs b/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs new file mode 100644 index 000000000..1554408c1 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs @@ -0,0 +1,9 @@ +// edition:2018 + +#[must_not_suspend = "You gotta use Umm's, ya know?"] //~ ERROR the `#[must_not_suspend]` +struct Umm { + _i: i64 +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr b/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr new file mode 100644 index 000000000..ab20a8be8 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[must_not_suspend]` attribute is an experimental feature + --> $DIR/feature-gate-must_not_suspend.rs:3:1 + | +LL | #[must_not_suspend = "You gotta use Umm's, ya know?"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information + = help: add `#![feature(must_not_suspend)]` 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/lint/must_not_suspend/gated.rs b/tests/ui/lint/must_not_suspend/gated.rs new file mode 100644 index 000000000..b73a76555 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/gated.rs @@ -0,0 +1,17 @@ +// check-pass + +// edition:2018 +#![deny(must_not_suspend)] +//~^ WARNING unknown lint: `must_not_suspend` +//~| WARNING unknown lint: `must_not_suspend` +//~| WARNING unknown lint: `must_not_suspend` + +async fn other() {} + +pub async fn uhoh(m: std::sync::Mutex<()>) { + let _guard = m.lock().unwrap(); + other().await; +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/gated.stderr b/tests/ui/lint/must_not_suspend/gated.stderr new file mode 100644 index 000000000..64de1ebea --- /dev/null +++ b/tests/ui/lint/must_not_suspend/gated.stderr @@ -0,0 +1,33 @@ +warning: unknown lint: `must_not_suspend` + --> $DIR/gated.rs:4:1 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `must_not_suspend` lint is unstable + = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information + = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable + = note: `#[warn(unknown_lints)]` on by default + +warning: unknown lint: `must_not_suspend` + --> $DIR/gated.rs:4:1 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `must_not_suspend` lint is unstable + = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information + = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable + +warning: unknown lint: `must_not_suspend` + --> $DIR/gated.rs:4:1 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `must_not_suspend` lint is unstable + = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information + = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/must_not_suspend/generic.rs b/tests/ui/lint/must_not_suspend/generic.rs new file mode 100644 index 000000000..b3effa020 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/generic.rs @@ -0,0 +1,20 @@ +// edition:2018 +// run-pass +// +// this test shows a case where the lint doesn't fire in generic code +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] +struct No {} + +async fn shushspend() {} + +async fn wheeee<T>(t: T) { + shushspend().await; + drop(t); +} + +fn main() { + let _fut = wheeee(No {}); +} diff --git a/tests/ui/lint/must_not_suspend/handled.rs b/tests/ui/lint/must_not_suspend/handled.rs new file mode 100644 index 000000000..8714be644 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/handled.rs @@ -0,0 +1,28 @@ +// edition:2018 +// run-pass +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + _i: i64 +} + + +fn bar() -> Umm { + Umm { + _i: 1 + } +} + +async fn other() {} + +pub async fn uhoh() { + { + let _guard = bar(); + } + other().await; +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/issue-89562.rs b/tests/ui/lint/must_not_suspend/issue-89562.rs new file mode 100644 index 000000000..acdb36fcd --- /dev/null +++ b/tests/ui/lint/must_not_suspend/issue-89562.rs @@ -0,0 +1,19 @@ +// edition:2018 +// run-pass + +use std::sync::Mutex; + +// Copied from the issue. Allow-by-default for now, so run-pass +pub async fn foo() { + let foo = Mutex::new(1); + let lock = foo.lock().unwrap(); + + // Prevent mutex lock being held across `.await` point. + drop(lock); + + bar().await; +} + +async fn bar() {} + +fn main() {} diff --git a/tests/ui/lint/must_not_suspend/mutex.rs b/tests/ui/lint/must_not_suspend/mutex.rs new file mode 100644 index 000000000..7bb895e7d --- /dev/null +++ b/tests/ui/lint/must_not_suspend/mutex.rs @@ -0,0 +1,13 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +async fn other() {} + +pub async fn uhoh(m: std::sync::Mutex<()>) { + let _guard = m.lock().unwrap(); //~ ERROR `MutexGuard` held across + other().await; +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/mutex.stderr b/tests/ui/lint/must_not_suspend/mutex.stderr new file mode 100644 index 000000000..c251cb845 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/mutex.stderr @@ -0,0 +1,26 @@ +error: `MutexGuard` held across a suspend point, but should not be + --> $DIR/mutex.rs:8:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ +LL | other().await; + | ------ the value is held across this suspend point + | +note: holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send` + --> $DIR/mutex.rs:8:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/mutex.rs:8:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ +note: the lint level is defined here + --> $DIR/mutex.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/other_items.rs b/tests/ui/lint/must_not_suspend/other_items.rs new file mode 100644 index 000000000..5aa1abb14 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/other_items.rs @@ -0,0 +1,8 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] //~ ERROR attribute should be +mod inner {} + +fn main() {} diff --git a/tests/ui/lint/must_not_suspend/other_items.stderr b/tests/ui/lint/must_not_suspend/other_items.stderr new file mode 100644 index 000000000..41c889692 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/other_items.stderr @@ -0,0 +1,10 @@ +error: `must_not_suspend` attribute should be applied to a struct, enum, or trait + --> $DIR/other_items.rs:5:1 + | +LL | #[must_not_suspend] + | ^^^^^^^^^^^^^^^^^^^ +LL | mod inner {} + | ------------ is not a struct, enum, or trait + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/ref-drop-tracking.rs b/tests/ui/lint/must_not_suspend/ref-drop-tracking.rs new file mode 100644 index 000000000..1bc4a3812 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/ref-drop-tracking.rs @@ -0,0 +1,30 @@ +// edition:2018 +// compile-flags: -Zdrop-tracking +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + i: i64 +} + +struct Bar { + u: Umm, +} + +async fn other() {} + +impl Bar { + async fn uhoh(&mut self) { + let guard = &mut self.u; //~ ERROR `Umm` held across + + other().await; + + *guard = Umm { + i: 2 + } + } +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/ref-drop-tracking.stderr b/tests/ui/lint/must_not_suspend/ref-drop-tracking.stderr new file mode 100644 index 000000000..180e187c1 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/ref-drop-tracking.stderr @@ -0,0 +1,27 @@ +error: reference to `Umm` held across a suspend point, but should not be + --> $DIR/ref-drop-tracking.rs:19:13 + | +LL | let guard = &mut self.u; + | ^^^^^ +LL | +LL | other().await; + | ------ the value is held across this suspend point + | +note: You gotta use Umm's, ya know? + --> $DIR/ref-drop-tracking.rs:19:13 + | +LL | let guard = &mut self.u; + | ^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/ref-drop-tracking.rs:19:13 + | +LL | let guard = &mut self.u; + | ^^^^^ +note: the lint level is defined here + --> $DIR/ref-drop-tracking.rs:4:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr b/tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr new file mode 100644 index 000000000..abf76711b --- /dev/null +++ b/tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr @@ -0,0 +1,27 @@ +error: reference to `Umm` held across a suspend point, but should not be + --> $DIR/ref.rs:21:13 + | +LL | let guard = &mut self.u; + | ^^^^^ +LL | +LL | other().await; + | ------ the value is held across this suspend point + | +note: You gotta use Umm's, ya know? + --> $DIR/ref.rs:21:13 + | +LL | let guard = &mut self.u; + | ^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/ref.rs:21:13 + | +LL | let guard = &mut self.u; + | ^^^^^ +note: the lint level is defined here + --> $DIR/ref.rs:6:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr b/tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr new file mode 100644 index 000000000..41ac09ea7 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr @@ -0,0 +1,27 @@ +error: `Umm` held across a suspend point, but should not be + --> $DIR/ref.rs:21:26 + | +LL | let guard = &mut self.u; + | ^^^^^^ +LL | +LL | other().await; + | ------ the value is held across this suspend point + | +note: You gotta use Umm's, ya know? + --> $DIR/ref.rs:21:26 + | +LL | let guard = &mut self.u; + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/ref.rs:21:26 + | +LL | let guard = &mut self.u; + | ^^^^^^ +note: the lint level is defined here + --> $DIR/ref.rs:6:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/ref.rs b/tests/ui/lint/must_not_suspend/ref.rs new file mode 100644 index 000000000..f6b23746f --- /dev/null +++ b/tests/ui/lint/must_not_suspend/ref.rs @@ -0,0 +1,29 @@ +// edition:2018 +// revisions: no_drop_tracking drop_tracking +// [drop_tracking] compile-flags: -Zdrop-tracking=yes +// [no_drop_tracking] compile-flags: -Zdrop-tracking=no +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + i: i64, +} + +struct Bar { + u: Umm, +} + +async fn other() {} + +impl Bar { + async fn uhoh(&mut self) { + let guard = &mut self.u; //~ ERROR `Umm` held across + + other().await; + + *guard = Umm { i: 2 } + } +} + +fn main() {} diff --git a/tests/ui/lint/must_not_suspend/return.rs b/tests/ui/lint/must_not_suspend/return.rs new file mode 100644 index 000000000..5b1fa5e27 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/return.rs @@ -0,0 +1,9 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] //~ ERROR attribute should be +fn foo() -> i32 { + 0 +} +fn main() {} diff --git a/tests/ui/lint/must_not_suspend/return.stderr b/tests/ui/lint/must_not_suspend/return.stderr new file mode 100644 index 000000000..fdada85eb --- /dev/null +++ b/tests/ui/lint/must_not_suspend/return.stderr @@ -0,0 +1,12 @@ +error: `must_not_suspend` attribute should be applied to a struct, enum, or trait + --> $DIR/return.rs:5:1 + | +LL | #[must_not_suspend] + | ^^^^^^^^^^^^^^^^^^^ +LL | / fn foo() -> i32 { +LL | | 0 +LL | | } + | |_- is not a struct, enum, or trait + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/trait.rs b/tests/ui/lint/must_not_suspend/trait.rs new file mode 100644 index 000000000..6c911cb4b --- /dev/null +++ b/tests/ui/lint/must_not_suspend/trait.rs @@ -0,0 +1,28 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] +trait Wow {} + +impl Wow for i32 {} + +fn r#impl() -> impl Wow { + 1 +} + +fn r#dyn() -> Box<dyn Wow> { + Box::new(1) +} + +async fn other() {} + +pub async fn uhoh() { + let _guard1 = r#impl(); //~ ERROR implementer of `Wow` held across + let _guard2 = r#dyn(); //~ ERROR boxed `Wow` trait object held across + + other().await; +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/trait.stderr b/tests/ui/lint/must_not_suspend/trait.stderr new file mode 100644 index 000000000..d64d25aae --- /dev/null +++ b/tests/ui/lint/must_not_suspend/trait.stderr @@ -0,0 +1,37 @@ +error: implementer of `Wow` held across a suspend point, but should not be + --> $DIR/trait.rs:21:9 + | +LL | let _guard1 = r#impl(); + | ^^^^^^^ +... +LL | other().await; + | ------ the value is held across this suspend point + | +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/trait.rs:21:9 + | +LL | let _guard1 = r#impl(); + | ^^^^^^^ +note: the lint level is defined here + --> $DIR/trait.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: boxed `Wow` trait object held across a suspend point, but should not be + --> $DIR/trait.rs:22:9 + | +LL | let _guard2 = r#dyn(); + | ^^^^^^^ +LL | +LL | other().await; + | ------ the value is held across this suspend point + | +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/trait.rs:22:9 + | +LL | let _guard2 = r#dyn(); + | ^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/must_not_suspend/tuple-mismatch.rs b/tests/ui/lint/must_not_suspend/tuple-mismatch.rs new file mode 100644 index 000000000..c7e14e425 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/tuple-mismatch.rs @@ -0,0 +1,9 @@ +#![feature(generators)] + +fn main() { + let _generator = || { + yield ((), ((), ())); + yield ((), ()); + //~^ ERROR mismatched types + }; +} diff --git a/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr b/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr new file mode 100644 index 000000000..cca8cd9bd --- /dev/null +++ b/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/tuple-mismatch.rs:6:20 + | +LL | yield ((), ()); + | ^^ expected tuple, found `()` + | + = note: expected tuple `((), ())` + found unit type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lint/must_not_suspend/unit.rs b/tests/ui/lint/must_not_suspend/unit.rs new file mode 100644 index 000000000..d3a19f704 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/unit.rs @@ -0,0 +1,25 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + i: i64 +} + + +fn bar() -> Umm { + Umm { + i: 1 + } +} + +async fn other() {} + +pub async fn uhoh() { + let _guard = bar(); //~ ERROR `Umm` held across + other().await; +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/unit.stderr b/tests/ui/lint/must_not_suspend/unit.stderr new file mode 100644 index 000000000..c967dbac5 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/unit.stderr @@ -0,0 +1,26 @@ +error: `Umm` held across a suspend point, but should not be + --> $DIR/unit.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +LL | other().await; + | ------ the value is held across this suspend point + | +note: You gotta use Umm's, ya know? + --> $DIR/unit.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/unit.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +note: the lint level is defined here + --> $DIR/unit.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/warn.rs b/tests/ui/lint/must_not_suspend/warn.rs new file mode 100644 index 000000000..7fdea66a2 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/warn.rs @@ -0,0 +1,26 @@ +// edition:2018 +// run-pass +#![feature(must_not_suspend)] +#![warn(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + _i: i64 +} + + +fn bar() -> Umm { + Umm { + _i: 1 + } +} + +async fn other() {} + +pub async fn uhoh() { + let _guard = bar(); //~ WARNING `Umm` held across + other().await; +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/warn.stderr b/tests/ui/lint/must_not_suspend/warn.stderr new file mode 100644 index 000000000..fe551c652 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/warn.stderr @@ -0,0 +1,26 @@ +warning: `Umm` held across a suspend point, but should not be + --> $DIR/warn.rs:21:9 + | +LL | let _guard = bar(); + | ^^^^^^ +LL | other().await; + | ------ the value is held across this suspend point + | +note: You gotta use Umm's, ya know? + --> $DIR/warn.rs:21:9 + | +LL | let _guard = bar(); + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/warn.rs:21:9 + | +LL | let _guard = bar(); + | ^^^^^^ +note: the lint level is defined here + --> $DIR/warn.rs:4:9 + | +LL | #![warn(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/no-coverage.rs b/tests/ui/lint/no-coverage.rs new file mode 100644 index 000000000..ff24c12b2 --- /dev/null +++ b/tests/ui/lint/no-coverage.rs @@ -0,0 +1,55 @@ +#![feature(extern_types)] +#![feature(no_coverage)] +#![feature(type_alias_impl_trait)] +#![warn(unused_attributes)] +#![no_coverage] +//~^ WARN: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly + +#[no_coverage] +//~^ WARN: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly +trait Trait { + #[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code + const X: u32; + + #[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code + type T; + + type U; +} + +#[no_coverage] +//~^ WARN: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly +impl Trait for () { + const X: u32 = 0; + + #[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code + type T = Self; + + #[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code + type U = impl Trait; //~ ERROR unconstrained opaque type +} + +extern "C" { + #[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code + static X: u32; + + #[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code + type T; +} + +#[no_coverage] +fn main() { + #[no_coverage] + //~^ WARN `#[no_coverage]` may only be applied to function definitions + let _ = (); + + match () { + #[no_coverage] + //~^ WARN `#[no_coverage]` may only be applied to function definitions + () => (), + } + + #[no_coverage] + //~^ WARN `#[no_coverage]` may only be applied to function definitions + return (); +} diff --git a/tests/ui/lint/no-coverage.stderr b/tests/ui/lint/no-coverage.stderr new file mode 100644 index 000000000..404efbeac --- /dev/null +++ b/tests/ui/lint/no-coverage.stderr @@ -0,0 +1,101 @@ +warning: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly + --> $DIR/no-coverage.rs:8:1 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/no-coverage.rs:4:9 + | +LL | #![warn(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +warning: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly + --> $DIR/no-coverage.rs:20:1 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ + +warning: `#[no_coverage]` may only be applied to function definitions + --> $DIR/no-coverage.rs:42:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ + +warning: `#[no_coverage]` may only be applied to function definitions + --> $DIR/no-coverage.rs:47:9 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ + +warning: `#[no_coverage]` may only be applied to function definitions + --> $DIR/no-coverage.rs:52:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ + +error[E0788]: `#[no_coverage]` must be applied to coverable code + --> $DIR/no-coverage.rs:11:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ +LL | const X: u32; + | ------------- not coverable code + +error[E0788]: `#[no_coverage]` must be applied to coverable code + --> $DIR/no-coverage.rs:14:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ +LL | type T; + | ------- not coverable code + +error[E0788]: `#[no_coverage]` must be applied to coverable code + --> $DIR/no-coverage.rs:25:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ +LL | type T = Self; + | -------------- not coverable code + +error[E0788]: `#[no_coverage]` must be applied to coverable code + --> $DIR/no-coverage.rs:28:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ +LL | type U = impl Trait; + | -------------------- not coverable code + +error[E0788]: `#[no_coverage]` must be applied to coverable code + --> $DIR/no-coverage.rs:33:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ +LL | static X: u32; + | -------------- not coverable code + +error[E0788]: `#[no_coverage]` must be applied to coverable code + --> $DIR/no-coverage.rs:36:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ +LL | type T; + | ------- not coverable code + +warning: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly + --> $DIR/no-coverage.rs:5:1 + | +LL | #![no_coverage] + | ^^^^^^^^^^^^^^^ + +error: unconstrained opaque type + --> $DIR/no-coverage.rs:29:14 + | +LL | type U = impl Trait; + | ^^^^^^^^^^ + | + = note: `U` must be used in combination with a concrete type within the same impl + +error: aborting due to 7 previous errors; 6 warnings emitted + +For more information about this error, try `rustc --explain E0788`. diff --git a/tests/ui/lint/noop-method-call.rs b/tests/ui/lint/noop-method-call.rs new file mode 100644 index 000000000..89b296635 --- /dev/null +++ b/tests/ui/lint/noop-method-call.rs @@ -0,0 +1,55 @@ +// check-pass + +#![allow(unused)] +#![warn(noop_method_call)] + +use std::borrow::Borrow; +use std::ops::Deref; + +struct PlainType<T>(T); + +#[derive(Clone)] +struct CloneType<T>(T); + +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 + + let clone_type_ref = &CloneType(1u32); + let clone_type_ref_clone: CloneType<u32> = clone_type_ref.clone(); + + // Calling clone on a double reference doesn't warn since the method call itself + // peels the outer reference off + 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.deref(); + //~^ WARNING call to `.deref()` on a reference in this situation does nothing + + // Dereferencing a &&T does not warn since it has collapsed the double reference + let non_deref_type = &&PlainType(1u32); + let non_deref_type_deref: &PlainType<u32> = non_deref_type.deref(); + + 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 + + // 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(); // ok, but could use `*x` instead +} + +fn generic<T>(non_clone_type: &PlainType<T>) { + non_clone_type.clone(); + //~^ WARNING 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 +} diff --git a/tests/ui/lint/noop-method-call.stderr b/tests/ui/lint/noop-method-call.stderr new file mode 100644 index 000000000..6a904d01a --- /dev/null +++ b/tests/ui/lint/noop-method-call.stderr @@ -0,0 +1,47 @@ +warning: call to `.clone()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:16:71 + | +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 | #![warn(noop_method_call)] + | ^^^^^^^^^^^^^^^^ + +warning: call to `.deref()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:28:63 + | +LL | let non_deref_type_deref: &PlainType<u32> = non_deref_type.deref(); + | ^^^^^^^^ unnecessary method 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 + +warning: call to `.borrow()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:36: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: call to `.clone()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:48:19 + | +LL | non_clone_type.clone(); + | ^^^^^^^^ unnecessary method 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 + +warning: call to `.clone()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:53:19 + | +LL | non_clone_type.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 + +warning: 5 warnings emitted + diff --git a/tests/ui/lint/not_found.rs b/tests/ui/lint/not_found.rs new file mode 100644 index 000000000..de120b6e0 --- /dev/null +++ b/tests/ui/lint/not_found.rs @@ -0,0 +1,21 @@ +// check-pass + +// this tests the `unknown_lint` lint, especially the suggestions + +// the suggestion only appears if a lint with the lowercase name exists +#[allow(FOO_BAR)] +//~^ WARNING unknown lint + +// the suggestion appears on all-uppercase names +#[warn(DEAD_CODE)] +//~^ WARNING unknown lint +//~| HELP did you mean + +// the suggestion appears also on mixed-case names +#[deny(Warnings)] +//~^ WARNING unknown lint +//~| HELP did you mean + +fn main() { + unimplemented!(); +} diff --git a/tests/ui/lint/not_found.stderr b/tests/ui/lint/not_found.stderr new file mode 100644 index 000000000..ea118c73c --- /dev/null +++ b/tests/ui/lint/not_found.stderr @@ -0,0 +1,22 @@ +warning: unknown lint: `FOO_BAR` + --> $DIR/not_found.rs:6:9 + | +LL | #[allow(FOO_BAR)] + | ^^^^^^^ + | + = note: `#[warn(unknown_lints)]` on by default + +warning: unknown lint: `DEAD_CODE` + --> $DIR/not_found.rs:10:8 + | +LL | #[warn(DEAD_CODE)] + | ^^^^^^^^^ help: did you mean: `dead_code` + +warning: unknown lint: `Warnings` + --> $DIR/not_found.rs:15:8 + | +LL | #[deny(Warnings)] + | ^^^^^^^^ help: did you mean (notice the capitalization): `warnings` + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/opaque-ty-ffi-normalization-cycle.rs b/tests/ui/lint/opaque-ty-ffi-normalization-cycle.rs new file mode 100644 index 000000000..c83bca4a4 --- /dev/null +++ b/tests/ui/lint/opaque-ty-ffi-normalization-cycle.rs @@ -0,0 +1,41 @@ +#![feature(type_alias_impl_trait)] +#![allow(unused)] +#![deny(improper_ctypes)] + +pub trait TraitA { + type Assoc; +} + +impl TraitA for u32 { + type Assoc = u32; +} + +pub trait TraitB { + type Assoc; +} + +impl<T> TraitB for T +where + T: TraitA, +{ + type Assoc = <T as TraitA>::Assoc; +} + +type AliasA = impl TraitA<Assoc = u32>; + +type AliasB = impl TraitB; + +fn use_of_a() -> AliasA { + 3 +} + +fn use_of_b() -> AliasB { + 3 +} + +extern "C" { + fn lint_me() -> <AliasB as TraitB>::Assoc; + //~^ ERROR `extern` block uses type `AliasB`, which is not FFI-safe +} + +fn main() {} diff --git a/tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr b/tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr new file mode 100644 index 000000000..e8d696477 --- /dev/null +++ b/tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `AliasB`, which is not FFI-safe + --> $DIR/opaque-ty-ffi-normalization-cycle.rs:37:21 + | +LL | fn lint_me() -> <AliasB as TraitB>::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: opaque types have no C equivalent +note: the lint level is defined here + --> $DIR/opaque-ty-ffi-normalization-cycle.rs:3:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/opaque-ty-ffi-unsafe.rs b/tests/ui/lint/opaque-ty-ffi-unsafe.rs new file mode 100644 index 000000000..b7cc38e99 --- /dev/null +++ b/tests/ui/lint/opaque-ty-ffi-unsafe.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +type A = impl Fn(); + +pub fn ret_closure() -> A { + || {} +} + +extern "C" { + pub fn a(_: A); + //~^ ERROR `extern` block uses type `A`, which is not FFI-safe [improper_ctypes] +} + +fn main() {} diff --git a/tests/ui/lint/opaque-ty-ffi-unsafe.stderr b/tests/ui/lint/opaque-ty-ffi-unsafe.stderr new file mode 100644 index 000000000..33aa95854 --- /dev/null +++ b/tests/ui/lint/opaque-ty-ffi-unsafe.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `A`, which is not FFI-safe + --> $DIR/opaque-ty-ffi-unsafe.rs:11:17 + | +LL | pub fn a(_: A); + | ^ not FFI-safe + | + = note: opaque types have no C equivalent +note: the lint level is defined here + --> $DIR/opaque-ty-ffi-unsafe.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/outer-forbid.rs b/tests/ui/lint/outer-forbid.rs new file mode 100644 index 000000000..ba330258d --- /dev/null +++ b/tests/ui/lint/outer-forbid.rs @@ -0,0 +1,32 @@ +// Forbidding a group (here, `unused`) overrules subsequent allowance of both +// the group, and an individual lint in the group (here, `unused_variables`); +// and, forbidding an individual lint (here, `non_snake_case`) overrules +// subsequent allowance of a lint group containing it (here, `nonstandard_style`). See +// Issue #42873. + +// If you turn off deduplicate diagnostics (which rustc turns on by default but +// compiletest turns off when it runs ui tests), then the errors are +// (unfortunately) repeated here because the checking is done as we read in the +// errors, and currently that happens two or three different times, depending on +// compiler flags. +// +// The test is much cleaner if we deduplicate, though. + +// compile-flags: -Z deduplicate-diagnostics=yes + +#![forbid(unused, non_snake_case)] +#![forbid(forbidden_lint_groups)] + +#[allow(unused_variables)] +//~^ ERROR incompatible with previous +//~| WARNING this was previously accepted by the compiler +fn foo() {} + +#[allow(unused)] //~ ERROR incompatible with previous +//~^ WARNING this was previously accepted by the compiler +fn bar() {} + +#[allow(nonstandard_style)] //~ ERROR incompatible with previous +fn main() { + println!("hello forbidden world") +} diff --git a/tests/ui/lint/outer-forbid.stderr b/tests/ui/lint/outer-forbid.stderr new file mode 100644 index 000000000..a47877980 --- /dev/null +++ b/tests/ui/lint/outer-forbid.stderr @@ -0,0 +1,41 @@ +error: allow(unused_variables) incompatible with previous forbid + --> $DIR/outer-forbid.rs:20:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + +error[E0453]: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/outer-forbid.rs:29:9 + | +LL | #![forbid(unused, non_snake_case)] + | -------------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/reasons-erroneous.rs b/tests/ui/lint/reasons-erroneous.rs new file mode 100644 index 000000000..cd693ae16 --- /dev/null +++ b/tests/ui/lint/reasons-erroneous.rs @@ -0,0 +1,54 @@ +#![feature(lint_reasons)] + +#![warn(absolute_paths_not_starting_with_crate, reason = 0)] +//~^ ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE reason must be a string literal +//~| NOTE reason must be a string literal +#![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] +//~^ ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE reason must be a string literal +//~| NOTE reason must be a string literal +#![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] +//~^ ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +#![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] +//~^ ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +#![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] +//~^ ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +#![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] +//~^ ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE reason in lint attribute must come last +//~| NOTE reason in lint attribute must come last +#![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] +//~^ ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE reason in lint attribute must come last +//~| NOTE reason in lint attribute must come last +#![warn(missing_copy_implementations, reason)] +//~^ WARN unknown lint +//~| NOTE `#[warn(unknown_lints)]` on by default + +fn main() {} diff --git a/tests/ui/lint/reasons-erroneous.stderr b/tests/ui/lint/reasons-erroneous.stderr new file mode 100644 index 000000000..5521af17c --- /dev/null +++ b/tests/ui/lint/reasons-erroneous.stderr @@ -0,0 +1,131 @@ +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:3:58 + | +LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)] + | ^ reason must be a string literal + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:8:40 + | +LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:13:29 + | +LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:13:29 + | +LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:22:23 + | +LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:22:23 + | +LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:31:36 + | +LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:31:36 + | +LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:40:44 + | +LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] + | ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:45:25 + | +LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:3:58 + | +LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)] + | ^ reason must be a string literal + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:8:40 + | +LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:13:29 + | +LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:13:29 + | +LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:22:23 + | +LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:22:23 + | +LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:31:36 + | +LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:31:36 + | +LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:40:44 + | +LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] + | ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:45:25 + | +LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last + +warning: unknown lint: `reason` + --> $DIR/reasons-erroneous.rs:50:39 + | +LL | #![warn(missing_copy_implementations, reason)] + | ^^^^^^ + | + = note: `#[warn(unknown_lints)]` on by default + +error: aborting due to 20 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/lint/reasons-forbidden.rs b/tests/ui/lint/reasons-forbidden.rs new file mode 100644 index 000000000..9c2edec4d --- /dev/null +++ b/tests/ui/lint/reasons-forbidden.rs @@ -0,0 +1,34 @@ +#![feature(lint_reasons)] + +// If you turn off deduplicate diagnostics (which rustc turns on by default but +// compiletest turns off when it runs ui tests), then the errors are +// (unfortunately) repeated here because the checking is done as we read in the +// errors, and currently that happens two or three different times, depending on +// compiler flags. +// +// The test is much cleaner if we deduplicate, though. + +// compile-flags: -Z deduplicate-diagnostics=yes + +#![forbid( + unsafe_code, + //~^ NOTE `forbid` level set here + //~| NOTE the lint level is defined here + reason = "our errors & omissions insurance policy doesn't cover unsafe Rust" +)] + +use std::ptr; + +fn main() { + let a_billion_dollar_mistake = ptr::null(); + + #[allow(unsafe_code)] + //~^ ERROR allow(unsafe_code) incompatible with previous forbid + //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust + //~| NOTE overruled by previous forbid + unsafe { + //~^ ERROR usage of an `unsafe` block + //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust + *a_billion_dollar_mistake + } +} diff --git a/tests/ui/lint/reasons-forbidden.stderr b/tests/ui/lint/reasons-forbidden.stderr new file mode 100644 index 000000000..ab6f19a01 --- /dev/null +++ b/tests/ui/lint/reasons-forbidden.stderr @@ -0,0 +1,31 @@ +error[E0453]: allow(unsafe_code) incompatible with previous forbid + --> $DIR/reasons-forbidden.rs:25:13 + | +LL | unsafe_code, + | ----------- `forbid` level set here +... +LL | #[allow(unsafe_code)] + | ^^^^^^^^^^^ overruled by previous forbid + | + = note: our errors & omissions insurance policy doesn't cover unsafe Rust + +error: usage of an `unsafe` block + --> $DIR/reasons-forbidden.rs:29:5 + | +LL | / unsafe { +LL | | +LL | | +LL | | *a_billion_dollar_mistake +LL | | } + | |_____^ + | + = note: our errors & omissions insurance policy doesn't cover unsafe Rust +note: the lint level is defined here + --> $DIR/reasons-forbidden.rs:14:5 + | +LL | unsafe_code, + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/reasons.rs b/tests/ui/lint/reasons.rs new file mode 100644 index 000000000..da1c740c4 --- /dev/null +++ b/tests/ui/lint/reasons.rs @@ -0,0 +1,35 @@ +// check-pass + +#![feature(lint_reasons)] +#![warn(elided_lifetimes_in_paths, + //~^ NOTE the lint level is defined here + reason = "explicit anonymous lifetimes aid reasoning about ownership")] +#![warn( + nonstandard_style, + //~^ NOTE the lint level is defined here + reason = r#"people shouldn't have to change their usual style habits +to contribute to our project"# +)] +#![allow(unused, reason = "unused code has never killed anypony")] + +use std::fmt; + +pub struct CheaterDetectionMechanism {} + +impl fmt::Debug for CheaterDetectionMechanism { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + //~^ WARN hidden lifetime parameters in types are deprecated + //~| NOTE expected lifetime parameter + //~| NOTE explicit anonymous lifetimes aid + //~| HELP indicate the anonymous lifetime + fmt.debug_struct("CheaterDetectionMechanism").finish() + } +} + +fn main() { + let Social_exchange_psychology = CheaterDetectionMechanism {}; + //~^ WARN should have a snake case name + //~| NOTE #[warn(non_snake_case)]` implied by `#[warn(nonstandard_style)] + //~| NOTE people shouldn't have to change their usual style habits + //~| HELP convert the identifier to snake case +} diff --git a/tests/ui/lint/reasons.stderr b/tests/ui/lint/reasons.stderr new file mode 100644 index 000000000..cd8412153 --- /dev/null +++ b/tests/ui/lint/reasons.stderr @@ -0,0 +1,36 @@ +warning: hidden lifetime parameters in types are deprecated + --> $DIR/reasons.rs:20:34 + | +LL | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + | -----^^^^^^^^^ + | | + | expected lifetime parameter + | + = note: explicit anonymous lifetimes aid reasoning about ownership +note: the lint level is defined here + --> $DIR/reasons.rs:4:9 + | +LL | #![warn(elided_lifetimes_in_paths, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: indicate the anonymous lifetime + | +LL | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + | ++++ + +warning: variable `Social_exchange_psychology` should have a snake case name + --> $DIR/reasons.rs:30:9 + | +LL | let Social_exchange_psychology = CheaterDetectionMechanism {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `social_exchange_psychology` + | + = note: people shouldn't have to change their usual style habits + to contribute to our project +note: the lint level is defined here + --> $DIR/reasons.rs:8:5 + | +LL | nonstandard_style, + | ^^^^^^^^^^^^^^^^^ + = note: `#[warn(non_snake_case)]` implied by `#[warn(nonstandard_style)]` + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/recommend-literal.rs b/tests/ui/lint/recommend-literal.rs new file mode 100644 index 000000000..453cbf285 --- /dev/null +++ b/tests/ui/lint/recommend-literal.rs @@ -0,0 +1,42 @@ +type Real = double; +//~^ ERROR cannot find type `double` in this scope +//~| HELP perhaps you intended to use this type + +fn main() { + let x: Real = 3.5; + let y: long = 74802374902374923; + //~^ ERROR cannot find type `long` in this scope + //~| HELP perhaps you intended to use this type + let v1: Boolean = true; + //~^ ERROR: cannot find type `Boolean` in this scope [E0412] + //~| HELP perhaps you intended to use this type + let v2: Bool = true; + //~^ ERROR: cannot find type `Bool` in this scope [E0412] + //~| HELP a builtin type with a similar name exists + //~| HELP perhaps you intended to use this type +} + +fn z(a: boolean) { + //~^ ERROR cannot find type `boolean` in this scope + //~| HELP perhaps you intended to use this type +} + +fn a() -> byte { +//~^ ERROR cannot find type `byte` in this scope +//~| HELP perhaps you intended to use this type + 3 +} + +struct Data { //~ HELP you might be missing a type parameter + width: float, + //~^ ERROR cannot find type `float` in this scope + //~| HELP perhaps you intended to use this type + depth: Option<int>, + //~^ ERROR cannot find type `int` in this scope + //~| HELP perhaps you intended to use this type +} + +trait Stuff {} +impl Stuff for short {} +//~^ ERROR cannot find type `short` in this scope +//~| HELP perhaps you intended to use this type diff --git a/tests/ui/lint/recommend-literal.stderr b/tests/ui/lint/recommend-literal.stderr new file mode 100644 index 000000000..424ecadd4 --- /dev/null +++ b/tests/ui/lint/recommend-literal.stderr @@ -0,0 +1,96 @@ +error[E0412]: cannot find type `double` in this scope + --> $DIR/recommend-literal.rs:1:13 + | +LL | type Real = double; + | ^^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `f64` + +error[E0412]: cannot find type `long` in this scope + --> $DIR/recommend-literal.rs:7:12 + | +LL | let y: long = 74802374902374923; + | ^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `i64` + +error[E0412]: cannot find type `Boolean` in this scope + --> $DIR/recommend-literal.rs:10:13 + | +LL | let v1: Boolean = true; + | ^^^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `bool` + +error[E0412]: cannot find type `Bool` in this scope + --> $DIR/recommend-literal.rs:13:13 + | +LL | let v2: Bool = true; + | ^^^^ + | +help: a builtin type with a similar name exists + | +LL | let v2: bool = true; + | ~~~~ +help: perhaps you intended to use this type + | +LL | let v2: bool = true; + | ~~~~ + +error[E0412]: cannot find type `boolean` in this scope + --> $DIR/recommend-literal.rs:19:9 + | +LL | fn z(a: boolean) { + | ^^^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `bool` + +error[E0412]: cannot find type `byte` in this scope + --> $DIR/recommend-literal.rs:24:11 + | +LL | fn a() -> byte { + | ^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `u8` + +error[E0412]: cannot find type `float` in this scope + --> $DIR/recommend-literal.rs:31:12 + | +LL | width: float, + | ^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `f32` + +error[E0412]: cannot find type `int` in this scope + --> $DIR/recommend-literal.rs:34:19 + | +LL | depth: Option<int>, + | ^^^ not found in this scope + | +help: perhaps you intended to use this type + | +LL | depth: Option<i32>, + | ~~~ +help: you might be missing a type parameter + | +LL | struct Data<int> { + | +++++ + +error[E0412]: cannot find type `short` in this scope + --> $DIR/recommend-literal.rs:40:16 + | +LL | impl Stuff for short {} + | ^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `i16` + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs b/tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs new file mode 100644 index 000000000..5a94ccd74 --- /dev/null +++ b/tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic +#![crate_type="proc-macro"] +#![crate_name="redundant_semi_proc_macro"] +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn should_preserve_spans(_attr: TokenStream, item: TokenStream) -> TokenStream { + eprintln!("{:?}", item); + item +} diff --git a/tests/ui/lint/redundant-semicolon/item-stmt-semi.rs b/tests/ui/lint/redundant-semicolon/item-stmt-semi.rs new file mode 100644 index 000000000..8c79630b7 --- /dev/null +++ b/tests/ui/lint/redundant-semicolon/item-stmt-semi.rs @@ -0,0 +1,6 @@ +#![deny(redundant_semicolons)] + +fn main() { + fn inner() {}; //~ ERROR unnecessary + struct Bar {}; //~ ERROR unnecessary +} diff --git a/tests/ui/lint/redundant-semicolon/item-stmt-semi.stderr b/tests/ui/lint/redundant-semicolon/item-stmt-semi.stderr new file mode 100644 index 000000000..451b152cb --- /dev/null +++ b/tests/ui/lint/redundant-semicolon/item-stmt-semi.stderr @@ -0,0 +1,20 @@ +error: unnecessary trailing semicolon + --> $DIR/item-stmt-semi.rs:4:18 + | +LL | fn inner() {}; + | ^ help: remove this semicolon + | +note: the lint level is defined here + --> $DIR/item-stmt-semi.rs:1:9 + | +LL | #![deny(redundant_semicolons)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary trailing semicolon + --> $DIR/item-stmt-semi.rs:5:18 + | +LL | struct Bar {}; + | ^ help: remove this semicolon + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs new file mode 100644 index 000000000..08a5c6c2b --- /dev/null +++ b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs @@ -0,0 +1,19 @@ +// aux-build:redundant-semi-proc-macro-def.rs + +#![deny(redundant_semicolons)] +extern crate redundant_semi_proc_macro; +use redundant_semi_proc_macro::should_preserve_spans; + +#[should_preserve_spans] +fn span_preservation() { + let tst = 123;; //~ ERROR unnecessary trailing semicolon + match tst { + // Redundant semicolons are parsed as empty tuple exprs + // for the lint, so ensure the lint doesn't affect + // empty tuple exprs explicitly in source. + 123 => (), + _ => () + };;; //~ ERROR unnecessary trailing semicolons +} + +fn main() {} diff --git a/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr new file mode 100644 index 000000000..e31d14c55 --- /dev/null +++ b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr @@ -0,0 +1,21 @@ +TokenStream [Ident { ident: "fn", span: #0 bytes(198..200) }, Ident { ident: "span_preservation", span: #0 bytes(201..218) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(218..220) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(228..231) }, Ident { ident: "tst", span: #0 bytes(232..235) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(236..237) }, Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(238..241) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(241..242) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(242..243) }, Ident { ident: "match", span: #0 bytes(289..294) }, Ident { ident: "tst", span: #0 bytes(295..298) }, Group { delimiter: Brace, stream: TokenStream [Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(483..486) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(487..488) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(488..489) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(490..492) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(492..493) }, Ident { ident: "_", span: #0 bytes(502..503) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(504..505) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(505..506) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(507..509) }], span: #0 bytes(299..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(516..517) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(517..518) }], span: #0 bytes(222..562) }] +error: unnecessary trailing semicolon + --> $DIR/redundant-semi-proc-macro.rs:9:19 + | +LL | let tst = 123;; + | ^ help: remove this semicolon + | +note: the lint level is defined here + --> $DIR/redundant-semi-proc-macro.rs:3:9 + | +LL | #![deny(redundant_semicolons)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary trailing semicolons + --> $DIR/redundant-semi-proc-macro.rs:16:7 + | +LL | };;; + | ^^ help: remove these semicolons + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/register-tool-lint.rs b/tests/ui/lint/register-tool-lint.rs new file mode 100644 index 000000000..17d3afbf6 --- /dev/null +++ b/tests/ui/lint/register-tool-lint.rs @@ -0,0 +1,9 @@ +#![crate_type = "lib"] +#![feature(register_tool)] +#![register_tool(xyz)] +#![warn(xyz::my_lint)] // this should not error +#![warn(abc::my_lint)] +//~^ ERROR unknown tool name `abc` found in scoped lint +//~| HELP add `#![register_tool(abc)]` +//~| ERROR unknown tool name `abc` +//~| HELP add `#![register_tool(abc)]` diff --git a/tests/ui/lint/register-tool-lint.stderr b/tests/ui/lint/register-tool-lint.stderr new file mode 100644 index 000000000..842d845ff --- /dev/null +++ b/tests/ui/lint/register-tool-lint.stderr @@ -0,0 +1,19 @@ +error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint` + --> $DIR/register-tool-lint.rs:5:9 + | +LL | #![warn(abc::my_lint)] + | ^^^ + | + = help: add `#![register_tool(abc)]` to the crate root + +error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint` + --> $DIR/register-tool-lint.rs:5:9 + | +LL | #![warn(abc::my_lint)] + | ^^^ + | + = help: add `#![register_tool(abc)]` to the crate root + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0710`. diff --git a/tests/ui/lint/renamed-lints-still-apply.rs b/tests/ui/lint/renamed-lints-still-apply.rs new file mode 100644 index 000000000..01cd32536 --- /dev/null +++ b/tests/ui/lint/renamed-lints-still-apply.rs @@ -0,0 +1,9 @@ +// compile-flags: --crate-type lib +#![deny(single_use_lifetime)] +//~^ WARNING renamed +//~| NOTE `#[warn(renamed_and_removed_lints)]` on by default +//~| NOTE defined here +fn _foo<'a>(_x: &'a u32) {} +//~^ ERROR only used once +//~| NOTE this lifetime +//~| NOTE is used only here diff --git a/tests/ui/lint/renamed-lints-still-apply.stderr b/tests/ui/lint/renamed-lints-still-apply.stderr new file mode 100644 index 000000000..e926719bb --- /dev/null +++ b/tests/ui/lint/renamed-lints-still-apply.stderr @@ -0,0 +1,29 @@ +warning: lint `single_use_lifetime` has been renamed to `single_use_lifetimes` + --> $DIR/renamed-lints-still-apply.rs:2:9 + | +LL | #![deny(single_use_lifetime)] + | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `single_use_lifetimes` + | + = note: `#[warn(renamed_and_removed_lints)]` on by default + +error: lifetime parameter `'a` only used once + --> $DIR/renamed-lints-still-apply.rs:6:9 + | +LL | fn _foo<'a>(_x: &'a u32) {} + | ^^ -- ...is used only here + | | + | this lifetime... + | +note: the lint level is defined here + --> $DIR/renamed-lints-still-apply.rs:2:9 + | +LL | #![deny(single_use_lifetime)] + | ^^^^^^^^^^^^^^^^^^^ +help: elide the single-use lifetime + | +LL - fn _foo<'a>(_x: &'a u32) {} +LL + fn _foo(_x: &u32) {} + | + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs b/tests/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs new file mode 100644 index 000000000..912e831d8 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs @@ -0,0 +1,8 @@ +// check-pass +#![feature(lint_reasons)] + +#[expect(drop_bounds)] +fn trigger_rustc_lints<T: Drop>() { +} + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs b/tests/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs new file mode 100644 index 000000000..6b255b799 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs @@ -0,0 +1,45 @@ +// check-pass + +#![feature(lint_reasons)] + +#![warn(unused)] + +// This expect attribute should catch all lint triggers +#[expect(unused_variables)] +fn check_multiple_lints_1() { + let value_i = 0xff00ff; + let value_ii = 0xff00ff; + let value_iii = 0xff00ff; + let value_iiii = 0xff00ff; + let value_iiiii = 0xff00ff; +} + +// This expect attribute should catch all lint triggers +#[expect(unused_mut)] +fn check_multiple_lints_2() { + let mut a = 0xa; + let mut b = 0xb; + let mut c = 0xc; + println!("The ABC goes as: {:#x} {:#x} {:#x}", a, b, c); +} + +// This expect attribute should catch all lint triggers +#[expect(while_true)] +fn check_multiple_lints_3() { + // `while_true` is an early lint + while true {} + + while true {} + + while true {} + + while true {} + + while true {} +} + +fn main() { + check_multiple_lints_1(); + check_multiple_lints_2(); + check_multiple_lints_3(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs b/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs new file mode 100644 index 000000000..9f591ba98 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(lint_reasons)] + +#![warn(unused)] + +#![expect(unused_mut)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default + +#![expect(unused_variables)] + +fn main() { + let x = 0; +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr b/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr new file mode 100644 index 000000000..7237f6fb6 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr @@ -0,0 +1,10 @@ +warning: this lint expectation is unfulfilled + --> $DIR/crate_level_expect.rs:7:11 + | +LL | #![expect(unused_mut)] + | ^^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs new file mode 100644 index 000000000..b95815bc5 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(lint_reasons)] + +#![warn(unused)] + +macro_rules! expect_inside_macro { + () => { + #[expect(unused_variables)] + let x = 0; + }; +} + +fn main() { + expect_inside_macro!(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs new file mode 100644 index 000000000..07c60fa0c --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs @@ -0,0 +1,42 @@ +// check-pass + +#![feature(lint_reasons)] + +#![warn(unused_variables)] + +macro_rules! trigger_unused_variables_macro { + () => { + let x = 0; + //~^ WARNING unused variable: `x` [unused_variables] + //~| WARNING unused variable: `x` [unused_variables] + }; +} + +pub fn check_macro() { + // This should trigger the `unused_variables` from inside the macro + trigger_unused_variables_macro!(); +} + +// This should be fulfilled by the macro +#[expect(unused_variables)] +pub fn check_expect_on_item() { + trigger_unused_variables_macro!(); +} + +pub fn check_expect_on_macro() { + // This should be fulfilled by the macro + #[expect(unused_variables)] + trigger_unused_variables_macro!(); + + // FIXME: Lint attributes currently don't work directly on macros, and + // therefore also doesn't work for the new `expect` attribute. This bug + // is being tracked in rust#87391. The test will until then produce two + // warnings about the unused variable x. + // + // The expectation is still marked as fulfilled. I'm not totally why but + // my guess is that this will remain working when rust#87391 has been fixed. +} + +fn main() { + +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr new file mode 100644 index 000000000..817e16fdc --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr @@ -0,0 +1,29 @@ +warning: unused variable: `x` + --> $DIR/expect_lint_from_macro.rs:9:13 + | +LL | let x = 0; + | ^ help: if this is intentional, prefix it with an underscore: `_x` +... +LL | trigger_unused_variables_macro!(); + | --------------------------------- in this macro invocation + | +note: the lint level is defined here + --> $DIR/expect_lint_from_macro.rs:5:9 + | +LL | #![warn(unused_variables)] + | ^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `trigger_unused_variables_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unused variable: `x` + --> $DIR/expect_lint_from_macro.rs:9:13 + | +LL | let x = 0; + | ^ help: if this is intentional, prefix it with an underscore: `_x` +... +LL | trigger_unused_variables_macro!(); + | --------------------------------- in this macro invocation + | + = note: this warning originates in the macro `trigger_unused_variables_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs new file mode 100644 index 000000000..928e16106 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs @@ -0,0 +1,9 @@ +// should error due to missing feature gate. + +#![warn(unused)] + +#[expect(unused)] +//~^ ERROR: the `#[expect]` attribute is an experimental feature [E0658] +fn main() { + let x = 1; +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr new file mode 100644 index 000000000..b5601cf9e --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[expect]` attribute is an experimental feature + --> $DIR/expect_missing_feature_gate.rs:5:1 + | +LL | #[expect(unused)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #54503 <https://github.com/rust-lang/rust/issues/54503> for more information + = help: add `#![feature(lint_reasons)]` 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/lint/rfc-2383-lint-reason/expect_multiple_lints.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs new file mode 100644 index 000000000..dc9a719a3 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs @@ -0,0 +1,58 @@ +// check-pass + +#![feature(lint_reasons)] + +#![warn(unused)] + +// The warnings are not double triggers, they identify different unfulfilled lint +// expectations one for each listed lint. + +#[expect(unused_variables, unused_mut, while_true)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default +//~| WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +fn check_multiple_lints_1() { + // This only trigger `unused_variables` + let who_am_i = 666; +} + +#[expect(unused_variables, unused_mut, while_true)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +fn check_multiple_lints_2() { + // This only triggers `unused_mut` + let mut x = 0; + println!("I use x: {}", x); +} + +#[expect(unused_variables, unused_mut, while_true)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +fn check_multiple_lints_3() { + // This only triggers `while_true` which is also an early lint + while true {} +} + +#[expect(unused, while_true)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +fn check_multiple_lints_with_lint_group_1() { + let who_am_i = 666; + + let mut x = 0; + println!("I use x: {}", x); +} + +#[expect(unused, while_true)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +fn check_multiple_lints_with_lint_group_2() { + while true {} +} + +fn main() { + check_multiple_lints_1(); + check_multiple_lints_2(); + check_multiple_lints_3(); + + check_multiple_lints_with_lint_group_1(); + check_multiple_lints_with_lint_group_2(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr new file mode 100644 index 000000000..90ee744b2 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr @@ -0,0 +1,52 @@ +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:10:28 + | +LL | #[expect(unused_variables, unused_mut, while_true)] + | ^^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:10:40 + | +LL | #[expect(unused_variables, unused_mut, while_true)] + | ^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:19:10 + | +LL | #[expect(unused_variables, unused_mut, while_true)] + | ^^^^^^^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:19:40 + | +LL | #[expect(unused_variables, unused_mut, while_true)] + | ^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:28:10 + | +LL | #[expect(unused_variables, unused_mut, while_true)] + | ^^^^^^^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:28:28 + | +LL | #[expect(unused_variables, unused_mut, while_true)] + | ^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:36:18 + | +LL | #[expect(unused, while_true)] + | ^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:45:10 + | +LL | #[expect(unused, while_true)] + | ^^^^^^ + +warning: 8 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs new file mode 100644 index 000000000..8f94bd6ec --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs @@ -0,0 +1,53 @@ +// ignore-tidy-linelength + +#![feature(lint_reasons)] +#![warn(unused_mut)] + +#[expect( + unused_mut, + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + //~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default + //~| NOTE this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered + reason = "this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered" +)] +mod foo { + fn bar() { + #[allow( + unused_mut, + reason = "this overrides the previous `expect` lint level and allows the `unused_mut` lint here" + )] + let mut v = 0; + } +} + +#[expect( + unused_mut, + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + //~| NOTE this `expect` is overridden by a `warn` attribute before the `unused_mut` lint is triggered + reason = "this `expect` is overridden by a `warn` attribute before the `unused_mut` lint is triggered" +)] +mod oof { + #[warn( + unused_mut, + //~^ NOTE the lint level is defined here + reason = "this overrides the previous `expect` lint level and warns about the `unused_mut` lint here" + )] + fn bar() { + let mut v = 0; + //~^ WARNING variable does not need to be mutable [unused_mut] + //~| NOTE this overrides the previous `expect` lint level and warns about the `unused_mut` lint here + //~| HELP remove this `mut` + } +} + +#[expect(unused_variables)] +//~^ WARNING this lint expectation is unfulfilled +#[forbid(unused_variables)] +//~^ NOTE the lint level is defined here +fn check_expect_then_forbid() { + let this_is_my_function = 3; + //~^ ERROR unused variable: `this_is_my_function` [unused_variables] + //~| HELP if this is intentional, prefix it with an underscore +} + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr new file mode 100644 index 000000000..2c35647b8 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr @@ -0,0 +1,52 @@ +error: unused variable: `this_is_my_function` + --> $DIR/expect_nested_lint_levels.rs:48:9 + | +LL | let this_is_my_function = 3; + | ^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_is_my_function` + | +note: the lint level is defined here + --> $DIR/expect_nested_lint_levels.rs:45:10 + | +LL | #[forbid(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +warning: variable does not need to be mutable + --> $DIR/expect_nested_lint_levels.rs:36:13 + | +LL | let mut v = 0; + | ----^ + | | + | help: remove this `mut` + | + = note: this overrides the previous `expect` lint level and warns about the `unused_mut` lint here +note: the lint level is defined here + --> $DIR/expect_nested_lint_levels.rs:31:9 + | +LL | unused_mut, + | ^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect_nested_lint_levels.rs:7:5 + | +LL | unused_mut, + | ^^^^^^^^^^ + | + = note: this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: this lint expectation is unfulfilled + --> $DIR/expect_nested_lint_levels.rs:24:5 + | +LL | unused_mut, + | ^^^^^^^^^^ + | + = note: this `expect` is overridden by a `warn` attribute before the `unused_mut` lint is triggered + +warning: this lint expectation is unfulfilled + --> $DIR/expect_nested_lint_levels.rs:43:10 + | +LL | #[expect(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 4 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs new file mode 100644 index 000000000..5fdb71041 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs @@ -0,0 +1,15 @@ +// check-pass +#![feature(lint_reasons)] + +#[warn(unused_variables)] + +/// This should catch the unused_variables lint and not emit anything +fn check_fulfilled_expectation(#[expect(unused_variables)] unused_value: u32) {} + +fn check_unfulfilled_expectation(#[expect(unused_variables)] used_value: u32) { + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + //~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default + println!("I use the value {used_value}"); +} + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.stderr new file mode 100644 index 000000000..69f7cda08 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.stderr @@ -0,0 +1,10 @@ +warning: this lint expectation is unfulfilled + --> $DIR/expect_on_fn_params.rs:9:43 + | +LL | fn check_unfulfilled_expectation(#[expect(unused_variables)] used_value: u32) { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs new file mode 100644 index 000000000..f80fe88cb --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs @@ -0,0 +1,155 @@ +// check-pass +#![feature(lint_reasons)] + +//! This file tests the `#[expect]` attribute implementation for tool lints. The same +//! file is used to test clippy and rustdoc. Any changes to this file should be synced +//! to the other test files. +//! +//! Expectations: +//! * rustc: only rustc lint expectations are emitted +//! * clippy: rustc and Clippy's expectations are emitted +//! * rustdoc: only rustdoc lint expectations are emitted +//! +//! This test can't cover every lint from Clippy, rustdoc and potentially other +//! tools that will be developed. This therefore only tests a small subset of lints + +#![expect(rustdoc::missing_crate_level_docs)] + +mod rustc_ok { + //! See <https://doc.rust-lang.org/rustc/lints/index.html> + + #[expect(dead_code)] + pub fn rustc_lints() { + let x = 42.0; + + #[expect(illegal_floating_point_literal_pattern)] + match x { + 5.0 => {} + 6.0 => {} + _ => {} + } + } +} + +mod rustc_warn { + //! See <https://doc.rust-lang.org/rustc/lints/index.html> + + #[expect(dead_code)] + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + //~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default + pub fn rustc_lints() { + let x = 42; + + #[expect(illegal_floating_point_literal_pattern)] + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + match x { + 5 => {} + 6 => {} + _ => {} + } + } +} + +pub mod rustdoc_ok { + //! See <https://doc.rust-lang.org/rustdoc/lints.html> + + #[expect(rustdoc::broken_intra_doc_links)] + /// I want to link to [`Nonexistent`] but it doesn't exist! + pub fn foo() {} + + #[expect(rustdoc::invalid_html_tags)] + /// <h1> + pub fn bar() {} + + #[expect(rustdoc::bare_urls)] + /// http://example.org + pub fn baz() {} +} + +pub mod rustdoc_warn { + //! See <https://doc.rust-lang.org/rustdoc/lints.html> + + #[expect(rustdoc::broken_intra_doc_links)] + /// I want to link to [`bar`] but it doesn't exist! + pub fn foo() {} + + #[expect(rustdoc::invalid_html_tags)] + /// <h1></h1> + pub fn bar() {} + + #[expect(rustdoc::bare_urls)] + /// <http://example.org> + pub fn baz() {} +} + +mod clippy_ok { + //! See <https://rust-lang.github.io/rust-clippy/master/index.html> + + #[expect(clippy::almost_swapped)] + fn foo() { + let mut a = 0; + let mut b = 9; + a = b; + b = a; + } + + #[expect(clippy::bytes_nth)] + fn bar() { + let _ = "Hello".bytes().nth(3); + } + + #[expect(clippy::if_same_then_else)] + fn baz() { + let _ = if true { + 42 + } else { + 42 + }; + } + + #[expect(clippy::logic_bug)] + fn burger() { + let a = false; + let b = true; + + if a && b || a {} + } +} + +mod clippy_warn { + //! See <https://rust-lang.github.io/rust-clippy/master/index.html> + + #[expect(clippy::almost_swapped)] + fn foo() { + let mut a = 0; + let mut b = 9; + a = b; + } + + #[expect(clippy::bytes_nth)] + fn bar() { + let _ = "Hello".as_bytes().get(3); + } + + #[expect(clippy::if_same_then_else)] + fn baz() { + let _ = if true { + 33 + } else { + 42 + }; + } + + #[expect(clippy::logic_bug)] + fn burger() { + let a = false; + let b = true; + let c = false; + + if a && b || c {} + } +} + +fn main() { + rustc_warn::rustc_lints(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr new file mode 100644 index 000000000..6d49e7543 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr @@ -0,0 +1,16 @@ +warning: this lint expectation is unfulfilled + --> $DIR/expect_tool_lint_rfc_2383.rs:37:14 + | +LL | #[expect(dead_code)] + | ^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: this lint expectation is unfulfilled + --> $DIR/expect_tool_lint_rfc_2383.rs:43:18 + | +LL | #[expect(illegal_floating_point_literal_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs new file mode 100644 index 000000000..d38e65533 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs @@ -0,0 +1,39 @@ +// check-pass +// ignore-tidy-linelength + +#![feature(lint_reasons)] +#![warn(unused_mut)] + +#![expect(unfulfilled_lint_expectations, reason = "idk why you would expect this")] +//~^ WARNING this lint expectation is unfulfilled +//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default +//~| NOTE idk why you would expect this +//~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + +#[expect(unfulfilled_lint_expectations, reason = "a local: idk why you would expect this")] +//~^ WARNING this lint expectation is unfulfilled +//~| NOTE a local: idk why you would expect this +//~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message +pub fn normal_test_fn() { + #[expect(unused_mut, reason = "this expectation will create a diagnostic with the default lint level")] + //~^ WARNING this lint expectation is unfulfilled + //~| NOTE this expectation will create a diagnostic with the default lint level + let mut v = vec![1, 1, 2, 3, 5]; + v.sort(); + + // Check that lint lists including `unfulfilled_lint_expectations` are also handled correctly + #[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")] + //~^ WARNING this lint expectation is unfulfilled + //~| NOTE the expectation for `unused` should be fulfilled + //~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + let value = "I'm unused"; +} + +#[expect(warnings, reason = "this suppresses all warnings and also suppresses itself. No warning will be issued")] +pub fn expect_warnings() { + // This lint trigger will be suppressed + #[warn(unused_mut)] + let mut v = vec![1, 1, 2, 3, 5]; +} + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr new file mode 100644 index 000000000..9a1c3e442 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr @@ -0,0 +1,38 @@ +warning: this lint expectation is unfulfilled + --> $DIR/expect_unfulfilled_expectation.rs:7:11 + | +LL | #![expect(unfulfilled_lint_expectations, reason = "idk why you would expect this")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: idk why you would expect this + = note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: this lint expectation is unfulfilled + --> $DIR/expect_unfulfilled_expectation.rs:13:10 + | +LL | #[expect(unfulfilled_lint_expectations, reason = "a local: idk why you would expect this")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a local: idk why you would expect this + = note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + +warning: this lint expectation is unfulfilled + --> $DIR/expect_unfulfilled_expectation.rs:18:14 + | +LL | #[expect(unused_mut, reason = "this expectation will create a diagnostic with the default lint level")] + | ^^^^^^^^^^ + | + = note: this expectation will create a diagnostic with the default lint level + +warning: this lint expectation is unfulfilled + --> $DIR/expect_unfulfilled_expectation.rs:25:22 + | +LL | #[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the expectation for `unused` should be fulfilled + = note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + +warning: 4 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs new file mode 100644 index 000000000..479ee198e --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs @@ -0,0 +1,34 @@ +#![feature(lint_reasons)] + +#[forbid(unused_variables)] +//~^ NOTE `forbid` level set here +//~| NOTE `forbid` level set here +#[expect(unused_variables)] +//~^ ERROR incompatible with previous forbid [E0453] +//~| NOTE overruled by previous forbid +//~| ERROR incompatible with previous forbid [E0453] +//~| NOTE overruled by previous forbid +fn expect_forbidden_lint_1() {} + +#[forbid(while_true)] +//~^ NOTE `forbid` level set here +//~| NOTE `forbid` level set here +//~| NOTE the lint level is defined here +#[expect(while_true)] +//~^ ERROR incompatible with previous forbid [E0453] +//~| NOTE overruled by previous forbid +//~| ERROR incompatible with previous forbid [E0453] +//~| NOTE overruled by previous forbid +fn expect_forbidden_lint_2() { + // This while loop will produce a `while_true` lint as the lint level + // at this node is still `forbid` and the `while_true` check happens + // before the compilation terminates due to `E0453` + while true {} + //~^ ERROR denote infinite loops with `loop { ... }` + //~| HELP use `loop` +} + +fn main() { + expect_forbidden_lint_1(); + expect_forbidden_lint_2(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr new file mode 100644 index 000000000..a8116e934 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr @@ -0,0 +1,51 @@ +error[E0453]: expect(unused_variables) incompatible with previous forbid + --> $DIR/expect_with_forbid.rs:6:10 + | +LL | #[forbid(unused_variables)] + | ---------------- `forbid` level set here +... +LL | #[expect(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + +error[E0453]: expect(while_true) incompatible with previous forbid + --> $DIR/expect_with_forbid.rs:17:10 + | +LL | #[forbid(while_true)] + | ---------- `forbid` level set here +... +LL | #[expect(while_true)] + | ^^^^^^^^^^ overruled by previous forbid + +error[E0453]: expect(unused_variables) incompatible with previous forbid + --> $DIR/expect_with_forbid.rs:6:10 + | +LL | #[forbid(unused_variables)] + | ---------------- `forbid` level set here +... +LL | #[expect(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + +error[E0453]: expect(while_true) incompatible with previous forbid + --> $DIR/expect_with_forbid.rs:17:10 + | +LL | #[forbid(while_true)] + | ---------- `forbid` level set here +... +LL | #[expect(while_true)] + | ^^^^^^^^^^ overruled by previous forbid + +error: denote infinite loops with `loop { ... }` + --> $DIR/expect_with_forbid.rs:26:5 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/expect_with_forbid.rs:13:10 + | +LL | #[forbid(while_true)] + | ^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs new file mode 100644 index 000000000..b4183d982 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(lint_reasons)] +#![warn(unused)] + +#![expect(unused_variables, reason = "<This should fail and display this reason>")] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default +//~| NOTE <This should fail and display this reason> + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr new file mode 100644 index 000000000..e349e4081 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr @@ -0,0 +1,11 @@ +warning: this lint expectation is unfulfilled + --> $DIR/expect_with_reason.rs:6:11 + | +LL | #![expect(unused_variables, reason = "<This should fail and display this reason>")] + | ^^^^^^^^^^^^^^^^ + | + = note: <This should fail and display this reason> + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.rs b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.rs new file mode 100644 index 000000000..a3c3933d7 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.rs @@ -0,0 +1,48 @@ +// compile-flags: --force-warn while_true +// compile-flags: --force-warn unused_variables +// compile-flags: --force-warn unused_mut +// check-pass + +#![feature(lint_reasons)] + +fn expect_early_pass_lint() { + #[expect(while_true)] + while true { + //~^ WARNING denote infinite loops with `loop { ... }` [while_true] + //~| NOTE requested on the command line with `--force-warn while-true` + //~| HELP use `loop` + println!("I never stop") + } +} + +#[expect(unused_variables, reason="<this should fail and display this reason>")] +fn check_specific_lint() { + let x = 2; + //~^ WARNING unused variable: `x` [unused_variables] + //~| NOTE requested on the command line with `--force-warn unused-variables` + //~| HELP if this is intentional, prefix it with an underscore +} + +#[expect(unused)] +fn check_multiple_lints_with_lint_group() { + let fox_name = "Sir Nibbles"; + //~^ WARNING unused variable: `fox_name` [unused_variables] + //~| HELP if this is intentional, prefix it with an underscore + + let mut what_does_the_fox_say = "*ding* *deng* *dung*"; + //~^ WARNING variable does not need to be mutable [unused_mut] + //~| NOTE requested on the command line with `--force-warn unused-mut` + //~| HELP remove this `mut` + + println!("The fox says: {what_does_the_fox_say}"); +} + +#[allow(unused_variables)] +fn check_expect_overrides_allow_lint_level() { + #[expect(unused_variables)] + let this_should_fulfill_the_expectation = "The `#[allow]` has no power here"; + //~^ WARNING unused variable: `this_should_fulfill_the_expectation` [unused_variables] + //~| HELP if this is intentional, prefix it with an underscore +} + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr new file mode 100644 index 000000000..5942fa8ae --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr @@ -0,0 +1,40 @@ +warning: unused variable: `x` + --> $DIR/force_warn_expected_lints_fulfilled.rs:20:9 + | +LL | let x = 2; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `--force-warn unused-variables` + +warning: unused variable: `fox_name` + --> $DIR/force_warn_expected_lints_fulfilled.rs:28:9 + | +LL | let fox_name = "Sir Nibbles"; + | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_fox_name` + +warning: unused variable: `this_should_fulfill_the_expectation` + --> $DIR/force_warn_expected_lints_fulfilled.rs:43:9 + | +LL | let this_should_fulfill_the_expectation = "The `#[allow]` has no power here"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_should_fulfill_the_expectation` + +warning: variable does not need to be mutable + --> $DIR/force_warn_expected_lints_fulfilled.rs:32:9 + | +LL | let mut what_does_the_fox_say = "*ding* *deng* *dung*"; + | ----^^^^^^^^^^^^^^^^^^^^^ + | | + | help: remove this `mut` + | + = note: requested on the command line with `--force-warn unused-mut` + +warning: denote infinite loops with `loop { ... }` + --> $DIR/force_warn_expected_lints_fulfilled.rs:10:5 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + | + = note: requested on the command line with `--force-warn while-true` + +warning: 5 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.rs b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.rs new file mode 100644 index 000000000..080e30023 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.rs @@ -0,0 +1,49 @@ +// compile-flags: --force-warn while_true +// compile-flags: --force-warn unused_variables +// compile-flags: --force-warn unused_mut +// check-pass + +#![feature(lint_reasons)] + +fn expect_early_pass_lint(terminate: bool) { + #[expect(while_true)] + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + //~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default + while !terminate { + println!("Do you know what a spin lock is?") + } +} + +#[expect(unused_variables, reason="<this should fail and display this reason>")] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| NOTE <this should fail and display this reason> +fn check_specific_lint() { + let _x = 2; +} + +#[expect(unused)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +fn check_multiple_lints_with_lint_group() { + let fox_name = "Sir Nibbles"; + + let what_does_the_fox_say = "*ding* *deng* *dung*"; + + println!("The fox says: {what_does_the_fox_say}"); + println!("~ {fox_name}") +} + + +#[expect(unused)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +fn check_overridden_expectation_lint_level() { + #[allow(unused_variables)] + let this_should_not_fulfill_the_expectation = "maybe"; + //~^ WARNING unused variable: `this_should_not_fulfill_the_expectation` [unused_variables] + //~| NOTE requested on the command line with `--force-warn unused-variables` + //~| HELP if this is intentional, prefix it with an underscore +} + +fn main() { + check_multiple_lints_with_lint_group(); + check_overridden_expectation_lint_level(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.stderr b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.stderr new file mode 100644 index 000000000..c74fabe27 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.stderr @@ -0,0 +1,38 @@ +warning: unused variable: `this_should_not_fulfill_the_expectation` + --> $DIR/force_warn_expected_lints_unfulfilled.rs:40:9 + | +LL | let this_should_not_fulfill_the_expectation = "maybe"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_should_not_fulfill_the_expectation` + | + = note: requested on the command line with `--force-warn unused-variables` + +warning: this lint expectation is unfulfilled + --> $DIR/force_warn_expected_lints_unfulfilled.rs:9:14 + | +LL | #[expect(while_true)] + | ^^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: this lint expectation is unfulfilled + --> $DIR/force_warn_expected_lints_unfulfilled.rs:17:10 + | +LL | #[expect(unused_variables, reason="<this should fail and display this reason>")] + | ^^^^^^^^^^^^^^^^ + | + = note: <this should fail and display this reason> + +warning: this lint expectation is unfulfilled + --> $DIR/force_warn_expected_lints_unfulfilled.rs:24:10 + | +LL | #[expect(unused)] + | ^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/force_warn_expected_lints_unfulfilled.rs:36:10 + | +LL | #[expect(unused)] + | ^^^^^^ + +warning: 5 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs b/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs new file mode 100644 index 000000000..6624b930e --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(lint_reasons)] + +fn expect_early_pass_lints() { + #[expect(while_true)] + while true { + println!("I never stop") + } + + #[expect(unused_doc_comments)] + /// This comment triggers the `unused_doc_comments` lint + let _sheep = "wolf"; + + let x = 123; + #[expect(ellipsis_inclusive_range_patterns)] + match x { + 0...100 => {} + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs b/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs new file mode 100644 index 000000000..5d928b3ca --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs @@ -0,0 +1,43 @@ +// check-pass + +#![feature(lint_reasons)] +#![warn(unused)] + +#[expect(unused_variables)] +fn check_specific_lint() { + let x = 2; +} + +#[expect(unused)] +fn check_lint_group() { + let x = 15; +} + +#[expect(unused_variables)] +fn check_multiple_lint_emissions() { + let r = 1; + let u = 8; + let s = 2; + let t = 9; +} + +mod check_fulfilled_expect_in_macro { + macro_rules! expect_inside_macro { + () => { + #[expect(unused_variables)] + let x = 0; + }; + } + + pub fn check_macro() { + expect_inside_macro!(); + } +} + +fn main() { + check_specific_lint(); + check_lint_group(); + check_multiple_lint_emissions(); + + check_fulfilled_expect_in_macro::check_macro(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs new file mode 100644 index 000000000..bafdea96e --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs @@ -0,0 +1,14 @@ +#![feature(lint_reasons)] + +#![deny(unused_attributes)] + +#[allow(reason = "I want to allow something")]//~ ERROR unused attribute +#[expect(reason = "I don't know what I'm waiting for")]//~ ERROR unused attribute +#[warn(reason = "This should be warn by default")]//~ ERROR unused attribute +#[deny(reason = "All listed lints are denied")]//~ ERROR unused attribute +#[forbid(reason = "Just some reason")]//~ ERROR unused attribute + +#[allow(clippy::box_collection, reason = "This is still valid")] +#[warn(dead_code, reason = "This is also reasonable")] + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr new file mode 100644 index 000000000..3e9d70821 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr @@ -0,0 +1,47 @@ +error: unused attribute + --> $DIR/lint-attribute-only-with-reason.rs:5:1 + | +LL | #[allow(reason = "I want to allow something")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `allow` without any lints has no effect +note: the lint level is defined here + --> $DIR/lint-attribute-only-with-reason.rs:3:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/lint-attribute-only-with-reason.rs:6:1 + | +LL | #[expect(reason = "I don't know what I'm waiting for")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `expect` without any lints has no effect + +error: unused attribute + --> $DIR/lint-attribute-only-with-reason.rs:7:1 + | +LL | #[warn(reason = "This should be warn by default")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `warn` without any lints has no effect + +error: unused attribute + --> $DIR/lint-attribute-only-with-reason.rs:8:1 + | +LL | #[deny(reason = "All listed lints are denied")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `deny` without any lints has no effect + +error: unused attribute + --> $DIR/lint-attribute-only-with-reason.rs:9:1 + | +LL | #[forbid(reason = "Just some reason")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `forbid` without any lints has no effect + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs b/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs new file mode 100644 index 000000000..98080b4e8 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(lint_reasons)] +#![warn(unused)] + +#[warn(unused_variables)] +#[expect(unused_variables)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default +#[allow(unused_variables)] +#[expect(unused_variables)] // Only this expectation will be fulfilled +fn main() { + let x = 2; +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr b/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr new file mode 100644 index 000000000..df7d6584f --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr @@ -0,0 +1,10 @@ +warning: this lint expectation is unfulfilled + --> $DIR/multiple_expect_attrs.rs:7:10 + | +LL | #[expect(unused_variables)] + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs new file mode 100644 index 000000000..2b6c3c6a1 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs @@ -0,0 +1,16 @@ +// This ensures that ICEs like rust#94953 don't happen +// check-pass +// compile-flags: -Z unpretty=expanded + +#![feature(lint_reasons)] + +// This `expect` will create an expectation with an unstable expectation id +#[expect(while_true)] +fn create_early_lint_pass_expectation() { + // `while_true` is an early lint + while true {} +} + +fn main() { + create_early_lint_pass_expectation(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout new file mode 100644 index 000000000..0ee3a03c3 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout @@ -0,0 +1,20 @@ +#![feature(prelude_import)] +#![no_std] +// This ensures that ICEs like rust#94953 don't happen +// check-pass +// compile-flags: -Z unpretty=expanded + +#![feature(lint_reasons)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +// This `expect` will create an expectation with an unstable expectation id +#[expect(while_true)] +fn create_early_lint_pass_expectation() { + // `while_true` is an early lint + while true {} +} + +fn main() { create_early_lint_pass_expectation(); } 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 new file mode 100644 index 000000000..e7da825ae --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs @@ -0,0 +1,16 @@ +#![deny(confusable_idents)] +#![allow(uncommon_codepoints, non_upper_case_globals)] + +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 + not_affected(); +} + +fn not_affected() { + let s1 = 1; + let sl = 'l'; +} 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 new file mode 100644 index 000000000..e9906c83d --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.stderr @@ -0,0 +1,26 @@ +error: identifier pair considered confusable between `s` and `s` + --> $DIR/lint-confusable-idents.rs:8:9 + | +LL | const s: usize = 42; + | -- this is where the previous identifier occurred +... +LL | let s = "rust"; + | ^ + | +note: the lint level is defined here + --> $DIR/lint-confusable-idents.rs:1:9 + | +LL | #![deny(confusable_idents)] + | ^^^^^^^^^^^^^^^^^ + +error: identifier pair considered confusable between `s_s` and `s_s` + --> $DIR/lint-confusable-idents.rs:9:9 + | +LL | const s_s: usize = 42; + | --- this is where the previous identifier occurred +... +LL | let s_s = "rust2"; + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables-2.rs b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables-2.rs new file mode 100644 index 000000000..f62c8a190 --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables-2.rs @@ -0,0 +1,19 @@ +// check-pass +#![deny(mixed_script_confusables)] + +struct ΑctuallyNotLatin; + +fn main() { + let λ = 42; // this usage of Greek confirms that Greek is used intentionally. +} + +mod роре { + const エ: &'static str = "アイウ"; + + // this usage of Katakana confirms that Katakana is used intentionally. + fn ニャン() { + let д: usize = 100; // this usage of Cyrillic confirms that Cyrillic is used intentionally. + + println!("meow!"); + } +} diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs new file mode 100644 index 000000000..9d837d41f --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs @@ -0,0 +1,14 @@ +#![deny(mixed_script_confusables)] + +struct ΑctuallyNotLatin; +//~^ ERROR the usage of Script Group `Greek` in this crate consists solely of + +fn main() { + let v = ΑctuallyNotLatin; +} + +mod роре { +//~^ ERROR the usage of Script Group `Cyrillic` in this crate consists solely of + const エ: &'static str = "アイウ"; + //~^ ERROR the usage of Script Group `Japanese, Katakana` in this crate consists solely of +} diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr new file mode 100644 index 000000000..884a4a453 --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr @@ -0,0 +1,34 @@ +error: the usage of Script Group `Greek` in this crate consists solely of mixed script confusables + --> $DIR/lint-mixed-script-confusables.rs:3:8 + | +LL | struct ΑctuallyNotLatin; + | ^^^^^^^^^^^^^^^^ + | + = note: the usage includes 'Α' (U+0391) + = note: please recheck to make sure their usages are indeed what you want +note: the lint level is defined here + --> $DIR/lint-mixed-script-confusables.rs:1:9 + | +LL | #![deny(mixed_script_confusables)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the usage of Script Group `Cyrillic` in this crate consists solely of mixed script confusables + --> $DIR/lint-mixed-script-confusables.rs:10:5 + | +LL | mod роре { + | ^^^^ + | + = note: the usage includes 'е' (U+0435), 'о' (U+043E), 'р' (U+0440) + = note: please recheck to make sure their usages are indeed what you want + +error: the usage of Script Group `Japanese, Katakana` in this crate consists solely of mixed script confusables + --> $DIR/lint-mixed-script-confusables.rs:12:11 + | +LL | const エ: &'static str = "アイウ"; + | ^^ + | + = note: the usage includes 'エ' (U+30A8) + = note: please recheck to make sure their usages are indeed what you want + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.rs b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.rs new file mode 100644 index 000000000..8ae174409 --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.rs @@ -0,0 +1,12 @@ +#![deny(non_ascii_idents)] + +const חלודה: usize = 2; //~ ERROR identifier contains non-ASCII characters + +fn coöperation() {} //~ ERROR identifier contains non-ASCII characters + +fn main() { + let naïveté = 2; //~ ERROR identifier contains non-ASCII characters + + // using the same identifier the second time won't trigger the lint. + println!("{}", naïveté); +} diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.stderr b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.stderr new file mode 100644 index 000000000..8ed7f093c --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.stderr @@ -0,0 +1,26 @@ +error: identifier contains non-ASCII characters + --> $DIR/lint-non-ascii-idents.rs:3:7 + | +LL | const חלודה: usize = 2; + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-non-ascii-idents.rs:1:9 + | +LL | #![deny(non_ascii_idents)] + | ^^^^^^^^^^^^^^^^ + +error: identifier contains non-ASCII characters + --> $DIR/lint-non-ascii-idents.rs:5:4 + | +LL | fn coöperation() {} + | ^^^^^^^^^^^ + +error: identifier contains non-ASCII characters + --> $DIR/lint-non-ascii-idents.rs:8:9 + | +LL | let naïveté = 2; + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs new file mode 100644 index 000000000..ed8e7dddd --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs @@ -0,0 +1,13 @@ +#![deny(uncommon_codepoints)] + +const µ: f64 = 0.000001; //~ ERROR identifier contains uncommon Unicode codepoints +//~| WARNING should have an upper case name + +fn dijkstra() {} //~ ERROR identifier contains uncommon Unicode codepoints + +fn main() { + let ㇻㇲㇳ = "rust"; //~ ERROR identifier contains uncommon Unicode codepoints + + // using the same identifier the second time won't trigger the lint. + println!("{}", ㇻㇲㇳ); +} diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.stderr b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.stderr new file mode 100644 index 000000000..0533da030 --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.stderr @@ -0,0 +1,34 @@ +error: identifier contains uncommon Unicode codepoints + --> $DIR/lint-uncommon-codepoints.rs:3:7 + | +LL | const µ: f64 = 0.000001; + | ^ + | +note: the lint level is defined here + --> $DIR/lint-uncommon-codepoints.rs:1:9 + | +LL | #![deny(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: identifier contains uncommon Unicode codepoints + --> $DIR/lint-uncommon-codepoints.rs:6:4 + | +LL | fn dijkstra() {} + | ^^^^^^^ + +error: identifier contains uncommon Unicode codepoints + --> $DIR/lint-uncommon-codepoints.rs:9:9 + | +LL | let ㇻㇲㇳ = "rust"; + | ^^^^^^ + +warning: constant `µ` should have an upper case name + --> $DIR/lint-uncommon-codepoints.rs:3:7 + | +LL | const µ: f64 = 0.000001; + | ^ help: convert the identifier to upper case: `Μ` + | + = note: `#[warn(non_upper_case_globals)]` on by default + +error: aborting due to 3 previous errors; 1 warning emitted + diff --git a/tests/ui/lint/rustdoc-group.rs b/tests/ui/lint/rustdoc-group.rs new file mode 100644 index 000000000..130abe425 --- /dev/null +++ b/tests/ui/lint/rustdoc-group.rs @@ -0,0 +1,5 @@ +// check-pass +// compile-flags: --crate-type lib +#![deny(rustdoc)] +//~^ WARNING removed: use `rustdoc::all` +#![deny(rustdoc::all)] // has no effect when run with rustc directly diff --git a/tests/ui/lint/rustdoc-group.stderr b/tests/ui/lint/rustdoc-group.stderr new file mode 100644 index 000000000..fddc863ae --- /dev/null +++ b/tests/ui/lint/rustdoc-group.stderr @@ -0,0 +1,10 @@ +warning: lint `rustdoc` has been removed: use `rustdoc::all` instead + --> $DIR/rustdoc-group.rs:3:9 + | +LL | #![deny(rustdoc)] + | ^^^^^^^ + | + = note: `#[warn(renamed_and_removed_lints)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/rustdoc-renamed.rs b/tests/ui/lint/rustdoc-renamed.rs new file mode 100644 index 000000000..ecd6155b7 --- /dev/null +++ b/tests/ui/lint/rustdoc-renamed.rs @@ -0,0 +1,15 @@ +#![crate_type = "lib"] + +#![deny(unknown_lints)] +#![deny(renamed_and_removed_lints)] +//~^ NOTE lint level is defined + +// both allowed, since the compiler doesn't yet know what rustdoc lints are valid +#![deny(rustdoc::x)] +#![deny(rustdoc::intra_doc_link_resolution_failure)] + +#![deny(intra_doc_link_resolution_failure)] +//~^ ERROR removed: use `rustdoc::broken_intra_doc_links` +#![deny(non_autolinks)] +// FIXME: the old names for rustdoc lints should warn by default once `rustdoc::` makes it to the +// stable channel. diff --git a/tests/ui/lint/rustdoc-renamed.stderr b/tests/ui/lint/rustdoc-renamed.stderr new file mode 100644 index 000000000..096e867aa --- /dev/null +++ b/tests/ui/lint/rustdoc-renamed.stderr @@ -0,0 +1,14 @@ +error: lint `intra_doc_link_resolution_failure` has been removed: use `rustdoc::broken_intra_doc_links` instead + --> $DIR/rustdoc-renamed.rs:11:9 + | +LL | #![deny(intra_doc_link_resolution_failure)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/rustdoc-renamed.rs:4:9 + | +LL | #![deny(renamed_and_removed_lints)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/auxiliary/foreign-crate.rs b/tests/ui/lint/semicolon-in-expressions-from-macros/auxiliary/foreign-crate.rs new file mode 100644 index 000000000..781391cc5 --- /dev/null +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/auxiliary/foreign-crate.rs @@ -0,0 +1,4 @@ +#[macro_export] +macro_rules! my_macro { + () => { true; } +} diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/foreign-crate.rs b/tests/ui/lint/semicolon-in-expressions-from-macros/foreign-crate.rs new file mode 100644 index 000000000..374506366 --- /dev/null +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/foreign-crate.rs @@ -0,0 +1,9 @@ +// aux-build:foreign-crate.rs +// check-pass + +extern crate foreign_crate; + +// Test that we do not lint for a macro in a foreign crate +fn main() { + let _ = foreign_crate::my_macro!(); +} diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs new file mode 100644 index 000000000..fff380934 --- /dev/null +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs @@ -0,0 +1,51 @@ +// check-pass +// edition:2018 +#![feature(stmt_expr_attributes)] +#![warn(semicolon_in_expressions_from_macros)] + +#[allow(dead_code)] +macro_rules! foo { + ($val:ident) => { + true; //~ WARN trailing semicolon in macro + //~| WARN this was previously accepted + //~| WARN trailing semicolon in macro + //~| WARN this was previously accepted + //~| WARN trailing semicolon in macro + //~| WARN this was previously accepted + } +} + +#[allow(semicolon_in_expressions_from_macros)] +async fn bar() { + foo!(first); +} + +fn main() { + #[allow(semicolon_in_expressions_from_macros)] + let _ = { + foo!(first) + }; + + #[allow(semicolon_in_expressions_from_macros)] + let _ = foo!(second); + + #[allow(semicolon_in_expressions_from_macros)] + fn inner() { + let _ = foo!(third); + } + + #[allow(semicolon_in_expressions_from_macros)] + async { + let _ = foo!(fourth); + }; + + let _ = { + foo!(warn_in_block) + }; + + let _ = foo!(warn_in_expr); + + // This `#[allow]` does not work, since the attribute gets dropped + // when we expand the macro + let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work); +} diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr new file mode 100644 index 000000000..c60120061 --- /dev/null +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr @@ -0,0 +1,185 @@ +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | foo!(warn_in_block) + | ------------------- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> + = note: macro invocations at the end of a block are treated as expressions + = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo` +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:4:9 + | +LL | #![warn(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = foo!(warn_in_expr); + | ------------------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work); + | ------------------------- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 3 warnings emitted + +Future incompatibility report: Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | foo!(first) + | ----------- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> + = note: macro invocations at the end of a block are treated as expressions + = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo` +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:24:13 + | +LL | #[allow(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = foo!(second); + | ------------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:29:13 + | +LL | #[allow(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = foo!(third); + | ----------- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:32:13 + | +LL | #[allow(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = foo!(fourth); + | ------------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:37:13 + | +LL | #[allow(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | foo!(warn_in_block) + | ------------------- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> + = note: macro invocations at the end of a block are treated as expressions + = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo` +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:4:9 + | +LL | #![warn(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = foo!(warn_in_expr); + | ------------------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:4:9 + | +LL | #![warn(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work); + | ------------------------- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:4:9 + | +LL | #![warn(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.rs b/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.rs new file mode 100644 index 000000000..2c63311e6 --- /dev/null +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.rs @@ -0,0 +1,16 @@ +// check-pass +// Ensure that trailing semicolons cause warnings by default + +macro_rules! foo { + () => { + true; //~ WARN trailing semicolon in macro + //~| WARN this was previously + } +} + +fn main() { + let _val = match true { + true => false, + _ => foo!() + }; +} diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr b/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr new file mode 100644 index 000000000..0fec4996f --- /dev/null +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr @@ -0,0 +1,31 @@ +warning: trailing semicolon in macro used in expression position + --> $DIR/warn-semicolon-in-expressions-from-macros.rs:6:13 + | +LL | true; + | ^ +... +LL | _ => foo!() + | ------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> + = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/warn-semicolon-in-expressions-from-macros.rs:6:13 + | +LL | true; + | ^ +... +LL | _ => foo!() + | ------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> + = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/lint/special-upper-lower-cases.rs b/tests/ui/lint/special-upper-lower-cases.rs new file mode 100644 index 000000000..761be61fa --- /dev/null +++ b/tests/ui/lint/special-upper-lower-cases.rs @@ -0,0 +1,23 @@ +// (#77273) These characters are in the general categories of +// "Uppercase/Lowercase Letter". +// The diagnostics don't provide meaningful suggestions for them +// as we cannot convert them properly. + +// check-pass + +#![allow(uncommon_codepoints, unused)] + +struct 𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝; +//~^ WARN: type `𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝` should have an upper camel case name + +// FIXME: How we should handle this? +struct 𝕟𝕠𝕥_𝕒_𝕔𝕒𝕞𝕖𝕝; +//~^ WARN: type `𝕟𝕠𝕥_𝕒_𝕔𝕒𝕞𝕖𝕝` should have an upper camel case name + +static 𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲: i32 = 1; +//~^ WARN: static variable `𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲` should have an upper case name + +fn main() { + let 𝓢𝓝𝓐𝓐𝓐𝓐𝓚𝓔𝓢 = 1; + //~^ WARN: variable `𝓢𝓝𝓐𝓐𝓐𝓐𝓚𝓔𝓢` should have a snake case name +} diff --git a/tests/ui/lint/special-upper-lower-cases.stderr b/tests/ui/lint/special-upper-lower-cases.stderr new file mode 100644 index 000000000..2aa13c33b --- /dev/null +++ b/tests/ui/lint/special-upper-lower-cases.stderr @@ -0,0 +1,32 @@ +warning: type `𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝` should have an upper camel case name + --> $DIR/special-upper-lower-cases.rs:10:8 + | +LL | struct 𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝; + | ^^^^^^^^^ should have an UpperCamelCase name + | + = note: `#[warn(non_camel_case_types)]` on by default + +warning: type `𝕟𝕠𝕥_𝕒_𝕔𝕒𝕞𝕖𝕝` should have an upper camel case name + --> $DIR/special-upper-lower-cases.rs:14:8 + | +LL | struct 𝕟𝕠𝕥_𝕒_𝕔𝕒𝕞𝕖𝕝; + | ^^^^^^^^^^^ should have an UpperCamelCase name + +warning: static variable `𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲` should have an upper case name + --> $DIR/special-upper-lower-cases.rs:17:8 + | +LL | static 𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲: i32 = 1; + | ^^^^^^^^^^^^ should have an UPPER_CASE name + | + = note: `#[warn(non_upper_case_globals)]` on by default + +warning: variable `𝓢𝓝𝓐𝓐𝓐𝓐𝓚𝓔𝓢` should have a snake case name + --> $DIR/special-upper-lower-cases.rs:21:9 + | +LL | let 𝓢𝓝𝓐𝓐𝓐𝓐𝓚𝓔𝓢 = 1; + | ^^^^^^^^^ should have a snake_case name + | + = note: `#[warn(non_snake_case)]` on by default + +warning: 4 warnings emitted + diff --git a/tests/ui/lint/suggestions.fixed b/tests/ui/lint/suggestions.fixed new file mode 100644 index 000000000..35851690b --- /dev/null +++ b/tests/ui/lint/suggestions.fixed @@ -0,0 +1,66 @@ +// ignore-tidy-tab +// run-rustfix + +#![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 + +#[no_mangle] pub static DISCOVERY: usize = 1; +//~^ ERROR const items should never be `#[no_mangle]` +//~| HELP try a static value + + +//~^ HELP remove this attribute +pub fn defiant<T>(_t: T) {} +//~^ WARN functions generic over types or consts must be mangled + +#[no_mangle] +fn rio_grande() {} + +mod badlands { + // The private-no-mangle lints shouldn't suggest inserting `pub` when the + // item is already `pub` (but triggered the lint because, e.g., it's in a + // private module). (Issue #47383) + #[no_mangle] pub static DAUNTLESS: bool = true; + //~^ ERROR const items should never be `#[no_mangle]` + //~| HELP try a static value + #[allow(dead_code)] // for rustfix + pub fn val_jean<T>() {} + //~^ WARN functions generic over types or consts must be mangled + //~| HELP remove this attribute + + // ... but we can suggest just-`pub` instead of restricted + #[no_mangle] pub static VETAR: bool = true; + //~^ ERROR const items should never be `#[no_mangle]` + //~| HELP try a static value + #[allow(dead_code)] // for rustfix + pub(crate) fn crossfield<T>() {} + //~^ WARN functions generic over types or consts must be mangled + //~| HELP remove this attribute +} + +struct Equinox { + warp_factor: f32, +} + +fn main() { + loop { + //~^ WARN denote infinite loops + //~| HELP use `loop` + let registry_no = format!("NX-{}", 74205); + //~^ WARN does not need to be mutable + //~| HELP remove this `mut` + //~| WARN unnecessary parentheses + //~| HELP remove these parentheses + // the line after `mut` has a `\t` at the beginning, this is on purpose + let b = 1; + //~^^ WARN does not need to be mutable + //~| HELP remove this `mut` + let d = Equinox { warp_factor: 9.975 }; + match d { + #[allow(unused_variables)] // for rustfix + Equinox { warp_factor } => {} + //~^ WARN this pattern is redundant + //~| HELP use shorthand field pattern + } + println!("{} {}", registry_no, b); + } +} diff --git a/tests/ui/lint/suggestions.rs b/tests/ui/lint/suggestions.rs new file mode 100644 index 000000000..be6f0d6b3 --- /dev/null +++ b/tests/ui/lint/suggestions.rs @@ -0,0 +1,67 @@ +// ignore-tidy-tab +// run-rustfix + +#![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 + +#[no_mangle] const DISCOVERY: usize = 1; +//~^ ERROR const items should never be `#[no_mangle]` +//~| HELP try a static value + +#[no_mangle] +//~^ HELP remove this attribute +pub fn defiant<T>(_t: T) {} +//~^ WARN functions generic over types or consts must be mangled + +#[no_mangle] +fn rio_grande() {} + +mod badlands { + // The private-no-mangle lints shouldn't suggest inserting `pub` when the + // item is already `pub` (but triggered the lint because, e.g., it's in a + // private module). (Issue #47383) + #[no_mangle] pub const DAUNTLESS: bool = true; + //~^ ERROR const items should never be `#[no_mangle]` + //~| HELP try a static value + #[allow(dead_code)] // for rustfix + #[no_mangle] pub fn val_jean<T>() {} + //~^ WARN functions generic over types or consts must be mangled + //~| HELP remove this attribute + + // ... but we can suggest just-`pub` instead of restricted + #[no_mangle] pub(crate) const VETAR: bool = true; + //~^ ERROR const items should never be `#[no_mangle]` + //~| HELP try a static value + #[allow(dead_code)] // for rustfix + #[no_mangle] pub(crate) fn crossfield<T>() {} + //~^ WARN functions generic over types or consts must be mangled + //~| HELP remove this attribute +} + +struct Equinox { + warp_factor: f32, +} + +fn main() { + while true { + //~^ WARN denote infinite loops + //~| HELP use `loop` + let mut registry_no = (format!("NX-{}", 74205)); + //~^ WARN does not need to be mutable + //~| HELP remove this `mut` + //~| WARN unnecessary parentheses + //~| HELP remove these parentheses + // the line after `mut` has a `\t` at the beginning, this is on purpose + let mut + b = 1; + //~^^ WARN does not need to be mutable + //~| HELP remove this `mut` + let d = Equinox { warp_factor: 9.975 }; + match d { + #[allow(unused_variables)] // for rustfix + Equinox { warp_factor: warp_factor } => {} + //~^ WARN this pattern is redundant + //~| HELP use shorthand field pattern + } + println!("{} {}", registry_no, b); + } +} diff --git a/tests/ui/lint/suggestions.stderr b/tests/ui/lint/suggestions.stderr new file mode 100644 index 000000000..4caee777a --- /dev/null +++ b/tests/ui/lint/suggestions.stderr @@ -0,0 +1,114 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/suggestions.rs:45:5 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +warning: unnecessary parentheses around assigned value + --> $DIR/suggestions.rs:48:31 + | +LL | let mut registry_no = (format!("NX-{}", 74205)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/suggestions.rs:4:21 + | +LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let mut registry_no = (format!("NX-{}", 74205)); +LL + let mut registry_no = format!("NX-{}", 74205); + | + +warning: variable does not need to be mutable + --> $DIR/suggestions.rs:48:13 + | +LL | let mut registry_no = (format!("NX-{}", 74205)); + | ----^^^^^^^^^^^ + | | + | help: remove this `mut` + | +note: the lint level is defined here + --> $DIR/suggestions.rs:4:9 + | +LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 + | ^^^^^^^^^^ + +warning: variable does not need to be mutable + --> $DIR/suggestions.rs:54:13 + | +LL | let mut + | ______________^ + | | _____________| + | || +LL | || b = 1; + | ||____________-^ + | |_____________| + | help: remove this `mut` + +error: const items should never be `#[no_mangle]` + --> $DIR/suggestions.rs:6:14 + | +LL | #[no_mangle] const DISCOVERY: usize = 1; + | -----^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: try a static value: `pub static` + | + = note: `#[deny(no_mangle_const_items)]` on by default + +warning: functions generic over types or consts must be mangled + --> $DIR/suggestions.rs:12:1 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | +LL | pub fn defiant<T>(_t: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(no_mangle_generic_items)]` on by default + +warning: the `warp_factor:` in this pattern is redundant + --> $DIR/suggestions.rs:61:23 + | +LL | Equinox { warp_factor: warp_factor } => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use shorthand field pattern: `warp_factor` + | + = note: `#[warn(non_shorthand_field_patterns)]` on by default + +error: const items should never be `#[no_mangle]` + --> $DIR/suggestions.rs:22:18 + | +LL | #[no_mangle] pub const DAUNTLESS: bool = true; + | ---------^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: try a static value: `pub static` + +warning: functions generic over types or consts must be mangled + --> $DIR/suggestions.rs:26:18 + | +LL | #[no_mangle] pub fn val_jean<T>() {} + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: remove this attribute + +error: const items should never be `#[no_mangle]` + --> $DIR/suggestions.rs:31:18 + | +LL | #[no_mangle] pub(crate) const VETAR: bool = true; + | ----------------^^^^^^^^^^^^^^^^^^^^ + | | + | help: try a static value: `pub static` + +warning: functions generic over types or consts must be mangled + --> $DIR/suggestions.rs:35:18 + | +LL | #[no_mangle] pub(crate) fn crossfield<T>() {} + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: remove this attribute + +error: aborting due to 3 previous errors; 8 warnings emitted + diff --git a/tests/ui/lint/test-allow-dead-extern-static-no-warning.rs b/tests/ui/lint/test-allow-dead-extern-static-no-warning.rs new file mode 100644 index 000000000..2583e431e --- /dev/null +++ b/tests/ui/lint/test-allow-dead-extern-static-no-warning.rs @@ -0,0 +1,11 @@ +// run-pass +// compile-flags: --test + +#![deny(dead_code)] + +extern "C" { + #[allow(dead_code)] + static Qt: u64; +} + +fn main() {} diff --git a/tests/ui/lint/test-inner-fn.rs b/tests/ui/lint/test-inner-fn.rs new file mode 100644 index 000000000..d419cc6fa --- /dev/null +++ b/tests/ui/lint/test-inner-fn.rs @@ -0,0 +1,19 @@ +// compile-flags: --test -D unnameable_test_items + +#[test] +fn foo() { + #[test] //~ ERROR cannot test inner items [unnameable_test_items] + fn bar() {} + bar(); +} + +mod x { + #[test] + fn foo() { + #[test] //~ ERROR cannot test inner items [unnameable_test_items] + fn bar() {} + bar(); + } +} + +fn main() {} diff --git a/tests/ui/lint/test-inner-fn.stderr b/tests/ui/lint/test-inner-fn.stderr new file mode 100644 index 000000000..7a32bc86b --- /dev/null +++ b/tests/ui/lint/test-inner-fn.stderr @@ -0,0 +1,19 @@ +error: cannot test inner items + --> $DIR/test-inner-fn.rs:5:5 + | +LL | #[test] + | ^^^^^^^ + | + = note: requested on the command line with `-D unnameable-test-items` + = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot test inner items + --> $DIR/test-inner-fn.rs:13:9 + | +LL | #[test] + | ^^^^^^^ + | + = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/trivial-cast-ice.rs b/tests/ui/lint/trivial-cast-ice.rs new file mode 100644 index 000000000..f781fab22 --- /dev/null +++ b/tests/ui/lint/trivial-cast-ice.rs @@ -0,0 +1,12 @@ +// aux-build:trivial-cast-ice.rs +// check-pass + +// Demonstrates the ICE in #102561 + +#![deny(trivial_casts)] + +extern crate trivial_cast_ice; + +fn main() { + trivial_cast_ice::foo!(); +} diff --git a/tests/ui/lint/trivial-casts-featuring-type-ascription.rs b/tests/ui/lint/trivial-casts-featuring-type-ascription.rs new file mode 100644 index 000000000..96bf2dcfb --- /dev/null +++ b/tests/ui/lint/trivial-casts-featuring-type-ascription.rs @@ -0,0 +1,10 @@ +#![deny(trivial_casts, trivial_numeric_casts)] +#![feature(type_ascription)] + +fn main() { + let lugubrious = 12i32 as i32; + //~^ ERROR trivial numeric cast + let haunted: &u32 = &99; + let _ = haunted as *const u32; + //~^ ERROR trivial cast +} diff --git a/tests/ui/lint/trivial-casts-featuring-type-ascription.stderr b/tests/ui/lint/trivial-casts-featuring-type-ascription.stderr new file mode 100644 index 000000000..5087807b6 --- /dev/null +++ b/tests/ui/lint/trivial-casts-featuring-type-ascription.stderr @@ -0,0 +1,28 @@ +error: trivial numeric cast: `i32` as `i32` + --> $DIR/trivial-casts-featuring-type-ascription.rs:5:22 + | +LL | let lugubrious = 12i32 as i32; + | ^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require type ascription or a temporary variable +note: the lint level is defined here + --> $DIR/trivial-casts-featuring-type-ascription.rs:1:24 + | +LL | #![deny(trivial_casts, trivial_numeric_casts)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: trivial cast: `&u32` as `*const u32` + --> $DIR/trivial-casts-featuring-type-ascription.rs:8:13 + | +LL | let _ = haunted as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require type ascription or a temporary variable +note: the lint level is defined here + --> $DIR/trivial-casts-featuring-type-ascription.rs:1:9 + | +LL | #![deny(trivial_casts, trivial_numeric_casts)] + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/trivial-casts.rs b/tests/ui/lint/trivial-casts.rs new file mode 100644 index 000000000..b17de624a --- /dev/null +++ b/tests/ui/lint/trivial-casts.rs @@ -0,0 +1,9 @@ +#![deny(trivial_casts, trivial_numeric_casts)] + +fn main() { + let lugubrious = 12i32 as i32; + //~^ ERROR trivial numeric cast + let haunted: &u32 = &99; + let _ = haunted as *const u32; + //~^ ERROR trivial cast +} diff --git a/tests/ui/lint/trivial-casts.stderr b/tests/ui/lint/trivial-casts.stderr new file mode 100644 index 000000000..7ace353de --- /dev/null +++ b/tests/ui/lint/trivial-casts.stderr @@ -0,0 +1,28 @@ +error: trivial numeric cast: `i32` as `i32` + --> $DIR/trivial-casts.rs:4:22 + | +LL | let lugubrious = 12i32 as i32; + | ^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable +note: the lint level is defined here + --> $DIR/trivial-casts.rs:1:24 + | +LL | #![deny(trivial_casts, trivial_numeric_casts)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: trivial cast: `&u32` as `*const u32` + --> $DIR/trivial-casts.rs:7:13 + | +LL | let _ = haunted as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable +note: the lint level is defined here + --> $DIR/trivial-casts.rs:1:9 + | +LL | #![deny(trivial_casts, trivial_numeric_casts)] + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/trivial_casts.rs b/tests/ui/lint/trivial_casts.rs new file mode 100644 index 000000000..0a8b9de1d --- /dev/null +++ b/tests/ui/lint/trivial_casts.rs @@ -0,0 +1,85 @@ +// Test the trivial_casts and trivial_numeric_casts lints. For each error we also +// check that the cast can be done using just coercion. + +#![deny(trivial_casts, trivial_numeric_casts)] + +trait Foo { + fn foo(&self) {} +} + +pub struct Bar; + +impl Foo for Bar {} + +pub fn main() { + // Numeric + let _ = 42_i32 as i32; //~ ERROR trivial numeric cast: `i32` as `i32` + let _: i32 = 42_i32; + + let _ = 42_u8 as u8; //~ ERROR trivial numeric cast: `u8` as `u8` + let _: u8 = 42_u8; + + // & to * pointers + let x: &u32 = &42; + let _ = x as *const u32; //~ERROR trivial cast: `&u32` as `*const u32` + let _: *const u32 = x; + + let x: &mut u32 = &mut 42; + let _ = x as *mut u32; //~ERROR trivial cast: `&mut u32` as `*mut u32` + let _: *mut u32 = x; + + // unsize array + let x: &[u32; 3] = &[42, 43, 44]; + let _ = x as &[u32]; //~ERROR trivial cast: `&[u32; 3]` as `&[u32]` + let _ = x as *const [u32]; //~ERROR trivial cast: `&[u32; 3]` as `*const [u32]` + let _: &[u32] = x; + let _: *const [u32] = x; + + let x: &mut [u32; 3] = &mut [42, 43, 44]; + let _ = x as &mut [u32]; //~ERROR trivial cast: `&mut [u32; 3]` as `&mut [u32]` + let _ = x as *mut [u32]; //~ERROR trivial cast: `&mut [u32; 3]` as `*mut [u32]` + let _: &mut [u32] = x; + let _: *mut [u32] = x; + + let x: Box<[u32; 3]> = Box::new([42, 43, 44]); + let _ = x as Box<[u32]>; + //~^ ERROR trivial cast: `Box<[u32; 3]>` as `Box<[u32]>` + let x: Box<[u32; 3]> = Box::new([42, 43, 44]); + let _: Box<[u32]> = x; + + // unsize trait + let x: &Bar = &Bar; + let _ = x as &dyn Foo; //~ERROR trivial cast: `&Bar` as `&dyn Foo` + let _ = x as *const dyn Foo; //~ERROR trivial cast: `&Bar` as `*const dyn Foo` + let _: &dyn Foo = x; + let _: *const dyn Foo = x; + + let x: &mut Bar = &mut Bar; + let _ = x as &mut dyn Foo; //~ERROR trivial cast: `&mut Bar` as `&mut dyn Foo` + let _ = x as *mut dyn Foo; //~ERROR trivial cast: `&mut Bar` as `*mut dyn Foo` + let _: &mut dyn Foo = x; + let _: *mut dyn Foo = x; + + let x: Box<Bar> = Box::new(Bar); + let _ = x as Box<dyn Foo>; //~ERROR `Box<Bar>` as `Box<dyn Foo>` + let x: Box<Bar> = Box::new(Bar); + let _: Box<dyn Foo> = x; + + // functions + fn baz(_x: i32) {} + let _ = &baz as &dyn Fn(i32); //~ERROR `&fn(i32) {baz}` as `&dyn Fn(i32)` + let _: &dyn Fn(i32) = &baz; + let x = |_x: i32| {}; + let _ = &x as &dyn Fn(i32); //~ERROR trivial cast + let _: &dyn Fn(i32) = &x; +} + +// subtyping +pub fn test_subtyping<'a, 'b: 'a>(a: &'a Bar, b: &'b Bar) { + let _ = a as &'a Bar; //~ERROR trivial cast + let _: &'a Bar = a; + let _ = b as &'a Bar; //~ERROR trivial cast + let _: &'a Bar = b; + let _ = b as &'b Bar; //~ERROR trivial cast + let _: &'b Bar = b; +} diff --git a/tests/ui/lint/trivial_casts.stderr b/tests/ui/lint/trivial_casts.stderr new file mode 100644 index 000000000..74f962835 --- /dev/null +++ b/tests/ui/lint/trivial_casts.stderr @@ -0,0 +1,164 @@ +error: trivial numeric cast: `i32` as `i32` + --> $DIR/trivial_casts.rs:16:13 + | +LL | let _ = 42_i32 as i32; + | ^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable +note: the lint level is defined here + --> $DIR/trivial_casts.rs:4:24 + | +LL | #![deny(trivial_casts, trivial_numeric_casts)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: trivial numeric cast: `u8` as `u8` + --> $DIR/trivial_casts.rs:19:13 + | +LL | let _ = 42_u8 as u8; + | ^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&u32` as `*const u32` + --> $DIR/trivial_casts.rs:24:13 + | +LL | let _ = x as *const u32; + | ^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable +note: the lint level is defined here + --> $DIR/trivial_casts.rs:4:9 + | +LL | #![deny(trivial_casts, trivial_numeric_casts)] + | ^^^^^^^^^^^^^ + +error: trivial cast: `&mut u32` as `*mut u32` + --> $DIR/trivial_casts.rs:28:13 + | +LL | let _ = x as *mut u32; + | ^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&[u32; 3]` as `&[u32]` + --> $DIR/trivial_casts.rs:33:13 + | +LL | let _ = x as &[u32]; + | ^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&[u32; 3]` as `*const [u32]` + --> $DIR/trivial_casts.rs:34:13 + | +LL | let _ = x as *const [u32]; + | ^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&mut [u32; 3]` as `&mut [u32]` + --> $DIR/trivial_casts.rs:39:13 + | +LL | let _ = x as &mut [u32]; + | ^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&mut [u32; 3]` as `*mut [u32]` + --> $DIR/trivial_casts.rs:40:13 + | +LL | let _ = x as *mut [u32]; + | ^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `Box<[u32; 3]>` as `Box<[u32]>` + --> $DIR/trivial_casts.rs:45:13 + | +LL | let _ = x as Box<[u32]>; + | ^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&Bar` as `&dyn Foo` + --> $DIR/trivial_casts.rs:52:13 + | +LL | let _ = x as &dyn Foo; + | ^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&Bar` as `*const dyn Foo` + --> $DIR/trivial_casts.rs:53:13 + | +LL | let _ = x as *const dyn Foo; + | ^^^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&mut Bar` as `&mut dyn Foo` + --> $DIR/trivial_casts.rs:58:13 + | +LL | let _ = x as &mut dyn Foo; + | ^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&mut Bar` as `*mut dyn Foo` + --> $DIR/trivial_casts.rs:59:13 + | +LL | let _ = x as *mut dyn Foo; + | ^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `Box<Bar>` as `Box<dyn Foo>` + --> $DIR/trivial_casts.rs:64:13 + | +LL | let _ = x as Box<dyn Foo>; + | ^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&fn(i32) {baz}` as `&dyn Fn(i32)` + --> $DIR/trivial_casts.rs:70:13 + | +LL | let _ = &baz as &dyn Fn(i32); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&[closure@$DIR/trivial_casts.rs:72:13: 72:22]` as `&dyn Fn(i32)` + --> $DIR/trivial_casts.rs:73:13 + | +LL | let _ = &x as &dyn Fn(i32); + | ^^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&'a Bar` as `&'a Bar` + --> $DIR/trivial_casts.rs:79:13 + | +LL | let _ = a as &'a Bar; + | ^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&'b Bar` as `&'a Bar` + --> $DIR/trivial_casts.rs:81:13 + | +LL | let _ = b as &'a Bar; + | ^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&'b Bar` as `&'b Bar` + --> $DIR/trivial_casts.rs:83:13 + | +LL | let _ = b as &'b Bar; + | ^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: aborting due to 19 previous errors + diff --git a/tests/ui/lint/type-overflow.rs b/tests/ui/lint/type-overflow.rs new file mode 100644 index 000000000..6234b794c --- /dev/null +++ b/tests/ui/lint/type-overflow.rs @@ -0,0 +1,22 @@ +// check-pass +#![warn(overflowing_literals)] + +fn main() { + let error = 255i8; //~WARNING literal out of range for `i8` + + let ok = 0b1000_0001; // should be ok -> i32 + let ok = 0b0111_1111i8; // should be ok -> 127i8 + + let fail = 0b1000_0001i8; //~WARNING literal out of range for `i8` + + let fail = 0x8000_0000_0000_0000i64; //~WARNING literal out of range for `i64` + + let fail = 0x1_FFFF_FFFFu32; //~WARNING literal out of range for `u32` + + let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; + //~^ WARNING literal out of range for `i128` + + let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for `i32` + + let fail = -0b1111_1111i8; //~WARNING literal out of range for `i8` +} diff --git a/tests/ui/lint/type-overflow.stderr b/tests/ui/lint/type-overflow.stderr new file mode 100644 index 000000000..62cb1f7f4 --- /dev/null +++ b/tests/ui/lint/type-overflow.stderr @@ -0,0 +1,67 @@ +warning: literal out of range for `i8` + --> $DIR/type-overflow.rs:5:17 + | +LL | let error = 255i8; + | ^^^^^ + | + = note: the literal `255i8` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead +note: the lint level is defined here + --> $DIR/type-overflow.rs:2:9 + | +LL | #![warn(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +warning: literal out of range for `i8` + --> $DIR/type-overflow.rs:10:16 + | +LL | let fail = 0b1000_0001i8; + | ^^^^^^^^^^^^^ help: consider using the type `u8` instead: `0b1000_0001u8` + | + = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into the type `i8` and will become `-127i8` + +warning: literal out of range for `i64` + --> $DIR/type-overflow.rs:12:16 + | +LL | let fail = 0x8000_0000_0000_0000i64; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the type `u64` instead: `0x8000_0000_0000_0000u64` + | + = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into the type `i64` and will become `-9223372036854775808i64` + +warning: literal out of range for `u32` + --> $DIR/type-overflow.rs:14:16 + | +LL | let fail = 0x1_FFFF_FFFFu32; + | ^^^^^^^^^^^^^^^^ help: consider using the type `u64` instead: `0x1_FFFF_FFFFu64` + | + = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into the type `u32` and will become `4294967295u32` + +warning: literal out of range for `i128` + --> $DIR/type-overflow.rs:16:22 + | +LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i128` and will become `-170141183460469231731687303715884105728i128` + = help: consider using the type `u128` instead + +warning: literal out of range for `i32` + --> $DIR/type-overflow.rs:19:16 + | +LL | let fail = 0x8FFF_FFFF_FFFF_FFFE; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into the type `i32` and will become `-2i32` + = help: consider using the type `i128` instead + +warning: literal out of range for `i8` + --> $DIR/type-overflow.rs:21:17 + | +LL | let fail = -0b1111_1111i8; + | ^^^^^^^^^^^^^ help: consider using the type `i16` instead: `0b1111_1111i16` + | + = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into the type `i8` + = note: and the value `-0b1111_1111i8` will become `1i8` + +warning: 7 warnings emitted + diff --git a/tests/ui/lint/unaligned_references.rs b/tests/ui/lint/unaligned_references.rs new file mode 100644 index 000000000..e547f031a --- /dev/null +++ b/tests/ui/lint/unaligned_references.rs @@ -0,0 +1,103 @@ +#![deny(unaligned_references)] + +#[repr(packed)] +pub struct Good { + data: u64, + ptr: &'static u64, + data2: [u64; 2], + aligned: [u8; 32], +} + +#[repr(packed(2))] +pub struct Packed2 { + x: u32, + y: u16, + z: u8, +} + +fn main() { + unsafe { + let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] }; + + let _ = &good.ptr; //~ ERROR reference to packed field + //~^ previously accepted + let _ = &good.data; //~ ERROR reference to packed field + //~^ previously accepted + // Error even when turned into raw pointer immediately. + let _ = &good.data as *const _; //~ ERROR reference to packed field + //~^ previously accepted + let _: *const _ = &good.data; //~ ERROR reference to packed field + //~^ previously accepted + // Error on method call. + let _ = good.data.clone(); //~ ERROR reference to packed field + //~^ previously accepted + // Error for nested fields. + let _ = &good.data2[0]; //~ ERROR reference to packed field + //~^ previously accepted + + let _ = &*good.ptr; // ok, behind a pointer + let _ = &good.aligned; // ok, has align 1 + let _ = &good.aligned[2]; // ok, has align 1 + } + + unsafe { + let packed2 = Packed2 { x: 0, y: 0, z: 0 }; + let _ = &packed2.x; //~ ERROR reference to packed field + //~^ previously accepted + let _ = &packed2.y; // ok, has align 2 in packed(2) struct + let _ = &packed2.z; // ok, has align 1 + } + + unsafe { + struct U16(u16); + + impl Drop for U16 { + fn drop(&mut self) { + println!("{:p}", self); + } + } + + struct HasDrop; + + impl Drop for HasDrop { + fn drop(&mut self) {} + } + + #[allow(unused)] + struct Wrapper { + a: U16, + b: HasDrop, + } + #[allow(unused)] + #[repr(packed(2))] + struct Wrapper2 { + a: U16, + b: HasDrop, + } + + // An outer struct with more restrictive packing than the inner struct -- make sure we + // notice that! + #[repr(packed)] + struct Misalign<T>(u8, T); + + let m1 = Misalign( + 0, + Wrapper { + a: U16(10), + b: HasDrop, + }, + ); + let _ref = &m1.1.a; //~ ERROR reference to packed field + //~^ previously accepted + + let m2 = Misalign( + 0, + Wrapper2 { + a: U16(10), + b: HasDrop, + }, + ); + let _ref = &m2.1.a; //~ ERROR reference to packed field + //~^ previously accepted + } +} diff --git a/tests/ui/lint/unaligned_references.stderr b/tests/ui/lint/unaligned_references.stderr new file mode 100644 index 000000000..346f49b92 --- /dev/null +++ b/tests/ui/lint/unaligned_references.stderr @@ -0,0 +1,259 @@ +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:22:17 + | +LL | let _ = &good.ptr; + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:24:17 + | +LL | let _ = &good.data; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:27:17 + | +LL | let _ = &good.data as *const _; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:29:27 + | +LL | let _: *const _ = &good.data; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:32:17 + | +LL | let _ = good.data.clone(); + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:35:17 + | +LL | let _ = &good.data2[0]; + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:45:17 + | +LL | let _ = &packed2.x; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:90:20 + | +LL | let _ref = &m1.1.a; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:100:20 + | +LL | let _ref = &m2.1.a; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: aborting due to 9 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:22:17 + | +LL | let _ = &good.ptr; + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:24:17 + | +LL | let _ = &good.data; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:27:17 + | +LL | let _ = &good.data as *const _; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:29:27 + | +LL | let _: *const _ = &good.data; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:32:17 + | +LL | let _ = good.data.clone(); + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:35:17 + | +LL | let _ = &good.data2[0]; + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:45:17 + | +LL | let _ = &packed2.x; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:90:20 + | +LL | let _ref = &m1.1.a; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:100:20 + | +LL | let _ref = &m2.1.a; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/lint/unaligned_references_external_macro.rs b/tests/ui/lint/unaligned_references_external_macro.rs new file mode 100644 index 000000000..cb597c38e --- /dev/null +++ b/tests/ui/lint/unaligned_references_external_macro.rs @@ -0,0 +1,13 @@ +// aux-build:unaligned_references_external_crate.rs + +extern crate unaligned_references_external_crate; + +unaligned_references_external_crate::mac! { //~ERROR reference to packed field is unaligned + //~^ previously accepted + #[repr(packed)] + pub struct X { + pub field: u16 + } +} + +fn main() {} diff --git a/tests/ui/lint/unaligned_references_external_macro.stderr b/tests/ui/lint/unaligned_references_external_macro.stderr new file mode 100644 index 000000000..c46ca6742 --- /dev/null +++ b/tests/ui/lint/unaligned_references_external_macro.stderr @@ -0,0 +1,61 @@ +error: reference to packed field is unaligned + --> $DIR/unaligned_references_external_macro.rs:5:1 + | +LL | / unaligned_references_external_crate::mac! { +LL | | +LL | | #[repr(packed)] +LL | | pub struct X { +LL | | pub field: u16 +LL | | } +LL | | } + | |_^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references_external_macro.rs:5:1 + | +LL | / unaligned_references_external_crate::mac! { +LL | | +LL | | #[repr(packed)] +LL | | pub struct X { +LL | | pub field: u16 +LL | | } +LL | | } + | |_^ + = note: this error originates in the macro `unaligned_references_external_crate::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +Future incompatibility report: Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references_external_macro.rs:5:1 + | +LL | / unaligned_references_external_crate::mac! { +LL | | +LL | | #[repr(packed)] +LL | | pub struct X { +LL | | pub field: u16 +LL | | } +LL | | } + | |_^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references_external_macro.rs:5:1 + | +LL | / unaligned_references_external_crate::mac! { +LL | | +LL | | #[repr(packed)] +LL | | pub struct X { +LL | | pub field: u16 +LL | | } +LL | | } + | |_^ + = note: this error originates in the macro `unaligned_references_external_crate::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/lint/unnecessary-extern-crate.rs b/tests/ui/lint/unnecessary-extern-crate.rs new file mode 100644 index 000000000..af2bd84bd --- /dev/null +++ b/tests/ui/lint/unnecessary-extern-crate.rs @@ -0,0 +1,71 @@ +// edition:2018 + +#![deny(unused_extern_crates)] +#![feature(test, rustc_private)] + +extern crate libc; +//~^ ERROR unused extern crate +//~| HELP remove +extern crate libc as x; +//~^ ERROR unused extern crate +//~| HELP remove + +extern crate proc_macro; + +#[macro_use] +extern crate test; + +pub extern crate test as y; + +pub extern crate alloc; + +pub(crate) extern crate alloc as a; + +pub(crate) extern crate alloc as b; + +mod foo { + pub(in crate::foo) extern crate alloc as c; + + pub(super) extern crate alloc as d; + + extern crate libc; + //~^ ERROR unused extern crate + //~| HELP remove + + extern crate libc as x; + //~^ ERROR unused extern crate + //~| HELP remove + + pub extern crate test; + + pub extern crate test as y; + + mod bar { + extern crate libc; + //~^ ERROR unused extern crate + //~| HELP remove + + extern crate libc as x; + //~^ ERROR unused extern crate + //~| HELP remove + + pub(in crate::foo::bar) extern crate alloc as e; + + fn dummy() { + e::string::String::new(); + } + } + + fn dummy() { + c::string::String::new(); + d::string::String::new(); + } +} + + +fn main() { + a::string::String::new(); + b::string::String::new(); + + proc_macro::TokenStream::new(); +} diff --git a/tests/ui/lint/unnecessary-extern-crate.stderr b/tests/ui/lint/unnecessary-extern-crate.stderr new file mode 100644 index 000000000..14ba9d052 --- /dev/null +++ b/tests/ui/lint/unnecessary-extern-crate.stderr @@ -0,0 +1,44 @@ +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:6:1 + | +LL | extern crate libc; + | ^^^^^^^^^^^^^^^^^^ help: remove it + | +note: the lint level is defined here + --> $DIR/unnecessary-extern-crate.rs:3:9 + | +LL | #![deny(unused_extern_crates)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:9:1 + | +LL | extern crate libc as x; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:31:5 + | +LL | extern crate libc; + | ^^^^^^^^^^^^^^^^^^ help: remove it + +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:35:5 + | +LL | extern crate libc as x; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:44:9 + | +LL | extern crate libc; + | ^^^^^^^^^^^^^^^^^^ help: remove it + +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:48:9 + | +LL | extern crate libc as x; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + +error: aborting due to 6 previous errors + diff --git a/tests/ui/lint/unreachable-async-fn.rs b/tests/ui/lint/unreachable-async-fn.rs new file mode 100644 index 000000000..eedd877fe --- /dev/null +++ b/tests/ui/lint/unreachable-async-fn.rs @@ -0,0 +1,9 @@ +// check-pass +// edition:2018 + +#[allow(dead_code)] +async fn foo () { // unreachable lint doesn't trigger + unimplemented!() +} + +fn main() {} diff --git a/tests/ui/lint/unreachable_pub.rs b/tests/ui/lint/unreachable_pub.rs new file mode 100644 index 000000000..a50467ce8 --- /dev/null +++ b/tests/ui/lint/unreachable_pub.rs @@ -0,0 +1,66 @@ +// check-pass + +#![allow(unused)] +#![warn(unreachable_pub)] + +mod private_mod { + // non-leaked `pub` items in private module should be linted + pub use std::fmt; //~ WARNING unreachable_pub + pub use std::env::{Args}; // braced-use has different item spans than unbraced + //~^ WARNING unreachable_pub + + pub struct Hydrogen { //~ WARNING unreachable_pub + // `pub` struct fields, too + pub neutrons: usize, //~ WARNING unreachable_pub + // (... but not more-restricted fields) + pub(crate) electrons: usize + } + impl Hydrogen { + // impls, too + pub fn count_neutrons(&self) -> usize { self.neutrons } //~ WARNING unreachable_pub + pub(crate) fn count_electrons(&self) -> usize { self.electrons } + } + impl Clone for Hydrogen { + fn clone(&self) -> Hydrogen { + Hydrogen { neutrons: self.neutrons, electrons: self.electrons } + } + } + + pub enum Helium {} //~ WARNING unreachable_pub + pub union Lithium { c1: usize, c2: u8 } //~ WARNING unreachable_pub + pub fn beryllium() {} //~ WARNING unreachable_pub + pub trait Boron {} //~ WARNING unreachable_pub + pub const CARBON: usize = 1; //~ WARNING unreachable_pub + pub static NITROGEN: usize = 2; //~ WARNING unreachable_pub + pub type Oxygen = bool; //~ WARNING unreachable_pub + + macro_rules! define_empty_struct_with_visibility { + ($visibility: vis, $name: ident) => { $visibility struct $name {} } + //~^ WARNING unreachable_pub + } + define_empty_struct_with_visibility!(pub, Fluorine); + + extern "C" { + pub fn catalyze() -> bool; //~ WARNING unreachable_pub + } + + // items leaked through signatures (see `get_neon` below) are OK + pub struct Neon {} + + // crate-visible items are OK + pub(crate) struct Sodium {} +} + +pub mod public_mod { + // module is public: these are OK, too + pub struct Magnesium {} + pub(crate) struct Aluminum {} +} + +pub fn get_neon() -> private_mod::Neon { + private_mod::Neon {} +} + +fn main() { + let _ = get_neon(); +} diff --git a/tests/ui/lint/unreachable_pub.stderr b/tests/ui/lint/unreachable_pub.stderr new file mode 100644 index 000000000..762834b97 --- /dev/null +++ b/tests/ui/lint/unreachable_pub.stderr @@ -0,0 +1,148 @@ +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:8:13 + | +LL | pub use std::fmt; + | --- ^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates +note: the lint level is defined here + --> $DIR/unreachable_pub.rs:4:9 + | +LL | #![warn(unreachable_pub)] + | ^^^^^^^^^^^^^^^ + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:9:24 + | +LL | pub use std::env::{Args}; // braced-use has different item spans than unbraced + | --- ^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:12:5 + | +LL | pub struct Hydrogen { + | ---^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` field + --> $DIR/unreachable_pub.rs:14:9 + | +LL | pub neutrons: usize, + | ---^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:20:9 + | +LL | pub fn count_neutrons(&self) -> usize { self.neutrons } + | ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:29:5 + | +LL | pub enum Helium {} + | ---^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:30:5 + | +LL | pub union Lithium { c1: usize, c2: u8 } + | ---^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:31:5 + | +LL | pub fn beryllium() {} + | ---^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:32:5 + | +LL | pub trait Boron {} + | ---^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:33:5 + | +LL | pub const CARBON: usize = 1; + | ---^^^^^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:34:5 + | +LL | pub static NITROGEN: usize = 2; + | ---^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:35:5 + | +LL | pub type Oxygen = bool; + | ---^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:38:47 + | +LL | ($visibility: vis, $name: ident) => { $visibility struct $name {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | define_empty_struct_with_visibility!(pub, Fluorine); + | --------------------------------------------------- + | | | + | | help: consider restricting its visibility: `pub(crate)` + | in this macro invocation + | + = help: or consider exporting it for use by other crates + = note: this warning originates in the macro `define_empty_struct_with_visibility` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:44:9 + | +LL | pub fn catalyze() -> bool; + | ---^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: 14 warnings emitted + diff --git a/tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs b/tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs new file mode 100644 index 000000000..26871c98d --- /dev/null +++ b/tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs @@ -0,0 +1,16 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; + +#[proc_macro] +pub fn forge_unsafe_block(input: TokenStream) -> TokenStream { + let mut output = TokenStream::new(); + output.extend(Some(TokenTree::from(Ident::new("unsafe", Span::call_site())))); + output.extend(Some(TokenTree::from(Group::new(Delimiter::Brace, input)))); + output +} diff --git a/tests/ui/lint/unsafe_code/forge_unsafe_block.rs b/tests/ui/lint/unsafe_code/forge_unsafe_block.rs new file mode 100644 index 000000000..a1bd7b413 --- /dev/null +++ b/tests/ui/lint/unsafe_code/forge_unsafe_block.rs @@ -0,0 +1,16 @@ +// check-pass +// aux-build:forge_unsafe_block.rs + +#[macro_use] +extern crate forge_unsafe_block; + +unsafe fn foo() {} + +#[forbid(unsafe_code)] +fn main() { + // `forbid` doesn't work for non-user-provided unsafe blocks. + // see `UnsafeCode::check_expr`. + forge_unsafe_block! { + foo(); + } +} diff --git a/tests/ui/lint/unused-borrows.rs b/tests/ui/lint/unused-borrows.rs new file mode 100644 index 000000000..4518522ae --- /dev/null +++ b/tests/ui/lint/unused-borrows.rs @@ -0,0 +1,33 @@ +#![deny(unused_must_use)] + +fn foo(_: i32) -> bool { todo!() } + +fn bar() -> &'static i32 { + &42; + //~^ unused + + &mut foo(42); + //~^ unused + + &&42; + //~^ unused + + &&mut 42; + //~^ unused + + &mut &42; + //~^ unused + + let _result = foo(4) + && foo(2); // Misplaced semi-colon (perhaps due to reordering of lines) + && foo(42); + //~^ unused + + let _ = &42; // ok + + &42 // ok +} + +fn main() { + let _ = bar(); +} diff --git a/tests/ui/lint/unused-borrows.stderr b/tests/ui/lint/unused-borrows.stderr new file mode 100644 index 000000000..d8dd2b5fd --- /dev/null +++ b/tests/ui/lint/unused-borrows.stderr @@ -0,0 +1,73 @@ +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:6:5 + | +LL | &42; + | ^^^ the borrow produces a value + | +note: the lint level is defined here + --> $DIR/unused-borrows.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = &42; + | +++++++ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:9:5 + | +LL | &mut foo(42); + | ^^^^^^^^^^^^ the borrow produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = &mut foo(42); + | +++++++ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:12:5 + | +LL | &&42; + | ^^^^ the borrow produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = &&42; + | +++++++ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:15:5 + | +LL | &&mut 42; + | ^^^^^^^^ the borrow produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = &&mut 42; + | +++++++ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:18:5 + | +LL | &mut &42; + | ^^^^^^^^ the borrow produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = &mut &42; + | +++++++ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:23:5 + | +LL | && foo(42); + | ^^^^^^^^^^ the borrow produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = && foo(42); + | +++++++ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/lint/unused-braces-while-let-with-mutable-value.rs b/tests/ui/lint/unused-braces-while-let-with-mutable-value.rs new file mode 100644 index 000000000..ac547293c --- /dev/null +++ b/tests/ui/lint/unused-braces-while-let-with-mutable-value.rs @@ -0,0 +1,12 @@ +// check-pass + +#![deny(unused_braces)] + +fn main() { + let mut a = Some(3); + // Shouldn't warn below `a`. + while let Some(ref mut v) = {a} { + a.as_mut().map(|a| std::mem::swap(a, v)); + break; + } +} diff --git a/tests/ui/lint/unused-qualification-in-derive-expansion.rs b/tests/ui/lint/unused-qualification-in-derive-expansion.rs new file mode 100644 index 000000000..c2efbf507 --- /dev/null +++ b/tests/ui/lint/unused-qualification-in-derive-expansion.rs @@ -0,0 +1,16 @@ +// run-pass +// aux-build:add-impl.rs + +#![forbid(unused_qualifications)] + +#[macro_use] +extern crate add_impl; + +#[derive(AddImpl)] +struct B; + +fn main() { + B.foo(); + foo(); + bar::foo(); +} diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate.rs new file mode 100644 index 000000000..b76b4321d --- /dev/null +++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate2.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate2.rs new file mode 100644 index 000000000..b76b4321d --- /dev/null +++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate2.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate3.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate3.rs new file mode 100644 index 000000000..b76b4321d --- /dev/null +++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate3.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate4.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate4.rs new file mode 100644 index 000000000..d11c69f81 --- /dev/null +++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate4.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate5.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate5.rs new file mode 100644 index 000000000..d11c69f81 --- /dev/null +++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate5.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/tests/ui/lint/unused/issue-104397.rs b/tests/ui/lint/unused/issue-104397.rs new file mode 100644 index 000000000..94e15cd96 --- /dev/null +++ b/tests/ui/lint/unused/issue-104397.rs @@ -0,0 +1,18 @@ +// check-pass + +#![warn(unused)] +#![deny(warnings)] + +struct Inv<'a>(&'a mut &'a ()); + +trait Trait {} +impl Trait for for<'a> fn(Inv<'a>) {} + +fn with_bound() +where + (for<'a> fn(Inv<'a>)): Trait, +{} + +fn main() { + with_bound(); +} diff --git a/tests/ui/lint/unused/issue-105061-array-lint.rs b/tests/ui/lint/unused/issue-105061-array-lint.rs new file mode 100644 index 000000000..9b06a4fde --- /dev/null +++ b/tests/ui/lint/unused/issue-105061-array-lint.rs @@ -0,0 +1,11 @@ +#![warn(unused)] +#![deny(warnings)] + +fn main() { + let _x: ([u32; 3]); //~ ERROR unnecessary parentheses around type + let _y: [u8; (3)]; //~ ERROR unnecessary parentheses around const expression + let _z: ([u8; (3)]); + //~^ ERROR unnecessary parentheses around const expression + //~| ERROR unnecessary parentheses around type + +} diff --git a/tests/ui/lint/unused/issue-105061-array-lint.stderr b/tests/ui/lint/unused/issue-105061-array-lint.stderr new file mode 100644 index 000000000..7eb761aee --- /dev/null +++ b/tests/ui/lint/unused/issue-105061-array-lint.stderr @@ -0,0 +1,56 @@ +error: unnecessary parentheses around type + --> $DIR/issue-105061-array-lint.rs:5:13 + | +LL | let _x: ([u32; 3]); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-105061-array-lint.rs:2:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_parens)]` implied by `#[deny(warnings)]` +help: remove these parentheses + | +LL - let _x: ([u32; 3]); +LL + let _x: [u32; 3]; + | + +error: unnecessary parentheses around const expression + --> $DIR/issue-105061-array-lint.rs:6:18 + | +LL | let _y: [u8; (3)]; + | ^ ^ + | +help: remove these parentheses + | +LL - let _y: [u8; (3)]; +LL + let _y: [u8; 3]; + | + +error: unnecessary parentheses around type + --> $DIR/issue-105061-array-lint.rs:7:13 + | +LL | let _z: ([u8; (3)]); + | ^ ^ + | +help: remove these parentheses + | +LL - let _z: ([u8; (3)]); +LL + let _z: [u8; (3)]; + | + +error: unnecessary parentheses around const expression + --> $DIR/issue-105061-array-lint.rs:7:19 + | +LL | let _z: ([u8; (3)]); + | ^ ^ + | +help: remove these parentheses + | +LL - let _z: ([u8; (3)]); +LL + let _z: ([u8; 3]); + | + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/unused/issue-105061-should-lint.rs b/tests/ui/lint/unused/issue-105061-should-lint.rs new file mode 100644 index 000000000..7e4e09473 --- /dev/null +++ b/tests/ui/lint/unused/issue-105061-should-lint.rs @@ -0,0 +1,23 @@ +#![warn(unused)] +#![deny(warnings)] + +struct Inv<'a>(&'a mut &'a ()); + +trait Trait<'a> {} +impl<'b> Trait<'b> for for<'a> fn(Inv<'a>) {} + +fn with_bound() +where + for<'b> (for<'a> fn(Inv<'a>)): Trait<'b>, //~ ERROR unnecessary parentheses around type +{} + +trait Hello<T> {} +fn with_dyn_bound<T>() +where + (dyn Hello<(for<'b> fn(&'b ()))>): Hello<T> //~ ERROR unnecessary parentheses around type +{} + +fn main() { + with_bound(); + with_dyn_bound(); +} diff --git a/tests/ui/lint/unused/issue-105061-should-lint.stderr b/tests/ui/lint/unused/issue-105061-should-lint.stderr new file mode 100644 index 000000000..e591f1ffb --- /dev/null +++ b/tests/ui/lint/unused/issue-105061-should-lint.stderr @@ -0,0 +1,32 @@ +error: unnecessary parentheses around type + --> $DIR/issue-105061-should-lint.rs:11:13 + | +LL | for<'b> (for<'a> fn(Inv<'a>)): Trait<'b>, + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-105061-should-lint.rs:2:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_parens)]` implied by `#[deny(warnings)]` +help: remove these parentheses + | +LL - for<'b> (for<'a> fn(Inv<'a>)): Trait<'b>, +LL + for<'b> for<'a> fn(Inv<'a>): Trait<'b>, + | + +error: unnecessary parentheses around type + --> $DIR/issue-105061-should-lint.rs:17:16 + | +LL | (dyn Hello<(for<'b> fn(&'b ()))>): Hello<T> + | ^ ^ + | +help: remove these parentheses + | +LL - (dyn Hello<(for<'b> fn(&'b ()))>): Hello<T> +LL + (dyn Hello<for<'b> fn(&'b ())>): Hello<T> + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/issue-105061.rs b/tests/ui/lint/unused/issue-105061.rs new file mode 100644 index 000000000..92d636d0a --- /dev/null +++ b/tests/ui/lint/unused/issue-105061.rs @@ -0,0 +1,17 @@ +#![warn(unused)] +#![deny(warnings)] + +struct Inv<'a>(&'a mut &'a ()); + +trait Trait {} +impl Trait for (for<'a> fn(Inv<'a>),) {} + + +fn with_bound() +where + ((for<'a> fn(Inv<'a>)),): Trait, //~ ERROR unnecessary parentheses around type +{} + +fn main() { + with_bound(); +} diff --git a/tests/ui/lint/unused/issue-105061.stderr b/tests/ui/lint/unused/issue-105061.stderr new file mode 100644 index 000000000..f07aa2012 --- /dev/null +++ b/tests/ui/lint/unused/issue-105061.stderr @@ -0,0 +1,20 @@ +error: unnecessary parentheses around type + --> $DIR/issue-105061.rs:12:6 + | +LL | ((for<'a> fn(Inv<'a>)),): Trait, + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-105061.rs:2:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_parens)]` implied by `#[deny(warnings)]` +help: remove these parentheses + | +LL - ((for<'a> fn(Inv<'a>)),): Trait, +LL + (for<'a> fn(Inv<'a>),): Trait, + | + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/issue-30730.rs b/tests/ui/lint/unused/issue-30730.rs new file mode 100644 index 000000000..d6be90c81 --- /dev/null +++ b/tests/ui/lint/unused/issue-30730.rs @@ -0,0 +1,5 @@ +#![warn(unused)] +#![deny(warnings)] +use std::thread; +//~^ ERROR: unused import +fn main() {} diff --git a/tests/ui/lint/unused/issue-30730.stderr b/tests/ui/lint/unused/issue-30730.stderr new file mode 100644 index 000000000..b299e99a3 --- /dev/null +++ b/tests/ui/lint/unused/issue-30730.stderr @@ -0,0 +1,15 @@ +error: unused import: `std::thread` + --> $DIR/issue-30730.rs:3:5 + | +LL | use std::thread; + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-30730.rs:2:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]` + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/issue-46576.rs b/tests/ui/lint/unused/issue-46576.rs new file mode 100644 index 000000000..15f458f38 --- /dev/null +++ b/tests/ui/lint/unused/issue-46576.rs @@ -0,0 +1,21 @@ +#![allow(dead_code)] +#![deny(unused_imports)] + +use std::fs::File; +use std::io::{BufRead, BufReader, Read}; +//~^ ERROR unused import: `BufRead` + +pub fn read_from_file(path: &str) { + let file = File::open(&path).unwrap(); + let mut reader = BufReader::new(file); + let mut s = String::new(); + reader.read_to_string(&mut s).unwrap(); +} + +pub fn read_lines(s: &str) { + for _line in s.lines() { + + } +} + +fn main() {} diff --git a/tests/ui/lint/unused/issue-46576.stderr b/tests/ui/lint/unused/issue-46576.stderr new file mode 100644 index 000000000..6f4d97068 --- /dev/null +++ b/tests/ui/lint/unused/issue-46576.stderr @@ -0,0 +1,14 @@ +error: unused import: `BufRead` + --> $DIR/issue-46576.rs:5:15 + | +LL | use std::io::{BufRead, BufReader, Read}; + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-46576.rs:2:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs b/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs new file mode 100644 index 000000000..4822a9b2c --- /dev/null +++ b/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs @@ -0,0 +1,88 @@ +// check-pass + +#![feature(box_patterns)] + +#![warn(unused)] // UI tests pass `-A unused` (#43896) + +struct SoulHistory { + corridors_of_light: usize, + hours_are_suns: bool, + endless_and_singing: bool +} + +struct LovelyAmbition { + lips: usize, + fire: usize +} + +#[derive(Clone, Copy)] +enum Large { + Suit { case: () } +} + +struct Tuple(Large, ()); + +fn main() { + let i_think_continually = 2; //~ WARNING unused variable: `i_think_continually` + let who_from_the_womb_remembered = SoulHistory { + corridors_of_light: 5, + hours_are_suns: true, + endless_and_singing: true + }; + + let mut mut_unused_var = 1; + //~^ WARNING unused variable: `mut_unused_var` + //~| WARNING variable does not need to be mutable + + let (mut var, unused_var) = (1, 2); + //~^ WARNING unused variable: `var` + //~| WARNING unused variable: `unused_var` + //~| WARNING variable does not need to be mutable + // NOTE: `var` comes after `unused_var` lexicographically yet the warning + // for `var` will be emitted before the one for `unused_var`. We use an + // `IndexMap` to ensure this is the case instead of a `BTreeMap`. + + if let SoulHistory { corridors_of_light, //~ WARNING unused variable: `corridors_of_light` + mut hours_are_suns, //~ WARNING `hours_are_suns` is assigned to, but + endless_and_singing: true } = who_from_the_womb_remembered { + hours_are_suns = false; //~ WARNING unused_assignments + } + + let the_spirit = LovelyAmbition { lips: 1, fire: 2 }; + let LovelyAmbition { lips, fire } = the_spirit; //~ WARNING unused variable: `fire` + println!("{}", lips); + + let bag = Large::Suit { + case: () + }; + + // Plain struct + match bag { + Large::Suit { case } => {} //~ WARNING unused variable: `case` + }; + + // Referenced struct + match &bag { + &Large::Suit { case } => {} //~ WARNING unused variable: `case` + }; + + // Boxed struct + match Box::new(bag) { + box Large::Suit { case } => {} //~ WARNING unused variable: `case` + }; + + // Tuple with struct + match (bag,) { + (Large::Suit { case },) => {} //~ WARNING unused variable: `case` + }; + + // Slice with struct + match [bag] { + [Large::Suit { case }] => {} //~ WARNING unused variable: `case` + }; + + // Tuple struct with struct + match Tuple(bag, ()) { + Tuple(Large::Suit { case }, ()) => {} //~ WARNING unused variable: `case` + }; +} diff --git a/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr b/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr new file mode 100644 index 000000000..fe2e3afc8 --- /dev/null +++ b/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr @@ -0,0 +1,116 @@ +warning: unused variable: `i_think_continually` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:26:9 + | +LL | let i_think_continually = 2; + | ^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_i_think_continually` + | +note: the lint level is defined here + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:5:9 + | +LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: unused variable: `mut_unused_var` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:33:13 + | +LL | let mut mut_unused_var = 1; + | ^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_mut_unused_var` + +warning: unused variable: `var` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:14 + | +LL | let (mut var, unused_var) = (1, 2); + | ^^^ help: if this is intentional, prefix it with an underscore: `_var` + +warning: unused variable: `unused_var` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:19 + | +LL | let (mut var, unused_var) = (1, 2); + | ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_var` + +warning: unused variable: `corridors_of_light` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:45:26 + | +LL | if let SoulHistory { corridors_of_light, + | ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _` + +warning: variable `hours_are_suns` is assigned to, but never used + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:46:30 + | +LL | mut hours_are_suns, + | ^^^^^^^^^^^^^^ + | + = note: consider using `_hours_are_suns` instead + +warning: value assigned to `hours_are_suns` is never read + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:48:9 + | +LL | hours_are_suns = false; + | ^^^^^^^^^^^^^^ + | + = help: maybe it is overwritten before being read? + = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]` + +warning: unused variable: `fire` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:52:32 + | +LL | let LovelyAmbition { lips, fire } = the_spirit; + | ^^^^ help: try ignoring the field: `fire: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:61:23 + | +LL | Large::Suit { case } => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:66:24 + | +LL | &Large::Suit { case } => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:71:27 + | +LL | box Large::Suit { case } => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:76:24 + | +LL | (Large::Suit { case },) => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:81:24 + | +LL | [Large::Suit { case }] => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:86:29 + | +LL | Tuple(Large::Suit { case }, ()) => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: variable does not need to be mutable + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:33:9 + | +LL | let mut mut_unused_var = 1; + | ----^^^^^^^^^^^^^^ + | | + | help: remove this `mut` + | + = note: `#[warn(unused_mut)]` implied by `#[warn(unused)]` + +warning: variable does not need to be mutable + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:10 + | +LL | let (mut var, unused_var) = (1, 2); + | ----^^^ + | | + | help: remove this `mut` + +warning: 16 warnings emitted + diff --git a/tests/ui/lint/unused/issue-54180-unused-ref-field.fixed b/tests/ui/lint/unused/issue-54180-unused-ref-field.fixed new file mode 100644 index 000000000..1350b7ca6 --- /dev/null +++ b/tests/ui/lint/unused/issue-54180-unused-ref-field.fixed @@ -0,0 +1,34 @@ +// run-rustfix + +#![deny(unused)] + +pub struct S { + pub f1: i32, +} + +pub struct Point { + pub x: i32, + pub y: i32, +} + +pub enum E { + Variant { field: String } +} + +pub fn foo(arg: &E) { + match arg { + E::Variant { field: _ } => (), //~ ERROR unused variable + } +} + +fn main() { + let s = S { f1: 123 }; + let S { f1: _ } = s; //~ ERROR unused variable + + let points = vec![Point { x: 1, y: 2 }]; + let _: i32 = points.iter().map(|Point { x: _, y }| y).sum(); //~ ERROR unused variable + + match (Point { x: 1, y: 2 }) { + Point { y, x: _ } => y, //~ ERROR unused variable + }; +} diff --git a/tests/ui/lint/unused/issue-54180-unused-ref-field.rs b/tests/ui/lint/unused/issue-54180-unused-ref-field.rs new file mode 100644 index 000000000..7b3392b60 --- /dev/null +++ b/tests/ui/lint/unused/issue-54180-unused-ref-field.rs @@ -0,0 +1,34 @@ +// run-rustfix + +#![deny(unused)] + +pub struct S { + pub f1: i32, +} + +pub struct Point { + pub x: i32, + pub y: i32, +} + +pub enum E { + Variant { field: String } +} + +pub fn foo(arg: &E) { + match arg { + E::Variant { ref field } => (), //~ ERROR unused variable + } +} + +fn main() { + let s = S { f1: 123 }; + let S { ref f1 } = s; //~ ERROR unused variable + + let points = vec![Point { x: 1, y: 2 }]; + let _: i32 = points.iter().map(|Point { x, y }| y).sum(); //~ ERROR unused variable + + match (Point { x: 1, y: 2 }) { + Point { y, ref mut x } => y, //~ ERROR unused variable + }; +} diff --git a/tests/ui/lint/unused/issue-54180-unused-ref-field.stderr b/tests/ui/lint/unused/issue-54180-unused-ref-field.stderr new file mode 100644 index 000000000..f2e616899 --- /dev/null +++ b/tests/ui/lint/unused/issue-54180-unused-ref-field.stderr @@ -0,0 +1,33 @@ +error: unused variable: `field` + --> $DIR/issue-54180-unused-ref-field.rs:20:22 + | +LL | E::Variant { ref field } => (), + | ^^^^^^^^^ help: try ignoring the field: `field: _` + | +note: the lint level is defined here + --> $DIR/issue-54180-unused-ref-field.rs:3:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: unused variable: `f1` + --> $DIR/issue-54180-unused-ref-field.rs:26:13 + | +LL | let S { ref f1 } = s; + | ^^^^^^ help: try ignoring the field: `f1: _` + +error: unused variable: `x` + --> $DIR/issue-54180-unused-ref-field.rs:32:20 + | +LL | Point { y, ref mut x } => y, + | ^^^^^^^^^ help: try ignoring the field: `x: _` + +error: unused variable: `x` + --> $DIR/issue-54180-unused-ref-field.rs:29:45 + | +LL | let _: i32 = points.iter().map(|Point { x, y }| y).sum(); + | ^ help: try ignoring the field: `x: _` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed b/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed new file mode 100644 index 000000000..71ebaea8e --- /dev/null +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed @@ -0,0 +1,113 @@ +// run-rustfix + +#![feature(box_patterns, stmt_expr_attributes, yeet_expr)] + +#![allow( + dead_code, + ellipsis_inclusive_range_patterns, + irrefutable_let_patterns, + unreachable_patterns, + unused_mut, + unused_variables +)] +#![deny(unused_parens)] + +fn lint_on_top_level() { + let a = 0; //~ ERROR unnecessary parentheses around pattern + for a in 0..1 {} //~ ERROR unnecessary parentheses around pattern + if let a = 0 {} //~ ERROR unnecessary parentheses around pattern + while let a = 0 {} //~ ERROR unnecessary parentheses around pattern + fn foo(a: u8) {} //~ ERROR unnecessary parentheses around pattern + let _ = |a: u8| 0; //~ ERROR unnecessary parentheses around pattern +} + +fn _no_lint_attr() { + let _x = #[allow(dead_code)] (1 + 2); +} + +fn _no_lint_yeet() -> Result<(), ()> { + #[allow(unreachable_code)] + if (do yeet) {} + + Ok(()) +} + +// Don't lint in these cases (#64106). +fn or_patterns_no_lint() { + match Box::new(0) { + box (0 | 1) => {} // Should not lint as `box 0 | 1` binds as `(box 0) | 1`. + _ => {} + } + + match 0 { + x @ (0 | 1) => {} // Should not lint as `x @ 0 | 1` binds as `(x @ 0) | 1`. + _ => {} + } + + if let &(0 | 1) = &0 {} // Should also not lint. + if let &mut (0 | 1) = &mut 0 {} // Same. + + fn foo((Ok(a) | Err(a)): Result<u8, u8>) {} // Doesn't parse if we remove parens for now. + + let _ = |(Ok(a) | Err(a)): Result<u8, u8>| 1; // `|Ok(a) | Err(a)| 1` parses as bit-or. +} + +fn or_patterns_will_lint() { + if let 0 | 1 = 0 {} //~ ERROR unnecessary parentheses around pattern + if let (0 | 1,) = (0,) {} //~ ERROR unnecessary parentheses around pattern + if let [0 | 1] = [0] {} //~ ERROR unnecessary parentheses around pattern + if let 0 | 1 | 2 = 0 {} //~ ERROR unnecessary parentheses around pattern + struct TS(u8); + if let TS(0 | 1) = TS(0) {} //~ ERROR unnecessary parentheses around pattern + struct NS { f: u8 } + if let NS { f: 0 | 1 } = (NS { f: 0 }) {} //~ ERROR unnecessary parentheses around pattern +} + +// Don't lint on `&(mut x)` because `&mut x` means something else (#55342). +fn deref_mut_binding_no_lint() { + let &(mut x) = &0; +} + +fn main() { + match 1 { + _ => {} //~ ERROR unnecessary parentheses around pattern + y => {} //~ ERROR unnecessary parentheses around pattern + ref r => {} //~ ERROR unnecessary parentheses around pattern + e @ 1...2 => {} //~ ERROR unnecessary parentheses around pattern + (1...2) => {} // Non ambiguous range pattern should not warn + e @ (3...4) => {} // Non ambiguous range pattern should not warn + } + + match &1 { + e @ &(1...2) => {} //~ ERROR unnecessary parentheses around pattern + &_ => {} //~ ERROR unnecessary parentheses around pattern + e @ &(1...2) => {} // Ambiguous range pattern should not warn + &(1...2) => {} // Ambiguous range pattern should not warn + } + + match &1 { + e @ &(1...2) | e @ &(3...4) => {} // Complex ambiguous pattern should not warn + &_ => {} + } + + match 1 { + _ => {} //~ ERROR unnecessary parentheses around pattern + y => {} //~ ERROR unnecessary parentheses around pattern + ref r => {} //~ ERROR unnecessary parentheses around pattern + e @ 1..=2 => {} //~ ERROR unnecessary parentheses around pattern + (1..=2) => {} // Non ambiguous range pattern should not warn + e @ (3..=4) => {} // Non ambiguous range pattern should not warn + } + + match &1 { + e @ &(1..=2) => {} //~ ERROR unnecessary parentheses around pattern + &_ => {} //~ ERROR unnecessary parentheses around pattern + e @ &(1..=2) => {} // Ambiguous range pattern should not warn + &(1..=2) => {} // Ambiguous range pattern should not warn + } + + match &1 { + e @ &(1..=2) | e @ &(3..=4) => {} // Complex ambiguous pattern should not warn + &_ => {} + } +} diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs b/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs new file mode 100644 index 000000000..28b662dd0 --- /dev/null +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs @@ -0,0 +1,113 @@ +// run-rustfix + +#![feature(box_patterns, stmt_expr_attributes, yeet_expr)] + +#![allow( + dead_code, + ellipsis_inclusive_range_patterns, + irrefutable_let_patterns, + unreachable_patterns, + unused_mut, + unused_variables +)] +#![deny(unused_parens)] + +fn lint_on_top_level() { + let (a) = 0; //~ ERROR unnecessary parentheses around pattern + for (a) in 0..1 {} //~ ERROR unnecessary parentheses around pattern + if let (a) = 0 {} //~ ERROR unnecessary parentheses around pattern + while let (a) = 0 {} //~ ERROR unnecessary parentheses around pattern + fn foo((a): u8) {} //~ ERROR unnecessary parentheses around pattern + let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern +} + +fn _no_lint_attr() { + let _x = #[allow(dead_code)] (1 + 2); +} + +fn _no_lint_yeet() -> Result<(), ()> { + #[allow(unreachable_code)] + if (do yeet) {} + + Ok(()) +} + +// Don't lint in these cases (#64106). +fn or_patterns_no_lint() { + match Box::new(0) { + box (0 | 1) => {} // Should not lint as `box 0 | 1` binds as `(box 0) | 1`. + _ => {} + } + + match 0 { + x @ (0 | 1) => {} // Should not lint as `x @ 0 | 1` binds as `(x @ 0) | 1`. + _ => {} + } + + if let &(0 | 1) = &0 {} // Should also not lint. + if let &mut (0 | 1) = &mut 0 {} // Same. + + fn foo((Ok(a) | Err(a)): Result<u8, u8>) {} // Doesn't parse if we remove parens for now. + + let _ = |(Ok(a) | Err(a)): Result<u8, u8>| 1; // `|Ok(a) | Err(a)| 1` parses as bit-or. +} + +fn or_patterns_will_lint() { + if let (0 | 1) = 0 {} //~ ERROR unnecessary parentheses around pattern + if let ((0 | 1),) = (0,) {} //~ ERROR unnecessary parentheses around pattern + if let [(0 | 1)] = [0] {} //~ ERROR unnecessary parentheses around pattern + if let 0 | (1 | 2) = 0 {} //~ ERROR unnecessary parentheses around pattern + struct TS(u8); + if let TS((0 | 1)) = TS(0) {} //~ ERROR unnecessary parentheses around pattern + struct NS { f: u8 } + if let NS { f: (0 | 1) } = (NS { f: 0 }) {} //~ ERROR unnecessary parentheses around pattern +} + +// Don't lint on `&(mut x)` because `&mut x` means something else (#55342). +fn deref_mut_binding_no_lint() { + let &(mut x) = &0; +} + +fn main() { + match 1 { + (_) => {} //~ ERROR unnecessary parentheses around pattern + (y) => {} //~ ERROR unnecessary parentheses around pattern + (ref r) => {} //~ ERROR unnecessary parentheses around pattern + (e @ 1...2) => {} //~ ERROR unnecessary parentheses around pattern + (1...2) => {} // Non ambiguous range pattern should not warn + e @ (3...4) => {} // Non ambiguous range pattern should not warn + } + + match &1 { + (e @ &(1...2)) => {} //~ ERROR unnecessary parentheses around pattern + &(_) => {} //~ ERROR unnecessary parentheses around pattern + e @ &(1...2) => {} // Ambiguous range pattern should not warn + &(1...2) => {} // Ambiguous range pattern should not warn + } + + match &1 { + e @ &(1...2) | e @ &(3...4) => {} // Complex ambiguous pattern should not warn + &_ => {} + } + + match 1 { + (_) => {} //~ ERROR unnecessary parentheses around pattern + (y) => {} //~ ERROR unnecessary parentheses around pattern + (ref r) => {} //~ ERROR unnecessary parentheses around pattern + (e @ 1..=2) => {} //~ ERROR unnecessary parentheses around pattern + (1..=2) => {} // Non ambiguous range pattern should not warn + e @ (3..=4) => {} // Non ambiguous range pattern should not warn + } + + match &1 { + (e @ &(1..=2)) => {} //~ ERROR unnecessary parentheses around pattern + &(_) => {} //~ ERROR unnecessary parentheses around pattern + e @ &(1..=2) => {} // Ambiguous range pattern should not warn + &(1..=2) => {} // Ambiguous range pattern should not warn + } + + match &1 { + e @ &(1..=2) | e @ &(3..=4) => {} // Complex ambiguous pattern should not warn + &_ => {} + } +} diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr b/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr new file mode 100644 index 000000000..a5e69e6d9 --- /dev/null +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr @@ -0,0 +1,295 @@ +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:16:9 + | +LL | let (a) = 0; + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-54538-unused-parens-lint.rs:13:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let (a) = 0; +LL + let a = 0; + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:17:9 + | +LL | for (a) in 0..1 {} + | ^ ^ + | +help: remove these parentheses + | +LL - for (a) in 0..1 {} +LL + for a in 0..1 {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:18:12 + | +LL | if let (a) = 0 {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let (a) = 0 {} +LL + if let a = 0 {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:19:15 + | +LL | while let (a) = 0 {} + | ^ ^ + | +help: remove these parentheses + | +LL - while let (a) = 0 {} +LL + while let a = 0 {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:20:12 + | +LL | fn foo((a): u8) {} + | ^ ^ + | +help: remove these parentheses + | +LL - fn foo((a): u8) {} +LL + fn foo(a: u8) {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:21:14 + | +LL | let _ = |(a): u8| 0; + | ^ ^ + | +help: remove these parentheses + | +LL - let _ = |(a): u8| 0; +LL + let _ = |a: u8| 0; + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:56:12 + | +LL | if let (0 | 1) = 0 {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let (0 | 1) = 0 {} +LL + if let 0 | 1 = 0 {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:57:13 + | +LL | if let ((0 | 1),) = (0,) {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let ((0 | 1),) = (0,) {} +LL + if let (0 | 1,) = (0,) {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:58:13 + | +LL | if let [(0 | 1)] = [0] {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let [(0 | 1)] = [0] {} +LL + if let [0 | 1] = [0] {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:59:16 + | +LL | if let 0 | (1 | 2) = 0 {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let 0 | (1 | 2) = 0 {} +LL + if let 0 | 1 | 2 = 0 {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:61:15 + | +LL | if let TS((0 | 1)) = TS(0) {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let TS((0 | 1)) = TS(0) {} +LL + if let TS(0 | 1) = TS(0) {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:63:20 + | +LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let NS { f: (0 | 1) } = (NS { f: 0 }) {} +LL + if let NS { f: 0 | 1 } = (NS { f: 0 }) {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:73:9 + | +LL | (_) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (_) => {} +LL + _ => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:74:9 + | +LL | (y) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (y) => {} +LL + y => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:75:9 + | +LL | (ref r) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (ref r) => {} +LL + ref r => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:76:9 + | +LL | (e @ 1...2) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ 1...2) => {} +LL + e @ 1...2 => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:82:9 + | +LL | (e @ &(1...2)) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ &(1...2)) => {} +LL + e @ &(1...2) => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:83:10 + | +LL | &(_) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - &(_) => {} +LL + &_ => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:94:9 + | +LL | (_) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (_) => {} +LL + _ => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:95:9 + | +LL | (y) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (y) => {} +LL + y => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:96:9 + | +LL | (ref r) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (ref r) => {} +LL + ref r => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:97:9 + | +LL | (e @ 1..=2) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ 1..=2) => {} +LL + e @ 1..=2 => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:103:9 + | +LL | (e @ &(1..=2)) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ &(1..=2)) => {} +LL + e @ &(1..=2) => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:104:10 + | +LL | &(_) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - &(_) => {} +LL + &_ => {} + | + +error: aborting due to 24 previous errors + diff --git a/tests/ui/lint/unused/issue-59896.rs b/tests/ui/lint/unused/issue-59896.rs new file mode 100644 index 000000000..ff9f19acf --- /dev/null +++ b/tests/ui/lint/unused/issue-59896.rs @@ -0,0 +1,9 @@ +#![deny(unused_imports)] + +struct S; + +fn main() { + use S; //~ ERROR the item `S` is imported redundantly + + let _s = S; +} diff --git a/tests/ui/lint/unused/issue-59896.stderr b/tests/ui/lint/unused/issue-59896.stderr new file mode 100644 index 000000000..95b7938ae --- /dev/null +++ b/tests/ui/lint/unused/issue-59896.stderr @@ -0,0 +1,17 @@ +error: the item `S` is imported redundantly + --> $DIR/issue-59896.rs:6:9 + | +LL | struct S; + | --------- the item `S` is already defined here +... +LL | use S; + | ^ + | +note: the lint level is defined here + --> $DIR/issue-59896.rs:1:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.rs b/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.rs new file mode 100644 index 000000000..e3631d014 --- /dev/null +++ b/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.rs @@ -0,0 +1,85 @@ +// FIXME: should be run-rustfix, but rustfix doesn't currently support multipart suggestions, see +// #53934 + +#![deny(unused)] + +pub enum MyEnum { + A { i: i32, j: i32 }, + B { i: i32, j: i32 }, +} + +pub enum MixedEnum { + A { i: i32 }, + B(i32), +} + +pub fn no_ref(x: MyEnum) { + use MyEnum::*; + + match x { + A { i, j } | B { i, j } => { //~ ERROR unused variable + println!("{}", i); + } + } +} + +pub fn with_ref(x: MyEnum) { + use MyEnum::*; + + match x { + A { i, ref j } | B { i, ref j } => { //~ ERROR unused variable + println!("{}", i); + } + } +} + +pub fn inner_no_ref(x: Option<MyEnum>) { + use MyEnum::*; + + match x { + Some(A { i, j } | B { i, j }) => { //~ ERROR unused variable + println!("{}", i); + } + + _ => {} + } +} + +pub fn inner_with_ref(x: Option<MyEnum>) { + use MyEnum::*; + + match x { + Some(A { i, ref j } | B { i, ref j }) => { //~ ERROR unused variable + println!("{}", i); + } + + _ => {} + } +} + +pub fn mixed_no_ref(x: MixedEnum) { + match x { + MixedEnum::A { i } | MixedEnum::B(i) => { //~ ERROR unused variable + println!("match"); + } + } +} + +pub fn mixed_with_ref(x: MixedEnum) { + match x { + MixedEnum::A { ref i } | MixedEnum::B(ref i) => { //~ ERROR unused variable + println!("match"); + } + } +} + +pub fn main() { + no_ref(MyEnum::A { i: 1, j: 2 }); + with_ref(MyEnum::A { i: 1, j: 2 }); + + inner_no_ref(Some(MyEnum::A { i: 1, j: 2 })); + inner_with_ref(Some(MyEnum::A { i: 1, j: 2 })); + + mixed_no_ref(MixedEnum::B(5)); + mixed_with_ref(MixedEnum::B(5)); +} diff --git a/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.stderr b/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.stderr new file mode 100644 index 000000000..8fc2d1bc8 --- /dev/null +++ b/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.stderr @@ -0,0 +1,74 @@ +error: unused variable: `j` + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:20:16 + | +LL | A { i, j } | B { i, j } => { + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:4:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` +help: try ignoring the field + | +LL | A { i, j: _ } | B { i, j: _ } => { + | ~~~~ ~~~~ + +error: unused variable: `j` + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:30:16 + | +LL | A { i, ref j } | B { i, ref j } => { + | ^^^^^ ^^^^^ + | +help: try ignoring the field + | +LL | A { i, j: _ } | B { i, j: _ } => { + | ~~~~ ~~~~ + +error: unused variable: `j` + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:40:21 + | +LL | Some(A { i, j } | B { i, j }) => { + | ^ ^ + | +help: try ignoring the field + | +LL | Some(A { i, j: _ } | B { i, j: _ }) => { + | ~~~~ ~~~~ + +error: unused variable: `j` + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:52:21 + | +LL | Some(A { i, ref j } | B { i, ref j }) => { + | ^^^^^ ^^^^^ + | +help: try ignoring the field + | +LL | Some(A { i, j: _ } | B { i, j: _ }) => { + | ~~~~ ~~~~ + +error: unused variable: `i` + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:62:24 + | +LL | MixedEnum::A { i } | MixedEnum::B(i) => { + | ^ ^ + | +help: try ignoring the field + | +LL | MixedEnum::A { i: _ } | MixedEnum::B(_) => { + | ~~~~ ~ + +error: unused variable: `i` + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:70:24 + | +LL | MixedEnum::A { ref i } | MixedEnum::B(ref i) => { + | ^^^^^ ^^^^^ + | +help: try ignoring the field + | +LL | MixedEnum::A { i: _ } | MixedEnum::B(_) => { + | ~~~~ ~ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/lint/unused/issue-70041.rs b/tests/ui/lint/unused/issue-70041.rs new file mode 100644 index 000000000..22e42295e --- /dev/null +++ b/tests/ui/lint/unused/issue-70041.rs @@ -0,0 +1,13 @@ +// compile-flags: --edition=2018 +// run-pass + +macro_rules! regex { + //~^ WARN unused macro definition + () => {}; +} + +#[allow(dead_code)] +use regex; +//~^ WARN unused import + +fn main() {} diff --git a/tests/ui/lint/unused/issue-70041.stderr b/tests/ui/lint/unused/issue-70041.stderr new file mode 100644 index 000000000..b2e6d1aeb --- /dev/null +++ b/tests/ui/lint/unused/issue-70041.stderr @@ -0,0 +1,18 @@ +warning: unused macro definition: `regex` + --> $DIR/issue-70041.rs:4:14 + | +LL | macro_rules! regex { + | ^^^^^ + | + = note: `#[warn(unused_macros)]` on by default + +warning: unused import: `regex` + --> $DIR/issue-70041.rs:10:5 + | +LL | use regex; + | ^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/unused/issue-71290-unused-paren-binop.rs b/tests/ui/lint/unused/issue-71290-unused-paren-binop.rs new file mode 100644 index 000000000..24d77e36d --- /dev/null +++ b/tests/ui/lint/unused/issue-71290-unused-paren-binop.rs @@ -0,0 +1,23 @@ +// check-pass +// Make sure unused parens lint doesn't emit a false positive. +// See https://github.com/rust-lang/rust/issues/71290 for details. +#![deny(unused_parens)] + +fn x() -> u8 { + ({ 0 }) + 1 +} + +fn y() -> u8 { + ({ 0 } + 1) +} + +pub fn foo(a: bool, b: bool) -> u8 { + (if a { 1 } else { 0 } + if b { 1 } else { 0 }) +} + +pub fn bar() -> u8 { + // Make sure nested expressions are handled correctly as well + ({ 0 } + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9) +} + +fn main() {} diff --git a/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs new file mode 100644 index 000000000..8064c3a88 --- /dev/null +++ b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs @@ -0,0 +1,26 @@ +#![feature(generator_trait)] +#![feature(generators)] +#![deny(unused_braces, unused_parens)] + +use std::ops::Generator; +use std::pin::Pin; + +fn main() { + let mut x = |_| { + while let Some(_) = (yield) {} + while let Some(_) = {yield} {} + + // Only warn these cases + while let Some(_) = ({yield}) {} //~ ERROR: unnecessary parentheses + while let Some(_) = ((yield)) {} //~ ERROR: unnecessary parentheses + {{yield}}; //~ ERROR: unnecessary braces + {( yield )}; //~ ERROR: unnecessary parentheses + while let Some(_) = {(yield)} {} //~ ERROR: unnecessary parentheses + while let Some(_) = {{yield}} {} //~ ERROR: unnecessary braces + + // FIXME: It'd be great if we could also warn them. + ((yield)); + ({ yield }); + }; + let _ = Pin::new(&mut x).resume(Some(5)); +} diff --git a/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr new file mode 100644 index 000000000..3f1fee332 --- /dev/null +++ b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr @@ -0,0 +1,84 @@ +error: unnecessary parentheses around `let` scrutinee expression + --> $DIR/issue-74883-unused-paren-baren-yield.rs:14:29 + | +LL | while let Some(_) = ({yield}) {} + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:24 + | +LL | #![deny(unused_braces, unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - while let Some(_) = ({yield}) {} +LL + while let Some(_) = {yield} {} + | + +error: unnecessary parentheses around `let` scrutinee expression + --> $DIR/issue-74883-unused-paren-baren-yield.rs:15:29 + | +LL | while let Some(_) = ((yield)) {} + | ^ ^ + | +help: remove these parentheses + | +LL - while let Some(_) = ((yield)) {} +LL + while let Some(_) = (yield) {} + | + +error: unnecessary braces around block return value + --> $DIR/issue-74883-unused-paren-baren-yield.rs:16:10 + | +LL | {{yield}}; + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:9 + | +LL | #![deny(unused_braces, unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - {{yield}}; +LL + {yield}; + | + +error: unnecessary parentheses around block return value + --> $DIR/issue-74883-unused-paren-baren-yield.rs:17:10 + | +LL | {( yield )}; + | ^^ ^^ + | +help: remove these parentheses + | +LL - {( yield )}; +LL + {yield}; + | + +error: unnecessary parentheses around block return value + --> $DIR/issue-74883-unused-paren-baren-yield.rs:18:30 + | +LL | while let Some(_) = {(yield)} {} + | ^ ^ + | +help: remove these parentheses + | +LL - while let Some(_) = {(yield)} {} +LL + while let Some(_) = {yield} {} + | + +error: unnecessary braces around block return value + --> $DIR/issue-74883-unused-paren-baren-yield.rs:19:30 + | +LL | while let Some(_) = {{yield}} {} + | ^ ^ + | +help: remove these braces + | +LL - while let Some(_) = {{yield}} {} +LL + while let Some(_) = {yield} {} + | + +error: aborting due to 6 previous errors + diff --git a/tests/ui/lint/unused/issue-81314-unused-span-ident.fixed b/tests/ui/lint/unused/issue-81314-unused-span-ident.fixed new file mode 100644 index 000000000..aac918f2b --- /dev/null +++ b/tests/ui/lint/unused/issue-81314-unused-span-ident.fixed @@ -0,0 +1,12 @@ +// run-rustfix +// Regression test for #81314: Unused variable lint should +// span only the identifier and not the rest of the pattern + +#![deny(unused)] + +fn main() { + let [_rest @ ..] = [1, 2, 3]; //~ ERROR unused variable +} + +pub fn foo([_rest @ ..]: &[i32]) { //~ ERROR unused variable +} diff --git a/tests/ui/lint/unused/issue-81314-unused-span-ident.rs b/tests/ui/lint/unused/issue-81314-unused-span-ident.rs new file mode 100644 index 000000000..78296f425 --- /dev/null +++ b/tests/ui/lint/unused/issue-81314-unused-span-ident.rs @@ -0,0 +1,12 @@ +// run-rustfix +// Regression test for #81314: Unused variable lint should +// span only the identifier and not the rest of the pattern + +#![deny(unused)] + +fn main() { + let [rest @ ..] = [1, 2, 3]; //~ ERROR unused variable +} + +pub fn foo([rest @ ..]: &[i32]) { //~ ERROR unused variable +} diff --git a/tests/ui/lint/unused/issue-81314-unused-span-ident.stderr b/tests/ui/lint/unused/issue-81314-unused-span-ident.stderr new file mode 100644 index 000000000..519c71e94 --- /dev/null +++ b/tests/ui/lint/unused/issue-81314-unused-span-ident.stderr @@ -0,0 +1,21 @@ +error: unused variable: `rest` + --> $DIR/issue-81314-unused-span-ident.rs:8:10 + | +LL | let [rest @ ..] = [1, 2, 3]; + | ^^^^ help: if this is intentional, prefix it with an underscore: `_rest` + | +note: the lint level is defined here + --> $DIR/issue-81314-unused-span-ident.rs:5:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: unused variable: `rest` + --> $DIR/issue-81314-unused-span-ident.rs:11:13 + | +LL | pub fn foo([rest @ ..]: &[i32]) { + | ^^^^ help: if this is intentional, prefix it with an underscore: `_rest` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/issue-85913.rs b/tests/ui/lint/unused/issue-85913.rs new file mode 100644 index 000000000..7f3817b6e --- /dev/null +++ b/tests/ui/lint/unused/issue-85913.rs @@ -0,0 +1,13 @@ +#![deny(unused_must_use)] + +pub fn fun() -> i32 { + function() && return 1; + //~^ ERROR: unused logical operation that must be used + return 0; +} + +fn function() -> bool { + true +} + +fn main() {} diff --git a/tests/ui/lint/unused/issue-85913.stderr b/tests/ui/lint/unused/issue-85913.stderr new file mode 100644 index 000000000..8234ed3b1 --- /dev/null +++ b/tests/ui/lint/unused/issue-85913.stderr @@ -0,0 +1,18 @@ +error: unused logical operation that must be used + --> $DIR/issue-85913.rs:4:5 + | +LL | function() && return 1; + | ^^^^^^^^^^^^^^^^^^^^^^ the logical operation produces a value + | +note: the lint level is defined here + --> $DIR/issue-85913.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = function() && return 1; + | +++++++ + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/issue-88519-unused-paren.rs b/tests/ui/lint/unused/issue-88519-unused-paren.rs new file mode 100644 index 000000000..ce3d15ac1 --- /dev/null +++ b/tests/ui/lint/unused/issue-88519-unused-paren.rs @@ -0,0 +1,85 @@ +// check-pass +// Make sure unused parens lint doesn't emit a false positive. +// See https://github.com/rust-lang/rust/issues/88519 +#![deny(unused_parens)] +#![feature(type_ascription)] + +// binary ops are tested in issue-71290-unused-paren-binop.rs + +mod call { + fn noop() -> u8 { 0 } + fn outside() -> u8 { + ({ noop })() + } + fn inside() -> u8 { + ({ noop }()) + } + fn outside_match() -> u8 { + (match noop { x => x })() + } + fn inside_match() -> u8 { + (match noop { x => x }()) + } + fn outside_if() -> u8 { + (if false { noop } else { noop })() + } + fn inside_if() -> u8 { + (if false { noop } else { noop }()) + } +} + +mod casts { + fn outside() -> u8 { + ({ 0 }) as u8 + } + fn inside() -> u8 { + ({ 0 } as u8) + } + fn outside_match() -> u8 { + (match 0 { x => x }) as u8 + } + fn inside_match() -> u8 { + (match 0 { x => x } as u8) + } + fn outside_if() -> u8 { + (if false { 0 } else { 0 }) as u8 + } + fn inside_if() -> u8 { + (if false { 0 } else { 0 } as u8) + } +} + +mod typeascription { + fn outside() -> u8 { + type_ascribe!(({ 0 }), u8) + } + fn outside_match() -> u8 { + type_ascribe!((match 0 { x => x }), u8) + } + fn outside_if() -> u8 { + type_ascribe!((if false { 0 } else { 0 }), u8) + } +} + +mod index { + fn outside(x: &[u8]) -> u8 { + ({ x })[0] + } + fn inside(x: &[u8]) -> u8 { + ({ x }[0]) + } + fn outside_match(x: &[u8]) -> u8 { + (match x { x => x })[0] + } + fn inside_match(x: &[u8]) -> u8 { + (match x { x => x }[0]) + } + fn outside_if(x: &[u8]) -> u8 { + (if false { x } else { x })[0] + } + fn inside_if(x: &[u8]) -> u8 { + (if false { x } else { x }[0]) + } +} + +fn main() {} diff --git a/tests/ui/lint/unused/issue-90807-unused-paren-error.rs b/tests/ui/lint/unused/issue-90807-unused-paren-error.rs new file mode 100644 index 000000000..2fca2e262 --- /dev/null +++ b/tests/ui/lint/unused/issue-90807-unused-paren-error.rs @@ -0,0 +1,9 @@ +// Make sure unused parens lint emit is emitted for loop and match. +// See https://github.com/rust-lang/rust/issues/90807 +// and https://github.com/rust-lang/rust/pull/91956#discussion_r771647953 +#![deny(unused_parens)] + +fn main() { + for _ in (1..loop { break 2 }) {} //~ERROR + for _ in (1..match () { () => 2 }) {} //~ERROR +} diff --git a/tests/ui/lint/unused/issue-90807-unused-paren-error.stderr b/tests/ui/lint/unused/issue-90807-unused-paren-error.stderr new file mode 100644 index 000000000..b3b809d5f --- /dev/null +++ b/tests/ui/lint/unused/issue-90807-unused-paren-error.stderr @@ -0,0 +1,31 @@ +error: unnecessary parentheses around `for` iterator expression + --> $DIR/issue-90807-unused-paren-error.rs:7:14 + | +LL | for _ in (1..loop { break 2 }) {} + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-90807-unused-paren-error.rs:4:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - for _ in (1..loop { break 2 }) {} +LL + for _ in 1..loop { break 2 } {} + | + +error: unnecessary parentheses around `for` iterator expression + --> $DIR/issue-90807-unused-paren-error.rs:8:14 + | +LL | for _ in (1..match () { () => 2 }) {} + | ^ ^ + | +help: remove these parentheses + | +LL - for _ in (1..match () { () => 2 }) {} +LL + for _ in 1..match () { () => 2 } {} + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/issue-90807-unused-paren.rs b/tests/ui/lint/unused/issue-90807-unused-paren.rs new file mode 100644 index 000000000..4c0930f96 --- /dev/null +++ b/tests/ui/lint/unused/issue-90807-unused-paren.rs @@ -0,0 +1,8 @@ +// check-pass +// Make sure unused parens lint doesn't emit a false positive. +// See https://github.com/rust-lang/rust/issues/90807 +#![deny(unused_parens)] + +fn main() { + for _ in (1..{ 2 }) {} +} diff --git a/tests/ui/lint/unused/issue-92751.rs b/tests/ui/lint/unused/issue-92751.rs new file mode 100644 index 000000000..2fb292736 --- /dev/null +++ b/tests/ui/lint/unused/issue-92751.rs @@ -0,0 +1,9 @@ +#[deny(unused)] +pub fn broken(x: Option<()>) -> i32 { + match x { + Some(()) => (1), //~ ERROR unnecessary parentheses around match arm expression + None => (2), //~ ERROR unnecessary parentheses around match arm expression + } +} + +fn main() { } diff --git a/tests/ui/lint/unused/issue-92751.stderr b/tests/ui/lint/unused/issue-92751.stderr new file mode 100644 index 000000000..0a8d8e672 --- /dev/null +++ b/tests/ui/lint/unused/issue-92751.stderr @@ -0,0 +1,32 @@ +error: unnecessary parentheses around match arm expression + --> $DIR/issue-92751.rs:4:21 + | +LL | Some(()) => (1), + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-92751.rs:1:8 + | +LL | #[deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_parens)]` implied by `#[deny(unused)]` +help: remove these parentheses + | +LL - Some(()) => (1), +LL + Some(()) => 1, + | + +error: unnecessary parentheses around match arm expression + --> $DIR/issue-92751.rs:5:17 + | +LL | None => (2), + | ^ ^ + | +help: remove these parentheses + | +LL - None => (2), +LL + None => 2, + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/lint-unused-extern-crate.rs b/tests/ui/lint/unused/lint-unused-extern-crate.rs new file mode 100644 index 000000000..d5e4da526 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-extern-crate.rs @@ -0,0 +1,35 @@ +// aux-build:lint_unused_extern_crate.rs +// aux-build:lint_unused_extern_crate2.rs +// aux-build:lint_unused_extern_crate3.rs +// aux-build:lint_unused_extern_crate4.rs +// aux-build:lint_unused_extern_crate5.rs + +#![deny(unused_extern_crates)] +#![allow(unused_variables)] +#![allow(deprecated)] + +extern crate lint_unused_extern_crate5; //~ ERROR: unused extern crate + +pub extern crate lint_unused_extern_crate4; // no error, it is re-exported + +extern crate lint_unused_extern_crate3; // no error, it is used + +extern crate lint_unused_extern_crate2; // no error, the use marks it as used + // even if imported objects aren't used + +extern crate lint_unused_extern_crate as other; // no error, the use * marks it as used + +#[allow(unused_imports)] +use lint_unused_extern_crate2::foo as bar; + +use other::*; + +mod foo { + // Test that this is unused even though an earlier `extern crate` is used. + extern crate lint_unused_extern_crate2; //~ ERROR unused extern crate +} + +fn main() { + lint_unused_extern_crate3::foo(); + let y = foo(); +} diff --git a/tests/ui/lint/unused/lint-unused-extern-crate.stderr b/tests/ui/lint/unused/lint-unused-extern-crate.stderr new file mode 100644 index 000000000..46d8f3bee --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-extern-crate.stderr @@ -0,0 +1,20 @@ +error: unused extern crate + --> $DIR/lint-unused-extern-crate.rs:11:1 + | +LL | extern crate lint_unused_extern_crate5; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + | +note: the lint level is defined here + --> $DIR/lint-unused-extern-crate.rs:7:9 + | +LL | #![deny(unused_extern_crates)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unused extern crate + --> $DIR/lint-unused-extern-crate.rs:29:5 + | +LL | extern crate lint_unused_extern_crate2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/lint-unused-imports.rs b/tests/ui/lint/unused/lint-unused-imports.rs new file mode 100644 index 000000000..4754d8880 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-imports.rs @@ -0,0 +1,90 @@ +#![deny(unused_imports)] +#![allow(dead_code)] + +use bar::c::cc as cal; + +use std::mem::*; // shouldn't get errors for not using + // everything imported +use std::fmt::{}; +//~^ ERROR unused import: `std::fmt::{}` + +// Should get errors for both 'Some' and 'None' +use std::option::Option::{Some, None}; +//~^ ERROR unused imports: `None`, `Some` + +use test::A; //~ ERROR unused import: `test::A` +// Be sure that if we just bring some methods into scope that they're also +// counted as being used. +use test::B; +// But only when actually used: do not get confused by the method with the same name. +use test::B2; //~ ERROR unused import: `test::B2` + +// Make sure this import is warned about when at least one of its imported names +// is unused +use test2::{foo, bar}; //~ ERROR unused import: `bar` + +mod test2 { + pub fn foo() {} + pub fn bar() {} +} + +mod test { + pub trait A { fn a(&self) {} } + pub trait B { fn b(&self) {} } + pub trait B2 { fn b(&self) {} } + pub struct C; + impl A for C {} + impl B for C {} +} + +mod foo { + pub struct Point{pub x: isize, pub y: isize} + pub struct Square{pub p: Point, pub h: usize, pub w: usize} +} + +mod bar { + // Don't ignore on 'pub use' because we're not sure if it's used or not + pub use std::cmp::PartialEq; + pub struct Square; + + pub mod c { + use foo::Point; + use foo::Square; //~ ERROR unused import: `foo::Square` + pub fn cc(_p: Point) -> super::Square { + fn f() -> super::Square { + super::Square + } + f() + } + } + + #[allow(unused_imports)] + mod foo { + use std::cmp::PartialEq; + } +} + +fn g() { + use self::g; //~ ERROR unused import: `self::g` + //~^ ERROR the item `g` is imported redundantly + fn f() { + self::g(); + } +} + +// cf. issue #35135. +#[allow(unused_variables)] +fn h() { + use test2::foo; //~ ERROR unused import: `test2::foo` + //~^ ERROR the item `foo` is imported redundantly + let foo = 0; +} + +fn main() { + cal(foo::Point{x:3, y:9}); + let mut a = 3; + let mut b = 4; + swap(&mut a, &mut b); + test::C.b(); + let _a = foo(); +} diff --git a/tests/ui/lint/unused/lint-unused-imports.stderr b/tests/ui/lint/unused/lint-unused-imports.stderr new file mode 100644 index 000000000..0574ca456 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-imports.stderr @@ -0,0 +1,78 @@ +error: unused import: `std::fmt::{}` + --> $DIR/lint-unused-imports.rs:8:5 + | +LL | use std::fmt::{}; + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-unused-imports.rs:1:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: unused imports: `None`, `Some` + --> $DIR/lint-unused-imports.rs:12:27 + | +LL | use std::option::Option::{Some, None}; + | ^^^^ ^^^^ + +error: unused import: `test::A` + --> $DIR/lint-unused-imports.rs:15:5 + | +LL | use test::A; + | ^^^^^^^ + +error: unused import: `bar` + --> $DIR/lint-unused-imports.rs:24:18 + | +LL | use test2::{foo, bar}; + | ^^^ + +error: unused import: `foo::Square` + --> $DIR/lint-unused-imports.rs:52:13 + | +LL | use foo::Square; + | ^^^^^^^^^^^ + +error: the item `g` is imported redundantly + --> $DIR/lint-unused-imports.rs:68:9 + | +LL | / fn g() { +LL | | use self::g; + | | ^^^^^^^ +LL | | +LL | | fn f() { +LL | | self::g(); +LL | | } +LL | | } + | |_- the item `g` is already defined here + +error: unused import: `self::g` + --> $DIR/lint-unused-imports.rs:68:9 + | +LL | use self::g; + | ^^^^^^^ + +error: the item `foo` is imported redundantly + --> $DIR/lint-unused-imports.rs:78:9 + | +LL | use test2::{foo, bar}; + | --- the item `foo` is already imported here +... +LL | use test2::foo; + | ^^^^^^^^^^ + +error: unused import: `test2::foo` + --> $DIR/lint-unused-imports.rs:78:9 + | +LL | use test2::foo; + | ^^^^^^^^^^ + +error: unused import: `test::B2` + --> $DIR/lint-unused-imports.rs:20:5 + | +LL | use test::B2; + | ^^^^^^^^ + +error: aborting due to 10 previous errors + diff --git a/tests/ui/lint/unused/lint-unused-mut-self.fixed b/tests/ui/lint/unused/lint-unused-mut-self.fixed new file mode 100644 index 000000000..92ce10358 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-mut-self.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![allow(dead_code)] +#![deny(unused_mut)] + +struct Foo; +impl Foo { + fn foo(self) {} //~ ERROR: variable does not need to be mutable + fn bar(self: Box<Foo>) {} //~ ERROR: variable does not need to be mutable +} + +fn main() {} diff --git a/tests/ui/lint/unused/lint-unused-mut-self.rs b/tests/ui/lint/unused/lint-unused-mut-self.rs new file mode 100644 index 000000000..70736ce21 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-mut-self.rs @@ -0,0 +1,14 @@ +// run-rustfix + +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![allow(dead_code)] +#![deny(unused_mut)] + +struct Foo; +impl Foo { + fn foo(mut self) {} //~ ERROR: variable does not need to be mutable + fn bar(mut self: Box<Foo>) {} //~ ERROR: variable does not need to be mutable +} + +fn main() {} diff --git a/tests/ui/lint/unused/lint-unused-mut-self.stderr b/tests/ui/lint/unused/lint-unused-mut-self.stderr new file mode 100644 index 000000000..01a524bd3 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-mut-self.stderr @@ -0,0 +1,24 @@ +error: variable does not need to be mutable + --> $DIR/lint-unused-mut-self.rs:10:12 + | +LL | fn foo(mut self) {} + | ----^^^^ + | | + | help: remove this `mut` + | +note: the lint level is defined here + --> $DIR/lint-unused-mut-self.rs:6:9 + | +LL | #![deny(unused_mut)] + | ^^^^^^^^^^ + +error: variable does not need to be mutable + --> $DIR/lint-unused-mut-self.rs:11:12 + | +LL | fn bar(mut self: Box<Foo>) {} + | ----^^^^ + | | + | help: remove this `mut` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/lint-unused-mut-variables.rs b/tests/ui/lint/unused/lint-unused-mut-variables.rs new file mode 100644 index 000000000..67ec7facf --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-mut-variables.rs @@ -0,0 +1,207 @@ +// edition:2018 + +// Exercise the unused_mut attribute in some positive and negative cases + +#![warn(unused_mut)] +#![feature(async_closure, raw_ref_op)] + +async fn baz_async( + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, +) {} +fn baz( + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, + #[allow(unused_mut)] (mut c, d): (i32, i32) +) {} + +struct RefStruct {} +impl RefStruct { + async fn baz_async( + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, + ) {} + fn baz( + &self, + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, + #[allow(unused_mut)] (mut c, d): (i32, i32) + ) {} +} + +trait RefTrait { + fn baz( + &self, + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, + #[allow(unused_mut)] (mut c, d): (i32, i32) + ) {} +} +impl RefTrait for () { + fn baz( + &self, + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, + #[allow(unused_mut)] (mut c, d): (i32, i32) + ) {} +} + +fn main() { + let _ = async move | + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, + | {}; + let _ = | + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, + #[allow(unused_mut)] (mut c, d): (i32, i32) + | {}; + + // negative cases + let mut a = 3; //~ WARN: variable does not need to be mutable + + let mut a = 2; //~ WARN: variable does not need to be mutable + + let mut b = 3; //~ WARN: variable does not need to be mutable + + let mut a = vec![3]; //~ WARN: variable does not need to be mutable + + let (mut a, b) = (1, 2); //~ WARN: variable does not need to be mutable + + let mut a; //~ WARN: variable does not need to be mutable + + a = 3; + + let mut b; //~ WARN: variable does not need to be mutable + + if true { + b = 3; + } else { + b = 4; + } + + match 30 { + mut x => {} //~ WARN: variable does not need to be mutable + + } + + match (30, 2) { + // FIXME: Here's a false positive, + // shouldn't be removed `mut` not to be bound with a different way. + (mut x, 1) | //~ WARN: variable does not need to be mutable + + (mut x, 2) | + (mut x, 3) => { + } + _ => {} + } + + let x = |mut y: isize| 10; //~ WARN: variable does not need to be mutable + + fn what(mut foo: isize) {} //~ WARN: variable does not need to be mutable + + + let mut a = &mut 5; //~ WARN: variable does not need to be mutable + + *a = 4; + + let mut a = 5; + let mut b = (&mut a,); //~ WARN: variable does not need to be mutable + *b.0 = 4; + + let mut x = &mut 1; //~ WARN: variable does not need to be mutable + + let mut f = || { + *x += 1; + }; + f(); + + fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { + &mut arg[..] //~^ WARN: variable does not need to be mutable + + } + + let mut v : &mut Vec<()> = &mut vec![]; //~ WARN: variable does not need to be mutable + + v.push(()); + + // positive cases + let mut a = 2; + a = 3; + let mut a = Vec::new(); + a.push(3); + let mut a = Vec::new(); + callback(|| { + a.push(3); + }); + let mut a = Vec::new(); + callback(|| { + callback(|| { + a.push(3); + }); + }); + let (mut a, b) = (1, 2); + a = 34; + + match 30 { + mut x => { + x = 21; + } + } + + match (30, 2) { + (mut x, 1) | + (mut x, 2) | + (mut x, 3) => { + x = 21 + } + _ => {} + } + + // Attribute should be respected on match arms + match 0 { + #[allow(unused_mut)] + mut x => { + let mut y = 1; + }, + } + + let x = |mut y: isize| y = 32; + fn nothing(mut foo: isize) { foo = 37; } + + // leading underscore should avoid the warning, just like the + // unused variable lint. + let mut _allowed = 1; + + let mut raw_address_of_mut = 1; // OK + let mut_ptr = &raw mut raw_address_of_mut; + + let mut raw_address_of_const = 1; //~ WARN: variable does not need to be mutable + let const_ptr = &raw const raw_address_of_const; +} + +fn callback<F>(f: F) where F: FnOnce() {} + +// make sure the lint attribute can be turned off +#[allow(unused_mut)] +fn foo(mut a: isize) { + let mut a = 3; + let mut b = vec![2]; +} + +// make sure the lint attribute can be turned off on let statements +#[deny(unused_mut)] +fn bar() { + #[allow(unused_mut)] + let mut a = 3; + let mut b = vec![2]; //~ ERROR: variable does not need to be mutable + +} diff --git a/tests/ui/lint/unused/lint-unused-mut-variables.stderr b/tests/ui/lint/unused/lint-unused-mut-variables.stderr new file mode 100644 index 000000000..805ed2b40 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-mut-variables.stderr @@ -0,0 +1,222 @@ +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:9:5 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + | +note: the lint level is defined here + --> $DIR/lint-unused-mut-variables.rs:5:9 + | +LL | #![warn(unused_mut)] + | ^^^^^^^^^^ + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:23:9 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:14:5 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:29:9 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:39:9 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:48:9 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:57:9 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:62:9 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:107:14 + | +LL | let x = |mut y: isize| 10; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:69:9 + | +LL | let mut a = 3; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:71:9 + | +LL | let mut a = 2; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:73:9 + | +LL | let mut b = 3; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:75:9 + | +LL | let mut a = vec![3]; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:77:10 + | +LL | let (mut a, b) = (1, 2); + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:79:9 + | +LL | let mut a; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:83:9 + | +LL | let mut b; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:92:9 + | +LL | mut x => {} + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:99:10 + | +LL | (mut x, 1) | + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:112:9 + | +LL | let mut a = &mut 5; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:117:9 + | +LL | let mut b = (&mut a,); + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:120:9 + | +LL | let mut x = &mut 1; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:132:9 + | +LL | let mut v : &mut Vec<()> = &mut vec![]; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:187:9 + | +LL | let mut raw_address_of_const = 1; + | ----^^^^^^^^^^^^^^^^^^^^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:109:13 + | +LL | fn what(mut foo: isize) {} + | ----^^^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:127:20 + | +LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { + | ----^^^ + | | + | help: remove this `mut` + +error: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:205:9 + | +LL | let mut b = vec![2]; + | ----^ + | | + | help: remove this `mut` + | +note: the lint level is defined here + --> $DIR/lint-unused-mut-variables.rs:201:8 + | +LL | #[deny(unused_mut)] + | ^^^^^^^^^^ + +error: aborting due to previous error; 25 warnings emitted + diff --git a/tests/ui/lint/unused/lint-unused-variables.rs b/tests/ui/lint/unused/lint-unused-variables.rs new file mode 100644 index 000000000..6850e9992 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-variables.rs @@ -0,0 +1,79 @@ +// compile-flags: --cfg something +// edition:2018 + +#![feature(async_closure)] +#![deny(unused_variables)] + +async fn foo_async( + a: i32, + //~^ ERROR unused variable: `a` + #[allow(unused_variables)] b: i32, +) {} +fn foo( + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` +) {} + +struct RefStruct {} +impl RefStruct { + async fn bar_async( + &self, + a: i32, + //~^ ERROR unused variable: `a` + #[allow(unused_variables)] b: i32, + ) {} + fn bar( + &self, + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} + fn issue_64682_associated_fn( + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} +} +trait RefTrait { + fn bar( + &self, + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} + fn issue_64682_associated_fn( + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} +} +impl RefTrait for RefStruct { + fn bar( + &self, + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} + fn issue_64682_associated_fn( + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} +} + +fn main() { + let _: fn(_, _) = foo; + let a = async move | + a: i32, + //~^ ERROR unused variable: `a` + #[allow(unused_variables)] b: i32, + | {}; + let b = | + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + | {}; + let _ = a(1, 2); + let _ = b(1, 2); +} diff --git a/tests/ui/lint/unused/lint-unused-variables.stderr b/tests/ui/lint/unused/lint-unused-variables.stderr new file mode 100644 index 000000000..fd9a5bcbf --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-variables.stderr @@ -0,0 +1,74 @@ +error: unused variable: `a` + --> $DIR/lint-unused-variables.rs:8:5 + | +LL | a: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_a` + | +note: the lint level is defined here + --> $DIR/lint-unused-variables.rs:5:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:14:5 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/lint-unused-variables.rs:22:9 + | +LL | a: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:29:9 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:34:9 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:42:9 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:47:9 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:55:9 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:60:9 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/lint-unused-variables.rs:68:9 + | +LL | a: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:74:9 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: aborting due to 11 previous errors + diff --git a/tests/ui/lint/unused/must-use-box-from-raw.rs b/tests/ui/lint/unused/must-use-box-from-raw.rs new file mode 100644 index 000000000..9ea772689 --- /dev/null +++ b/tests/ui/lint/unused/must-use-box-from-raw.rs @@ -0,0 +1,11 @@ +// #99269 + +// check-pass + +#![warn(unused_must_use)] + +unsafe fn free<T>(ptr: *mut T) { + Box::from_raw(ptr); //~ WARNING unused return value +} + +fn main() {} diff --git a/tests/ui/lint/unused/must-use-box-from-raw.stderr b/tests/ui/lint/unused/must-use-box-from-raw.stderr new file mode 100644 index 000000000..47ab613be --- /dev/null +++ b/tests/ui/lint/unused/must-use-box-from-raw.stderr @@ -0,0 +1,15 @@ +warning: unused return value of `Box::<T>::from_raw` that must be used + --> $DIR/must-use-box-from-raw.rs:8:5 + | +LL | Box::from_raw(ptr); + | ^^^^^^^^^^^^^^^^^^ + | + = note: call `drop(Box::from_raw(ptr))` if you intend to drop the `Box` +note: the lint level is defined here + --> $DIR/must-use-box-from-raw.rs:5:9 + | +LL | #![warn(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/unused/must-use-ops.rs b/tests/ui/lint/unused/must-use-ops.rs new file mode 100644 index 000000000..60f877aa8 --- /dev/null +++ b/tests/ui/lint/unused/must-use-ops.rs @@ -0,0 +1,51 @@ +// Issue #50124 - Test warning for unused operator expressions + +// check-pass + +#![warn(unused_must_use)] +#![feature(never_type)] + +fn deref_never(x: &!) { + // Don't lint for uninhabited typess + *x; +} + +fn main() { + let val = 1; + let val_pointer = &val; + + // Comparison Operators + val == 1; //~ WARNING unused comparison + val < 1; //~ WARNING unused comparison + val <= 1; //~ WARNING unused comparison + val != 1; //~ WARNING unused comparison + val >= 1; //~ WARNING unused comparison + val > 1; //~ WARNING unused comparison + + // Arithmetic Operators + val + 2; //~ WARNING unused arithmetic operation + val - 2; //~ WARNING unused arithmetic operation + val / 2; //~ WARNING unused arithmetic operation + val * 2; //~ WARNING unused arithmetic operation + val % 2; //~ WARNING unused arithmetic operation + + // Logical Operators + true && true; //~ WARNING unused logical operation + false || true; //~ WARNING unused logical operation + + // Bitwise Operators + 5 ^ val; //~ WARNING unused bitwise operation + 5 & val; //~ WARNING unused bitwise operation + 5 | val; //~ WARNING unused bitwise operation + 5 << val; //~ WARNING unused bitwise operation + 5 >> val; //~ WARNING unused bitwise operation + + // Unary Operators + !val; //~ WARNING unused unary operation + -val; //~ WARNING unused unary operation + *val_pointer; //~ WARNING unused unary operation + + if false { + deref_never(&panic!()); + } +} diff --git a/tests/ui/lint/unused/must-use-ops.stderr b/tests/ui/lint/unused/must-use-ops.stderr new file mode 100644 index 000000000..79a53d39c --- /dev/null +++ b/tests/ui/lint/unused/must-use-ops.stderr @@ -0,0 +1,238 @@ +warning: unused comparison that must be used + --> $DIR/must-use-ops.rs:18:5 + | +LL | val == 1; + | ^^^^^^^^ the comparison produces a value + | +note: the lint level is defined here + --> $DIR/must-use-ops.rs:5:9 + | +LL | #![warn(unused_must_use)] + | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val == 1; + | +++++++ + +warning: unused comparison that must be used + --> $DIR/must-use-ops.rs:19:5 + | +LL | val < 1; + | ^^^^^^^ the comparison produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val < 1; + | +++++++ + +warning: unused comparison that must be used + --> $DIR/must-use-ops.rs:20:5 + | +LL | val <= 1; + | ^^^^^^^^ the comparison produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val <= 1; + | +++++++ + +warning: unused comparison that must be used + --> $DIR/must-use-ops.rs:21:5 + | +LL | val != 1; + | ^^^^^^^^ the comparison produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val != 1; + | +++++++ + +warning: unused comparison that must be used + --> $DIR/must-use-ops.rs:22:5 + | +LL | val >= 1; + | ^^^^^^^^ the comparison produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val >= 1; + | +++++++ + +warning: unused comparison that must be used + --> $DIR/must-use-ops.rs:23:5 + | +LL | val > 1; + | ^^^^^^^ the comparison produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val > 1; + | +++++++ + +warning: unused arithmetic operation that must be used + --> $DIR/must-use-ops.rs:26:5 + | +LL | val + 2; + | ^^^^^^^ the arithmetic operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val + 2; + | +++++++ + +warning: unused arithmetic operation that must be used + --> $DIR/must-use-ops.rs:27:5 + | +LL | val - 2; + | ^^^^^^^ the arithmetic operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val - 2; + | +++++++ + +warning: unused arithmetic operation that must be used + --> $DIR/must-use-ops.rs:28:5 + | +LL | val / 2; + | ^^^^^^^ the arithmetic operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val / 2; + | +++++++ + +warning: unused arithmetic operation that must be used + --> $DIR/must-use-ops.rs:29:5 + | +LL | val * 2; + | ^^^^^^^ the arithmetic operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val * 2; + | +++++++ + +warning: unused arithmetic operation that must be used + --> $DIR/must-use-ops.rs:30:5 + | +LL | val % 2; + | ^^^^^^^ the arithmetic operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val % 2; + | +++++++ + +warning: unused logical operation that must be used + --> $DIR/must-use-ops.rs:33:5 + | +LL | true && true; + | ^^^^^^^^^^^^ the logical operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = true && true; + | +++++++ + +warning: unused logical operation that must be used + --> $DIR/must-use-ops.rs:34:5 + | +LL | false || true; + | ^^^^^^^^^^^^^ the logical operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = false || true; + | +++++++ + +warning: unused bitwise operation that must be used + --> $DIR/must-use-ops.rs:37:5 + | +LL | 5 ^ val; + | ^^^^^^^ the bitwise operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = 5 ^ val; + | +++++++ + +warning: unused bitwise operation that must be used + --> $DIR/must-use-ops.rs:38:5 + | +LL | 5 & val; + | ^^^^^^^ the bitwise operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = 5 & val; + | +++++++ + +warning: unused bitwise operation that must be used + --> $DIR/must-use-ops.rs:39:5 + | +LL | 5 | val; + | ^^^^^^^ the bitwise operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = 5 | val; + | +++++++ + +warning: unused bitwise operation that must be used + --> $DIR/must-use-ops.rs:40:5 + | +LL | 5 << val; + | ^^^^^^^^ the bitwise operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = 5 << val; + | +++++++ + +warning: unused bitwise operation that must be used + --> $DIR/must-use-ops.rs:41:5 + | +LL | 5 >> val; + | ^^^^^^^^ the bitwise operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = 5 >> val; + | +++++++ + +warning: unused unary operation that must be used + --> $DIR/must-use-ops.rs:44:5 + | +LL | !val; + | ^^^^ the unary operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = !val; + | +++++++ + +warning: unused unary operation that must be used + --> $DIR/must-use-ops.rs:45:5 + | +LL | -val; + | ^^^^ the unary operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = -val; + | +++++++ + +warning: unused unary operation that must be used + --> $DIR/must-use-ops.rs:46:5 + | +LL | *val_pointer; + | ^^^^^^^^^^^^ the unary operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = *val_pointer; + | +++++++ + +warning: 21 warnings emitted + diff --git a/tests/ui/lint/unused/must_use-array.rs b/tests/ui/lint/unused/must_use-array.rs new file mode 100644 index 000000000..b7bae4b0a --- /dev/null +++ b/tests/ui/lint/unused/must_use-array.rs @@ -0,0 +1,54 @@ +#![deny(unused_must_use)] + +#[must_use] +#[derive(Clone, Copy)] +struct S; + +struct A; + +#[must_use] +trait T {} + +impl T for A {} + +fn empty() -> [S; 0] { + [] +} + +fn singleton() -> [S; 1] { + [S] +} + +fn many() -> [S; 4] { + [S, S, S, S] +} + +fn array_of_impl_trait() -> [impl T; 2] { + [A, A] +} + +fn impl_array() -> [(u8, Box<dyn T>); 2] { + [(0, Box::new(A)), (0, Box::new(A))] +} + +fn array_of_arrays_of_arrays() -> [[[S; 1]; 2]; 1] { + [[[S], [S]]] +} + +fn usize_max() -> [S; usize::MAX] { + [S; usize::MAX] +} + +fn main() { + empty(); // ok + singleton(); //~ ERROR unused array of `S` that must be used + many(); //~ ERROR unused array of `S` that must be used + ([S], 0, ()); //~ ERROR unused array of `S` in tuple element 0 that must be used + array_of_impl_trait(); //~ ERROR unused array of implementers of `T` that must be used + impl_array(); + //~^ ERROR unused array of boxed `T` trait objects in tuple element 1 that must be used + array_of_arrays_of_arrays(); + //~^ ERROR unused array of arrays of arrays of `S` that must be used + usize_max(); + //~^ ERROR unused array of `S` that must be used +} diff --git a/tests/ui/lint/unused/must_use-array.stderr b/tests/ui/lint/unused/must_use-array.stderr new file mode 100644 index 000000000..61ef2088d --- /dev/null +++ b/tests/ui/lint/unused/must_use-array.stderr @@ -0,0 +1,50 @@ +error: unused array of `S` that must be used + --> $DIR/must_use-array.rs:44:5 + | +LL | singleton(); + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/must_use-array.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused array of `S` that must be used + --> $DIR/must_use-array.rs:45:5 + | +LL | many(); + | ^^^^^^ + +error: unused array of `S` in tuple element 0 that must be used + --> $DIR/must_use-array.rs:46:6 + | +LL | ([S], 0, ()); + | ^^^ + +error: unused array of implementers of `T` that must be used + --> $DIR/must_use-array.rs:47:5 + | +LL | array_of_impl_trait(); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: unused array of boxed `T` trait objects in tuple element 1 that must be used + --> $DIR/must_use-array.rs:48:5 + | +LL | impl_array(); + | ^^^^^^^^^^^^ + +error: unused array of arrays of arrays of `S` that must be used + --> $DIR/must_use-array.rs:50:5 + | +LL | array_of_arrays_of_arrays(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused array of `S` that must be used + --> $DIR/must_use-array.rs:52:5 + | +LL | usize_max(); + | ^^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/lint/unused/must_use-in-stdlib-traits.rs b/tests/ui/lint/unused/must_use-in-stdlib-traits.rs new file mode 100644 index 000000000..70dddf61f --- /dev/null +++ b/tests/ui/lint/unused/must_use-in-stdlib-traits.rs @@ -0,0 +1,47 @@ +#![deny(unused_must_use)] +#![feature(arbitrary_self_types)] + +use std::iter::Iterator; +use std::future::Future; + +use std::task::{Context, Poll}; +use std::pin::Pin; +use std::unimplemented; + +struct MyFuture; + +impl Future for MyFuture { + type Output = u32; + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<u32> { + Poll::Pending + } +} + +fn iterator() -> impl Iterator { + std::iter::empty::<u32>() +} + +fn future() -> impl Future { + MyFuture +} + +fn square_fn_once() -> impl FnOnce(u32) -> u32 { + |x| x * x +} + +fn square_fn_mut() -> impl FnMut(u32) -> u32 { + |x| x * x +} + +fn square_fn() -> impl Fn(u32) -> u32 { + |x| x * x +} + +fn main() { + iterator(); //~ ERROR unused implementer of `Iterator` that must be used + future(); //~ ERROR unused implementer of `Future` that must be used + square_fn_once(); //~ ERROR unused implementer of `FnOnce` that must be used + square_fn_mut(); //~ ERROR unused implementer of `FnMut` that must be used + square_fn(); //~ ERROR unused implementer of `Fn` that must be used +} diff --git a/tests/ui/lint/unused/must_use-in-stdlib-traits.stderr b/tests/ui/lint/unused/must_use-in-stdlib-traits.stderr new file mode 100644 index 000000000..ef738708d --- /dev/null +++ b/tests/ui/lint/unused/must_use-in-stdlib-traits.stderr @@ -0,0 +1,47 @@ +error: unused implementer of `Iterator` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:42:4 + | +LL | iterator(); + | ^^^^^^^^^^ + | + = note: iterators are lazy and do nothing unless consumed +note: the lint level is defined here + --> $DIR/must_use-in-stdlib-traits.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused implementer of `Future` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:43:4 + | +LL | future(); + | ^^^^^^^^ + | + = note: futures do nothing unless you `.await` or poll them + +error: unused implementer of `FnOnce` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:44:4 + | +LL | square_fn_once(); + | ^^^^^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused implementer of `FnMut` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:45:4 + | +LL | square_fn_mut(); + | ^^^^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused implementer of `Fn` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:46:4 + | +LL | square_fn(); + | ^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/unused/must_use-trait.rs b/tests/ui/lint/unused/must_use-trait.rs new file mode 100644 index 000000000..0aa751443 --- /dev/null +++ b/tests/ui/lint/unused/must_use-trait.rs @@ -0,0 +1,39 @@ +#![deny(unused_must_use)] + +#[must_use] +trait Critical {} + +trait NotSoCritical {} + +trait DecidedlyUnimportant {} + +struct Anon; + +impl Critical for Anon {} +impl NotSoCritical for Anon {} +impl DecidedlyUnimportant for Anon {} + +fn get_critical() -> impl NotSoCritical + Critical + DecidedlyUnimportant { + Anon {} +} + +fn get_boxed_critical() -> Box<dyn Critical> { + Box::new(Anon {}) +} + +fn get_nested_boxed_critical() -> Box<Box<dyn Critical>> { + Box::new(Box::new(Anon {})) +} + +fn get_critical_tuple() -> (u32, Box<dyn Critical>, impl Critical, ()) { + (0, get_boxed_critical(), get_critical(), ()) +} + +fn main() { + get_critical(); //~ ERROR unused implementer of `Critical` that must be used + get_boxed_critical(); //~ ERROR unused boxed `Critical` trait object that must be used + get_nested_boxed_critical(); + //~^ ERROR unused boxed boxed `Critical` trait object that must be used + get_critical_tuple(); //~ ERROR unused boxed `Critical` trait object in tuple element 1 + //~^ ERROR unused implementer of `Critical` in tuple element 2 +} diff --git a/tests/ui/lint/unused/must_use-trait.stderr b/tests/ui/lint/unused/must_use-trait.stderr new file mode 100644 index 000000000..2f5496484 --- /dev/null +++ b/tests/ui/lint/unused/must_use-trait.stderr @@ -0,0 +1,38 @@ +error: unused implementer of `Critical` that must be used + --> $DIR/must_use-trait.rs:33:5 + | +LL | get_critical(); + | ^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/must_use-trait.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused boxed `Critical` trait object that must be used + --> $DIR/must_use-trait.rs:34:5 + | +LL | get_boxed_critical(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: unused boxed boxed `Critical` trait object that must be used + --> $DIR/must_use-trait.rs:35:5 + | +LL | get_nested_boxed_critical(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused boxed `Critical` trait object in tuple element 1 that must be used + --> $DIR/must_use-trait.rs:37:5 + | +LL | get_critical_tuple(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: unused implementer of `Critical` in tuple element 2 that must be used + --> $DIR/must_use-trait.rs:37:5 + | +LL | get_critical_tuple(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/unused/must_use-tuple.rs b/tests/ui/lint/unused/must_use-tuple.rs new file mode 100644 index 000000000..0f0aa2025 --- /dev/null +++ b/tests/ui/lint/unused/must_use-tuple.rs @@ -0,0 +1,17 @@ +#![deny(unused_must_use)] + +fn foo() -> (Result<(), ()>, ()) { + (Ok::<(), ()>(()), ()) +} + +fn main() { + (Ok::<(), ()>(()),); //~ ERROR unused `Result` + + (Ok::<(), ()>(()), 0, Ok::<(), ()>(()), 5); + //~^ ERROR unused `Result` + //~^^ ERROR unused `Result` + + foo(); //~ ERROR unused `Result` + + ((Err::<(), ()>(()), ()), ()); //~ ERROR unused `Result` +} diff --git a/tests/ui/lint/unused/must_use-tuple.stderr b/tests/ui/lint/unused/must_use-tuple.stderr new file mode 100644 index 000000000..63e0318fb --- /dev/null +++ b/tests/ui/lint/unused/must_use-tuple.stderr @@ -0,0 +1,47 @@ +error: unused `Result` in tuple element 0 that must be used + --> $DIR/must_use-tuple.rs:8:6 + | +LL | (Ok::<(), ()>(()),); + | ^^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled +note: the lint level is defined here + --> $DIR/must_use-tuple.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused `Result` in tuple element 0 that must be used + --> $DIR/must_use-tuple.rs:10:6 + | +LL | (Ok::<(), ()>(()), 0, Ok::<(), ()>(()), 5); + | ^^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled + +error: unused `Result` in tuple element 2 that must be used + --> $DIR/must_use-tuple.rs:10:27 + | +LL | (Ok::<(), ()>(()), 0, Ok::<(), ()>(()), 5); + | ^^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled + +error: unused `Result` in tuple element 0 that must be used + --> $DIR/must_use-tuple.rs:14:5 + | +LL | foo(); + | ^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled + +error: unused `Result` in tuple element 0 that must be used + --> $DIR/must_use-tuple.rs:16:7 + | +LL | ((Err::<(), ()>(()), ()), ()); + | ^^^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/unused/must_use-unit.rs b/tests/ui/lint/unused/must_use-unit.rs new file mode 100644 index 000000000..4dd4798ab --- /dev/null +++ b/tests/ui/lint/unused/must_use-unit.rs @@ -0,0 +1,16 @@ +#![feature(never_type)] +#![deny(unused_must_use)] + +#[must_use] +fn foo() {} + +#[must_use] +fn bar() -> ! { + unimplemented!() +} + +fn main() { + foo(); //~ unused return value of `foo` + + bar(); //~ unused return value of `bar` +} diff --git a/tests/ui/lint/unused/must_use-unit.stderr b/tests/ui/lint/unused/must_use-unit.stderr new file mode 100644 index 000000000..9fcbc5074 --- /dev/null +++ b/tests/ui/lint/unused/must_use-unit.stderr @@ -0,0 +1,20 @@ +error: unused return value of `foo` that must be used + --> $DIR/must_use-unit.rs:13:5 + | +LL | foo(); + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/must_use-unit.rs:2:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused return value of `bar` that must be used + --> $DIR/must_use-unit.rs:15:5 + | +LL | bar(); + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/no-unused-parens-return-block.rs b/tests/ui/lint/unused/no-unused-parens-return-block.rs new file mode 100644 index 000000000..37dc519a2 --- /dev/null +++ b/tests/ui/lint/unused/no-unused-parens-return-block.rs @@ -0,0 +1,9 @@ +// run-pass + +#![deny(unused_parens)] +#![allow(unreachable_code)] + +fn main() { + match (return) {} // ok + if (return) {} // ok +} diff --git a/tests/ui/lint/unused/unused-async.rs b/tests/ui/lint/unused/unused-async.rs new file mode 100644 index 000000000..4be93aa15 --- /dev/null +++ b/tests/ui/lint/unused/unused-async.rs @@ -0,0 +1,62 @@ +// edition:2018 +#![deny(unused_must_use)] + + +#[must_use] +async fn foo() -> i32 { + 1 +} + +#[must_use] +fn bar() -> impl std::future::Future<Output=i32> { + async { + 42 + } +} + +async fn baz() -> i32 { + 0 +} + +struct Wowee {} + +impl Wowee { + #[must_use] + async fn test_method() -> i32 { + 1 + } +} + +async fn test() { + foo(); //~ ERROR unused return value of `foo` that must be used + //~^ ERROR unused implementer of `Future` that must be used + foo().await; //~ ERROR unused output of future returned by `foo` that must be used + bar(); //~ ERROR unused return value of `bar` that must be used + //~^ ERROR unused implementer of `Future` that must be used + bar().await; //~ ERROR unused output of future returned by `bar` that must be used + baz(); //~ ERROR unused implementer of `Future` that must be used + baz().await; // ok +} + +/* FIXME(guswynn) update this test when async-fn-in-traits works +trait Doer { + #[must_use] + async fn test_trait_method() -> i32; + WARNING must_use + async fn test_other_trait() -> i32; +} + +impl Doer for Wowee { + async fn test_trait_method() -> i32 { + 1 + } + #[must_use] + async fn test_other_trait() -> i32 { + WARNING must_use + 1 + } +} +*/ + +fn main() { +} diff --git a/tests/ui/lint/unused/unused-async.stderr b/tests/ui/lint/unused/unused-async.stderr new file mode 100644 index 000000000..4bcb26dc1 --- /dev/null +++ b/tests/ui/lint/unused/unused-async.stderr @@ -0,0 +1,55 @@ +error: unused implementer of `Future` that must be used + --> $DIR/unused-async.rs:31:5 + | +LL | foo(); + | ^^^^^ + | + = note: futures do nothing unless you `.await` or poll them +note: the lint level is defined here + --> $DIR/unused-async.rs:2:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused return value of `foo` that must be used + --> $DIR/unused-async.rs:31:5 + | +LL | foo(); + | ^^^^^ + +error: unused output of future returned by `foo` that must be used + --> $DIR/unused-async.rs:33:5 + | +LL | foo().await; + | ^^^^^^^^^^^ + +error: unused implementer of `Future` that must be used + --> $DIR/unused-async.rs:34:5 + | +LL | bar(); + | ^^^^^ + | + = note: futures do nothing unless you `.await` or poll them + +error: unused return value of `bar` that must be used + --> $DIR/unused-async.rs:34:5 + | +LL | bar(); + | ^^^^^ + +error: unused output of future returned by `bar` that must be used + --> $DIR/unused-async.rs:36:5 + | +LL | bar().await; + | ^^^^^^^^^^^ + +error: unused implementer of `Future` that must be used + --> $DIR/unused-async.rs:37:5 + | +LL | baz(); + | ^^^^^ + | + = note: futures do nothing unless you `.await` or poll them + +error: aborting due to 7 previous errors + diff --git a/tests/ui/lint/unused/unused-attr-duplicate.rs b/tests/ui/lint/unused/unused-attr-duplicate.rs new file mode 100644 index 000000000..692617eac --- /dev/null +++ b/tests/ui/lint/unused/unused-attr-duplicate.rs @@ -0,0 +1,105 @@ +// Tests for repeating attribute warnings. +// aux-build:lint_unused_extern_crate.rs +// compile-flags:--test +// Not tested due to extra requirements: +// - panic_handler: needs extra setup +// - target_feature: platform-specific +// - link_section: platform-specific +// - proc_macro, proc_macro_derive, proc_macro_attribute: needs to be a +// proc-macro, and have special handling for mixing. +// - unstable attributes (not going to bother) +// - no_main: extra setup +#![deny(unused_attributes)] +#![crate_name = "unused_attr_duplicate"] +#![crate_name = "unused_attr_duplicate2"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![recursion_limit = "128"] +#![recursion_limit = "256"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![type_length_limit = "1048576"] +#![type_length_limit = "1"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![no_std] +#![no_std] //~ ERROR unused attribute +#![no_implicit_prelude] +#![no_implicit_prelude] //~ ERROR unused attribute +#![windows_subsystem = "console"] +#![windows_subsystem = "windows"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![no_builtins] +#![no_builtins] //~ ERROR unused attribute + +#[no_link] +#[no_link] //~ ERROR unused attribute +extern crate lint_unused_extern_crate; + +#[macro_use] +#[macro_use] //~ ERROR unused attribute +pub mod m { + #[macro_export] + #[macro_export] //~ ERROR unused attribute + macro_rules! foo { + () => {}; + } +} + +#[path = "auxiliary/lint_unused_extern_crate.rs"] +#[path = "bar.rs"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +pub mod from_path; + +#[test] +#[ignore] +#[ignore = "some text"] //~ ERROR unused attribute +#[should_panic] +#[should_panic(expected = "values don't match")] //~ ERROR unused attribute +//~^ WARN this was previously accepted +fn t1() {} + +#[must_use] +#[must_use = "some message"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +// No warnings for #[repr], would require more logic. +#[repr(C)] +#[repr(C)] +#[non_exhaustive] +#[non_exhaustive] //~ ERROR unused attribute +pub struct X; + +#[automatically_derived] +#[automatically_derived] //~ ERROR unused attribute +impl X {} + +#[inline(always)] +#[inline(never)] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#[cold] +#[cold] //~ ERROR unused attribute +#[track_caller] +#[track_caller] //~ ERROR unused attribute +pub fn xyz() {} + +// No warnings for #[link], would require more logic. +#[link(name = "rust_test_helpers", kind = "static")] +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + #[link_name = "this_does_not_exist"] //~ ERROR unused attribute + //~^ WARN this was previously accepted + #[link_name = "rust_dbg_extern_identity_u32"] + pub fn name_in_rust(v: u32) -> u32; +} + +#[export_name = "exported_symbol_name"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#[export_name = "exported_symbol_name2"] +pub fn export_test() {} + +#[no_mangle] +#[no_mangle] //~ ERROR unused attribute +pub fn no_mangle_test() {} + +#[used] +#[used] //~ ERROR unused attribute +static FOO: u32 = 0; + +fn main() {} diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr new file mode 100644 index 000000000..769b17487 --- /dev/null +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -0,0 +1,293 @@ +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:33:1 + | +LL | #[no_link] + | ^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:32:1 + | +LL | #[no_link] + | ^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/unused-attr-duplicate.rs:12:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:37:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:36:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:47:1 + | +LL | #[path = "bar.rs"] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:46:1 + | +LL | #[path = "auxiliary/lint_unused_extern_crate.rs"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:53:1 + | +LL | #[ignore = "some text"] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:52:1 + | +LL | #[ignore] + | ^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:55:1 + | +LL | #[should_panic(expected = "values don't match")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:54:1 + | +LL | #[should_panic] + | ^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:60:1 + | +LL | #[must_use = "some message"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:59:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:66:1 + | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:65:1 + | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:70:1 + | +LL | #[automatically_derived] + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:69:1 + | +LL | #[automatically_derived] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:74:1 + | +LL | #[inline(never)] + | ^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:73:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:77:1 + | +LL | #[cold] + | ^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:76:1 + | +LL | #[cold] + | ^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:79:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:78:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:92:1 + | +LL | #[export_name = "exported_symbol_name"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:94:1 + | +LL | #[export_name = "exported_symbol_name2"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:98:1 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:97:1 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:102:1 + | +LL | #[used] + | ^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:101:1 + | +LL | #[used] + | ^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:86:5 + | +LL | #[link_name = "this_does_not_exist"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:88:5 + | +LL | #[link_name = "rust_dbg_extern_identity_u32"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:14:1 + | +LL | #![crate_name = "unused_attr_duplicate2"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:13:1 + | +LL | #![crate_name = "unused_attr_duplicate"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:17:1 + | +LL | #![recursion_limit = "256"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:16:1 + | +LL | #![recursion_limit = "128"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:20:1 + | +LL | #![type_length_limit = "1"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:19:1 + | +LL | #![type_length_limit = "1048576"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:23:1 + | +LL | #![no_std] + | ^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:22:1 + | +LL | #![no_std] + | ^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:25:1 + | +LL | #![no_implicit_prelude] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:24:1 + | +LL | #![no_implicit_prelude] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:27:1 + | +LL | #![windows_subsystem = "windows"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:26:1 + | +LL | #![windows_subsystem = "console"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:30:1 + | +LL | #![no_builtins] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:29:1 + | +LL | #![no_builtins] + | ^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:40:5 + | +LL | #[macro_export] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:39:5 + | +LL | #[macro_export] + | ^^^^^^^^^^^^^^^ + +error: aborting due to 23 previous errors + diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.rs b/tests/ui/lint/unused/unused-attr-macro-rules.rs new file mode 100644 index 000000000..c0fc280ab --- /dev/null +++ b/tests/ui/lint/unused/unused-attr-macro-rules.rs @@ -0,0 +1,33 @@ +#![deny(unused_attributes)] +// Unused attributes on macro_rules requires special handling since the +// macro_rules definition does not survive towards HIR. + +// A sample of various built-in attributes. +#[macro_export] +#[macro_use] //~ ERROR `#[macro_use]` only has an effect +#[path="foo"] //~ ERROR #[path]` only has an effect +#[recursion_limit="1"] //~ ERROR crate-level attribute should be an inner attribute +macro_rules! foo { + () => {}; +} + +// The following should not warn about unused attributes. +#[allow(unused)] +macro_rules! foo2 { + () => {}; +} + +#[cfg(FALSE)] +macro_rules! foo { + () => {}; +} + +/// Some docs +#[deprecated] +#[doc = "more docs"] +#[macro_export] +macro_rules! bar { + () => {}; +} + +fn main() {} diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.stderr b/tests/ui/lint/unused/unused-attr-macro-rules.stderr new file mode 100644 index 000000000..e3ca90d9a --- /dev/null +++ b/tests/ui/lint/unused/unused-attr-macro-rules.stderr @@ -0,0 +1,26 @@ +error: `#[macro_use]` only has an effect on `extern crate` and modules + --> $DIR/unused-attr-macro-rules.rs:7:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-attr-macro-rules.rs:1:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: `#[path]` only has an effect on modules + --> $DIR/unused-attr-macro-rules.rs:8:1 + | +LL | #[path="foo"] + | ^^^^^^^^^^^^^ + +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/unused-attr-macro-rules.rs:9:1 + | +LL | #[recursion_limit="1"] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused/unused-closure.rs b/tests/ui/lint/unused/unused-closure.rs new file mode 100644 index 000000000..c96c90731 --- /dev/null +++ b/tests/ui/lint/unused/unused-closure.rs @@ -0,0 +1,35 @@ +// Test that closures and generators are "must use" types. +// edition:2018 + +#![feature(async_closure)] +#![feature(generators)] +#![deny(unused_must_use)] + +fn unused() { + || { //~ ERROR unused closure that must be used + println!("Hello!"); + }; + + async {}; //~ ERROR unused implementer of `Future` that must be used + || async {}; //~ ERROR unused closure that must be used + async || {}; //~ ERROR unused closure that must be used + + + [Box::new([|| {}; 10]); 1]; //~ ERROR unused array of boxed arrays of closures that must be used + + vec![|| "a"].pop().unwrap(); //~ ERROR unused closure that must be used + + let b = false; + || true; //~ ERROR unused closure that must be used + println!("{}", b); +} + +fn ignored() { + let _ = || {}; + let _ = || yield 42; +} + +fn main() { + unused(); + ignored(); +} diff --git a/tests/ui/lint/unused/unused-closure.stderr b/tests/ui/lint/unused/unused-closure.stderr new file mode 100644 index 000000000..c3a82402e --- /dev/null +++ b/tests/ui/lint/unused/unused-closure.stderr @@ -0,0 +1,65 @@ +error: unused closure that must be used + --> $DIR/unused-closure.rs:9:5 + | +LL | / || { +LL | | println!("Hello!"); +LL | | }; + | |_____^ + | + = note: closures are lazy and do nothing unless called +note: the lint level is defined here + --> $DIR/unused-closure.rs:6:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused implementer of `Future` that must be used + --> $DIR/unused-closure.rs:13:5 + | +LL | async {}; + | ^^^^^^^^ + | + = note: futures do nothing unless you `.await` or poll them + +error: unused closure that must be used + --> $DIR/unused-closure.rs:14:5 + | +LL | || async {}; + | ^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused closure that must be used + --> $DIR/unused-closure.rs:15:5 + | +LL | async || {}; + | ^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused array of boxed arrays of closures that must be used + --> $DIR/unused-closure.rs:18:5 + | +LL | [Box::new([|| {}; 10]); 1]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused closure that must be used + --> $DIR/unused-closure.rs:20:5 + | +LL | vec![|| "a"].pop().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused closure that must be used + --> $DIR/unused-closure.rs:23:9 + | +LL | || true; + | ^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: aborting due to 7 previous errors + diff --git a/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs b/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs new file mode 100644 index 000000000..54d86c31f --- /dev/null +++ b/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs @@ -0,0 +1,46 @@ +#![deny(unused_doc_comments)] + +fn doc_comment_on_match_arms(num: u8) -> bool { + match num { + 3 => true, + /// useless doc comment + //~^ ERROR: unused doc comment + _ => false, + } +} + +fn doc_comment_between_if_else(num: u8) -> bool { + if num == 3 { + true //~ ERROR: mismatched types + } + /// useless doc comment + else { //~ ERROR: expected expression, found keyword `else` + false + } +} + +fn doc_comment_on_expr(num: u8) -> bool { + /// useless doc comment + //~^ ERROR: attributes on expressions are experimental + //~| ERROR: unused doc comment + num == 3 +} + +fn doc_comment_on_generic<#[doc = "x"] T>(val: T) {} +//~^ ERROR: unused doc comment + +fn doc_comment_on_block() { + /// unused doc comment + //~^ ERROR: unused doc comment + { + let x = 12; + } +} + +/// unused doc comment +//~^ ERROR: unused doc comment +extern "C" { + fn foo(); +} + +fn main() {} diff --git a/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr b/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr new file mode 100644 index 000000000..078b780d8 --- /dev/null +++ b/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr @@ -0,0 +1,95 @@ +error: expected expression, found keyword `else` + --> $DIR/unused-doc-comments-edge-cases.rs:17:5 + | +LL | else { + | ^^^^ expected expression + +error[E0658]: attributes on expressions are experimental + --> $DIR/unused-doc-comments-edge-cases.rs:23:5 + | +LL | /// useless doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + = help: `///` is for documentation comments. For a plain comment, use `//`. + +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:6:9 + | +LL | /// useless doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | _ => false, + | ---------- rustdoc does not generate documentation for match arms + | + = help: use `//` for a plain comment +note: the lint level is defined here + --> $DIR/unused-doc-comments-edge-cases.rs:1:9 + | +LL | #![deny(unused_doc_comments)] + | ^^^^^^^^^^^^^^^^^^^ + +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:23:5 + | +LL | /// useless doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | num == 3 + | --- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:29:27 + | +LL | fn doc_comment_on_generic<#[doc = "x"] T>(val: T) {} + | ^^^^^^^^^^^^ - rustdoc does not generate documentation for generic parameters + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:33:5 + | +LL | /// unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / { +LL | | let x = 12; +LL | | } + | |_____- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:40:1 + | +LL | /// unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / extern "C" { +LL | | fn foo(); +LL | | } + | |_- rustdoc does not generate documentation for extern blocks + | + = help: use `//` for a plain comment + +error[E0308]: mismatched types + --> $DIR/unused-doc-comments-edge-cases.rs:14:9 + | +LL | / if num == 3 { +LL | | true + | | ^^^^ expected `()`, found `bool` +LL | | } + | |_____- expected this to be `()` + | +help: you might have meant to return this value + | +LL | return true; + | ++++++ + + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/lint/unused/unused-doc-comments-for-macros.rs b/tests/ui/lint/unused/unused-doc-comments-for-macros.rs new file mode 100644 index 000000000..05828ebb2 --- /dev/null +++ b/tests/ui/lint/unused/unused-doc-comments-for-macros.rs @@ -0,0 +1,17 @@ +#![deny(unused_doc_comments)] +#![feature(rustc_attrs)] + +macro_rules! foo { () => {}; } + +fn main() { + /// line1 //~ ERROR: unused doc comment + /// line2 + /// line3 + foo!(); + + // Ensure we still detect another doc-comment block. + /// line1 //~ ERROR: unused doc comment + /// line2 + /// line3 + foo!(); +} diff --git a/tests/ui/lint/unused/unused-doc-comments-for-macros.stderr b/tests/ui/lint/unused/unused-doc-comments-for-macros.stderr new file mode 100644 index 000000000..26b1c2b05 --- /dev/null +++ b/tests/ui/lint/unused/unused-doc-comments-for-macros.stderr @@ -0,0 +1,31 @@ +error: unused doc comment + --> $DIR/unused-doc-comments-for-macros.rs:7:5 + | +LL | / /// line1 +LL | | /// line2 +LL | | /// line3 + | |_____--------^ + | | + | rustdoc does not generate documentation for macro invocations + | + = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion +note: the lint level is defined here + --> $DIR/unused-doc-comments-for-macros.rs:1:9 + | +LL | #![deny(unused_doc_comments)] + | ^^^^^^^^^^^^^^^^^^^ + +error: unused doc comment + --> $DIR/unused-doc-comments-for-macros.rs:13:5 + | +LL | / /// line1 +LL | | /// line2 +LL | | /// line3 + | |_____--------^ + | | + | rustdoc does not generate documentation for macro invocations + | + = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/unused-macro-rules-compile-error.rs b/tests/ui/lint/unused/unused-macro-rules-compile-error.rs new file mode 100644 index 000000000..4d51db89b --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules-compile-error.rs @@ -0,0 +1,27 @@ +#![deny(unused_macro_rules)] +// To make sure we are not hitting this +#![deny(unused_macros)] + +macro_rules! num { + (one) => { 1 }; + // Most simple (and common) case + (two) => { compile_error!("foo"); }; + // Some nested use + (two_) => { foo(compile_error!("foo")); }; + (three) => { 3 }; + (four) => { 4 }; //~ ERROR: rule of macro +} +const _NUM: u8 = num!(one) + num!(three); + +// compile_error not used as a macro invocation +macro_rules! num2 { + (one) => { 1 }; + // Only identifier present + (two) => { fn compile_error() {} }; //~ ERROR: rule of macro + // Only identifier and bang present + (two_) => { compile_error! }; //~ ERROR: rule of macro + (three) => { 3 }; +} +const _NUM2: u8 = num2!(one) + num2!(three); + +fn main() {} diff --git a/tests/ui/lint/unused/unused-macro-rules-compile-error.stderr b/tests/ui/lint/unused/unused-macro-rules-compile-error.stderr new file mode 100644 index 000000000..76af8c967 --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules-compile-error.stderr @@ -0,0 +1,26 @@ +error: 5th rule of macro `num` is never used + --> $DIR/unused-macro-rules-compile-error.rs:12:5 + | +LL | (four) => { 4 }; + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macro-rules-compile-error.rs:1:9 + | +LL | #![deny(unused_macro_rules)] + | ^^^^^^^^^^^^^^^^^^ + +error: 3rd rule of macro `num2` is never used + --> $DIR/unused-macro-rules-compile-error.rs:22:5 + | +LL | (two_) => { compile_error! }; + | ^^^^^^ + +error: 2nd rule of macro `num2` is never used + --> $DIR/unused-macro-rules-compile-error.rs:20:5 + | +LL | (two) => { fn compile_error() {} }; + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused/unused-macro-rules-decl.rs b/tests/ui/lint/unused/unused-macro-rules-decl.rs new file mode 100644 index 000000000..537c84940 --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules-decl.rs @@ -0,0 +1,49 @@ +#![feature(decl_macro)] +#![deny(unused_macro_rules)] +// To make sure we are not hitting this +#![deny(unused_macros)] + +// Most simple case +macro num { + (one) => { 1 }, + (two) => { 2 }, //~ ERROR: 2nd rule of macro + (three) => { 3 }, + (four) => { 4 }, //~ ERROR: 4th rule of macro +} +const _NUM: u8 = num!(one) + num!(three); + +// Check that allowing the lint works +#[allow(unused_macro_rules)] +macro num_allowed { + (one) => { 1 }, + (two) => { 2 }, + (three) => { 3 }, + (four) => { 4 }, +} +const _NUM_ALLOWED: u8 = num_allowed!(one) + num_allowed!(three); + +// Check that macro calls inside the macro trigger as usage +macro num_rec { + (one) => { 1 }, + (two) => { + num_rec!(one) + num_rec!(one) + }, + (three) => { //~ ERROR: 3rd rule of macro + num_rec!(one) + num_rec!(two) + }, + (four) => { + num_rec!(two) + num_rec!(two) + }, +} +const _NUM_RECURSIVE: u8 = num_rec!(four); + +// No error if the macro is public +pub macro num_public { + (one) => { 1 }, + (two) => { 2 }, + (three) => { 3 }, + (four) => { 4 }, +} +const _NUM_PUBLIC: u8 = num_public!(one) + num_public!(three); + +fn main() {} diff --git a/tests/ui/lint/unused/unused-macro-rules-decl.stderr b/tests/ui/lint/unused/unused-macro-rules-decl.stderr new file mode 100644 index 000000000..4d9b22fed --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules-decl.stderr @@ -0,0 +1,26 @@ +error: 4th rule of macro `num` is never used + --> $DIR/unused-macro-rules-decl.rs:11:5 + | +LL | (four) => { 4 }, + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macro-rules-decl.rs:2:9 + | +LL | #![deny(unused_macro_rules)] + | ^^^^^^^^^^^^^^^^^^ + +error: 2nd rule of macro `num` is never used + --> $DIR/unused-macro-rules-decl.rs:9:5 + | +LL | (two) => { 2 }, + | ^^^^^ + +error: 3rd rule of macro `num_rec` is never used + --> $DIR/unused-macro-rules-decl.rs:31:5 + | +LL | (three) => { + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused/unused-macro-rules-malformed-rule.rs b/tests/ui/lint/unused/unused-macro-rules-malformed-rule.rs new file mode 100644 index 000000000..a826026ec --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules-malformed-rule.rs @@ -0,0 +1,11 @@ +#![deny(unused_macro_rules)] + +macro_rules! foo { + (v) => {}; + (w) => {}; + () => 0; //~ ERROR: macro rhs must be delimited +} + +fn main() { + foo!(v); +} diff --git a/tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr b/tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr new file mode 100644 index 000000000..797c86710 --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr @@ -0,0 +1,8 @@ +error: macro rhs must be delimited + --> $DIR/unused-macro-rules-malformed-rule.rs:6:11 + | +LL | () => 0; + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/unused-macro-rules.rs b/tests/ui/lint/unused/unused-macro-rules.rs new file mode 100644 index 000000000..eeaf4d1b0 --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules.rs @@ -0,0 +1,47 @@ +#![deny(unused_macro_rules)] +// To make sure we are not hitting this +#![deny(unused_macros)] + +// Most simple case +macro_rules! num { + (one) => { 1 }; + (two) => { 2 }; //~ ERROR: 2nd rule of macro + (three) => { 3 }; + (four) => { 4 }; //~ ERROR: 4th rule of macro +} +const _NUM: u8 = num!(one) + num!(three); + +// Check that allowing the lint works +#[allow(unused_macro_rules)] +macro_rules! num_allowed { + (one) => { 1 }; + (two) => { 2 }; + (three) => { 3 }; + (four) => { 4 }; +} +const _NUM_ALLOWED: u8 = num_allowed!(one) + num_allowed!(three); + +// Check that macro calls inside the macro trigger as usage +macro_rules! num_rec { + (one) => { 1 }; + (two) => { + num_rec!(one) + num_rec!(one) + }; + (three) => { //~ ERROR: 3rd rule of macro + num_rec!(one) + num_rec!(two) + }; + (four) => { num_rec!(two) + num_rec!(two) }; +} +const _NUM_RECURSIVE: u8 = num_rec!(four); + +// No error if the macro is being exported +#[macro_export] +macro_rules! num_exported { + (one) => { 1 }; + (two) => { 2 }; + (three) => { 3 }; + (four) => { 4 }; +} +const _NUM_EXPORTED: u8 = num_exported!(one) + num_exported!(three); + +fn main() {} diff --git a/tests/ui/lint/unused/unused-macro-rules.stderr b/tests/ui/lint/unused/unused-macro-rules.stderr new file mode 100644 index 000000000..2b3098a51 --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules.stderr @@ -0,0 +1,26 @@ +error: 4th rule of macro `num` is never used + --> $DIR/unused-macro-rules.rs:10:5 + | +LL | (four) => { 4 }; + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macro-rules.rs:1:9 + | +LL | #![deny(unused_macro_rules)] + | ^^^^^^^^^^^^^^^^^^ + +error: 2nd rule of macro `num` is never used + --> $DIR/unused-macro-rules.rs:8:5 + | +LL | (two) => { 2 }; + | ^^^^^ + +error: 3rd rule of macro `num_rec` is never used + --> $DIR/unused-macro-rules.rs:30:5 + | +LL | (three) => { + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.rs b/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.rs new file mode 100644 index 000000000..ce187047b --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.rs @@ -0,0 +1,9 @@ +#![allow(unused_macros)] + +// Issue #21370 + +macro_rules! test { + ($wrong:t_ty) => () //~ ERROR invalid fragment specifier `t_ty` +} + +fn main() { } diff --git a/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr b/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr new file mode 100644 index 000000000..6edf0a2cf --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr @@ -0,0 +1,10 @@ +error: invalid fragment specifier `t_ty` + --> $DIR/unused-macro-with-bad-frag-spec.rs:6:6 + | +LL | ($wrong:t_ty) => () + | ^^^^^^^^^^^ + | + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/unused-macro-with-follow-violation.rs b/tests/ui/lint/unused/unused-macro-with-follow-violation.rs new file mode 100644 index 000000000..1666dae69 --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-with-follow-violation.rs @@ -0,0 +1,7 @@ +#![allow(unused_macros)] + +macro_rules! test { + ($e:expr +) => () //~ ERROR not allowed for `expr` fragments +} + +fn main() { } diff --git a/tests/ui/lint/unused/unused-macro-with-follow-violation.stderr b/tests/ui/lint/unused/unused-macro-with-follow-violation.stderr new file mode 100644 index 000000000..5eced4f06 --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-with-follow-violation.stderr @@ -0,0 +1,10 @@ +error: `$e:expr` is followed by `+`, which is not allowed for `expr` fragments + --> $DIR/unused-macro-with-follow-violation.rs:4:14 + | +LL | ($e:expr +) => () + | ^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/unused-macros-decl.rs b/tests/ui/lint/unused/unused-macros-decl.rs new file mode 100644 index 000000000..21f6108b1 --- /dev/null +++ b/tests/ui/lint/unused/unused-macros-decl.rs @@ -0,0 +1,28 @@ +#![feature(decl_macro)] +#![deny(unused_macros)] +// To make sure we are not hitting this +#![deny(unused_macro_rules)] + +// Most simple case +macro unused { //~ ERROR: unused macro definition + () => {} +} + +#[allow(unused_macros)] +mod bar { + // Test that putting the #[deny] close to the macro's definition + // works. + + #[deny(unused_macros)] + macro unused { //~ ERROR: unused macro definition + () => {} + } +} + +mod boo { + pub(crate) macro unused { //~ ERROR: unused macro definition + () => {} + } +} + +fn main() {} diff --git a/tests/ui/lint/unused/unused-macros-decl.stderr b/tests/ui/lint/unused/unused-macros-decl.stderr new file mode 100644 index 000000000..1f426b9d9 --- /dev/null +++ b/tests/ui/lint/unused/unused-macros-decl.stderr @@ -0,0 +1,32 @@ +error: unused macro definition: `unused` + --> $DIR/unused-macros-decl.rs:7:7 + | +LL | macro unused { + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macros-decl.rs:2:9 + | +LL | #![deny(unused_macros)] + | ^^^^^^^^^^^^^ + +error: unused macro definition: `unused` + --> $DIR/unused-macros-decl.rs:17:11 + | +LL | macro unused { + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macros-decl.rs:16:12 + | +LL | #[deny(unused_macros)] + | ^^^^^^^^^^^^^ + +error: unused macro definition: `unused` + --> $DIR/unused-macros-decl.rs:23:22 + | +LL | pub(crate) macro unused { + | ^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused/unused-macros-malformed-rule.rs b/tests/ui/lint/unused/unused-macros-malformed-rule.rs new file mode 100644 index 000000000..d4c35fad9 --- /dev/null +++ b/tests/ui/lint/unused/unused-macros-malformed-rule.rs @@ -0,0 +1,15 @@ +#![deny(unused_macros)] + +macro_rules! foo { //~ ERROR: unused macro definition + (v) => {}; + () => 0; //~ ERROR: macro rhs must be delimited +} + +macro_rules! bar { + (v) => {}; + () => 0; //~ ERROR: macro rhs must be delimited +} + +fn main() { + bar!(v); +} diff --git a/tests/ui/lint/unused/unused-macros-malformed-rule.stderr b/tests/ui/lint/unused/unused-macros-malformed-rule.stderr new file mode 100644 index 000000000..9a880dccf --- /dev/null +++ b/tests/ui/lint/unused/unused-macros-malformed-rule.stderr @@ -0,0 +1,26 @@ +error: macro rhs must be delimited + --> $DIR/unused-macros-malformed-rule.rs:5:11 + | +LL | () => 0; + | ^ + +error: macro rhs must be delimited + --> $DIR/unused-macros-malformed-rule.rs:10:11 + | +LL | () => 0; + | ^ + +error: unused macro definition: `foo` + --> $DIR/unused-macros-malformed-rule.rs:3:14 + | +LL | macro_rules! foo { + | ^^^ + | +note: the lint level is defined here + --> $DIR/unused-macros-malformed-rule.rs:1:9 + | +LL | #![deny(unused_macros)] + | ^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused/unused-macros.rs b/tests/ui/lint/unused/unused-macros.rs new file mode 100644 index 000000000..70b50b208 --- /dev/null +++ b/tests/ui/lint/unused/unused-macros.rs @@ -0,0 +1,31 @@ +#![deny(unused_macros)] +// To make sure we are not hitting this +#![deny(unused_macro_rules)] + +// Most simple case +macro_rules! unused { //~ ERROR: unused macro definition + () => {}; +} + +// Test macros created by macros +macro_rules! create_macro { + () => { + macro_rules! m { //~ ERROR: unused macro definition + () => {}; + } + }; +} +create_macro!(); + +#[allow(unused_macros)] +mod bar { + // Test that putting the #[deny] close to the macro's definition + // works. + + #[deny(unused_macros)] + macro_rules! unused { //~ ERROR: unused macro definition + () => {}; + } +} + +fn main() {} diff --git a/tests/ui/lint/unused/unused-macros.stderr b/tests/ui/lint/unused/unused-macros.stderr new file mode 100644 index 000000000..d0baf5bec --- /dev/null +++ b/tests/ui/lint/unused/unused-macros.stderr @@ -0,0 +1,32 @@ +error: unused macro definition: `unused` + --> $DIR/unused-macros.rs:6:14 + | +LL | macro_rules! unused { + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macros.rs:1:9 + | +LL | #![deny(unused_macros)] + | ^^^^^^^^^^^^^ + +error: unused macro definition: `m` + --> $DIR/unused-macros.rs:13:22 + | +LL | macro_rules! m { + | ^ + +error: unused macro definition: `unused` + --> $DIR/unused-macros.rs:26:18 + | +LL | macro_rules! unused { + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macros.rs:25:12 + | +LL | #[deny(unused_macros)] + | ^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused/unused-mut-warning-captured-var.fixed b/tests/ui/lint/unused/unused-mut-warning-captured-var.fixed new file mode 100644 index 000000000..c21f18015 --- /dev/null +++ b/tests/ui/lint/unused/unused-mut-warning-captured-var.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +#![forbid(unused_mut)] + +fn main() { + let x = 1; + //~^ ERROR: variable does not need to be mutable + (move|| { println!("{}", x); })(); +} diff --git a/tests/ui/lint/unused/unused-mut-warning-captured-var.rs b/tests/ui/lint/unused/unused-mut-warning-captured-var.rs new file mode 100644 index 000000000..3119d83a0 --- /dev/null +++ b/tests/ui/lint/unused/unused-mut-warning-captured-var.rs @@ -0,0 +1,9 @@ +// run-rustfix + +#![forbid(unused_mut)] + +fn main() { + let mut x = 1; + //~^ ERROR: variable does not need to be mutable + (move|| { println!("{}", x); })(); +} diff --git a/tests/ui/lint/unused/unused-mut-warning-captured-var.stderr b/tests/ui/lint/unused/unused-mut-warning-captured-var.stderr new file mode 100644 index 000000000..20aeedcc2 --- /dev/null +++ b/tests/ui/lint/unused/unused-mut-warning-captured-var.stderr @@ -0,0 +1,16 @@ +error: variable does not need to be mutable + --> $DIR/unused-mut-warning-captured-var.rs:6:9 + | +LL | let mut x = 1; + | ----^ + | | + | help: remove this `mut` + | +note: the lint level is defined here + --> $DIR/unused-mut-warning-captured-var.rs:3:11 + | +LL | #![forbid(unused_mut)] + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/unused-result.rs b/tests/ui/lint/unused/unused-result.rs new file mode 100644 index 000000000..e283eaa88 --- /dev/null +++ b/tests/ui/lint/unused/unused-result.rs @@ -0,0 +1,42 @@ +#![allow(dead_code)] +#![deny(unused_results, unused_must_use)] +//~^ NOTE: the lint level is defined here +//~| NOTE: the lint level is defined here + +#[must_use] +enum MustUse { Test } + +#[must_use = "some message"] +enum MustUseMsg { Test2 } + +fn foo<T>() -> T { panic!() } + +fn bar() -> isize { return foo::<isize>(); } +fn baz() -> MustUse { return foo::<MustUse>(); } +fn qux() -> MustUseMsg { return foo::<MustUseMsg>(); } + +#[allow(unused_results)] +fn test() { + foo::<isize>(); + foo::<MustUse>(); //~ ERROR: unused `MustUse` that must be used + foo::<MustUseMsg>(); //~ ERROR: unused `MustUseMsg` that must be used + //~^ NOTE: some message +} + +#[allow(unused_results, unused_must_use)] +fn test2() { + foo::<isize>(); + foo::<MustUse>(); + foo::<MustUseMsg>(); +} + +fn main() { + foo::<isize>(); //~ ERROR: unused result of type `isize` + foo::<MustUse>(); //~ ERROR: unused `MustUse` that must be used + foo::<MustUseMsg>(); //~ ERROR: unused `MustUseMsg` that must be used + //~^ NOTE: some message + + let _ = foo::<isize>(); + let _ = foo::<MustUse>(); + let _ = foo::<MustUseMsg>(); +} diff --git a/tests/ui/lint/unused/unused-result.stderr b/tests/ui/lint/unused/unused-result.stderr new file mode 100644 index 000000000..4e1ba1fd9 --- /dev/null +++ b/tests/ui/lint/unused/unused-result.stderr @@ -0,0 +1,48 @@ +error: unused `MustUse` that must be used + --> $DIR/unused-result.rs:21:5 + | +LL | foo::<MustUse>(); + | ^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-result.rs:2:25 + | +LL | #![deny(unused_results, unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused `MustUseMsg` that must be used + --> $DIR/unused-result.rs:22:5 + | +LL | foo::<MustUseMsg>(); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: some message + +error: unused result of type `isize` + --> $DIR/unused-result.rs:34:5 + | +LL | foo::<isize>(); + | ^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-result.rs:2:9 + | +LL | #![deny(unused_results, unused_must_use)] + | ^^^^^^^^^^^^^^ + +error: unused `MustUse` that must be used + --> $DIR/unused-result.rs:35:5 + | +LL | foo::<MustUse>(); + | ^^^^^^^^^^^^^^^^ + +error: unused `MustUseMsg` that must be used + --> $DIR/unused-result.rs:36:5 + | +LL | foo::<MustUseMsg>(); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: some message + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/unused/unused-supertrait.rs b/tests/ui/lint/unused/unused-supertrait.rs new file mode 100644 index 000000000..64a8e5204 --- /dev/null +++ b/tests/ui/lint/unused/unused-supertrait.rs @@ -0,0 +1,11 @@ +#![deny(unused_must_use)] + +fn it() -> impl ExactSizeIterator<Item = ()> { + let x: Box<dyn ExactSizeIterator<Item = ()>> = todo!(); + x +} + +fn main() { + it(); + //~^ ERROR unused implementer of `Iterator` that must be used +} diff --git a/tests/ui/lint/unused/unused-supertrait.stderr b/tests/ui/lint/unused/unused-supertrait.stderr new file mode 100644 index 000000000..cb45add9c --- /dev/null +++ b/tests/ui/lint/unused/unused-supertrait.stderr @@ -0,0 +1,15 @@ +error: unused implementer of `Iterator` that must be used + --> $DIR/unused-supertrait.rs:9:5 + | +LL | it(); + | ^^^^ + | + = note: iterators are lazy and do nothing unless consumed +note: the lint level is defined here + --> $DIR/unused-supertrait.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/unused_attributes-must_use.rs b/tests/ui/lint/unused/unused_attributes-must_use.rs new file mode 100644 index 000000000..51f868706 --- /dev/null +++ b/tests/ui/lint/unused/unused_attributes-must_use.rs @@ -0,0 +1,131 @@ +#![allow(dead_code, path_statements)] +#![deny(unused_attributes, unused_must_use)] +#![feature(asm_experimental_arch, stmt_expr_attributes, trait_alias)] + +#[must_use] //~ ERROR `#[must_use]` has no effect +extern crate std as std2; + +#[must_use] //~ ERROR `#[must_use]` has no effect +mod test_mod {} + +#[must_use] //~ ERROR `#[must_use]` has no effect +use std::arch::global_asm; + +#[must_use] //~ ERROR `#[must_use]` has no effect +const CONST: usize = 4; +#[must_use] //~ ERROR `#[must_use]` has no effect +#[no_mangle] +static STATIC: usize = 4; + +#[must_use] +struct X; + +#[must_use] +enum Y { + Z, +} + +#[must_use] +union U { + unit: (), +} + +#[must_use] //~ ERROR `#[must_use]` has no effect +impl U { + #[must_use] + fn method() -> i32 { + 4 + } +} + +#[must_use] +#[no_mangle] +fn foo() -> i64 { + 4 +} + +#[must_use] //~ ERROR `#[must_use]` has no effect +extern "Rust" { + #[link_name = "STATIC"] + #[must_use] //~ ERROR `#[must_use]` has no effect + static FOREIGN_STATIC: usize; + + #[link_name = "foo"] + #[must_use] + fn foreign_foo() -> i64; +} + +#[must_use] //~ ERROR unused attribute +global_asm!(""); + +#[must_use] //~ ERROR `#[must_use]` has no effect +type UseMe = (); + +fn qux<#[must_use] T>(_: T) {} //~ ERROR `#[must_use]` has no effect + +#[must_use] +trait Use { + #[must_use] //~ ERROR `#[must_use]` has no effect + const ASSOC_CONST: usize = 4; + #[must_use] //~ ERROR `#[must_use]` has no effect + type AssocTy; + + #[must_use] + fn get_four(&self) -> usize { + 4 + } +} + +#[must_use] //~ ERROR `#[must_use]` has no effect +impl Use for () { + type AssocTy = (); +} + +#[must_use] //~ ERROR `#[must_use]` has no effect +trait Alias = Use; + +#[must_use] //~ ERROR `#[must_use]` has no effect +macro_rules! cool_macro { + () => { + 4 + }; +} + +fn main() { + #[must_use] //~ ERROR `#[must_use]` has no effect + let x = || {}; + x(); + + let x = #[must_use] //~ ERROR `#[must_use]` has no effect + || {}; + x(); + + X; //~ ERROR that must be used + Y::Z; //~ ERROR that must be used + U { unit: () }; //~ ERROR that must be used + U::method(); //~ ERROR that must be used + foo(); //~ ERROR that must be used + + unsafe { + foreign_foo(); //~ ERROR that must be used + }; + + CONST; + STATIC; + unsafe { FOREIGN_STATIC }; + cool_macro!(); + qux(4); + ().get_four(); //~ ERROR that must be used + + match Some(4) { + #[must_use] //~ ERROR `#[must_use]` has no effect + Some(res) => res, + None => 0, + }; + + struct PatternField { + foo: i32, + } + let s = PatternField { #[must_use] foo: 123 }; //~ ERROR `#[must_use]` has no effect + let PatternField { #[must_use] foo } = s; //~ ERROR `#[must_use]` has no effect +} diff --git a/tests/ui/lint/unused/unused_attributes-must_use.stderr b/tests/ui/lint/unused/unused_attributes-must_use.stderr new file mode 100644 index 000000000..0f699429e --- /dev/null +++ b/tests/ui/lint/unused/unused_attributes-must_use.stderr @@ -0,0 +1,187 @@ +error: unused attribute `must_use` + --> $DIR/unused_attributes-must_use.rs:58:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + | +note: the built-in attribute `must_use` will be ignored, since it's applied to the macro invocation `global_asm` + --> $DIR/unused_attributes-must_use.rs:59:1 + | +LL | global_asm!(""); + | ^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/unused_attributes-must_use.rs:2:9 + | +LL | #![deny(unused_attributes, unused_must_use)] + | ^^^^^^^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to an extern crate + --> $DIR/unused_attributes-must_use.rs:5:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a module + --> $DIR/unused_attributes-must_use.rs:8:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a use + --> $DIR/unused_attributes-must_use.rs:11:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a constant item + --> $DIR/unused_attributes-must_use.rs:14:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a static item + --> $DIR/unused_attributes-must_use.rs:16:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to an implementation block + --> $DIR/unused_attributes-must_use.rs:33:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a foreign module + --> $DIR/unused_attributes-must_use.rs:47:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a type alias + --> $DIR/unused_attributes-must_use.rs:61:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a type parameter + --> $DIR/unused_attributes-must_use.rs:64:8 + | +LL | fn qux<#[must_use] T>(_: T) {} + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to an implementation block + --> $DIR/unused_attributes-must_use.rs:79:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a trait alias + --> $DIR/unused_attributes-must_use.rs:84:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a macro def + --> $DIR/unused_attributes-must_use.rs:87:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a statement + --> $DIR/unused_attributes-must_use.rs:95:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a closure + --> $DIR/unused_attributes-must_use.rs:99:13 + | +LL | let x = #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to an match arm + --> $DIR/unused_attributes-must_use.rs:121:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a struct field + --> $DIR/unused_attributes-must_use.rs:129:28 + | +LL | let s = PatternField { #[must_use] foo: 123 }; + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a pattern field + --> $DIR/unused_attributes-must_use.rs:130:24 + | +LL | let PatternField { #[must_use] foo } = s; + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to an associated const + --> $DIR/unused_attributes-must_use.rs:68:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to an associated type + --> $DIR/unused_attributes-must_use.rs:70:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a foreign static item + --> $DIR/unused_attributes-must_use.rs:50:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: unused `X` that must be used + --> $DIR/unused_attributes-must_use.rs:103:5 + | +LL | X; + | ^ + | +note: the lint level is defined here + --> $DIR/unused_attributes-must_use.rs:2:28 + | +LL | #![deny(unused_attributes, unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused `Y` that must be used + --> $DIR/unused_attributes-must_use.rs:104:5 + | +LL | Y::Z; + | ^^^^ + +error: unused `U` that must be used + --> $DIR/unused_attributes-must_use.rs:105:5 + | +LL | U { unit: () }; + | ^^^^^^^^^^^^^^ + +error: unused return value of `U::method` that must be used + --> $DIR/unused_attributes-must_use.rs:106:5 + | +LL | U::method(); + | ^^^^^^^^^^^ + +error: unused return value of `foo` that must be used + --> $DIR/unused_attributes-must_use.rs:107:5 + | +LL | foo(); + | ^^^^^ + +error: unused return value of `foreign_foo` that must be used + --> $DIR/unused_attributes-must_use.rs:110:9 + | +LL | foreign_foo(); + | ^^^^^^^^^^^^^ + +error: unused return value of `Use::get_four` that must be used + --> $DIR/unused_attributes-must_use.rs:118:5 + | +LL | ().get_four(); + | ^^^^^^^^^^^^^ + +error: aborting due to 28 previous errors + diff --git a/tests/ui/lint/unused/useless-comment.rs b/tests/ui/lint/unused/useless-comment.rs new file mode 100644 index 000000000..7d2e5ab6f --- /dev/null +++ b/tests/ui/lint/unused/useless-comment.rs @@ -0,0 +1,45 @@ +#![feature(stmt_expr_attributes)] + +#![deny(unused_doc_comments)] + +macro_rules! mac { + () => {} +} + +/// foo //~ ERROR unused doc comment +mac!(); + +fn foo() { + /// a //~ ERROR unused doc comment + let x = 12; + + /// multi-line //~ unused doc comment + /// doc comment + /// that is unused + match x { + /// c //~ ERROR unused doc comment + 1 => {}, + _ => {} + } + + /// foo //~ ERROR unused doc comment + unsafe {} + + #[doc = "foo"] //~ ERROR unused doc comment + #[doc = "bar"] //~ ERROR unused doc comment + 3; + + /// bar //~ ERROR unused doc comment + mac!(); + + let x = /** comment */ 47; //~ ERROR unused doc comment + + /// dox //~ ERROR unused doc comment + { + + } +} + +fn main() { + foo(); +} diff --git a/tests/ui/lint/unused/useless-comment.stderr b/tests/ui/lint/unused/useless-comment.stderr new file mode 100644 index 000000000..8bb5bdaeb --- /dev/null +++ b/tests/ui/lint/unused/useless-comment.stderr @@ -0,0 +1,110 @@ +error: unused doc comment + --> $DIR/useless-comment.rs:9:1 + | +LL | /// foo + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macro invocations + | + = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion +note: the lint level is defined here + --> $DIR/useless-comment.rs:3:9 + | +LL | #![deny(unused_doc_comments)] + | ^^^^^^^^^^^^^^^^^^^ + +error: unused doc comment + --> $DIR/useless-comment.rs:32:5 + | +LL | /// bar + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macro invocations + | + = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion + +error: unused doc comment + --> $DIR/useless-comment.rs:13:5 + | +LL | /// a + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = 12; + | ----------- rustdoc does not generate documentation for statements + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:16:5 + | +LL | / /// multi-line +LL | | /// doc comment +LL | | /// that is unused + | |______________________^ +LL | / match x { +LL | | /// c +LL | | 1 => {}, +LL | | _ => {} +LL | | } + | |_____- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:20:9 + | +LL | /// c + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | 1 => {}, + | ------- rustdoc does not generate documentation for match arms + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:25:5 + | +LL | /// foo + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe {} + | --------- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:28:5 + | +LL | #[doc = "foo"] + | ^^^^^^^^^^^^^^ +LL | #[doc = "bar"] +LL | 3; + | - rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:29:5 + | +LL | #[doc = "bar"] + | ^^^^^^^^^^^^^^ +LL | 3; + | - rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:35:13 + | +LL | let x = /** comment */ 47; + | ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions + | + = help: use `/* */` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:37:5 + | +LL | /// dox + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / { +LL | | +LL | | } + | |_____- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: aborting due to 10 previous errors + diff --git a/tests/ui/lint/unused_braces.fixed b/tests/ui/lint/unused_braces.fixed new file mode 100644 index 000000000..e691fb37e --- /dev/null +++ b/tests/ui/lint/unused_braces.fixed @@ -0,0 +1,57 @@ +// check-pass +// run-rustfix + +#![warn(unused_braces, unused_parens)] +#![allow(unreachable_code, unused_unsafe)] // for rustfix + +fn consume<T>(_: T) {} + +fn main() { + let _ = 7; + //~^WARN unnecessary parentheses + + // Do not emit a lint in these cases, + // as we have to be careful with + // `ref` patterns. + { + let _ = { 7 }; + + if let 7 = { 7 } { } + + match { 7 } { + _ => (), + } + } + + if true { + //~^ WARN unnecessary braces + } + + while false { + //~^ WARN unnecessary braces + } + + let _: [u8; 3]; + //~^ WARN unnecessary braces + + consume(7); + //~^ WARN unnecessary braces + + // Do not emit lint for multiline blocks. + let _ = { + 7 + }; + + // Do not emit lint for unsafe blocks. + let _ = unsafe { 7 }; + + // Do not emit lint, as the `{` would then + // be parsed as part of the `return`. + if { return } { + + } + + // regression test for https://github.com/rust-lang/rust/issues/106899 + return println!("!"); + //~^ WARN unnecessary braces +} diff --git a/tests/ui/lint/unused_braces.rs b/tests/ui/lint/unused_braces.rs new file mode 100644 index 000000000..0d260d2cb --- /dev/null +++ b/tests/ui/lint/unused_braces.rs @@ -0,0 +1,57 @@ +// check-pass +// run-rustfix + +#![warn(unused_braces, unused_parens)] +#![allow(unreachable_code, unused_unsafe)] // for rustfix + +fn consume<T>(_: T) {} + +fn main() { + let _ = (7); + //~^WARN unnecessary parentheses + + // Do not emit a lint in these cases, + // as we have to be careful with + // `ref` patterns. + { + let _ = { 7 }; + + if let 7 = { 7 } { } + + match { 7 } { + _ => (), + } + } + + if { true } { + //~^ WARN unnecessary braces + } + + while { false } { + //~^ WARN unnecessary braces + } + + let _: [u8; { 3 }]; + //~^ WARN unnecessary braces + + consume({ 7 }); + //~^ WARN unnecessary braces + + // Do not emit lint for multiline blocks. + let _ = { + 7 + }; + + // Do not emit lint for unsafe blocks. + let _ = unsafe { 7 }; + + // Do not emit lint, as the `{` would then + // be parsed as part of the `return`. + if { return } { + + } + + // regression test for https://github.com/rust-lang/rust/issues/106899 + return { println!("!") }; + //~^ WARN unnecessary braces +} diff --git a/tests/ui/lint/unused_braces.stderr b/tests/ui/lint/unused_braces.stderr new file mode 100644 index 000000000..0b4a1c321 --- /dev/null +++ b/tests/ui/lint/unused_braces.stderr @@ -0,0 +1,84 @@ +warning: unnecessary parentheses around assigned value + --> $DIR/unused_braces.rs:10:13 + | +LL | let _ = (7); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/unused_braces.rs:4:24 + | +LL | #![warn(unused_braces, unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let _ = (7); +LL + let _ = 7; + | + +warning: unnecessary braces around `if` condition + --> $DIR/unused_braces.rs:26:8 + | +LL | if { true } { + | ^^ ^^ + | +note: the lint level is defined here + --> $DIR/unused_braces.rs:4:9 + | +LL | #![warn(unused_braces, unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - if { true } { +LL + if true { + | + +warning: unnecessary braces around `while` condition + --> $DIR/unused_braces.rs:30:11 + | +LL | while { false } { + | ^^ ^^ + | +help: remove these braces + | +LL - while { false } { +LL + while false { + | + +warning: unnecessary braces around const expression + --> $DIR/unused_braces.rs:34:17 + | +LL | let _: [u8; { 3 }]; + | ^^ ^^ + | +help: remove these braces + | +LL - let _: [u8; { 3 }]; +LL + let _: [u8; 3]; + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces.rs:37:13 + | +LL | consume({ 7 }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume({ 7 }); +LL + consume(7); + | + +warning: unnecessary braces around `return` value + --> $DIR/unused_braces.rs:55:12 + | +LL | return { println!("!") }; + | ^^ ^^ + | +help: remove these braces + | +LL - return { println!("!") }; +LL + return println!("!"); + | + +warning: 6 warnings emitted + diff --git a/tests/ui/lint/unused_braces_borrow.fixed b/tests/ui/lint/unused_braces_borrow.fixed new file mode 100644 index 000000000..583506f89 --- /dev/null +++ b/tests/ui/lint/unused_braces_borrow.fixed @@ -0,0 +1,26 @@ +// check-pass +// run-rustfix + +#![warn(unused_braces)] + +// changing `&{ expr }` to `&expr` changes the semantic of the program +// so we should not warn this case + +#[repr(packed)] +pub struct A { + pub a: u8, + pub b: u32, +} + +fn consume<T>(_: T) {} + +fn main() { + let a = A { + a: 42, + b: 1729, + }; + + consume(&{ a.b }); + consume(a.b); + //~^ WARN unnecessary braces +} diff --git a/tests/ui/lint/unused_braces_borrow.rs b/tests/ui/lint/unused_braces_borrow.rs new file mode 100644 index 000000000..b7c529d73 --- /dev/null +++ b/tests/ui/lint/unused_braces_borrow.rs @@ -0,0 +1,26 @@ +// check-pass +// run-rustfix + +#![warn(unused_braces)] + +// changing `&{ expr }` to `&expr` changes the semantic of the program +// so we should not warn this case + +#[repr(packed)] +pub struct A { + pub a: u8, + pub b: u32, +} + +fn consume<T>(_: T) {} + +fn main() { + let a = A { + a: 42, + b: 1729, + }; + + consume(&{ a.b }); + consume({ a.b }); + //~^ WARN unnecessary braces +} diff --git a/tests/ui/lint/unused_braces_borrow.stderr b/tests/ui/lint/unused_braces_borrow.stderr new file mode 100644 index 000000000..05f7432b8 --- /dev/null +++ b/tests/ui/lint/unused_braces_borrow.stderr @@ -0,0 +1,19 @@ +warning: unnecessary braces around function argument + --> $DIR/unused_braces_borrow.rs:24:13 + | +LL | consume({ a.b }); + | ^^ ^^ + | +note: the lint level is defined here + --> $DIR/unused_braces_borrow.rs:4:9 + | +LL | #![warn(unused_braces)] + | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - consume({ a.b }); +LL + consume(a.b); + | + +warning: 1 warning emitted + diff --git a/tests/ui/lint/unused_braces_macro.rs b/tests/ui/lint/unused_braces_macro.rs new file mode 100644 index 000000000..bfee95378 --- /dev/null +++ b/tests/ui/lint/unused_braces_macro.rs @@ -0,0 +1,6 @@ +// build-pass +pub fn foo<const BAR: bool> () {} + +fn main() { + foo::<{cfg!(feature = "foo")}>(); +} diff --git a/tests/ui/lint/unused_import_warning_issue_45268.rs b/tests/ui/lint/unused_import_warning_issue_45268.rs new file mode 100644 index 000000000..5ae482863 --- /dev/null +++ b/tests/ui/lint/unused_import_warning_issue_45268.rs @@ -0,0 +1,49 @@ +// check-pass + +#![warn(unused_imports)] // Warning explanation here, it's OK + +mod test { + pub trait A { + fn a(); + } + + impl A for () { + fn a() { } + } + + pub trait B { + fn b(self); + } + + impl B for () { + fn b(self) { } + } + + pub trait Unused { + } +} + +use test::Unused; // This is really unused, so warning is OK + //~^ WARNING unused import +use test::A; // This is used by the test2::func() through import of super::* +use test::B; // This is used by the test2::func() through import of super::* + +mod test2 { + use super::*; + pub fn func() { + let _ = <()>::a(); + let _ = ().b(); + test3::inner_func(); + } + mod test3 { + use super::*; + pub fn inner_func() { + let _ = <()>::a(); + let _ = ().b(); + } + } +} + +fn main() { + test2::func(); +} diff --git a/tests/ui/lint/unused_import_warning_issue_45268.stderr b/tests/ui/lint/unused_import_warning_issue_45268.stderr new file mode 100644 index 000000000..fa8699abc --- /dev/null +++ b/tests/ui/lint/unused_import_warning_issue_45268.stderr @@ -0,0 +1,14 @@ +warning: unused import: `test::Unused` + --> $DIR/unused_import_warning_issue_45268.rs:26:5 + | +LL | use test::Unused; // This is really unused, so warning is OK + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused_import_warning_issue_45268.rs:3:9 + | +LL | #![warn(unused_imports)] // Warning explanation here, it's OK + | ^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/unused_labels.rs b/tests/ui/lint/unused_labels.rs new file mode 100644 index 000000000..87a5392fd --- /dev/null +++ b/tests/ui/lint/unused_labels.rs @@ -0,0 +1,85 @@ +// The output should warn when a loop label is not used. However, it +// should also deal with the edge cases where a label is shadowed, +// within nested loops + +// check-pass + +#![warn(unused_labels)] + +fn main() { + 'unused_while_label: while 0 == 0 { + //~^ WARN unused label + } + + let opt = Some(0); + 'unused_while_let_label: while let Some(_) = opt { + //~^ WARN unused label + } + + 'unused_for_label: for _ in 0..10 { + //~^ WARN unused label + } + + 'used_loop_label: loop { + break 'used_loop_label; + } + + 'used_loop_label_outer_1: for _ in 0..10 { + 'used_loop_label_inner_1: for _ in 0..10 { + break 'used_loop_label_inner_1; + } + break 'used_loop_label_outer_1; + } + + 'used_loop_label_outer_2: for _ in 0..10 { + 'unused_loop_label_inner_2: for _ in 0..10 { + //~^ WARN unused label + break 'used_loop_label_outer_2; + } + } + + 'unused_loop_label_outer_3: for _ in 0..10 { + //~^ WARN unused label + 'used_loop_label_inner_3: for _ in 0..10 { + break 'used_loop_label_inner_3; + } + } + + // You should be able to break the same label many times + 'many_used: loop { + if true { + break 'many_used; + } else { + break 'many_used; + } + } + + // Test breaking many times with the same inner label doesn't break the + // warning on the outer label + 'many_used_shadowed: for _ in 0..10 { + //~^ WARN unused label + 'many_used_shadowed: for _ in 0..10 { + //~^ WARN label name `'many_used_shadowed` shadows a label name that is already in scope + if 1 % 2 == 0 { + break 'many_used_shadowed; + } else { + break 'many_used_shadowed; + } + } + } + + 'unused_loop_label: loop { + //~^ WARN unused label + break; + } + + // Make sure unused block labels give warnings... + 'unused_block_label: { + //~^ WARN unused label + } + + // ...and that used ones don't: + 'used_block_label: { + break 'used_block_label; + } +} diff --git a/tests/ui/lint/unused_labels.stderr b/tests/ui/lint/unused_labels.stderr new file mode 100644 index 000000000..846da792b --- /dev/null +++ b/tests/ui/lint/unused_labels.stderr @@ -0,0 +1,65 @@ +warning: label name `'many_used_shadowed` shadows a label name that is already in scope + --> $DIR/unused_labels.rs:61:9 + | +LL | 'many_used_shadowed: for _ in 0..10 { + | ------------------- first declared here +LL | +LL | 'many_used_shadowed: for _ in 0..10 { + | ^^^^^^^^^^^^^^^^^^^ label `'many_used_shadowed` already in scope + +warning: unused label + --> $DIR/unused_labels.rs:10:5 + | +LL | 'unused_while_label: while 0 == 0 { + | ^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused_labels.rs:7:9 + | +LL | #![warn(unused_labels)] + | ^^^^^^^^^^^^^ + +warning: unused label + --> $DIR/unused_labels.rs:15:5 + | +LL | 'unused_while_let_label: while let Some(_) = opt { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused label + --> $DIR/unused_labels.rs:19:5 + | +LL | 'unused_for_label: for _ in 0..10 { + | ^^^^^^^^^^^^^^^^^ + +warning: unused label + --> $DIR/unused_labels.rs:35:9 + | +LL | 'unused_loop_label_inner_2: for _ in 0..10 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused label + --> $DIR/unused_labels.rs:41:5 + | +LL | 'unused_loop_label_outer_3: for _ in 0..10 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused label + --> $DIR/unused_labels.rs:59:5 + | +LL | 'many_used_shadowed: for _ in 0..10 { + | ^^^^^^^^^^^^^^^^^^^ + +warning: unused label + --> $DIR/unused_labels.rs:71:5 + | +LL | 'unused_loop_label: loop { + | ^^^^^^^^^^^^^^^^^^ + +warning: unused label + --> $DIR/unused_labels.rs:77:5 + | +LL | 'unused_block_label: { + | ^^^^^^^^^^^^^^^^^^^ + +warning: 9 warnings emitted + diff --git a/tests/ui/lint/unused_parens_json_suggestion.fixed b/tests/ui/lint/unused_parens_json_suggestion.fixed new file mode 100644 index 000000000..c40045404 --- /dev/null +++ b/tests/ui/lint/unused_parens_json_suggestion.fixed @@ -0,0 +1,26 @@ +// compile-flags: --error-format json +// run-rustfix + +// The output for humans should just highlight the whole span without showing +// the suggested replacement, but we also want to test that suggested +// replacement only removes one set of parentheses, rather than naïvely +// stripping away any starting or ending parenthesis characters—hence this +// test of the JSON error format. + +#![deny(unused_parens)] +#![allow(unreachable_code)] + +fn main() { + // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not + // the malformed `1 / (2 + 3` + let _a = 1 / (2 + 3); //~ERROR unnecessary parentheses + f(); +} + +fn f() -> bool { + loop { + if (break { return true }) { + } + } + false +} diff --git a/tests/ui/lint/unused_parens_json_suggestion.rs b/tests/ui/lint/unused_parens_json_suggestion.rs new file mode 100644 index 000000000..962c8bdd7 --- /dev/null +++ b/tests/ui/lint/unused_parens_json_suggestion.rs @@ -0,0 +1,26 @@ +// compile-flags: --error-format json +// run-rustfix + +// The output for humans should just highlight the whole span without showing +// the suggested replacement, but we also want to test that suggested +// replacement only removes one set of parentheses, rather than naïvely +// stripping away any starting or ending parenthesis characters—hence this +// test of the JSON error format. + +#![deny(unused_parens)] +#![allow(unreachable_code)] + +fn main() { + // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not + // the malformed `1 / (2 + 3` + let _a = (1 / (2 + 3)); //~ERROR unnecessary parentheses + f(); +} + +fn f() -> bool { + loop { + if (break { return true }) { + } + } + false +} diff --git a/tests/ui/lint/unused_parens_json_suggestion.stderr b/tests/ui/lint/unused_parens_json_suggestion.stderr new file mode 100644 index 000000000..ea19e0cdc --- /dev/null +++ b/tests/ui/lint/unused_parens_json_suggestion.stderr @@ -0,0 +1,21 @@ +{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":577,"byte_end":578,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3)); + --> $DIR/unused_parens_json_suggestion.rs:16:14 + | +LL | let _a = (1 / (2 + 3)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/unused_parens_json_suggestion.rs:10:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let _a = (1 / (2 + 3)); +LL + let _a = 1 / (2 + 3); + | + +"} +{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error + +"} diff --git a/tests/ui/lint/unused_parens_multibyte_recovery.rs b/tests/ui/lint/unused_parens_multibyte_recovery.rs new file mode 100644 index 000000000..8fcfae22a --- /dev/null +++ b/tests/ui/lint/unused_parens_multibyte_recovery.rs @@ -0,0 +1,11 @@ +// ignore-tidy-trailing-newlines +// +// error-pattern: this file contains an unclosed delimiter +// error-pattern: this file contains an unclosed delimiter +// error-pattern: this file contains an unclosed delimiter +// error-pattern: format argument must be a string literal +// +// Verify that unused parens lint does not try to create a span +// which points in the middle of a multibyte character. + +fn f(){(print!(á
\ No newline at end of file diff --git a/tests/ui/lint/unused_parens_multibyte_recovery.stderr b/tests/ui/lint/unused_parens_multibyte_recovery.stderr new file mode 100644 index 000000000..a0302b17e --- /dev/null +++ b/tests/ui/lint/unused_parens_multibyte_recovery.stderr @@ -0,0 +1,43 @@ +error: this file contains an unclosed delimiter + --> $DIR/unused_parens_multibyte_recovery.rs:11:17 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/unused_parens_multibyte_recovery.rs:11:17 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/unused_parens_multibyte_recovery.rs:11:17 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: format argument must be a string literal + --> $DIR/unused_parens_multibyte_recovery.rs:11:16 + | +LL | fn f(){(print!(á + | ^ + | +help: you might be missing a string literal to format with + | +LL | fn f(){(print!("{}", á + | +++++ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/unused_parens_remove_json_suggestion.fixed b/tests/ui/lint/unused_parens_remove_json_suggestion.fixed new file mode 100644 index 000000000..8a57cd573 --- /dev/null +++ b/tests/ui/lint/unused_parens_remove_json_suggestion.fixed @@ -0,0 +1,61 @@ +// compile-flags: --error-format json +// run-rustfix + +// The output for humans should just highlight the whole span without showing +// the suggested replacement, but we also want to test that suggested +// replacement only removes one set of parentheses, rather than naïvely +// stripping away any starting or ending parenthesis characters—hence this +// test of the JSON error format. + +#![deny(unused_parens)] +#![allow(unreachable_code)] + +fn main() { + + let _b = false; + + if _b { //~ ERROR unnecessary parentheses + println!("hello"); + } + + f(); + +} + +fn f() -> bool { + let c = false; + + if c { //~ ERROR unnecessary parentheses + println!("next"); + } + + if c { //~ ERROR unnecessary parentheses + println!("prev"); + } + + while false && true { + if c { //~ ERROR unnecessary parentheses + println!("norm"); + } + + } + + while true && false { //~ ERROR unnecessary parentheses + for _ in 0 .. 3 { //~ ERROR unnecessary parentheses + println!("e~") + } + } + + for _ in 0 .. 3 { //~ ERROR unnecessary parentheses + while true && false { //~ ERROR unnecessary parentheses + println!("e~") + } + } + + + loop { + if (break { return true }) { + } + } + false +} diff --git a/tests/ui/lint/unused_parens_remove_json_suggestion.rs b/tests/ui/lint/unused_parens_remove_json_suggestion.rs new file mode 100644 index 000000000..952332d54 --- /dev/null +++ b/tests/ui/lint/unused_parens_remove_json_suggestion.rs @@ -0,0 +1,61 @@ +// compile-flags: --error-format json +// run-rustfix + +// The output for humans should just highlight the whole span without showing +// the suggested replacement, but we also want to test that suggested +// replacement only removes one set of parentheses, rather than naïvely +// stripping away any starting or ending parenthesis characters—hence this +// test of the JSON error format. + +#![deny(unused_parens)] +#![allow(unreachable_code)] + +fn main() { + + let _b = false; + + if (_b) { //~ ERROR unnecessary parentheses + println!("hello"); + } + + f(); + +} + +fn f() -> bool { + let c = false; + + if(c) { //~ ERROR unnecessary parentheses + println!("next"); + } + + if (c){ //~ ERROR unnecessary parentheses + println!("prev"); + } + + while (false && true){ + if (c) { //~ ERROR unnecessary parentheses + println!("norm"); + } + + } + + while(true && false) { //~ ERROR unnecessary parentheses + for _ in (0 .. 3){ //~ ERROR unnecessary parentheses + println!("e~") + } + } + + for _ in (0 .. 3) { //~ ERROR unnecessary parentheses + while (true && false) { //~ ERROR unnecessary parentheses + println!("e~") + } + } + + + loop { + if (break { return true }) { + } + } + false +} diff --git a/tests/ui/lint/unused_parens_remove_json_suggestion.stderr b/tests/ui/lint/unused_parens_remove_json_suggestion.stderr new file mode 100644 index 000000000..f4c6ceaf1 --- /dev/null +++ b/tests/ui/lint/unused_parens_remove_json_suggestion.stderr @@ -0,0 +1,125 @@ +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":481,"byte_end":482,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) { + --> $DIR/unused_parens_remove_json_suggestion.rs:17:8 + | +LL | if (_b) { + | ^ ^ + | +note: the lint level is defined here + --> $DIR/unused_parens_remove_json_suggestion.rs:10:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - if (_b) { +LL + if _b { + | + +"} +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":612,"byte_end":613,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) { + --> $DIR/unused_parens_remove_json_suggestion.rs:28:7 + | +LL | if(c) { + | ^ ^ + | +help: remove these parentheses + | +LL - if(c) { +LL + if c { + | + +"} +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":692,"byte_end":693,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){ + --> $DIR/unused_parens_remove_json_suggestion.rs:32:8 + | +LL | if (c){ + | ^ ^ + | +help: remove these parentheses + | +LL - if (c){ +LL + if c { + | + +"} +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition + --> $DIR/unused_parens_remove_json_suggestion.rs:36:11 + | +LL | while (false && true){ + | ^ ^ + | +help: remove these parentheses + | +LL - while (false && true){ +LL + while false && true { + | + +"} +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":802,"byte_end":803,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) { + --> $DIR/unused_parens_remove_json_suggestion.rs:37:12 + | +LL | if (c) { + | ^ ^ + | +help: remove these parentheses + | +LL - if (c) { +LL + if c { + | + +"} +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":899,"byte_end":900,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) { + --> $DIR/unused_parens_remove_json_suggestion.rs:43:10 + | +LL | while(true && false) { + | ^ ^ + | +help: remove these parentheses + | +LL - while(true && false) { +LL + while true && false { + | + +"} +{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":968,"byte_end":969,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){ + --> $DIR/unused_parens_remove_json_suggestion.rs:44:18 + | +LL | for _ in (0 .. 3){ + | ^ ^ + | +help: remove these parentheses + | +LL - for _ in (0 .. 3){ +LL + for _ in 0 .. 3 { + | + +"} +{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1069,"byte_end":1070,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) { + --> $DIR/unused_parens_remove_json_suggestion.rs:49:14 + | +LL | for _ in (0 .. 3) { + | ^ ^ + | +help: remove these parentheses + | +LL - for _ in (0 .. 3) { +LL + for _ in 0 .. 3 { + | + +"} +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1128,"byte_end":1129,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) { + --> $DIR/unused_parens_remove_json_suggestion.rs:50:15 + | +LL | while (true && false) { + | ^ ^ + | +help: remove these parentheses + | +LL - while (true && false) { +LL + while true && false { + | + +"} +{"message":"aborting due to 9 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 9 previous errors + +"} diff --git a/tests/ui/lint/unused_variables-issue-82488.fixed b/tests/ui/lint/unused_variables-issue-82488.fixed new file mode 100644 index 000000000..3cb2c90d0 --- /dev/null +++ b/tests/ui/lint/unused_variables-issue-82488.fixed @@ -0,0 +1,16 @@ +// run-rustfix +#![deny(unused_variables)] + +struct Point { + x: u32, + y: u32 +} + +fn process_point(Point { x, y: _renamed }: Point) { +//~^ ERROR unused variable: `renamed` + let _ = x; +} + +fn main() { + process_point(Point { x: 0, y: 0 }); +} diff --git a/tests/ui/lint/unused_variables-issue-82488.rs b/tests/ui/lint/unused_variables-issue-82488.rs new file mode 100644 index 000000000..007b0799b --- /dev/null +++ b/tests/ui/lint/unused_variables-issue-82488.rs @@ -0,0 +1,16 @@ +// run-rustfix +#![deny(unused_variables)] + +struct Point { + x: u32, + y: u32 +} + +fn process_point(Point { x, y: renamed }: Point) { +//~^ ERROR unused variable: `renamed` + let _ = x; +} + +fn main() { + process_point(Point { x: 0, y: 0 }); +} diff --git a/tests/ui/lint/unused_variables-issue-82488.stderr b/tests/ui/lint/unused_variables-issue-82488.stderr new file mode 100644 index 000000000..dce03a0f7 --- /dev/null +++ b/tests/ui/lint/unused_variables-issue-82488.stderr @@ -0,0 +1,14 @@ +error: unused variable: `renamed` + --> $DIR/unused_variables-issue-82488.rs:9:32 + | +LL | fn process_point(Point { x, y: renamed }: Point) { + | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_renamed` + | +note: the lint level is defined here + --> $DIR/unused_variables-issue-82488.rs:2:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/use-redundant.rs b/tests/ui/lint/use-redundant.rs new file mode 100644 index 000000000..53315dcf6 --- /dev/null +++ b/tests/ui/lint/use-redundant.rs @@ -0,0 +1,27 @@ +// check-pass +#![warn(unused_imports)] + +use crate::foo::Bar; + +mod foo { + pub type Bar = i32; +} + +fn baz() -> Bar { + 3 +} + +mod m1 { pub struct S {} } +mod m2 { pub struct S {} } + +use m1::*; //~ WARNING unused import +use m2::*; //~ WARNING unused import + +fn main() { + use crate::foo::Bar; //~ WARNING imported redundantly + let _a: Bar = 3; + baz(); + + use m1::S; + let _s = S {}; +} diff --git a/tests/ui/lint/use-redundant.stderr b/tests/ui/lint/use-redundant.stderr new file mode 100644 index 000000000..c861a1956 --- /dev/null +++ b/tests/ui/lint/use-redundant.stderr @@ -0,0 +1,29 @@ +warning: unused import: `m1::*` + --> $DIR/use-redundant.rs:17:5 + | +LL | use m1::*; + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/use-redundant.rs:2:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +warning: unused import: `m2::*` + --> $DIR/use-redundant.rs:18:5 + | +LL | use m2::*; + | ^^^^^ + +warning: the item `Bar` is imported redundantly + --> $DIR/use-redundant.rs:21:9 + | +LL | use crate::foo::Bar; + | --------------- the item `Bar` is already imported here +... +LL | use crate::foo::Bar; + | ^^^^^^^^^^^^^^^ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/use_suggestion_json.rs b/tests/ui/lint/use_suggestion_json.rs new file mode 100644 index 000000000..7d641e08b --- /dev/null +++ b/tests/ui/lint/use_suggestion_json.rs @@ -0,0 +1,13 @@ +// ignore-windows +// ignore-sgx std::os::fortanix_sgx::usercalls::alloc::Iter changes compiler suggestions +// compile-flags: --error-format pretty-json --json=diagnostic-rendered-ansi + +// The output for humans should just highlight the whole span without showing +// the suggested replacement, but we also want to test that suggested +// replacement only removes one set of parentheses, rather than naïvely +// stripping away any starting or ending parenthesis characters—hence this +// test of the JSON error format. + +fn main() { + let x: Iter; +} diff --git a/tests/ui/lint/use_suggestion_json.stderr b/tests/ui/lint/use_suggestion_json.stderr new file mode 100644 index 000000000..d17514303 --- /dev/null +++ b/tests/ui/lint/use_suggestion_json.stderr @@ -0,0 +1,3 @@ +{"message":"`--error-format=pretty-json` is unstable","code":null,"level":"error","spans":[],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: `--error-format=pretty-json` is unstable\u001b[0m + +"} diff --git a/tests/ui/lint/warn-ctypes-inhibit.rs b/tests/ui/lint/warn-ctypes-inhibit.rs new file mode 100644 index 000000000..15d8b09d2 --- /dev/null +++ b/tests/ui/lint/warn-ctypes-inhibit.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(dead_code)] +// compile-flags:-D improper-ctypes + +// pretty-expanded FIXME #23616 +#![allow(improper_ctypes)] + +mod libc { + extern "C" { + pub fn malloc(size: isize) -> *const u8; + } +} + +pub fn main() {} diff --git a/tests/ui/lint/warn-path-statement.rs b/tests/ui/lint/warn-path-statement.rs new file mode 100644 index 000000000..2435be623 --- /dev/null +++ b/tests/ui/lint/warn-path-statement.rs @@ -0,0 +1,17 @@ +// compile-flags: -D path-statements +struct Droppy; + +impl Drop for Droppy { + fn drop(&mut self) {} +} + +fn main() { + let x = 10; + x; //~ ERROR path statement with no effect + + let y = Droppy; + y; //~ ERROR path statement drops value + + let z = (Droppy,); + z; //~ ERROR path statement drops value +} diff --git a/tests/ui/lint/warn-path-statement.stderr b/tests/ui/lint/warn-path-statement.stderr new file mode 100644 index 000000000..248d2ef29 --- /dev/null +++ b/tests/ui/lint/warn-path-statement.stderr @@ -0,0 +1,22 @@ +error: path statement with no effect + --> $DIR/warn-path-statement.rs:10:5 + | +LL | x; + | ^^ + | + = note: requested on the command line with `-D path-statements` + +error: path statement drops value + --> $DIR/warn-path-statement.rs:13:5 + | +LL | y; + | ^^ help: use `drop` to clarify the intent: `drop(y);` + +error: path statement drops value + --> $DIR/warn-path-statement.rs:16:5 + | +LL | z; + | ^^ help: use `drop` to clarify the intent: `drop(z);` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs new file mode 100644 index 000000000..4684fe145 --- /dev/null +++ b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs @@ -0,0 +1,13 @@ +#![deny(unused_attributes)] + +trait Trait { + #[inline] //~ ERROR `#[inline]` is ignored on function prototypes + fn foo(); +} + +extern "C" { + #[inline] //~ ERROR `#[inline]` is ignored on function prototypes + fn foo(); +} + +fn main() {} diff --git a/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr new file mode 100644 index 000000000..ab19d80e7 --- /dev/null +++ b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr @@ -0,0 +1,20 @@ +error: `#[inline]` is ignored on function prototypes + --> $DIR/warn-unused-inline-on-fn-prototypes.rs:4:5 + | +LL | #[inline] + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/warn-unused-inline-on-fn-prototypes.rs:1:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: `#[inline]` is ignored on function prototypes + --> $DIR/warn-unused-inline-on-fn-prototypes.rs:9:5 + | +LL | #[inline] + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + |