summaryrefslogtreecommitdiffstats
path: root/src/test/ui/lint/rfc-2383-lint-reason
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/lint/rfc-2383-lint-reason')
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs8
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs45
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs15
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr10
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs16
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs42
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr29
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs9
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr12
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs58
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr52
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs53
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr52
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs15
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.stderr10
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs155
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr16
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs39
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr38
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs34
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr51
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs11
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr11
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.rs48
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr40
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.rs49
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.stderr38
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs23
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs43
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs14
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr47
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs14
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr10
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs16
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout20
35 files changed, 1143 insertions, 0 deletions
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs b/src/test/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs
new file mode 100644
index 000000000..912e831d8
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs b/src/test/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs
new file mode 100644
index 000000000..6b255b799
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs b/src/test/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs
new file mode 100644
index 000000000..9f591ba98
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr b/src/test/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr
new file mode 100644
index 000000000..7237f6fb6
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs
new file mode 100644
index 000000000..b95815bc5
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs
new file mode 100644
index 000000000..07c60fa0c
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr
new file mode 100644
index 000000000..817e16fdc
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs
new file mode 100644
index 000000000..928e16106
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr
new file mode 100644
index 000000000..b5601cf9e
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs
new file mode 100644
index 000000000..dc9a719a3
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr
new file mode 100644
index 000000000..90ee744b2
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs
new file mode 100644
index 000000000..8f94bd6ec
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr
new file mode 100644
index 000000000..370e51bf7
--- /dev/null
+++ b/src/test/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: `#[warn(unfulfilled_lint_expectations)]` on by default
+ = note: this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered
+
+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/src/test/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs
new file mode 100644
index 000000000..5fdb71041
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.stderr
new file mode 100644
index 000000000..69f7cda08
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs
new file mode 100644
index 000000000..f80fe88cb
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr
new file mode 100644
index 000000000..6d49e7543
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs
new file mode 100644
index 000000000..d38e65533
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr
new file mode 100644
index 000000000..9bfee79b0
--- /dev/null
+++ b/src/test/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: `#[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
+
+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/src/test/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs
new file mode 100644
index 000000000..479ee198e
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr
new file mode 100644
index 000000000..a8116e934
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs
new file mode 100644
index 000000000..b4183d982
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr
new file mode 100644
index 000000000..82c1a4c08
--- /dev/null
+++ b/src/test/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: `#[warn(unfulfilled_lint_expectations)]` on by default
+ = note: <This should fail and display this reason>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.rs b/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.rs
new file mode 100644
index 000000000..a3c3933d7
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr b/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr
new file mode 100644
index 000000000..06befcbb5
--- /dev/null
+++ b/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr
@@ -0,0 +1,40 @@
+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: 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: 5 warnings emitted
+
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.rs b/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.rs
new file mode 100644
index 000000000..080e30023
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.stderr b/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.stderr
new file mode 100644
index 000000000..c74fabe27
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs b/src/test/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs
new file mode 100644
index 000000000..6624b930e
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs b/src/test/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs
new file mode 100644
index 000000000..5d928b3ca
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs b/src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs
new file mode 100644
index 000000000..bafdea96e
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr b/src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr
new file mode 100644
index 000000000..3bf8137dc
--- /dev/null
+++ b/src/test/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: the lint level is defined here
+ --> $DIR/lint-attribute-only-with-reason.rs:3:9
+ |
+LL | #![deny(unused_attributes)]
+ | ^^^^^^^^^^^^^^^^^
+ = note: attribute `allow` without any lints has no effect
+
+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/src/test/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs b/src/test/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs
new file mode 100644
index 000000000..98080b4e8
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr b/src/test/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr
new file mode 100644
index 000000000..df7d6584f
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs b/src/test/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs
new file mode 100644
index 000000000..2b6c3c6a1
--- /dev/null
+++ b/src/test/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/src/test/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout b/src/test/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout
new file mode 100644
index 000000000..0ee3a03c3
--- /dev/null
+++ b/src/test/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(); }