Repository navigation
Open
Labels
A-grammarArea: The grammar of RustArea: The grammar of RustA-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.Area: Lints (warnings about flaws in source code) such as unused_mut.A-parserArea: The lexing & parsing of Rust source code to an ASTArea: The lexing & parsing of Rust source code to an ASTC-future-incompatibilityCategory: Future-incompatibility lintsCategory: Future-incompatibility lintsC-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCL-unstable_syntax_pre_expansionLint: unstable-syntax-pre-expansionLint: unstable-syntax-pre-expansionT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language team
Description
Tip
If you've arrived here because you encountered a feature gate warning for unstable syntax behind #[cfg(…)], here's how you can transform your code while keeping the unstable syntax cfg-conditional:
Before (triggers a feature gate warning):
#[cfg(feature = "nightly")] // or a different cfg-condition
impl !Trait for Type {} // or a different unstable syntaxAfter (first approach) (idiomatic, doesn't trigger a warning):
macro_rules! generate { ($( $tt:tt )*) => { $( $tt )* } }
#[cfg(feature = "nightly")]
generate! { impl !Send for NotSend {} }After (second approach) (idiomatic, doesn't trigger a warning):
macro_rules! generate {
// Of course, you can use macro metavariables to avoid code duplication etc.
() => { impl !Trait for Type {} }
}
#[cfg(feature = "nightly")]
generate!();If you'd like to see a more realistic example, head on over to https://github.com/arcnmx/packed-rs/pull/1/changes.
Steps
- Find the most recent relevant crater runs and manually reaudit affected crates
- check if at least some crates have been fixed downstream by now
- Collect all features where the crater run has happened a long time ago & issue a single crater run for all of them at once
For all the other ones that also don't emit a pre-expansion warning yet, add warnings immediately(done)no further input from T-compiler/T-lang should be needed since it's already legitimized by MCP 535.
Affected Syntactic Constructs
- item modifier
default(featurespecializationormin_specializationfor fns only)- we potentially want to drop this feature in favor of a different approach...
- ...so a syntax gate would make it easier to phase out the syntax later on
- issue a pre-expansion feature gate warning (legitimized by MCP 535)
- turn the warning into a hard error (needs crater, T-lang FCP)
- trait impl modifier
!(featurenegative_impls)- likely to be stabilized in 1–3 years, so a syntax gate isn't super pressing
- issue a pre-expansion feature gate warning (legitimized by MCP 535)
- turn the warning into a hard error (needs crater, T-lang FCP)
- expression
try { … }(featuretry_blocks)- already has a pre-expansion feature gate warning
- incredibly likely to be stabilized this year...
- ...so a syntax gate would be counterproductive / harmful (!)
- turn the warning into a hard error (needs crater, T-lang FCP)
- pattern
box $pat(featurebox_patterns)- already has a pre-expansion feature gate warning
- incredibly likely to be replaced with explicit or implicit deref patterns...
- ...so a syntax gate would make it easier to phase out the syntax later on
-
turn the warning into a hard error(needs crater, T-lang FCP) - remove the feature entirely instead (cratered, fcp'ed): remove
box_patterns#156749
- pattern
$patpath { box $ident }, pseudo binding mode (featurebox_patterns)- incredibly likely to be replaced with explicit or implicit deref patterns...
- ...so a syntax gate would make it easier to phase out the syntax later on
- issue a pre-expansion feature gate warning (legitimized by MCP 535)
-
turn the warning into a hard error(needs crater, T-lang FCP) - remove the feature entirely instead (cratered, fcp'ed): remove
box_patterns#156749
- item
trait $ident $genericparams = $bounds;(featuretrait_alias)- already has a pre-expansion feature gate warning
- turn the warning into a hard error (needs crater, T-lang FCP)
- trait item modifier
auto(featureauto_traits)- already has a pre-expansion feature gate warning
- turn the warning into a hard error (needs crater, T-lang FCP)
- (not fitting 100%) syntax
impl $traitref for .. {}(early version of a now removed predecessor of featureauto_traits)- most recent crater run: PR RUST-121072
- issue a pre-expansion feature gate warning (legitimized by MCP 535, maybe?)
- reevaluate RUST-121072's crater report & send downstream patches
- turn the warning into a hard error (needs T-lang FCP, maybe another crater run)
- item
macro $ident$macroparams { $ttstar }(featuredecl_macro)- already has a pre-expansion feature gate warning
- turn the warning into a hard error (needs crater, T-lang FCP)
- (not fitting 100%) predicates
$ty = $tyand$ty == $ty(no corresp. feature was ever added (cc RUST-22074, RUST-87471))- straight up hard error (crater: 0 regressions, needs T-lang FCP): PR RUST-153513
- attribute in certain expression contexts (feature
stmt_expr_attributes)- META: FIXME: elaborate
- see also Stabilize attributes on closure and method call expressions #159581
Pre-History (Incomplete)
- Feature gate 'yield $expr?' pre-expansion #63545
- Pre-expansion gate most of the things #65742
- Re-land early syntax feature gating (was: Some features can no longer be controlled by conditional compilation) #65860
- Partially revert the early feature-gatings added in #65742. #66004
- Re-add most early unstable syntax gates as future-compat lints compiler-team#535
- Reenable disabled early syntax gates as future-incompatibility lints #99935
- Emit feature gate *warning* for
autotraits pre-expansion #116393 - Remove special handling of obsolete
impl Trait for ..syntax #121072
Implementation History
- Syntactically reject equality predicates #153513
- Emit a pre-expansion feature gate warning for
box'ed struct field patterns #154475 - Emit pre-expansion feature gate warnings for negative impls and specialization #154527
Downstream Patches
Reacted by Vadim Petrochenkov, Nik Rev, 许杰友 Jieyou Xu (Joe) and cyrgani
Reacted by Em Sharnoff
Reacted by Guillaume E
Metadata
Metadata
Assignees
Labels
A-grammarArea: The grammar of RustArea: The grammar of RustA-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.Area: Lints (warnings about flaws in source code) such as unused_mut.A-parserArea: The lexing & parsing of Rust source code to an ASTArea: The lexing & parsing of Rust source code to an ASTC-future-incompatibilityCategory: Future-incompatibility lintsCategory: Future-incompatibility lintsC-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCL-unstable_syntax_pre_expansionLint: unstable-syntax-pre-expansionLint: unstable-syntax-pre-expansionT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language team
Activity
fmease commentedon Mar 18, 2026
For why pre-expansion feature gates are superior to post-expansion ones, read my very recent comment: #153513 (comment).
fmease commentedon Mar 27, 2026
In case anybody is wondering where the supposed future-incompat lint is that's mentioned in MCP rust-lang/compiler-team#535 and enabled in PR #99935, it's called
unstable_syntax_pre_expansion(see also its entry in the rustc book) but (1) it's not advertised in the diagnostic (2) lint control attrs/flags (allow,warn,deny,forbid,expect) don't work for it (incl.-Dwarnings). I haven't found any reasoning behind that.Moreover, the diagnostic links to issue #65860 which I have closed in favor of this issue. In any case, it wasn't a proper C-future-incompatibilityCategory: Future-incompatibility lints
C-tracking-issue
Category: An issue tracking the progress of sth. like the implementation of an RFC
anyway.
I'm currently leaning towards removing that lint entirely (turning the improper lint warning into a proper non-lint warning) (not even keeping a removed entry since it isn't advertised anywhere & can't be controlled) however I do acknowledge that future-incompat lints allow for things like no-warn-in-deps vs. warn-in-deps, so that idea might not work out.
Once all gates have been turned into proper pre-expansion ones / the corresp. features have been stabilized, we can easily remove this hidden semi-functioning lint without any traces.
Rollup merge of rust-lang#154475 - fmease:soft-gate-box-struct-field-…
Unrolled build for #154475
Rollup merge of rust-lang#154527 - fmease:more-soft-gates, r=nnethercote
Rollup merge of rust-lang#154527 - fmease:more-soft-gates, r=nnethercote
Rollup merge of rust-lang#154527 - fmease:more-soft-gates, r=nnethercote
Rollup merge of rust-lang#154527 - fmease:more-soft-gates, r=nnethercote
Rollup merge of rust-lang#154527 - fmease:more-soft-gates, r=nnethercote
8 remaining items
Rollup merge of rust-lang#155017 - fmease:update-issue-number-unstabl…
Unrolled build for #155017
gendx commentedon Apr 9, 2026
Thanks a lot for the explanation and the guidance with the macro indirection, this fixes it for me! As long as there's a way to remediate the warning and to publish a new patch release on crates.io my concerns are resolved :)
Wrap nightly syntax inside a macro to avoid warnings and future errors.
Use pre-expansion cfg for feature spec
Fix unstable syntax warnings on recent nightly compilers
petrochenkov commentedon Jul 27, 2026
stmt_expr_attributesis also supposed to be a pre-expansion feature gate, but it's not.Rollup merge of rust-lang#156749 - cyrgani:unbox-full, r=Kivooeo,fmease
Rollup merge of rust-lang#156749 - cyrgani:unbox-full, r=Kivooeo,fmease
Rollup merge of rust-lang#156749 - cyrgani:unbox-full, r=Kivooeo,fmease
Rollup merge of rust-lang#156749 - cyrgani:unbox-full, r=Kivooeo,fmease
Unrolled build for #156749 in rollup 161731
Rollup merge of #156749 - cyrgani:unbox-full, r=Kivooeo,fmease