Skip to content

Tracking issue for migrating all remaining post-expansion feature gates to pre-expansion ones #154045

Open

Description

@fmease

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 syntax

After (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

  1. Find the most recent relevant crater runs and manually reaudit affected crates
    • check if at least some crates have been fixed downstream by now
  2. Collect all features where the crater run has happened a long time ago & issue a single crater run for all of them at once
  3. 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

  1. item modifier default (feature specialization or min_specialization for 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)
  2. trait impl modifier ! (feature negative_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)
  3. expression try { … } (feature try_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)
  4. pattern box $pat (feature box_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
  5. pattern $patpath { box $ident }, pseudo binding mode (feature box_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
  6. item trait $ident $genericparams = $bounds; (feature trait_alias)
    • already has a pre-expansion feature gate warning
    • turn the warning into a hard error (needs crater, T-lang FCP)
  7. trait item modifier auto (feature auto_traits)
    • already has a pre-expansion feature gate warning
    • turn the warning into a hard error (needs crater, T-lang FCP)
  8. (not fitting 100%) syntax impl $traitref for .. {} (early version of a now removed predecessor of feature auto_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)
  9. item macro $ident$macroparams { $ttstar } (feature decl_macro)
    • already has a pre-expansion feature gate warning
    • turn the warning into a hard error (needs crater, T-lang FCP)
  10. (not fitting 100%) predicates $ty = $ty and $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
  11. attribute in certain expression contexts (feature stmt_expr_attributes)

Pre-History (Incomplete)

Implementation History

Downstream Patches

Activity

  1. self-assigned this
    on Mar 18, 2026
  2. added
    A-grammarArea: The grammar of Rust
    A-parserArea: The lexing & parsing of Rust source code to an AST
    T-langRelevant to the language team
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Mar 18, 2026
  3. fmease commented on Mar 18, 2026

    @fmease
    MemberAuthor

    For why pre-expansion feature gates are superior to post-expansion ones, read my very recent comment: #153513 (comment).

  4. fmease commented on Mar 27, 2026

    @fmease
    MemberAuthor

    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-incompatibility Category: 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.

  5. added a commit that references this issue on Mar 28, 2026
  6. added a commit that references this issue on Mar 28, 2026
  7. added 2 commits that reference this issue on Apr 2, 2026
  8. added 3 commits that reference this issue on Apr 2, 2026
  9. 8 remaining items

  10. added a commit that references this issue on Apr 9, 2026
  11. added a commit that references this issue on Apr 9, 2026
  12. gendx commented on Apr 9, 2026

    @gendx
    Contributor

    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 :)

  13. added a commit that references this issue on Apr 11, 2026
  14. removed their assignment
    on Jul 6, 2026
  15. petrochenkov commented on Jul 27, 2026

    @petrochenkov
    Contributor

    stmt_expr_attributes is also supposed to be a pre-expansion feature gate, but it's not.

  16. added 2 commits that reference this issue on Aug 24, 2026
  17. added a commit that references this issue on Aug 24, 2026
  18. added a commit that references this issue on Aug 25, 2026
  19. added a commit that references this issue on Aug 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-grammarArea: The grammar of RustA-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.A-parserArea: The lexing & parsing of Rust source code to an ASTC-future-incompatibilityCategory: Future-incompatibility lintsC-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCL-unstable_syntax_pre_expansionLint: unstable-syntax-pre-expansionT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions