From 09806220337d559ebbb41b4fdfcc452365d328e7 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 10 Apr 2025 11:49:08 +0200 Subject: [PATCH 01/10] Don't allow flattened format_args in const. (cherry picked from commit cc791ebe60f936355ffa62a53789cc69bcfde7e6) --- library/core/src/fmt/rt.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index d27f7e6e0d8e6..eab48466599a6 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -205,8 +205,15 @@ impl Argument<'_> { /// let f = format_args!("{}", "a"); /// println!("{f}"); /// ``` + /// + /// This function should _not_ be const, to make sure we don't accept + /// format_args!() and panic!() with arguments in const, even when not evaluated: + /// + /// ```compile_fail,E0015 + /// const _: () = if false { panic!("a {}", "a") }; + /// ``` #[inline] - pub const fn none() -> [Self; 0] { + pub fn none() -> [Self; 0] { [] } } From 4ad0f1e1d3fd5e39cdd30c153ccf780cdc2d1c5b Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 30 Apr 2025 13:18:21 +0200 Subject: [PATCH 02/10] Add test for format_args!("{}", 0) in const. (cherry picked from commit 56426db0b634fcd8d7e5842f39593651a594e602) --- tests/ui/consts/const-eval/format.rs | 5 +++++ tests/ui/consts/const-eval/format.stderr | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/ui/consts/const-eval/format.rs b/tests/ui/consts/const-eval/format.rs index 1878fc0382767..a8085a786e189 100644 --- a/tests/ui/consts/const-eval/format.rs +++ b/tests/ui/consts/const-eval/format.rs @@ -9,4 +9,9 @@ const fn print() { //~| ERROR cannot call non-const function `_print` in constant functions } +const fn format_args() { + format_args!("{}", 0); + //~^ ERROR cannot call non-const formatting macro in constant functions +} + fn main() {} diff --git a/tests/ui/consts/const-eval/format.stderr b/tests/ui/consts/const-eval/format.stderr index e8d7bbcea0917..4c4cbb372a7fd 100644 --- a/tests/ui/consts/const-eval/format.stderr +++ b/tests/ui/consts/const-eval/format.stderr @@ -24,6 +24,14 @@ LL | println!("{:?}", 0); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 3 previous errors +error[E0015]: cannot call non-const formatting macro in constant functions + --> $DIR/format.rs:13:5 + | +LL | format_args!("{}", 0); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0015`. From 8ec60ca601d5dab5cb1fac0edc0cc5b1f07d8244 Mon Sep 17 00:00:00 2001 From: usamoi Date: Sun, 13 Apr 2025 23:18:39 +0800 Subject: [PATCH 03/10] set subsections_via_symbols for ld64 helper sections (cherry picked from commit b1a38313cb0dee9a7c5573ae37ad48b0a347cb7c) --- compiler/rustc_codegen_ssa/src/back/link.rs | 6 +++++ tests/ui/linking/cdylib-no-mangle.rs | 20 ++++++++++++++ .../ui/linking/executable-no-mangle-strip.rs | 27 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 tests/ui/linking/cdylib-no-mangle.rs create mode 100644 tests/ui/linking/executable-no-mangle-strip.rs diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index b59d73a9aae09..5f170be354dff 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2011,6 +2011,12 @@ fn add_linked_symbol_object( file.set_mangling(object::write::Mangling::None); } + if file.format() == object::BinaryFormat::MachO { + // Divide up the sections into sub-sections via symbols for dead code stripping. + // Without this flag, unused `#[no_mangle]` or `#[used]` cannot be discard on MachO targets. + file.set_subsections_via_symbols(); + } + // ld64 requires a relocation to load undefined symbols, see below. // Not strictly needed if linking with lld, but might as well do it there too. let ld64_section_helper = if file.format() == object::BinaryFormat::MachO { diff --git a/tests/ui/linking/cdylib-no-mangle.rs b/tests/ui/linking/cdylib-no-mangle.rs new file mode 100644 index 0000000000000..f442c3f584d6e --- /dev/null +++ b/tests/ui/linking/cdylib-no-mangle.rs @@ -0,0 +1,20 @@ +//@ only-apple +//@ build-fail +//@ dont-check-compiler-stderr +//@ dont-check-compiler-stdout + +// Regression test for . +// Functions in the dynamic library marked with no_mangle should not be GC-ed. + +#![crate_type = "cdylib"] + +unsafe extern "C" { + unsafe static THIS_SYMBOL_SHOULD_BE_UNDEFINED: usize; +} + +#[unsafe(no_mangle)] +pub unsafe fn function_marked_with_no_mangle() { + println!("FUNCTION_MARKED_WITH_NO_MANGLE = {}", unsafe { THIS_SYMBOL_SHOULD_BE_UNDEFINED }); +} + +//~? ERROR linking diff --git a/tests/ui/linking/executable-no-mangle-strip.rs b/tests/ui/linking/executable-no-mangle-strip.rs new file mode 100644 index 0000000000000..cc283dc53ee3a --- /dev/null +++ b/tests/ui/linking/executable-no-mangle-strip.rs @@ -0,0 +1,27 @@ +//@ run-pass +//@ ignore-windows-gnu: only statics marked with used can be GC-ed on windows-gnu + +// Regression test for . +// Functions in the binary marked with no_mangle should be GC-ed if they +// are not indirectly referenced by main. + +#![feature(used_with_arg)] + +#[cfg_attr(windows, link(name = "this_lib_does_not_exist", kind = "raw-dylib"))] +unsafe extern "C" { + unsafe static THIS_SYMBOL_SHOULD_BE_UNDEFINED: usize; +} + +#[unsafe(no_mangle)] +pub unsafe fn function_marked_with_no_mangle() { + println!("FUNCTION_MARKED_WITH_NO_MANGLE = {}", unsafe { THIS_SYMBOL_SHOULD_BE_UNDEFINED }); +} + +#[used(compiler)] +pub static FUNCTION_MARKED_WITH_USED: unsafe fn() = || { + println!("FUNCTION_MARKED_WITH_USED = {}", unsafe { THIS_SYMBOL_SHOULD_BE_UNDEFINED }); +}; + +fn main() { + println!("MAIN"); +} From 0457f2e9273b69c8e00a0a113e62e460a96c2fcf Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 23 Apr 2025 22:09:11 +0200 Subject: [PATCH 04/10] Fix detection of `main` function if there are expressions around it (cherry picked from commit 35363245657ee53a3735f1cef0df9a45e9ed44b9) --- src/librustdoc/doctest/make.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 56b1e76ae8cfd..3896a3c6761f9 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -411,15 +411,19 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { is_extern_crate = check_item(&item, &mut info, crate_name); } - StmtKind::Expr(ref expr) if matches!(expr.kind, ast::ExprKind::Err(_)) => { - reset_error_count(&psess); - return Err(()); + StmtKind::Expr(ref expr) => { + if matches!(expr.kind, ast::ExprKind::Err(_)) { + reset_error_count(&psess); + return Err(()); + } + has_non_module_items = true; } StmtKind::MacCall(ref mac_call) if !info.has_main_fn => { let mut iter = mac_call.mac.args.tokens.iter(); @@ -441,7 +445,11 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result {} + // We do nothing in this case. Not marking it as `non_module_items` either. + StmtKind::Empty => {} + _ => { + has_non_module_items = true; + } } // Weirdly enough, the `Stmt` span doesn't include its attributes, so we need to @@ -466,6 +474,11 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { From 745d54e5b29ccd3712d2739eace6e269e7c4cbfb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 23 Apr 2025 22:09:35 +0200 Subject: [PATCH 05/10] Add regression ui test for #140162 and for #139651 (cherry picked from commit 81438c0b05f177ae7bc0d6511d1cc507652eb241) --- .../doctest/test-main-alongside-exprs.rs | 22 +++++++++++++++++++ .../doctest/test-main-alongside-exprs.stdout | 6 +++++ 2 files changed, 28 insertions(+) create mode 100644 tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs create mode 100644 tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout diff --git a/tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs b/tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs new file mode 100644 index 0000000000000..ee2299c0fd87e --- /dev/null +++ b/tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs @@ -0,0 +1,22 @@ +// This test ensures that if there is an expression alongside a `main` +// function, it will not consider the entire code to be part of the `main` +// function and will generate its own function to wrap everything. +// +// This is a regression test for: +// * +// * +//@ compile-flags:--test +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ check-pass + +#![crate_name = "foo"] + +//! ``` +//! # if cfg!(miri) { return; } +//! use std::ops::Deref; +//! +//! fn main() { +//! println!("Hi!"); +//! } +//! ``` diff --git a/tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout b/tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout new file mode 100644 index 0000000000000..90d7c3546bf10 --- /dev/null +++ b/tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/test-main-alongside-exprs.rs - (line 15) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + From 692490898bc3350e37bbb9bb08c4b2b2811600c0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 25 Apr 2025 22:01:00 +0200 Subject: [PATCH 06/10] Improve code (cherry picked from commit 3ededc1053f752d993a0b25286faebfe3616819d) --- src/librustdoc/doctest/make.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 3896a3c6761f9..1d5d3daf67f4d 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -411,7 +411,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result) -> Result { let mut iter = mac_call.mac.args.tokens.iter(); @@ -448,7 +451,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result {} _ => { - has_non_module_items = true; + has_non_items = true; } } @@ -474,7 +477,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result Date: Fri, 25 Apr 2025 22:04:50 +0200 Subject: [PATCH 07/10] If there is a `;` alone, we consider that the doctest needs to be put inside a function (cherry picked from commit 3ef98a55ef95b058e55897f1b213dd965839e3ed) --- src/librustdoc/doctest/make.rs | 2 -- .../failed-doctest-extra-semicolon-on-item.rs | 4 +-- ...led-doctest-extra-semicolon-on-item.stdout | 27 ++----------------- 3 files changed, 4 insertions(+), 29 deletions(-) diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 1d5d3daf67f4d..d0758c521e089 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -448,8 +448,6 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result {} _ => { has_non_items = true; } diff --git a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs index 508faadcf6729..ca5dd78746789 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs +++ b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs @@ -4,12 +4,12 @@ //@ compile-flags:--test //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ failure-status: 101 +//@ check-pass /// /// /// ```rust -/// struct S {}; // unexpected semicolon after struct def +/// struct S {}; /// /// fn main() { /// assert_eq!(0, 1); diff --git a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout index 9eb8b391e7809..1068b98cb0fbb 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout +++ b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout @@ -1,29 +1,6 @@ running 1 test -test $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) ... FAILED +test $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) ... ok -failures: - ----- $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) stdout ---- -error: expected item, found `;` - --> $DIR/failed-doctest-extra-semicolon-on-item.rs:12:12 - | -LL | struct S {}; // unexpected semicolon after struct def - | ^ - | - = help: braced struct declarations are not followed by a semicolon -help: remove this semicolon - | -LL - struct S {}; // unexpected semicolon after struct def -LL + struct S {} // unexpected semicolon after struct def - | - -error: aborting due to 1 previous error - -Couldn't compile the test. - -failures: - $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) - -test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME From 1f6a6b1008f1ebf6aa4a8cf1a0a00ebd7f401792 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 27 Apr 2025 00:12:32 +0200 Subject: [PATCH 08/10] Fix bad handling of macros if there is already a `main` function (cherry picked from commit aa69e3a0cb8f1b2e086709a038baad6f39249150) --- src/librustdoc/doctest/make.rs | 5 ++++- .../doctest/auxiliary/macro-after-main.rs | 1 + tests/rustdoc-ui/doctest/macro-after-main.rs | 16 ++++++++++++++++ tests/rustdoc-ui/doctest/macro-after-main.stdout | 6 ++++++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs create mode 100644 tests/rustdoc-ui/doctest/macro-after-main.rs create mode 100644 tests/rustdoc-ui/doctest/macro-after-main.stdout diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index d0758c521e089..cdca25abec8c0 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -428,7 +428,10 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { + StmtKind::MacCall(ref mac_call) => { + if info.has_main_fn { + continue; + } let mut iter = mac_call.mac.args.tokens.iter(); while let Some(token) = iter.next() { diff --git a/tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs b/tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs new file mode 100644 index 0000000000000..ed7584b742533 --- /dev/null +++ b/tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs @@ -0,0 +1 @@ +use std::string::String; diff --git a/tests/rustdoc-ui/doctest/macro-after-main.rs b/tests/rustdoc-ui/doctest/macro-after-main.rs new file mode 100644 index 0000000000000..0a42343f1c272 --- /dev/null +++ b/tests/rustdoc-ui/doctest/macro-after-main.rs @@ -0,0 +1,16 @@ +// This test checks a corner case where the macro calls used to be skipped, +// making them considered as statement, and therefore some cases where +// `include!` macro was then put into a function body, making the doctest +// compilation fail. + +//@ compile-flags:--test +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ check-pass + +//! ``` +//! include!("./auxiliary/macro-after-main.rs"); +//! +//! fn main() {} +//! eprintln!(); +//! ``` diff --git a/tests/rustdoc-ui/doctest/macro-after-main.stdout b/tests/rustdoc-ui/doctest/macro-after-main.stdout new file mode 100644 index 0000000000000..72ffe2b5a27c5 --- /dev/null +++ b/tests/rustdoc-ui/doctest/macro-after-main.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/macro-after-main.rs - (line 11) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + From 8a4c4721cc1cab50c98552b97552d67d002a1c90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 29 Apr 2025 02:11:41 +0200 Subject: [PATCH 09/10] rustdoc: Fix doctest heuristic for main fn wrapping (cherry picked from commit 714ea10ea41e97310a1b3d90fed4cfb3e2dd6b73) --- src/librustdoc/doctest/make.rs | 65 ++++++++----------- tests/rustdoc-ui/doctest/auxiliary/items.rs | 1 + .../doctest/auxiliary/macro-after-main.rs | 1 - tests/rustdoc-ui/doctest/macro-after-main.rs | 16 ----- .../doctest/macro-after-main.stdout | 6 -- .../main-alongside-macro-calls.fail.stdout | 60 +++++++++++++++++ .../main-alongside-macro-calls.pass.stdout | 9 +++ .../doctest/main-alongside-macro-calls.rs | 44 +++++++++++++ .../doctest/main-alongside-stmts.rs | 33 ++++++++++ .../doctest/main-alongside-stmts.stdout | 7 ++ .../doctest/test-main-alongside-exprs.rs | 22 ------- .../doctest/test-main-alongside-exprs.stdout | 6 -- 12 files changed, 182 insertions(+), 88 deletions(-) create mode 100644 tests/rustdoc-ui/doctest/auxiliary/items.rs delete mode 100644 tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs delete mode 100644 tests/rustdoc-ui/doctest/macro-after-main.rs delete mode 100644 tests/rustdoc-ui/doctest/macro-after-main.stdout create mode 100644 tests/rustdoc-ui/doctest/main-alongside-macro-calls.fail.stdout create mode 100644 tests/rustdoc-ui/doctest/main-alongside-macro-calls.pass.stdout create mode 100644 tests/rustdoc-ui/doctest/main-alongside-macro-calls.rs create mode 100644 tests/rustdoc-ui/doctest/main-alongside-stmts.rs create mode 100644 tests/rustdoc-ui/doctest/main-alongside-stmts.stdout delete mode 100644 tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs delete mode 100644 tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index cdca25abec8c0..ea9b686c08016 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -301,8 +301,6 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result) -> Result) -> Result) -> bool { let mut is_extern_crate = false; if !info.has_global_allocator @@ -351,8 +347,6 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { - // We only push if it's the top item because otherwise, we would duplicate - // its content since the top-level item was already added. if item.ident.name == sym::main { info.has_main_fn = true; } @@ -416,44 +410,41 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { - is_extern_crate = check_item(&item, &mut info, crate_name); - } - StmtKind::Expr(ref expr) => { - if matches!(expr.kind, ast::ExprKind::Err(_)) { - reset_error_count(&psess); - return Err(()); - } - has_non_items = true; + is_extern_crate = check_item(item, &mut info, crate_name); } // We assume that the macro calls will expand to item(s) even though they could - // expand to statements and expressions. And the simple fact that we're trying - // to retrieve a `main` function inside it is a terrible idea. + // expand to statements and expressions. StmtKind::MacCall(ref mac_call) => { - if info.has_main_fn { - continue; - } - let mut iter = mac_call.mac.args.tokens.iter(); - - while let Some(token) = iter.next() { - if let TokenTree::Token(token, _) = token - && let TokenKind::Ident(name, _) = token.kind - && name == kw::Fn - && let Some(TokenTree::Token(fn_token, _)) = iter.peek() - && let TokenKind::Ident(fn_name, _) = fn_token.kind - && fn_name == sym::main - && let Some(TokenTree::Delimited(_, _, Delimiter::Parenthesis, _)) = { - iter.next(); - iter.peek() + if !info.has_main_fn { + // For backward compatibility, we look for the token sequence `fn main(…)` + // in the macro input (!) to crudely detect main functions "masked by a + // wrapper macro". For the record, this is a horrible heuristic! + // See . + let mut iter = mac_call.mac.args.tokens.iter(); + while let Some(token) = iter.next() { + if let TokenTree::Token(token, _) = token + && let TokenKind::Ident(kw::Fn, _) = token.kind + && let Some(TokenTree::Token(ident, _)) = iter.peek() + && let TokenKind::Ident(sym::main, _) = ident.kind + && let Some(TokenTree::Delimited(.., Delimiter::Parenthesis, _)) = { + iter.next(); + iter.peek() + } + { + info.has_main_fn = true; + break; } - { - info.has_main_fn = true; - break; } } } - _ => { + StmtKind::Expr(ref expr) => { + if matches!(expr.kind, ast::ExprKind::Err(_)) { + reset_error_count(&psess); + return Err(()); + } has_non_items = true; } + StmtKind::Let(_) | StmtKind::Semi(_) | StmtKind::Empty => has_non_items = true, } // Weirdly enough, the `Stmt` span doesn't include its attributes, so we need to diff --git a/tests/rustdoc-ui/doctest/auxiliary/items.rs b/tests/rustdoc-ui/doctest/auxiliary/items.rs new file mode 100644 index 0000000000000..40d4eb261e5a0 --- /dev/null +++ b/tests/rustdoc-ui/doctest/auxiliary/items.rs @@ -0,0 +1 @@ +fn item() {} diff --git a/tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs b/tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs deleted file mode 100644 index ed7584b742533..0000000000000 --- a/tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs +++ /dev/null @@ -1 +0,0 @@ -use std::string::String; diff --git a/tests/rustdoc-ui/doctest/macro-after-main.rs b/tests/rustdoc-ui/doctest/macro-after-main.rs deleted file mode 100644 index 0a42343f1c272..0000000000000 --- a/tests/rustdoc-ui/doctest/macro-after-main.rs +++ /dev/null @@ -1,16 +0,0 @@ -// This test checks a corner case where the macro calls used to be skipped, -// making them considered as statement, and therefore some cases where -// `include!` macro was then put into a function body, making the doctest -// compilation fail. - -//@ compile-flags:--test -//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" -//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ check-pass - -//! ``` -//! include!("./auxiliary/macro-after-main.rs"); -//! -//! fn main() {} -//! eprintln!(); -//! ``` diff --git a/tests/rustdoc-ui/doctest/macro-after-main.stdout b/tests/rustdoc-ui/doctest/macro-after-main.stdout deleted file mode 100644 index 72ffe2b5a27c5..0000000000000 --- a/tests/rustdoc-ui/doctest/macro-after-main.stdout +++ /dev/null @@ -1,6 +0,0 @@ - -running 1 test -test $DIR/macro-after-main.rs - (line 11) ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME - diff --git a/tests/rustdoc-ui/doctest/main-alongside-macro-calls.fail.stdout b/tests/rustdoc-ui/doctest/main-alongside-macro-calls.fail.stdout new file mode 100644 index 0000000000000..65989a8ef47c7 --- /dev/null +++ b/tests/rustdoc-ui/doctest/main-alongside-macro-calls.fail.stdout @@ -0,0 +1,60 @@ + +running 4 tests +test $DIR/main-alongside-macro-calls.rs - (line 19) ... ok +test $DIR/main-alongside-macro-calls.rs - (line 24) ... ok +test $DIR/main-alongside-macro-calls.rs - (line 28) ... FAILED +test $DIR/main-alongside-macro-calls.rs - (line 33) ... FAILED + +failures: + +---- $DIR/main-alongside-macro-calls.rs - (line 28) stdout ---- +error: macros that expand to items must be delimited with braces or followed by a semicolon + --> $DIR/main-alongside-macro-calls.rs:30:1 + | +LL | println!(); + | ^^^^^^^^^^ + | + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: macro expansion ignores `{` and any tokens following + --> $SRC_DIR/std/src/macros.rs:LL:COL + | + ::: $DIR/main-alongside-macro-calls.rs:30:1 + | +LL | println!(); + | ---------- caused by the macro expansion here + | + = note: the usage of `print!` is likely invalid in item context + +error: aborting due to 2 previous errors + +Couldn't compile the test. +---- $DIR/main-alongside-macro-calls.rs - (line 33) stdout ---- +error: macros that expand to items must be delimited with braces or followed by a semicolon + --> $DIR/main-alongside-macro-calls.rs:34:1 + | +LL | println!(); + | ^^^^^^^^^^ + | + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: macro expansion ignores `{` and any tokens following + --> $SRC_DIR/std/src/macros.rs:LL:COL + | + ::: $DIR/main-alongside-macro-calls.rs:34:1 + | +LL | println!(); + | ---------- caused by the macro expansion here + | + = note: the usage of `print!` is likely invalid in item context + +error: aborting due to 2 previous errors + +Couldn't compile the test. + +failures: + $DIR/main-alongside-macro-calls.rs - (line 28) + $DIR/main-alongside-macro-calls.rs - (line 33) + +test result: FAILED. 2 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/main-alongside-macro-calls.pass.stdout b/tests/rustdoc-ui/doctest/main-alongside-macro-calls.pass.stdout new file mode 100644 index 0000000000000..93a4bbd87368d --- /dev/null +++ b/tests/rustdoc-ui/doctest/main-alongside-macro-calls.pass.stdout @@ -0,0 +1,9 @@ + +running 4 tests +test $DIR/main-alongside-macro-calls.rs - (line 19) ... ok +test $DIR/main-alongside-macro-calls.rs - (line 24) ... ok +test $DIR/main-alongside-macro-calls.rs - (line 28) - compile fail ... ok +test $DIR/main-alongside-macro-calls.rs - (line 33) - compile fail ... ok + +test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/main-alongside-macro-calls.rs b/tests/rustdoc-ui/doctest/main-alongside-macro-calls.rs new file mode 100644 index 0000000000000..b455d8b0cc356 --- /dev/null +++ b/tests/rustdoc-ui/doctest/main-alongside-macro-calls.rs @@ -0,0 +1,44 @@ +// This test ensures that if there is are any macro calls alongside a `main` function, +// it will indeed consider the `main` function as the program entry point and *won't* +// generate its own `main` function to wrap everything even though macro calls are +// valid in statement contexts, too, and could just as well expand to statements or +// expressions (we don't perform any macro expansion to find `main`, see also +// ). +// +// See <./main-alongside-stmts.rs> for comparison. +// +//@ compile-flags:--test --test-args --test-threads=1 +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ revisions: pass fail +//@[pass] check-pass +//@[fail] failure-status: 101 + +// Regression test for : + +//! ``` +//! fn main() {} +//! include!("./auxiliary/items.rs"); +//! ``` +//! +//! ``` +//! include!("./auxiliary/items.rs"); +//! fn main() {} +//! ``` + +// Regression test for : +// We test the "same" thing twice: Once via `compile_fail` to more closely mirror the reported +// regression and once without it to make sure that it leads to the expected rustc errors, +// namely `println!(…)` not being valid in item contexts. + +#![cfg_attr(pass, doc = " ```compile_fail")] +#![cfg_attr(fail, doc = " ```")] +//! fn main() {} +//! println!(); +//! ``` +//! +#![cfg_attr(pass, doc = " ```compile_fail")] +#![cfg_attr(fail, doc = " ```")] +//! println!(); +//! fn main() {} +//! ``` diff --git a/tests/rustdoc-ui/doctest/main-alongside-stmts.rs b/tests/rustdoc-ui/doctest/main-alongside-stmts.rs new file mode 100644 index 0000000000000..5965f928cdd13 --- /dev/null +++ b/tests/rustdoc-ui/doctest/main-alongside-stmts.rs @@ -0,0 +1,33 @@ +// This test ensures that if there is are any statements alongside a `main` function, +// it will not consider the `main` function as the program entry point but instead +// will generate its own `main` function to wrap everything as it needs to reside in a +// module where only *items* are permitted syntactically. +// +// See <./main-alongside-macro-calls.rs> for comparison. +// +// This is a regression test for: +// * +// * +// +//@ compile-flags:--test --test-args --test-threads=1 +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ check-pass + +//! ``` +//! # if cfg!(miri) { return; } +//! use std::ops::Deref; +//! +//! fn main() { +//! assert!(false); +//! } +//! ``` +//! +//! ``` +//! let x = 2; +//! assert_eq!(x, 2); +//! +//! fn main() { +//! assert!(false); +//! } +//! ``` diff --git a/tests/rustdoc-ui/doctest/main-alongside-stmts.stdout b/tests/rustdoc-ui/doctest/main-alongside-stmts.stdout new file mode 100644 index 0000000000000..9b9a3fe8a68f7 --- /dev/null +++ b/tests/rustdoc-ui/doctest/main-alongside-stmts.stdout @@ -0,0 +1,7 @@ + +running 2 tests +test $DIR/main-alongside-stmts.rs - (line 17) ... ok +test $DIR/main-alongside-stmts.rs - (line 26) ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs b/tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs deleted file mode 100644 index ee2299c0fd87e..0000000000000 --- a/tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs +++ /dev/null @@ -1,22 +0,0 @@ -// This test ensures that if there is an expression alongside a `main` -// function, it will not consider the entire code to be part of the `main` -// function and will generate its own function to wrap everything. -// -// This is a regression test for: -// * -// * -//@ compile-flags:--test -//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" -//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ check-pass - -#![crate_name = "foo"] - -//! ``` -//! # if cfg!(miri) { return; } -//! use std::ops::Deref; -//! -//! fn main() { -//! println!("Hi!"); -//! } -//! ``` diff --git a/tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout b/tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout deleted file mode 100644 index 90d7c3546bf10..0000000000000 --- a/tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout +++ /dev/null @@ -1,6 +0,0 @@ - -running 1 test -test $DIR/test-main-alongside-exprs.rs - (line 15) ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME - From 260fcc67f395d6961b8c1776c6c5cf64e8839517 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 1 May 2025 19:17:56 +0000 Subject: [PATCH 10/10] extend the list of registered dylibs on `test::prepare_cargo_test` Signed-off-by: onur-ozkan (cherry picked from commit 7b25d4a99edc12909dc73c31cb6a44238c4b9bf9) --- src/bootstrap/src/core/build_steps/test.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 81f6b473c4593..0948a880827fa 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2570,9 +2570,9 @@ fn prepare_cargo_test( // We skip everything on Miri as then this overwrites the libdir set up // by `Cargo::new` and that actually makes things go wrong. if builder.kind != Kind::Miri { - let mut dylib_path = dylib_path(); - dylib_path.insert(0, PathBuf::from(&*builder.sysroot_target_libdir(compiler, target))); - cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); + let mut dylib_paths = builder.rustc_lib_paths(compiler); + dylib_paths.push(PathBuf::from(&builder.sysroot_target_libdir(compiler, target))); + helpers::add_dylib_path(dylib_paths, &mut cargo); } if builder.remote_tested(target) {