Repository navigation
Large fallout from semicolon_in_expressions_from_non_local_macros #162872
Description
The semicolon_in_expressions_from_macros lint has existed since forever; see #159218 for details. The lint was slowly ramped up over the course of more than 4 years. However, it only ever warned about macros defined in the crate they are used.
The following changes were made during the 1.99 development window:
- The old lint was extended to also fire if crate A uses a macro from crate B that has the semicolon problem (deny-by-default, report-in-deps).
- This caused a lot of errors so the cross-crate case was split into a separate lint,
semicolon_in_expressions_from_non_local_macros(warn-by-default, report-in-deps). - After beta branched off, that new lint was downgraded to warn-by-default, no-report-in-deps. ([beta] make semicolon_in_expressions_from_non_local_macros not report-in-deps #162765, landed via manual rollup)
This means that in Rust 1.99, we will have a new lint semicolon_in_expressions_from_non_local_macros that also fires if crate A uses a macro from crate B that has the semicolon problem. This lint is warn-by-default and does not show up in deps. In current nightly, which will become Rust 1.100, the lint is marked as report-in-deps (while remaining warn-by-default). That is a rather quick ramp-up for a lint that is triggered widely across the ecosystem:
- It triggered in two independent cases even in dependencies of the rustc workspace.
- Tracking Issue for denying trailing semicolons in expression macro bodies #79813 started getting a huge amount of backlinks when we started linting the non-local case on July 15th.
- Anecdotally, multiple people reported on Zulip that they encounter this lint way above the usual rate at which they encounter FCW.
Additionally, the reports one gets for this lint from dependencies are quite confusing, by nature of this being about macros: if the lint triggers in crate A when using macro M, then the actual issue is in crate B that defined the macro. A user just sees "the version of nix you are using will stop compiling in the future", but what they don't know and cannot easily find out is that they actually have to update cfg_aliases to make this warning disappear.
So, given all that... maybe we should slow down a little, and not ramp up the lint for the non-local case from "nothing" in 1.98 to "report in deps" in 1.100, over a mere two releases? It is anyway rather odd that the lint is warn-by-default but also report-in-deps; if we think it is too invasive to make it deny-by-default then maybe it is too early to make it report-in-deps. I think what happened is that people didn't realize that for 4 years we only linted for the local case, and when they realized they wanted to quickly add the non-local case to not slow down the cleanup that is blocked on this FCW... but I don't think that's a good enough reason to rush semicolon_in_expressions_from_non_local_macros as much as we are currently rushing it, given the fallout this is causing.
A crater run turning both lints into hard errors has been queued, to figure out the overall effect on the ecosystem.
@rust-lang/lang so given what we now know about the fallout of semicolon_in_expressions_from_non_local_macros, how would you like to proceed?
- Keep it as report-in-deps for Rust 1.100,
- or slow down and make it not-report-in-deps for now, let it bake for a bit, and then eventually bump it to deny + report-in-deps?
If we do nothing, then in 8 weeks Rust 1.100 will be released with the first option.
Activity
steffahn commentedon Sep 25, 2026
Usually lints becoming deny-on-default before (or at least not after) being report-in-deps makes sense; it makes that we work on getting the message to the right place first; the crate that causes the error and needs to update. Whereas in a dependency, all you can do is report upstream; or (as a secondary function) it notifies dependents to make sure that they update their dependencies (and/or their lockfiles) in order to actually receive an already existing updated version.
semicolon_in_expressions_from_non_local_macrosis a bit untypical though in that it will only affect dependencies (of the crate defining the macro) even when the actual problem is (often) in the macro definition itself. So as it's not necessarily something that's fixable by the depending (and linted-against) crate directly.This means it's reasonable to do report-in-deps without (or before) making things deny-by-default. Adding report-in-deps then serves to increase the chance that word of the problems actually makes it upstream to all affected crates.
IMHO, a slower ramp-up sounds like a good idea though! It leave some more time for people to resolve some of those cases where visibility only through reporting in direct users of the macro (and not also their dependents) is already suffiently noisy. It doesn't help anyone to drive more people than necessary to report such issues upstream - we all know how exhausting / pressuring that could end up being; let's not risk crate authors or maintainers could be seen as responsible for what ultimately was our oversight (for not linting against this case earlier).
[Perhaps it would have even made sense to leave it allow-by-default for some duration, and first identify some key affected crates in the ecosystem ourselves through crater; before turning on the warning which effectively delegates the reporting responsibility for the remaining cases to the respective dependent crates.]
RalfJung commentedon Sep 25, 2026
The crater run came back with the largest number of regressions I have ever seen in a crater run: more than 45k. This dwarves even the massive fallout from #162478 by almost a factor of 2.
I don't know what to do long-term, but short term I think we should remove the report-in-deps, and backport that to the beta that branched today.
xtqqczze commentedon Sep 25, 2026
Does the
semicolon_in_expressions_from_non_local_macroslint work transitively? For example, if crate A depends on crate B, which uses a macro from crate C that has the semicolon problem, will the lint also fire for crate A?asquared31415 commentedon Sep 25, 2026
Yes, and that's one of the big problems. The lint fires when the expansion happens, and the origin of the macro might be from a crate that's not even listed in the error message. The typical example was that anyone using the
nixcrate would get a FCW that "nixwill be rejected in future versions of rustc", when the problem was actually thatcfg_aliasesneeded to be upgraded (and nix could in fact be left alone in this case).xtqqczze commentedon Sep 25, 2026
Is there no note like this?
= note: this error originates in the macro `$crate::cfg_aliases` which comes from the expansion of the macro `cfg_aliases` (in Nightly builds, run with -Z macro-backtrace for more info)steffahn commentedon Sep 25, 2026
If the crater fallout is extraordinarily large, maybe a last-minute beta patch into
1.1001.99, lowering the level to allow-by-default, is still worth for consideration?This could allow us more time for targeted approaches to the most relevant root cause crates in the ecosystem without putting unnecessary pressure on them from already activating lints emitted to their direct users in stable Rust.
Do we happen to have any numbers on how many crates are still going to see this warning, without report-in-deps?
RalfJung commentedon Sep 26, 2026
No, there is not.
It is warn-by-default in 1.99. I think given that it's no-report-in-deps that's fine.
I don't know how we could get such numbers.
theemathas commentedon Sep 26, 2026
Running a crater with
+rustflags=-Dsemicolon_in_expressions_from_non_local_macrosshould do that. See https://github.com/rust-lang/crater/blob/master/docs/bot-usage.mdRalfJung commentedon Sep 26, 2026
I guess we can look at the "root regressions" section of the crater report. Unfortunately the report shows very confusing numbers but I think there are 1500 regressions directly in the root crate.
(That's for making both of the semicolon_in_expression lints into a hard error.)
That doesn't account for
allow(...)though.Auto merge of #163364 - RalfJung:semicolon-no-report-in-deps, r=mati865
Rollup merge of rust-lang#163364 - RalfJung:semicolon-no-report-in-de…
Rollup merge of rust-lang#163364 - RalfJung:semicolon-no-report-in-de…
Auto merge of #163364 - RalfJung:semicolon-no-report-in-deps, r=mati865
Unrolled build for #163364 in rollup 163829