diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 242d147b5ee..9d6ab0b75df 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4008,14 +4008,9 @@ declare_lint! { /// /// ### Example /// - /// ```rust,ignore (need FFI) - /// #![feature(ffi_unwind_calls)] + /// ```rust /// #![feature(c_unwind)] - /// - /// # mod impl { - /// # #[no_mangle] - /// # pub fn "C-unwind" fn foo() {} - /// # } + /// #![warn(ffi_unwind_calls)] /// /// extern "C-unwind" { /// fn foo(); diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs index 3842a649c6f..034c6aa0708 100644 --- a/src/tools/lint-docs/src/lib.rs +++ b/src/tools/lint-docs/src/lib.rs @@ -45,6 +45,36 @@ impl Lint { fn check_style(&self) -> Result<(), Box> { for &expected in &["### Example", "### Explanation", "{{produces}}"] { if expected == "{{produces}}" && self.is_ignored() { + if self.doc_contains("{{produces}}") { + return Err(format!( + "the lint example has `ignore`, but also contains the {{{{produces}}}} marker\n\ + \n\ + The documentation generator cannot generate the example output when the \ + example is ignored.\n\ + Manually include the sample output below the example. For example:\n\ + \n\ + /// ```rust,ignore (needs command line option)\n\ + /// #[cfg(widnows)]\n\ + /// fn foo() {{}}\n\ + /// ```\n\ + ///\n\ + /// This will produce:\n\ + /// \n\ + /// ```text\n\ + /// warning: unknown condition name used\n\ + /// --> lint_example.rs:1:7\n\ + /// |\n\ + /// 1 | #[cfg(widnows)]\n\ + /// | ^^^^^^^\n\ + /// |\n\ + /// = note: `#[warn(unexpected_cfgs)]` on by default\n\ + /// ```\n\ + \n\ + Replacing the output with the text of the example you \ + compiled manually yourself.\n\ + " + ).into()); + } continue; } if !self.doc_contains(expected) { @@ -317,10 +347,10 @@ impl<'a> LintExtractor<'a> { .., &format!( "This will produce:\n\ - \n\ - ```text\n\ - {}\ - ```", + \n\ + ```text\n\ + {}\ + ```", output ), ); @@ -392,37 +422,36 @@ impl<'a> LintExtractor<'a> { .filter(|line| line.starts_with('{')) .map(serde_json::from_str) .collect::, _>>()?; - match msgs + // First try to find the messages with the `code` field set to our lint. + let matches: Vec<_> = msgs .iter() - .find(|msg| matches!(&msg["code"]["code"], serde_json::Value::String(s) if s==name)) - { - Some(msg) => { - let rendered = msg["rendered"].as_str().expect("rendered field should exist"); - Ok(rendered.to_string()) - } - None => { - match msgs.iter().find( - |msg| matches!(&msg["rendered"], serde_json::Value::String(s) if s.contains(name)), - ) { - Some(msg) => { - let rendered = msg["rendered"].as_str().expect("rendered field should exist"); - Ok(rendered.to_string()) - } - None => { - let rendered: Vec<&str> = - msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect(); - let non_json: Vec<&str> = - stderr.lines().filter(|line| !line.starts_with('{')).collect(); - Err(format!( - "did not find lint `{}` in output of example, got:\n{}\n{}", - name, - non_json.join("\n"), - rendered.join("\n") - ) - .into()) - } - } + .filter(|msg| matches!(&msg["code"]["code"], serde_json::Value::String(s) if s==name)) + .map(|msg| msg["rendered"].as_str().expect("rendered field should exist").to_string()) + .collect(); + if matches.is_empty() { + // Some lints override their code to something else (E0566). + // Try to find something that looks like it could be our lint. + let matches: Vec<_> = msgs.iter().filter(|msg| + matches!(&msg["rendered"], serde_json::Value::String(s) if s.contains(name))) + .map(|msg| msg["rendered"].as_str().expect("rendered field should exist").to_string()) + .collect(); + if matches.is_empty() { + let rendered: Vec<&str> = + msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect(); + let non_json: Vec<&str> = + stderr.lines().filter(|line| !line.starts_with('{')).collect(); + Err(format!( + "did not find lint `{}` in output of example, got:\n{}\n{}", + name, + non_json.join("\n"), + rendered.join("\n") + ) + .into()) + } else { + Ok(matches.join("\n")) } + } else { + Ok(matches.join("\n")) } }