Simplify has_main_fn to be a boolean instead of a Option<Span>

This commit is contained in:
Guillaume Gomez 2024-06-11 00:01:59 +02:00
parent 010731d5b6
commit 03118fa80a
3 changed files with 37 additions and 31 deletions

View File

@ -536,13 +536,17 @@ fn run_test(
compiler.arg("--error-format=short"); compiler.arg("--error-format=short");
let input_file = let input_file =
doctest.test_opts.outdir.path().join(&format!("doctest_{}.rs", doctest.edition)); doctest.test_opts.outdir.path().join(&format!("doctest_{}.rs", doctest.edition));
eprintln!("OUUUUUUUT>>>>>>> {input_file:?}");
if std::fs::write(&input_file, &doctest.full_test_code).is_err() { if std::fs::write(&input_file, &doctest.full_test_code).is_err() {
// If we cannot write this file for any reason, we leave. All combined tests will be // If we cannot write this file for any reason, we leave. All combined tests will be
// tested as standalone tests. // tested as standalone tests.
return Err(TestFailure::CompileError); return Err(TestFailure::CompileError);
} }
compiler.arg(input_file); compiler.arg(input_file);
compiler.stderr(Stdio::null()); // compiler.stderr(Stdio::null());
let mut buffer = String::new();
eprintln!("Press ENTER");
let _ = std::io::stdin().read_line(&mut buffer);
} else { } else {
compiler.arg("-"); compiler.arg("-");
compiler.stdin(Stdio::piped()); compiler.stdin(Stdio::piped());
@ -764,7 +768,7 @@ struct CreateRunnableDoctests {
impl CreateRunnableDoctests { impl CreateRunnableDoctests {
fn new(rustdoc_options: RustdocOptions, opts: GlobalTestOptions) -> CreateRunnableDoctests { fn new(rustdoc_options: RustdocOptions, opts: GlobalTestOptions) -> CreateRunnableDoctests {
let can_merge_doctests = rustdoc_options.edition >= Edition::Edition2024; let can_merge_doctests = true;//rustdoc_options.edition >= Edition::Edition2024;
CreateRunnableDoctests { CreateRunnableDoctests {
standalone_tests: Vec::new(), standalone_tests: Vec::new(),
mergeable_tests: FxHashMap::default(), mergeable_tests: FxHashMap::default(),

View File

@ -13,14 +13,14 @@
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
use rustc_span::source_map::SourceMap; use rustc_span::source_map::SourceMap;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::{FileName, Span, DUMMY_SP}; use rustc_span::FileName;
use super::GlobalTestOptions; use super::GlobalTestOptions;
pub(crate) struct DocTest { pub(crate) struct DocTest {
pub(crate) supports_color: bool, pub(crate) supports_color: bool,
pub(crate) already_has_extern_crate: bool, pub(crate) already_has_extern_crate: bool,
pub(crate) main_fn_span: Option<Span>, pub(crate) has_main_fn: bool,
pub(crate) crate_attrs: String, pub(crate) crate_attrs: String,
pub(crate) crates: String, pub(crate) crates: String,
pub(crate) everything_else: String, pub(crate) everything_else: String,
@ -43,7 +43,7 @@ pub(crate) fn new(
// Uses librustc_ast to parse the doctest and find if there's a main fn and the extern // Uses librustc_ast to parse the doctest and find if there's a main fn and the extern
// crate already is included. // crate already is included.
let Ok((main_fn_span, already_has_extern_crate, failed_ast)) = let Ok((has_main_fn, already_has_extern_crate, failed_ast)) =
check_for_main_and_extern_crate( check_for_main_and_extern_crate(
crate_name, crate_name,
source, source,
@ -58,7 +58,7 @@ pub(crate) fn new(
// The error will be reported during compilation. // The error will be reported during compilation.
return DocTest { return DocTest {
supports_color: false, supports_color: false,
main_fn_span: None, has_main_fn: false,
crate_attrs, crate_attrs,
crates, crates,
everything_else, everything_else,
@ -70,7 +70,7 @@ pub(crate) fn new(
}; };
Self { Self {
supports_color, supports_color,
main_fn_span, has_main_fn,
crate_attrs, crate_attrs,
crates, crates,
everything_else, everything_else,
@ -141,7 +141,7 @@ pub(crate) fn generate_unique_doctest(
} }
// FIXME: This code cannot yet handle no_std test cases yet // FIXME: This code cannot yet handle no_std test cases yet
if dont_insert_main || self.main_fn_span.is_some() || prog.contains("![no_std]") { if dont_insert_main || self.has_main_fn || prog.contains("![no_std]") {
prog.push_str(everything_else); prog.push_str(everything_else);
} else { } else {
let returns_result = everything_else.ends_with("(())"); let returns_result = everything_else.ends_with("(())");
@ -218,7 +218,7 @@ fn cancel_error_count(psess: &ParseSess) {
fn parse_source( fn parse_source(
source: String, source: String,
found_main_span: &mut Option<Span>, has_main_fn: &mut bool,
found_extern_crate: &mut bool, found_extern_crate: &mut bool,
found_macro: &mut bool, found_macro: &mut bool,
crate_name: &Option<&str>, crate_name: &Option<&str>,
@ -263,22 +263,22 @@ fn parse_source(
// functions, we would thing all top-level items (so basically nothing). // functions, we would thing all top-level items (so basically nothing).
fn check_item( fn check_item(
item: &ast::Item, item: &ast::Item,
found_main_span: &mut Option<Span>, has_main_fn: &mut bool,
found_extern_crate: &mut bool, found_extern_crate: &mut bool,
found_macro: &mut bool, found_macro: &mut bool,
crate_name: &Option<&str>, crate_name: &Option<&str>,
) { ) {
match item.kind { match item.kind {
ast::ItemKind::Fn(ref fn_item) if found_main_span.is_none() => { ast::ItemKind::Fn(ref fn_item) if !*has_main_fn => {
if item.ident.name == sym::main { if item.ident.name == sym::main {
*found_main_span = Some(item.span); *has_main_fn = true;
} }
if let Some(ref body) = fn_item.body { if let Some(ref body) = fn_item.body {
for stmt in &body.stmts { for stmt in &body.stmts {
match stmt.kind { match stmt.kind {
ast::StmtKind::Item(ref item) => check_item( ast::StmtKind::Item(ref item) => check_item(
item, item,
found_main_span, has_main_fn,
found_extern_crate, found_extern_crate,
found_macro, found_macro,
crate_name, crate_name,
@ -305,9 +305,9 @@ fn check_item(
loop { loop {
match parser.parse_item(ForceCollect::No) { match parser.parse_item(ForceCollect::No) {
Ok(Some(item)) => { Ok(Some(item)) => {
check_item(&item, found_main_span, found_extern_crate, found_macro, crate_name); check_item(&item, has_main_fn, found_extern_crate, found_macro, crate_name);
if found_main_span.is_some() && *found_extern_crate { if *has_main_fn && *found_extern_crate {
break; break;
} }
} }
@ -319,7 +319,7 @@ fn check_item(
} }
} }
// The supplied slice is only used for diagnostics, // The supplied item is only used for diagnostics,
// which are swallowed here anyway. // which are swallowed here anyway.
parser.maybe_consume_incorrect_semicolon(None); parser.maybe_consume_incorrect_semicolon(None);
} }
@ -328,6 +328,7 @@ fn check_item(
parsing_result parsing_result
} }
/// Returns `(has_main_fn, already_has_extern_crate, failed_ast)`.
fn check_for_main_and_extern_crate( fn check_for_main_and_extern_crate(
crate_name: Option<&str>, crate_name: Option<&str>,
original_source_code: &str, original_source_code: &str,
@ -336,16 +337,16 @@ fn check_for_main_and_extern_crate(
edition: Edition, edition: Edition,
supports_color: &mut bool, supports_color: &mut bool,
can_merge_doctests: bool, can_merge_doctests: bool,
) -> Result<(Option<Span>, bool, bool), FatalError> { ) -> Result<(bool, bool, bool), FatalError> {
let result = rustc_driver::catch_fatal_errors(|| { let result = rustc_driver::catch_fatal_errors(|| {
rustc_span::create_session_if_not_set_then(edition, |_| { rustc_span::create_session_if_not_set_then(edition, |_| {
let mut found_main_span = None; let mut has_main_fn = false;
let mut found_extern_crate = crate_name.is_none(); let mut found_extern_crate = crate_name.is_none();
let mut found_macro = false; let mut found_macro = false;
let mut parsing_result = parse_source( let mut parsing_result = parse_source(
format!("{crates}{everything_else}"), format!("{crates}{everything_else}"),
&mut found_main_span, &mut has_main_fn,
&mut found_extern_crate, &mut found_extern_crate,
&mut found_macro, &mut found_macro,
&crate_name, &crate_name,
@ -366,7 +367,7 @@ fn check_for_main_and_extern_crate(
// faster doctests run time. // faster doctests run time.
parsing_result = parse_source( parsing_result = parse_source(
format!("{crates}\nfn __doctest_wrap(){{{everything_else}\n}}"), format!("{crates}\nfn __doctest_wrap(){{{everything_else}\n}}"),
&mut found_main_span, &mut has_main_fn,
&mut found_extern_crate, &mut found_extern_crate,
&mut found_macro, &mut found_macro,
&crate_name, &crate_name,
@ -374,13 +375,13 @@ fn check_for_main_and_extern_crate(
); );
} }
(found_main_span, found_extern_crate, found_macro, parsing_result) (has_main_fn, found_extern_crate, found_macro, parsing_result)
}) })
}); });
let (mut main_fn_span, already_has_extern_crate, found_macro, parsing_result) = match result { let (mut has_main_fn, already_has_extern_crate, found_macro, parsing_result) = match result {
Err(..) | Ok((_, _, _, ParsingResult::Failed)) => return Err(FatalError), Err(..) | Ok((_, _, _, ParsingResult::Failed)) => return Err(FatalError),
Ok((main_fn_span, already_has_extern_crate, found_macro, parsing_result)) => { Ok((has_main_fn, already_has_extern_crate, found_macro, parsing_result)) => {
(main_fn_span, already_has_extern_crate, found_macro, parsing_result) (has_main_fn, already_has_extern_crate, found_macro, parsing_result)
} }
}; };
@ -389,7 +390,7 @@ fn check_for_main_and_extern_crate(
// function written inside a macro invocation. See // function written inside a macro invocation. See
// https://github.com/rust-lang/rust/issues/56898 // https://github.com/rust-lang/rust/issues/56898
if found_macro if found_macro
&& main_fn_span.is_none() && !has_main_fn
&& original_source_code && original_source_code
.lines() .lines()
.map(|line| { .map(|line| {
@ -398,10 +399,10 @@ fn check_for_main_and_extern_crate(
}) })
.any(|code| code.contains("fn main")) .any(|code| code.contains("fn main"))
{ {
main_fn_span = Some(DUMMY_SP); has_main_fn = true;
} }
Ok((main_fn_span, already_has_extern_crate, parsing_result != ParsingResult::Ok)) Ok((has_main_fn, already_has_extern_crate, parsing_result != ParsingResult::Ok))
} }
fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool { fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
@ -448,6 +449,7 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
.unwrap_or(false) .unwrap_or(false)
} }
/// Returns `(crate_attrs, content, crates)`.
fn partition_source(s: &str, edition: Edition) -> (String, String, String) { fn partition_source(s: &str, edition: Edition) -> (String, String, String) {
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
enum PartitionState { enum PartitionState {
@ -456,7 +458,7 @@ enum PartitionState {
Other, Other,
} }
let mut state = PartitionState::Attrs; let mut state = PartitionState::Attrs;
let mut before = String::new(); let mut crate_attrs = String::new();
let mut crates = String::new(); let mut crates = String::new();
let mut after = String::new(); let mut after = String::new();
@ -520,8 +522,8 @@ enum PartitionState {
match state { match state {
PartitionState::Attrs => { PartitionState::Attrs => {
before.push_str(line); crate_attrs.push_str(line);
before.push('\n'); crate_attrs.push('\n');
} }
PartitionState::Crates => { PartitionState::Crates => {
crates.push_str(line); crates.push_str(line);

View File

@ -149,7 +149,7 @@ fn generate_mergeable_doctest(
writeln!(output, "mod {test_id} {{\n").unwrap(); writeln!(output, "mod {test_id} {{\n").unwrap();
} else { } else {
writeln!(output, "mod {test_id} {{\n{}", doctest.crates).unwrap(); writeln!(output, "mod {test_id} {{\n{}", doctest.crates).unwrap();
if doctest.main_fn_span.is_some() { if doctest.has_main_fn {
output.push_str(&doctest.everything_else); output.push_str(&doctest.everything_else);
} else { } else {
let returns_result = if doctest.everything_else.trim_end().ends_with("(())") { let returns_result = if doctest.everything_else.trim_end().ends_with("(())") {