-
Notifications
You must be signed in to change notification settings - Fork 13.3k
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
Conversation
fmease is on vacation. Please choose another assignee. |
r? @notriddle rustbot has assigned @notriddle. Use |
I'll review tonight! |
(If you're in vacations, it's fine not too but I really appreciate!) |
src/librustdoc/doctest/make.rs
Outdated
reset_error_count(&psess); | ||
return Err(()); | ||
} | ||
has_non_module_items = true; | ||
} | ||
StmtKind::MacCall(ref mac_call) if !info.has_main_fn => { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure!
There was a problem hiding this 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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here it is: #140310
src/librustdoc/doctest/make.rs
Outdated
@@ -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 => {} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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. :')
There was a problem hiding this comment.
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.
src/librustdoc/doctest/make.rs
Outdated
reset_error_count(&psess); | ||
return Err(()); | ||
} | ||
has_non_module_items = true; | ||
} | ||
StmtKind::MacCall(ref mac_call) if !info.has_main_fn => { |
There was a problem hiding this comment.
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.
src/librustdoc/doctest/make.rs
Outdated
reset_error_count(&psess); | ||
return Err(()); | ||
} | ||
has_non_module_items = true; | ||
} | ||
StmtKind::MacCall(ref mac_call) if !info.has_main_fn => { |
There was a problem hiding this comment.
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?
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+. |
@bors r=fmease rollup |
…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`
…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
…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
…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
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
…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
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
This seems like the most likely cause of #140356 (comment) @bors r- |
@bors try |
…, 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
☀️ Try build successful - checks-actions |
Huh, spurious then? @bors r=fmease rollup=maybe |
…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
…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
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
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 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 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. |
🤔 |
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