diff options
| author | Urgau <urgau@numericable.fr> | 2025-05-01 18:15:04 +0200 |
|---|---|---|
| committer | Urgau <urgau@numericable.fr> | 2025-05-22 20:10:32 +0200 |
| commit | 9d9705f4c360df5d8c77876496b0c5594cbc7fa0 (patch) | |
| tree | 98d9fb2cccee0efc04c7d028134e1e83b4871128 | |
| parent | 80c6a0885079038caa0bc90670afbf5ead806c17 (diff) | |
| download | rust-9d9705f4c360df5d8c77876496b0c5594cbc7fa0.tar.gz rust-9d9705f4c360df5d8c77876496b0c5594cbc7fa0.zip | |
Collect and use `#![doc(test(attr(..)))]` at module level too
| -rw-r--r-- | src/librustdoc/doctest.rs | 18 | ||||
| -rw-r--r-- | src/librustdoc/doctest/extracted.rs | 5 | ||||
| -rw-r--r-- | src/librustdoc/doctest/make.rs | 21 | ||||
| -rw-r--r-- | src/librustdoc/doctest/markdown.rs | 2 | ||||
| -rw-r--r-- | src/librustdoc/doctest/runner.rs | 11 | ||||
| -rw-r--r-- | src/librustdoc/doctest/rust.rs | 40 | ||||
| -rw-r--r-- | src/librustdoc/doctest/tests.rs | 68 | ||||
| -rw-r--r-- | src/librustdoc/html/markdown.rs | 1 | ||||
| -rw-r--r-- | tests/rustdoc-ui/doctest/dead-code-module-2.rs | 27 | ||||
| -rw-r--r-- | tests/rustdoc-ui/doctest/dead-code-module-2.stdout | 30 | ||||
| -rw-r--r-- | tests/rustdoc-ui/doctest/dead-code-module.rs | 18 | ||||
| -rw-r--r-- | tests/rustdoc-ui/doctest/dead-code-module.stdout | 29 | ||||
| -rw-r--r-- | tests/rustdoc-ui/doctest/doc-test-attr-pass-module.rs | 11 |
13 files changed, 229 insertions, 52 deletions
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index b2fe24db0a2..45e5c894bb9 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -45,8 +45,6 @@ pub(crate) struct GlobalTestOptions { /// Whether inserting extra indent spaces in code block, /// default is `false`, only `true` for generating code link of Rust playground pub(crate) insert_indent_space: bool, - /// Additional crate-level attributes to add to doctests. - pub(crate) attrs: Vec<String>, /// Path to file containing arguments for the invocation of rustc. pub(crate) args_file: PathBuf, } @@ -371,12 +369,9 @@ fn scrape_test_config( attrs: &[hir::Attribute], args_file: PathBuf, ) -> GlobalTestOptions { - use rustc_ast_pretty::pprust; - let mut opts = GlobalTestOptions { crate_name, no_crate_inject: false, - attrs: Vec::new(), insert_indent_space: false, args_file, }; @@ -393,13 +388,7 @@ fn scrape_test_config( if attr.has_name(sym::no_crate_inject) { opts.no_crate_inject = true; } - if attr.has_name(sym::attr) - && let Some(l) = attr.meta_item_list() - { - for item in l { - opts.attrs.push(pprust::meta_list_item_to_string(item)); - } - } + // NOTE: `test(attr(..))` is handled when discovering the individual tests } opts @@ -848,6 +837,7 @@ pub(crate) struct ScrapedDocTest { text: String, name: String, span: Span, + global_crate_attrs: Vec<String>, } impl ScrapedDocTest { @@ -858,6 +848,7 @@ impl ScrapedDocTest { langstr: LangString, text: String, span: Span, + global_crate_attrs: Vec<String>, ) -> Self { let mut item_path = logical_path.join("::"); item_path.retain(|c| c != ' '); @@ -867,7 +858,7 @@ impl ScrapedDocTest { let name = format!("{} - {item_path}(line {line})", filename.prefer_remapped_unconditionaly()); - Self { filename, line, langstr, text, name, span } + Self { filename, line, langstr, text, name, span, global_crate_attrs } } fn edition(&self, opts: &RustdocOptions) -> Edition { self.langstr.edition.unwrap_or(opts.edition) @@ -949,6 +940,7 @@ impl CreateRunnableDocTests { let edition = scraped_test.edition(&self.rustdoc_options); let doctest = BuildDocTestBuilder::new(&scraped_test.text) .crate_name(&self.opts.crate_name) + .global_crate_attrs(scraped_test.global_crate_attrs.clone()) .edition(edition) .can_merge_doctests(self.can_merge_doctests) .test_id(test_id) diff --git a/src/librustdoc/doctest/extracted.rs b/src/librustdoc/doctest/extracted.rs index 3b17ccc78c7..ebe6bfd22ba 100644 --- a/src/librustdoc/doctest/extracted.rs +++ b/src/librustdoc/doctest/extracted.rs @@ -35,13 +35,16 @@ impl ExtractedDocTests { ) { let edition = scraped_test.edition(options); - let ScrapedDocTest { filename, line, langstr, text, name, .. } = scraped_test; + let ScrapedDocTest { filename, line, langstr, text, name, global_crate_attrs, .. } = + scraped_test; let doctest = BuildDocTestBuilder::new(&text) .crate_name(&opts.crate_name) + .global_crate_attrs(global_crate_attrs) .edition(edition) .lang_str(&langstr) .build(None); + let (full_test_code, size) = doctest.generate_unique_doctest( &text, langstr.test_harness, diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 66647b88018..5e571613d6f 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -45,6 +45,7 @@ pub(crate) struct BuildDocTestBuilder<'a> { test_id: Option<String>, lang_str: Option<&'a LangString>, span: Span, + global_crate_attrs: Vec<String>, } impl<'a> BuildDocTestBuilder<'a> { @@ -57,6 +58,7 @@ impl<'a> BuildDocTestBuilder<'a> { test_id: None, lang_str: None, span: DUMMY_SP, + global_crate_attrs: Vec::new(), } } @@ -96,6 +98,12 @@ impl<'a> BuildDocTestBuilder<'a> { self } + #[inline] + pub(crate) fn global_crate_attrs(mut self, global_crate_attrs: Vec<String>) -> Self { + self.global_crate_attrs = global_crate_attrs; + self + } + pub(crate) fn build(self, dcx: Option<DiagCtxtHandle<'_>>) -> DocTestBuilder { let BuildDocTestBuilder { source, @@ -106,6 +114,7 @@ impl<'a> BuildDocTestBuilder<'a> { test_id, lang_str, span, + global_crate_attrs, } = self; let can_merge_doctests = can_merge_doctests && lang_str.is_some_and(|lang_str| { @@ -133,6 +142,7 @@ impl<'a> BuildDocTestBuilder<'a> { // If the AST returned an error, we don't want this doctest to be merged with the // others. return DocTestBuilder::invalid( + Vec::new(), String::new(), String::new(), String::new(), @@ -155,6 +165,7 @@ impl<'a> BuildDocTestBuilder<'a> { DocTestBuilder { supports_color, has_main_fn, + global_crate_attrs, crate_attrs, maybe_crate_attrs, crates, @@ -173,6 +184,7 @@ pub(crate) struct DocTestBuilder { pub(crate) supports_color: bool, pub(crate) already_has_extern_crate: bool, pub(crate) has_main_fn: bool, + pub(crate) global_crate_attrs: Vec<String>, pub(crate) crate_attrs: String, /// If this is a merged doctest, it will be put into `everything_else`, otherwise it will /// put into `crate_attrs`. @@ -186,6 +198,7 @@ pub(crate) struct DocTestBuilder { impl DocTestBuilder { fn invalid( + global_crate_attrs: Vec<String>, crate_attrs: String, maybe_crate_attrs: String, crates: String, @@ -195,6 +208,7 @@ impl DocTestBuilder { Self { supports_color: false, has_main_fn: false, + global_crate_attrs, crate_attrs, maybe_crate_attrs, crates, @@ -224,7 +238,8 @@ impl DocTestBuilder { let mut line_offset = 0; let mut prog = String::new(); let everything_else = self.everything_else.trim(); - if opts.attrs.is_empty() { + + if self.global_crate_attrs.is_empty() { // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some // lints that are commonly triggered in doctests. The crate-level test attributes are // commonly used to make tests fail in case they trigger warnings, so having this there in @@ -233,8 +248,8 @@ impl DocTestBuilder { line_offset += 1; } - // Next, any attributes that came from the crate root via #![doc(test(attr(...)))]. - for attr in &opts.attrs { + // Next, any attributes that came from #![doc(test(attr(...)))]. + for attr in &self.global_crate_attrs { prog.push_str(&format!("#![{attr}]\n")); line_offset += 1; } diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs index e358a7e44e5..7f26605f256 100644 --- a/src/librustdoc/doctest/markdown.rs +++ b/src/librustdoc/doctest/markdown.rs @@ -31,6 +31,7 @@ impl DocTestVisitor for MdCollector { config, test, DUMMY_SP, + Vec::new(), )); } @@ -96,7 +97,6 @@ pub(crate) fn test(input: &Input, options: Options) -> Result<(), String> { crate_name, no_crate_inject: true, insert_indent_space: false, - attrs: vec![], args_file, }; diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs index 39a4f23560a..f0914474c79 100644 --- a/src/librustdoc/doctest/runner.rs +++ b/src/librustdoc/doctest/runner.rs @@ -12,6 +12,7 @@ use crate::html::markdown::{Ignore, LangString}; /// Convenient type to merge compatible doctests into one. pub(crate) struct DocTestRunner { crate_attrs: FxIndexSet<String>, + global_crate_attrs: FxIndexSet<String>, ids: String, output: String, output_merged_tests: String, @@ -23,6 +24,7 @@ impl DocTestRunner { pub(crate) fn new() -> Self { Self { crate_attrs: FxIndexSet::default(), + global_crate_attrs: FxIndexSet::default(), ids: String::new(), output: String::new(), output_merged_tests: String::new(), @@ -46,6 +48,9 @@ impl DocTestRunner { for line in doctest.crate_attrs.split('\n') { self.crate_attrs.insert(line.to_string()); } + for line in &doctest.global_crate_attrs { + self.global_crate_attrs.insert(line.to_string()); + } } self.ids.push_str(&format!( "tests.push({}::TEST);\n", @@ -85,7 +90,7 @@ impl DocTestRunner { code_prefix.push('\n'); } - if opts.attrs.is_empty() { + if self.global_crate_attrs.is_empty() { // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some // lints that are commonly triggered in doctests. The crate-level test attributes are // commonly used to make tests fail in case they trigger warnings, so having this there in @@ -93,8 +98,8 @@ impl DocTestRunner { code_prefix.push_str("#![allow(unused)]\n"); } - // Next, any attributes that came from the crate root via #![doc(test(attr(...)))]. - for attr in &opts.attrs { + // Next, any attributes that came from #![doc(test(attr(...)))]. + for attr in &self.global_crate_attrs { code_prefix.push_str(&format!("#![{attr}]\n")); } diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index f9d2aa3d3b4..4e9b1ee36f3 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -4,6 +4,7 @@ use std::cell::Cell; use std::env; use std::sync::Arc; +use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_hir::{self as hir, CRATE_HIR_ID, intravisit}; @@ -11,7 +12,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_resolve::rustdoc::span_of_fragments; use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span}; +use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span, sym}; use super::{DocTestVisitor, ScrapedDocTest}; use crate::clean::{Attributes, extract_cfg_from_attrs}; @@ -22,6 +23,7 @@ struct RustCollector { tests: Vec<ScrapedDocTest>, cur_path: Vec<String>, position: Span, + global_crate_attrs: Vec<String>, } impl RustCollector { @@ -75,6 +77,7 @@ impl DocTestVisitor for RustCollector { config, test, span, + self.global_crate_attrs.clone(), )); } @@ -94,6 +97,7 @@ impl<'tcx> HirCollector<'tcx> { cur_path: vec![], position: DUMMY_SP, tests: vec![], + global_crate_attrs: Vec::new(), }; Self { codes, tcx, collector } } @@ -170,6 +174,40 @@ impl<'tcx> intravisit::Visitor<'tcx> for HirCollector<'tcx> { self.tcx } + fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, _s: Span, hir_id: hir::HirId) { + let attrs = self.tcx.hir_attrs(hir_id); + + if !attrs.is_empty() { + // Try collecting `#![doc(test(attr(...)))]` from the attribute module + let old_len = self.collector.global_crate_attrs.len(); + for doc_test_attrs in attrs + .iter() + .filter(|a| a.has_name(sym::doc)) + .flat_map(|a| a.meta_item_list().unwrap_or_default()) + .filter(|a| a.has_name(sym::test)) + { + let Some(doc_test_attrs) = doc_test_attrs.meta_item_list() else { continue }; + for attr in doc_test_attrs + .iter() + .filter(|a| a.has_name(sym::attr)) + .flat_map(|a| a.meta_item_list().unwrap_or_default()) + .map(|i| pprust::meta_list_item_to_string(i)) + { + // Add the additional attributes to the global_crate_attrs vector + self.collector.global_crate_attrs.push(attr); + } + } + + let r = intravisit::walk_mod(self, m); + + // Restore global_crate_attrs to it's previous size/content + self.collector.global_crate_attrs.truncate(old_len); + r + } else { + intravisit::walk_mod(self, m) + } + } + fn visit_item(&mut self, item: &'tcx hir::Item<'_>) { let name = match &item.kind { hir::ItemKind::Impl(impl_) => { diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs index 08248fdf39b..ce2984ced79 100644 --- a/src/librustdoc/doctest/tests.rs +++ b/src/librustdoc/doctest/tests.rs @@ -7,9 +7,11 @@ fn make_test( crate_name: Option<&str>, dont_insert_main: bool, opts: &GlobalTestOptions, + global_crate_attrs: Vec<&str>, test_id: Option<&str>, ) -> (String, usize) { - let mut builder = BuildDocTestBuilder::new(test_code); + let mut builder = BuildDocTestBuilder::new(test_code) + .global_crate_attrs(global_crate_attrs.into_iter().map(|a| a.to_string()).collect()); if let Some(crate_name) = crate_name { builder = builder.crate_name(crate_name); } @@ -28,7 +30,6 @@ fn default_global_opts(crate_name: impl Into<String>) -> GlobalTestOptions { crate_name: crate_name.into(), no_crate_inject: false, insert_indent_space: false, - attrs: vec![], args_file: PathBuf::new(), } } @@ -43,7 +44,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -58,7 +59,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -77,7 +78,7 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 3)); } @@ -94,7 +95,7 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -112,7 +113,7 @@ use std::*; assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("std"), false, &opts, None); + let (output, len) = make_test(input, Some("std"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -131,7 +132,7 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -148,7 +149,7 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -156,8 +157,7 @@ assert_eq!(2+2, 4); fn make_test_opts_attrs() { // If you supplied some doctest attributes with `#![doc(test(attr(...)))]`, it will use // those instead of the stock `#![allow(unused)]`. - let mut opts = default_global_opts("asdf"); - opts.attrs.push("feature(sick_rad)".to_string()); + let opts = default_global_opts("asdf"); let input = "use asdf::qwop; assert_eq!(2+2, 4);"; let expected = "#![feature(sick_rad)] @@ -168,11 +168,10 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = + make_test(input, Some("asdf"), false, &opts, vec!["feature(sick_rad)"], None); assert_eq!((output, len), (expected, 3)); - // Adding more will also bump the returned line offset. - opts.attrs.push("feature(hella_dope)".to_string()); let expected = "#![feature(sick_rad)] #![feature(hella_dope)] #[allow(unused_extern_crates)] @@ -182,7 +181,18 @@ use asdf::qwop; assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = make_test( + input, + Some("asdf"), + false, + &opts, + vec![ + "feature(sick_rad)", + // Adding more will also bump the returned line offset. + "feature(hella_dope)", + ], + None, + ); assert_eq!((output, len), (expected, 4)); } @@ -200,7 +210,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -216,7 +226,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 1)); } @@ -232,7 +242,7 @@ fn main() { assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -246,7 +256,7 @@ assert_eq!(2+2, 4);"; //Ceci n'est pas une `fn main` assert_eq!(2+2, 4);" .to_string(); - let (output, len) = make_test(input, None, true, &opts, None); + let (output, len) = make_test(input, None, true, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 1)); } @@ -264,7 +274,7 @@ assert_eq!(2+2, 4); }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -284,7 +294,7 @@ assert_eq!(asdf::foo, 4); }" .to_string(); - let (output, len) = make_test(input, Some("asdf"), false, &opts, None); + let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 3)); } @@ -302,7 +312,7 @@ test_wrapper! { }" .to_string(); - let (output, len) = make_test(input, Some("my_crate"), false, &opts, None); + let (output, len) = make_test(input, Some("my_crate"), false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 1)); } @@ -322,7 +332,7 @@ io::stdin().read_line(&mut input)?; Ok::<(), io:Error>(()) } _inner().unwrap() }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -336,7 +346,7 @@ fn main() { #[allow(non_snake_case)] fn _doctest_main__some_unique_name() { assert_eq!(2+2, 4); } _doctest_main__some_unique_name() }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, Some("_some_unique_name")); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), Some("_some_unique_name")); assert_eq!((output, len), (expected, 2)); } @@ -355,7 +365,7 @@ fn main() { eprintln!(\"hello anan\"); }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } @@ -375,7 +385,7 @@ fn main() { eprintln!(\"hello anan\"); }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 1)); } @@ -400,7 +410,7 @@ fn main() { }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); // And same, if there is a `main` function provided by the user, we ensure that it's @@ -420,7 +430,7 @@ fn main() {}"; fn main() {}" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 1)); } @@ -448,6 +458,6 @@ pub mod outer_module { } }" .to_string(); - let (output, len) = make_test(input, None, false, &opts, None); + let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index ad7dfafd90c..b48082defa7 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -300,7 +300,6 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> { crate_name: krate.map(String::from).unwrap_or_default(), no_crate_inject: false, insert_indent_space: true, - attrs: vec![], args_file: PathBuf::new(), }; let mut builder = doctest::BuildDocTestBuilder::new(&test).edition(edition); diff --git a/tests/rustdoc-ui/doctest/dead-code-module-2.rs b/tests/rustdoc-ui/doctest/dead-code-module-2.rs new file mode 100644 index 00000000000..de7b11b91ec --- /dev/null +++ b/tests/rustdoc-ui/doctest/dead-code-module-2.rs @@ -0,0 +1,27 @@ +// Same test as dead-code-module but with 2 doc(test(attr())) at different levels. + +//@ edition: 2024 +//@ compile-flags:--test +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ failure-status: 101 + +#![doc(test(attr(allow(unused_variables))))] + +mod my_mod { + #![doc(test(attr(deny(warnings))))] + + /// Example + /// + /// ```rust,no_run + /// trait T { fn f(); } + /// ``` + pub fn f() {} +} + +/// Example +/// +/// ```rust,no_run +/// trait OnlyWarning { fn no_deny_warnings(); } +/// ``` +pub fn g() {} diff --git a/tests/rustdoc-ui/doctest/dead-code-module-2.stdout b/tests/rustdoc-ui/doctest/dead-code-module-2.stdout new file mode 100644 index 00000000000..36b8eaed22b --- /dev/null +++ b/tests/rustdoc-ui/doctest/dead-code-module-2.stdout @@ -0,0 +1,30 @@ + +running 2 tests +test $DIR/dead-code-module-2.rs - my_mod::f (line 16) - compile ... FAILED +test $DIR/dead-code-module-2.rs - g (line 24) - compile ... ok + +failures: + +---- $DIR/dead-code-module-2.rs - my_mod::f (line 16) stdout ---- +error: trait `T` is never used + --> $DIR/dead-code-module-2.rs:17:7 + | +LL | trait T { fn f(); } + | ^ + | +note: the lint level is defined here + --> $DIR/dead-code-module-2.rs:15:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]` + +error: aborting due to 1 previous error + +Couldn't compile the test. + +failures: + $DIR/dead-code-module-2.rs - my_mod::f (line 16) + +test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/dead-code-module.rs b/tests/rustdoc-ui/doctest/dead-code-module.rs new file mode 100644 index 00000000000..f825749a6a2 --- /dev/null +++ b/tests/rustdoc-ui/doctest/dead-code-module.rs @@ -0,0 +1,18 @@ +// Same test as dead-code but inside a module. + +//@ edition: 2024 +//@ compile-flags:--test +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ failure-status: 101 + +mod my_mod { + #![doc(test(attr(allow(unused_variables), deny(warnings))))] + + /// Example + /// + /// ```rust,no_run + /// trait T { fn f(); } + /// ``` + pub fn f() {} +} diff --git a/tests/rustdoc-ui/doctest/dead-code-module.stdout b/tests/rustdoc-ui/doctest/dead-code-module.stdout new file mode 100644 index 00000000000..b5ccf225d25 --- /dev/null +++ b/tests/rustdoc-ui/doctest/dead-code-module.stdout @@ -0,0 +1,29 @@ + +running 1 test +test $DIR/dead-code-module.rs - my_mod::f (line 14) - compile ... FAILED + +failures: + +---- $DIR/dead-code-module.rs - my_mod::f (line 14) stdout ---- +error: trait `T` is never used + --> $DIR/dead-code-module.rs:15:7 + | +LL | trait T { fn f(); } + | ^ + | +note: the lint level is defined here + --> $DIR/dead-code-module.rs:13:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]` + +error: aborting due to 1 previous error + +Couldn't compile the test. + +failures: + $DIR/dead-code-module.rs - my_mod::f (line 14) + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/doc-test-attr-pass-module.rs b/tests/rustdoc-ui/doctest/doc-test-attr-pass-module.rs new file mode 100644 index 00000000000..e916ca41ea0 --- /dev/null +++ b/tests/rustdoc-ui/doctest/doc-test-attr-pass-module.rs @@ -0,0 +1,11 @@ +//@ check-pass + +#![crate_type = "lib"] +#![deny(invalid_doc_attributes)] +#![doc(test(no_crate_inject))] + +mod my_mod { + #![doc(test(attr(deny(warnings))))] + + pub fn foo() {} +} |
