Skip to content

Fix detection of main function if there are expressions around it #140220

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 28, 2025

Conversation

GuillaumeGomez
Copy link
Member

@GuillaumeGomez GuillaumeGomez commented Apr 23, 2025

Fixes #140162.
Fixes #139651.

Once this is merged, we can backport and I'll send a follow-up to emit a warning in case a main function is about to be "wrapped" (and therefore not run).

r? @fmease

try-job: x86_64-mingw-1

@rustbot
Copy link
Collaborator

rustbot commented Apr 23, 2025

fmease is on vacation.

Please choose another assignee.

@rustbot
Copy link
Collaborator

rustbot commented Apr 23, 2025

r? @notriddle

rustbot has assigned @notriddle.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels Apr 23, 2025
@fmease fmease assigned fmease and unassigned notriddle Apr 23, 2025
@fmease
Copy link
Member

fmease commented Apr 23, 2025

I'll review tonight!

@GuillaumeGomez
Copy link
Member Author

(If you're in vacations, it's fine not too but I really appreciate!)

reset_error_count(&psess);
return Err(());
}
has_non_module_items = true;
}
StmtKind::MacCall(ref mac_call) if !info.has_main_fn => {
Copy link
Member

@jyn514 jyn514 Apr 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think you need to also assume that macros can expand to expressions, not just items. in fact i think you need to do this for any statement other than an item.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I voluntarily ignored it for the simple fact that trying to match on a macro call is pretty much useless since we have no clue how it will be expanded. The fact that we match on fn main is already a pretty bad idea. If I start saying "everything that doesn't match the first condition means it's an expression", then this code would fail to compile:

include!("auxiliary/empty.rs");
fn main() {}

Because "auxiliary/empty.rs" would be considered an expression, meaning the whole code would be wrapped, and the compiler would be unhappy:

error: non-statement macro in statement position: include
  |
3 | include!("auxiliary/empty.rs");
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

So sadly, I think the best course of action here is to keep this ugly hack...

Copy link
Member

@fmease fmease Apr 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While Jyn is obviously right regarding macro expansion, older versions of rustdoc (e.g., 1.86, 1.75) don't handle those top-level macros calls correctly either, I mean ones which expand to exprs. At least from what I've gathered. I tested:

//! ```
//! macro_rules! mk { () => { if true { return; } } }
//! mk!();
//! fn main() {}
//! ```

1.88, 1.86, 1.75: macro expansion ignores keyword `if` and any tokens following // the usage of `mk!` is likely invalid in item context.


So it's fine to keep treating macro calls as item macro calls. All of this is a heuristic anyway and I'm so glad GuillaumeGomez threw out the janky partially string-based heuristics in #138104 which also used to reparse the input string multiple times.

As it's the case with all heuristics, there will always be false positives and negatives.

Copy link
Member

@fmease fmease Apr 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guillaume, could you add a short comment above the MacroCall arm mentioning that we assume that the macro calls expand to item(s) even though they could expand to stmts and exprs, too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure!

Copy link
Member

@fmease fmease left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r=me with nits addressed. sorry for the broken promise and the delay

@@ -462,6 +470,11 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
push_to_s(&mut info.crates, source, span, &mut prev_span_hi);
}
}
if has_non_module_items {
// FIXME: if `info.has_main_fn` is `true`, emit a warning here to mention that
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Could you open an issue for that unless we already have one for that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it is: #140310

@@ -437,7 +441,11 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
}
}
}
_ => {}
// We do nothing in this case. Not marking it as `non_module_items` either.
StmtKind::Empty => {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we should set has_non_module_items = true when encountering StmtKind::Empty since it represents lone ;s which are not valid items.

Consider:

//! ```
//! fn main() {};
//! ```

or

//! ```
//! ;fn main() {}
//! ```

which lead to expected item, found `;` on master.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However as a matter of fact, <=1.86 did not handle this 'correctly' either.

Copy link
Member Author

@GuillaumeGomez GuillaumeGomez Apr 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EDIT: This comment is completely wrong.

Weeeeell... Let me raise to you:

struct s{};

fn main() {}

:D

There is even tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs to check it. So sorry but I'll leave it as is for backward compatibility. :')

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, ignore my previous comment, it's not allowed to have a rogue semi-colon in code like that. I'll change it then.

