Skip to content

Commit fc5516b

Browse files
authored
Rollup merge of #108588 - ehuss:lint-docs-produces, r=eholk
Fix the ffi_unwind_calls lint documentation This fixes the [`ffi_unwind_calls`](https://doc.rust-lang.org/nightly/rustc/lints/listing/allowed-by-default.html#ffi-unwind-calls) documentation to show its output correctly. Currently it is showing the text `{{produces}}` which is not how it should look. This fixes it by not ignoring the example. I'm not sure why it was ignored, as the way the lint currently works it doesn't seem to require external linkage. This also fixes several mistakes in the example: * There is no `ffi_unwind_calls` feature. * Denies the lint (which is otherwise allow be default). * Removes the `mod impl` which is not valid Rust syntax, and doesn't appear to be needed anyways. The output now looks like: ``` warning: call to foreign function with FFI-unwind ABI --> lint_example.rs:10:14 | 10 | unsafe { foo(); } | ^^^^^ call to foreign function with FFI-unwind ABI | note: the lint level is defined here --> lint_example.rs:2:9 | 2 | #![warn(ffi_unwind_calls)] | ^^^^^^^^^^^^^^^^ warning: call to function pointer with FFI-unwind ABI --> lint_example.rs:12:14 | 12 | unsafe { ptr(); } | ^^^^^ call to function pointer with FFI-unwind ABI ``` This also includes some updates to the lint-docs tool to help with this issue: * Adds a check if a lint documentation has `{{produces}}` with an ignored example, and generates an error. * All instances of a lint are now displayed. Previously it only showed the first time the lint fires. Some examples may trigger a lint multiple times, and they are all now displayed.
2 parents 5a017d3 + ab2508a commit fc5516b

File tree

2 files changed

+64
-40
lines changed

2 files changed

+64
-40
lines changed

compiler/rustc_lint_defs/src/builtin.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -4008,14 +4008,9 @@ declare_lint! {
40084008
///
40094009
/// ### Example
40104010
///
4011-
/// ```rust,ignore (need FFI)
4012-
/// #![feature(ffi_unwind_calls)]
4011+
/// ```rust
40134012
/// #![feature(c_unwind)]
4014-
///
4015-
/// # mod impl {
4016-
/// # #[no_mangle]
4017-
/// # pub fn "C-unwind" fn foo() {}
4018-
/// # }
4013+
/// #![warn(ffi_unwind_calls)]
40194014
///
40204015
/// extern "C-unwind" {
40214016
/// fn foo();

src/tools/lint-docs/src/lib.rs

+62-33
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,36 @@ impl Lint {
4545
fn check_style(&self) -> Result<(), Box<dyn Error>> {
4646
for &expected in &["### Example", "### Explanation", "{{produces}}"] {
4747
if expected == "{{produces}}" && self.is_ignored() {
48+
if self.doc_contains("{{produces}}") {
49+
return Err(format!(
50+
"the lint example has `ignore`, but also contains the {{{{produces}}}} marker\n\
51+
\n\
52+
The documentation generator cannot generate the example output when the \
53+
example is ignored.\n\
54+
Manually include the sample output below the example. For example:\n\
55+
\n\
56+
/// ```rust,ignore (needs command line option)\n\
57+
/// #[cfg(widnows)]\n\
58+
/// fn foo() {{}}\n\
59+
/// ```\n\
60+
///\n\
61+
/// This will produce:\n\
62+
/// \n\
63+
/// ```text\n\
64+
/// warning: unknown condition name used\n\
65+
/// --> lint_example.rs:1:7\n\
66+
/// |\n\
67+
/// 1 | #[cfg(widnows)]\n\
68+
/// | ^^^^^^^\n\
69+
/// |\n\
70+
/// = note: `#[warn(unexpected_cfgs)]` on by default\n\
71+
/// ```\n\
72+
\n\
73+
Replacing the output with the text of the example you \
74+
compiled manually yourself.\n\
75+
"
76+
).into());
77+
}
4878
continue;
4979
}
5080
if !self.doc_contains(expected) {
@@ -317,10 +347,10 @@ impl<'a> LintExtractor<'a> {
317347
..,
318348
&format!(
319349
"This will produce:\n\
320-
\n\
321-
```text\n\
322-
{}\
323-
```",
350+
\n\
351+
```text\n\
352+
{}\
353+
```",
324354
output
325355
),
326356
);
@@ -392,37 +422,36 @@ impl<'a> LintExtractor<'a> {
392422
.filter(|line| line.starts_with('{'))
393423
.map(serde_json::from_str)
394424
.collect::<Result<Vec<serde_json::Value>, _>>()?;
395-
match msgs
425+
// First try to find the messages with the `code` field set to our lint.
426+
let matches: Vec<_> = msgs
396427
.iter()
397-
.find(|msg| matches!(&msg["code"]["code"], serde_json::Value::String(s) if s==name))
398-
{
399-
Some(msg) => {
400-
let rendered = msg["rendered"].as_str().expect("rendered field should exist");
401-
Ok(rendered.to_string())
402-
}
403-
None => {
404-
match msgs.iter().find(
405-
|msg| matches!(&msg["rendered"], serde_json::Value::String(s) if s.contains(name)),
406-
) {
407-
Some(msg) => {
408-
let rendered = msg["rendered"].as_str().expect("rendered field should exist");
409-
Ok(rendered.to_string())
410-
}
411-
None => {
412-
let rendered: Vec<&str> =
413-
msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
414-
let non_json: Vec<&str> =
415-
stderr.lines().filter(|line| !line.starts_with('{')).collect();
416-
Err(format!(
417-
"did not find lint `{}` in output of example, got:\n{}\n{}",
418-
name,
419-
non_json.join("\n"),
420-
rendered.join("\n")
421-
)
422-
.into())
423-
}
424-
}
428+
.filter(|msg| matches!(&msg["code"]["code"], serde_json::Value::String(s) if s==name))
429+
.map(|msg| msg["rendered"].as_str().expect("rendered field should exist").to_string())
430+
.collect();
431+
if matches.is_empty() {
432+
// Some lints override their code to something else (E0566).
433+
// Try to find something that looks like it could be our lint.
434+
let matches: Vec<_> = msgs.iter().filter(|msg|
435+
matches!(&msg["rendered"], serde_json::Value::String(s) if s.contains(name)))
436+
.map(|msg| msg["rendered"].as_str().expect("rendered field should exist").to_string())
437+
.collect();
438+
if matches.is_empty() {
439+
let rendered: Vec<&str> =
440+
msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
441+
let non_json: Vec<&str> =
442+
stderr.lines().filter(|line| !line.starts_with('{')).collect();
443+
Err(format!(
444+
"did not find lint `{}` in output of example, got:\n{}\n{}",
445+
name,
446+
non_json.join("\n"),
447+
rendered.join("\n")
448+
)
449+
.into())
450+
} else {
451+
Ok(matches.join("\n"))
425452
}
453+
} else {
454+
Ok(matches.join("\n"))
426455
}
427456
}
428457

0 commit comments

Comments
 (0)