Skip to content

Commit 897404e

Browse files
committed
Support #[expect] attributes for rustdoc lints (RFC 2383)
1 parent fb225d1 commit 897404e

File tree

3 files changed

+189
-0
lines changed

3 files changed

+189
-0
lines changed

src/librustdoc/core.rs

+4
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@ crate fn create_config(
232232
rustc_lint::builtin::RENAMED_AND_REMOVED_LINTS.name.to_string(),
233233
rustc_lint::builtin::UNKNOWN_LINTS.name.to_string(),
234234
rustc_lint::builtin::UNEXPECTED_CFGS.name.to_string(),
235+
// this lint is needed to support `#[expect]` attributes
236+
rustc_lint::builtin::UNFULFILLED_LINT_EXPECTATIONS.name.to_string(),
235237
];
236238
lints_to_show.extend(crate::lint::RUSTDOC_LINTS.iter().map(|lint| lint.name.to_string()));
237239

@@ -463,6 +465,8 @@ crate fn run_global_ctxt(
463465
}
464466
}
465467

468+
tcx.sess.time("check_lint_expectations", || tcx.check_expectations(Some(sym::rustdoc)));
469+
466470
if tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() {
467471
rustc_errors::FatalError.raise();
468472
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// check-pass
2+
#![feature(lint_reasons)]
3+
4+
//! This file tests the `#[expect]` attribute implementation for tool lints. The same
5+
//! file is used to test clippy and rustdoc. Any changes to this file should be synced
6+
//! to the other test files as well.
7+
//!
8+
//! Expectations:
9+
//! * rustc: only rustc lint expectations are emitted
10+
//! * clippy: rustc and Clippy's expectations are emitted
11+
//! * rustdoc: only rustdoc lint expectations are emitted
12+
//!
13+
//! This test can't cover every lint from Clippy, rustdoc and potentially other
14+
//! tools that will be developed. This therefore only tests a small subset of lints
15+
16+
#![expect(rustdoc::missing_crate_level_docs)]
17+
//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
18+
//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default
19+
20+
mod rustc_ok {
21+
//! See <https://doc.rust-lang.org/rustc/lints/index.html>
22+
23+
#[expect(dead_code)]
24+
pub fn rustc_lints() {
25+
let x = 42.0;
26+
27+
#[expect(illegal_floating_point_literal_pattern)]
28+
match x {
29+
5.0 => {}
30+
6.0 => {}
31+
_ => {}
32+
}
33+
}
34+
}
35+
36+
mod rustc_warn {
37+
//! See <https://doc.rust-lang.org/rustc/lints/index.html>
38+
39+
#[expect(dead_code)]
40+
pub fn rustc_lints() {
41+
let x = 42;
42+
43+
#[expect(illegal_floating_point_literal_pattern)]
44+
match x {
45+
5 => {}
46+
6 => {}
47+
_ => {}
48+
}
49+
}
50+
}
51+
52+
pub mod rustdoc_ok {
53+
//! See <https://doc.rust-lang.org/rustdoc/lints.html>
54+
55+
#[expect(rustdoc::broken_intra_doc_links)]
56+
/// I want to link to [`Nonexistent`] but it doesn't exist!
57+
pub fn foo() {}
58+
59+
#[expect(rustdoc::invalid_html_tags)]
60+
/// <h1>
61+
pub fn bar() {}
62+
63+
#[expect(rustdoc::bare_urls)]
64+
/// http://example.org
65+
pub fn baz() {}
66+
}
67+
68+
pub mod rustdoc_warn {
69+
//! See <https://doc.rust-lang.org/rustdoc/lints.html>
70+
71+
#[expect(rustdoc::broken_intra_doc_links)]
72+
//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
73+
/// I want to link to [`bar`] but it doesn't exist!
74+
pub fn foo() {}
75+
76+
#[expect(rustdoc::invalid_html_tags)]
77+
//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
78+
/// <h1></h1>
79+
pub fn bar() {}
80+
81+
#[expect(rustdoc::bare_urls)]
82+
//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
83+
/// <http://example.org>
84+
pub fn baz() {}
85+
}
86+
87+
mod clippy_ok {
88+
//! See <https://rust-lang.github.io/rust-clippy/master/index.html>
89+
90+
#[expect(clippy::almost_swapped)]
91+
fn foo() {
92+
let mut a = 0;
93+
let mut b = 9;
94+
a = b;
95+
b = a;
96+
}
97+
98+
#[expect(clippy::bytes_nth)]
99+
fn bar() {
100+
let _ = "Hello".bytes().nth(3);
101+
}
102+
103+
#[expect(clippy::if_same_then_else)]
104+
fn baz() {
105+
let _ = if true {
106+
42
107+
} else {
108+
42
109+
};
110+
}
111+
112+
#[expect(clippy::logic_bug)]
113+
fn burger() {
114+
let a = false;
115+
let b = true;
116+
117+
if a && b || a {}
118+
}
119+
}
120+
121+
mod clippy_warn {
122+
//! See <https://rust-lang.github.io/rust-clippy/master/index.html>
123+
124+
#[expect(clippy::almost_swapped)]
125+
fn foo() {
126+
let mut a = 0;
127+
let mut b = 9;
128+
a = b;
129+
}
130+
131+
#[expect(clippy::bytes_nth)]
132+
fn bar() {
133+
let _ = "Hello".as_bytes().get(3);
134+
}
135+
136+
#[expect(clippy::if_same_then_else)]
137+
fn baz() {
138+
let _ = if true {
139+
33
140+
} else {
141+
42
142+
};
143+
}
144+
145+
#[expect(clippy::logic_bug)]
146+
fn burger() {
147+
let a = false;
148+
let b = true;
149+
let c = false;
150+
151+
if a && b || c {}
152+
}
153+
}
154+
155+
fn main() {
156+
rustc_warn::rustc_lints();
157+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
warning: this lint expectation is unfulfilled
2+
--> $DIR/expect-tool-lint-rfc-2383.rs:16:11
3+
|
4+
LL | #![expect(rustdoc::missing_crate_level_docs)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(unfulfilled_lint_expectations)]` on by default
8+
9+
warning: this lint expectation is unfulfilled
10+
--> $DIR/expect-tool-lint-rfc-2383.rs:71:14
11+
|
12+
LL | #[expect(rustdoc::broken_intra_doc_links)]
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
15+
warning: this lint expectation is unfulfilled
16+
--> $DIR/expect-tool-lint-rfc-2383.rs:76:14
17+
|
18+
LL | #[expect(rustdoc::invalid_html_tags)]
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
21+
warning: this lint expectation is unfulfilled
22+
--> $DIR/expect-tool-lint-rfc-2383.rs:81:14
23+
|
24+
LL | #[expect(rustdoc::bare_urls)]
25+
| ^^^^^^^^^^^^^^^^^^
26+
27+
warning: 4 warnings emitted
28+

0 commit comments

Comments
 (0)