reset_error_count(&psess);
return Err(());
}
has_non_module_items = true;
}
StmtKind::MacCall(ref mac_call) if !info.has_main_fn => {
Copy link
Member

@fmease fmease Apr 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While Jyn is obviously right regarding macro expansion, older versions of rustdoc (e.g., 1.86, 1.75) don't handle those top-level macros calls correctly either, I mean ones which expand to exprs. At least from what I've gathered. I tested:

//! ```
//! macro_rules! mk { () => { if true { return; } } }
//! mk!();
//! fn main() {}
//! ```

1.88, 1.86, 1.75: macro expansion ignores keyword `if` and any tokens following // the usage of `mk!` is likely invalid in item context.


So it's fine to keep treating macro calls as item macro calls. All of this is a heuristic anyway and I'm so glad GuillaumeGomez threw out the janky partially string-based heuristics in #138104 which also used to reparse the input string multiple times.

As it's the case with all heuristics, there will always be false positives and negatives.

reset_error_count(&psess);
return Err(());
}
has_non_module_items = true;
}
StmtKind::MacCall(ref mac_call) if !info.has_main_fn => {
Copy link
Member

@fmease fmease Apr 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guillaume, could you add a short comment above the MacroCall arm mentioning that we assume that the macro calls expand to item(s) even though they could expand to stmts and exprs, too?

@fmease fmease added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. beta-nominated Nominated for backporting to the compiler in the beta channel. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 25, 2025
@GuillaumeGomez
Copy link
Member Author

r=me with nits addressed. sorry for the broken promise and the delay

No worries, you're supposed to be in vacation. If I had known, I wouldn't have set you as reviewer. But in any case, thanks a lot! Gonna update then r+.

@GuillaumeGomez
Copy link
Member Author

@bors r=fmease rollup

@bors
Copy link
Collaborator

bors commented Apr 25, 2025

📌 Commit 3ef98a5 has been approved by fmease

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 25, 2025
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Apr 25, 2025
…ng, r=fmease

Fix detection of main function if there are expressions around it

Fixes rust-lang#140162.
Fixes rust-lang#139651.

Once this is merged, we can backport and I'll send a follow-up to emit a warning in case a `main` function is about to be "wrapped" (and therefore not run).

r? `@fmease`
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 26, 2025
…iaskrgr

Rollup of 9 pull requests

Successful merges:

 - rust-lang#139865 (Stabilize proc_macro::Span::{start,end,line,column}.)
 - rust-lang#140086 (If creating a temporary directory fails with permission denied then retry with backoff)
 - rust-lang#140216 (Document that "extern blocks must be unsafe" in Rust 2024)
 - rust-lang#140220 (Fix detection of main function if there are expressions around it)
 - rust-lang#140253 (Add XtensaAsmPrinter)
 - rust-lang#140272 (Improve error message for `||` (or) in let chains)
 - rust-lang#140305 (Track per-obligation recursion depth only if there is inference in the new solver)
 - rust-lang#140306 (handle specialization in the new trait solver)
 - rust-lang#140308 (stall generator witness obligations: add regression test)

r? `@ghost`
`@rustbot` modify labels: rollup
tgross35 added a commit to tgross35/rust that referenced this pull request Apr 27, 2025
…ng, r=fmease

Fix detection of main function if there are expressions around it

Fixes rust-lang#140162.
Fixes rust-lang#139651.

Once this is merged, we can backport and I'll send a follow-up to emit a warning in case a `main` function is about to be "wrapped" (and therefore not run).

r? `@fmease`

try-job: x86_64-gnu-aux
tgross35 added a commit to tgross35/rust that referenced this pull request Apr 27, 2025
…ng, r=fmease

Fix detection of main function if there are expressions around it

Fixes rust-lang#140162.
Fixes rust-lang#139651.

Once this is merged, we can backport and I'll send a follow-up to emit a warning in case a `main` function is about to be "wrapped" (and therefore not run).

r? ``@fmease``

try-job: x86_64-gnu-aux
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 27, 2025
Rollup of 7 pull requests

Successful merges:

 - rust-lang#137439 (Stabilise `std::ffi::c_str`)
 - rust-lang#138737 (uefi: Update r-efi)
 - rust-lang#139646 (check types of const param defaults)
 - rust-lang#140220 (Fix detection of main function if there are expressions around it)
 - rust-lang#140291 (Correctly display stdout and stderr in case a doctest is failing)
 - rust-lang#140297 (Update example to use CStr::to_string_lossy)
 - rust-lang#140330 (Clarified bootstrap optimization "true" argument)

r? `@ghost`
`@rustbot` modify labels: rollup
tgross35 added a commit to tgross35/rust that referenced this pull request Apr 27, 2025
…ng, r=fmease

Fix detection of main function if there are expressions around it

Fixes rust-lang#140162.
Fixes rust-lang#139651.

Once this is merged, we can backport and I'll send a follow-up to emit a warning in case a `main` function is about to be "wrapped" (and therefore not run).

r? ```@fmease```

try-job: x86_64-gnu-aux
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 27, 2025
Rollup of 8 pull requests

Successful merges:

 - rust-lang#137439 (Stabilise `std::ffi::c_str`)
 - rust-lang#139031 (Use char::is_whitespace directly in str::trim*)
 - rust-lang#139090 (fix docs for `Peekable::next_if{_eq}`)
 - rust-lang#140220 (Fix detection of main function if there are expressions around it)
 - rust-lang#140297 (Update example to use CStr::to_string_lossy)
 - rust-lang#140330 (Clarified bootstrap optimization "true" argument)
 - rust-lang#140339 (session: Cleanup `CanonicalizedPath::new`)
 - rust-lang#140348 (Update lint-docs to default to Rust 2024)

r? `@ghost`
`@rustbot` modify labels: rollup
@tgross35
Copy link
Contributor

This seems like the most likely cause of #140356 (comment)

@bors r-

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Apr 27, 2025
@tgross35
Copy link
Contributor

@bors try

@bors
Copy link
Collaborator

bors commented Apr 27, 2025

⌛ Trying commit aa69e3a with merge eee34b5...

bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 27, 2025
…, r=<try>

Fix detection of main function if there are expressions around it

Fixes rust-lang#140162.
Fixes rust-lang#139651.

Once this is merged, we can backport and I'll send a follow-up to emit a warning in case a `main` function is about to be "wrapped" (and therefore not run).

r? `@fmease`

try-job: x86_64-mingw-1
@bors
Copy link
Collaborator

bors commented Apr 27, 2025

☀️ Try build successful - checks-actions
Build commit: eee34b5 (eee34b57cac5916bdbde87e06eb6149b92dfc405)

@tgross35
Copy link
Contributor

Huh, spurious then?

@bors r=fmease rollup=maybe

@bors
Copy link
Collaborator

bors commented Apr 27, 2025

📌 Commit aa69e3a has been approved by fmease

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 27, 2025
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 28, 2025
…llaumeGomez

Rollup of 7 pull requests

Successful merges:

 - rust-lang#140056 (Fix a wrong error message in 2024 edition)
 - rust-lang#140220 (Fix detection of main function if there are expressions around it)
 - rust-lang#140249 (Remove `weak` alias terminology)
 - rust-lang#140316 (Introduce `BoxMarker` to improve pretty-printing correctness)
 - rust-lang#140347 (ci: clean more disk space in codebuild)
 - rust-lang#140349 (ci: use aws codebuild for the `dist-x86_64-linux` job)
 - rust-lang#140379 (rustc-dev-guide subtree update)

r? `@ghost`
`@rustbot` modify labels: rollup
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 28, 2025
…llaumeGomez

Rollup of 7 pull requests

Successful merges:

 - rust-lang#140056 (Fix a wrong error message in 2024 edition)
 - rust-lang#140220 (Fix detection of main function if there are expressions around it)
 - rust-lang#140249 (Remove `weak` alias terminology)
 - rust-lang#140316 (Introduce `BoxMarker` to improve pretty-printing correctness)
 - rust-lang#140347 (ci: clean more disk space in codebuild)
 - rust-lang#140349 (ci: use aws codebuild for the `dist-x86_64-linux` job)
 - rust-lang#140379 (rustc-dev-guide subtree update)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit a782b54 into rust-lang:master Apr 28, 2025
7 checks passed
@rustbot rustbot added this to the 1.88.0 milestone Apr 28, 2025
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Apr 28, 2025
Rollup merge of rust-lang#140220 - GuillaumeGomez:doctest-main-wrapping, r=fmease

Fix detection of main function if there are expressions around it

Fixes rust-lang#140162.
Fixes rust-lang#139651.

Once this is merged, we can backport and I'll send a follow-up to emit a warning in case a `main` function is about to be "wrapped" (and therefore not run).

r? `@fmease`

try-job: x86_64-mingw-1
@matthiaskrgr
Copy link
Member

maybe we should have cratered this 🤔

@fmease
Copy link
Member

fmease commented Apr 29, 2025

maybe we should have cratered this

Not really, no. We employ crater if we intentionally change a behavior whereas the negative fallout you're seeing (the failed cargotest test and now issue #140412) is due to unintentional behavior changes.

As the reviewer I gladly take the blame here. The former issue I completely missed, that's totally on me. It's great that the cargotest smoke test caught it.

Regarding the latter (#140412), I have to note that I didn't have time to re-review the PR after the latest push (I only skimmed the comments). However, that's still my fault since I should've blocked the PR on a proper re-review given the delicate nature of the doctest impl and the previous failure.

@matthiaskrgr
Copy link
Member

🤔
what I mean is, we already knew we are likely to cause negative fallout because it slipped through the cracks once, so why not make sure there is nothing more we missed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
beta-nominated Nominated for backporting to the compiler in the beta channel. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
None yet
9 participants