Skip to content

rustc: target_features: allow for cfg-only stable target_features#155962

Open
romancardenas wants to merge 2 commits intorust-lang:mainfrom
romancardenas:cfg-only-stable-target-feature
Open

rustc: target_features: allow for cfg-only stable target_features#155962
romancardenas wants to merge 2 commits intorust-lang:mainfrom
romancardenas:cfg-only-stable-target-feature

Conversation

@romancardenas
Copy link
Copy Markdown

@romancardenas romancardenas commented Apr 29, 2026

This PR introduces a new stabilization level for target_features: CfgOnlyStable. The motivation is allowing the Rust compiler to expose target_features of targets so users can use cfg(target_feature = "feature") for conditional blocks depending on target features. However, CfgOnlyStable cannot be used for #[target_feature(enable = "feature")], as this is still considered unstable. Accordingly, the compiler will still raise an error if these expressions are used on stable.

This PR relates partially to #150257. As discussed, for RISC-V targets, having the "d", "e", and "f" target features exposed will allow baremetal developers to adapt the code depending on the target's properties.

r? @RalfJung

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 29, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 29, 2026

r? @nikomatsakis

rustbot has assigned @nikomatsakis.
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

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 73 candidates
  • Random selection from 20 candidates

@rustbot rustbot assigned RalfJung and unassigned nikomatsakis Apr 29, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 29, 2026

RalfJung is not on the review rotation at the moment.
They may take a while to respond.

Copy link
Copy Markdown
Member

@RalfJung RalfJung left a comment

Choose a reason for hiding this comment

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

Thanks! This is probably the easiest way to do it. It's not super clean since it cannot represent "feature is allowed in cfg but strictly forbidden otherwise", so the entire thing will need a refactor eventually... but I can't ask you to do that now so let's just go with this.

@rustbot author

View changes since this review

reason,
});
} else if stability.requires_nightly().is_some() {
} else if stability.requires_nightly(true).is_some() {
Copy link
Copy Markdown
Member

@RalfJung RalfJung Apr 30, 2026

Choose a reason for hiding this comment

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

Suggested change
} else if stability.requires_nightly(true).is_some() {
} else if stability.requires_nightly(/* in_cfg */ false).is_some() {

This is where we emit warnings for unstable things in -Ctarget-feature. Yes it's pretty hacky to do that as a side-effect of constructing the cfg data... codegen backend initialization is a terrible spaghetti mess and someone decided this was the place to put that check. 🤷 (It's probably here to avoid emitting the warnings multiple times, or something like that.)

reason,
});
} else if let Some(nightly_feature) = stability.requires_nightly()
} else if let Some(nightly_feature) = stability.requires_nightly(false)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
} else if let Some(nightly_feature) = stability.requires_nightly(false)
} else if let Some(nightly_feature) = stability.requires_nightly(/* in_cfg */ false)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

If I'm not wrong, here is the only place where the new error message should be triggered right? I push an additional commit with the new error message, if needed.

Copy link
Copy Markdown
Member

@RalfJung RalfJung May 4, 2026

Choose a reason for hiding this comment

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

I don't understand the question. There are 3 places where we query feature stability, corresponding to -Ctarget-feature, #[target_feature], and cfg(target_feature), respectively. Only one of them should set in_cfg to true.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

In your review, you mentioned that:

It's not super clean since it cannot represent "feature is allowed in cfg but strictly forbidden otherwise", so the entire thing will need a refactor eventually...

If this PR is OK so far, I can try to add a new error message near lines 65 and 318, which corresponds to the check for #[target_feature] and -Ctarget-feature, respectively.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am still confused. I did mention that, yes. What does it have to do with the diff I suggested here?

To resolve that concern, we'd need a more fundamental refactor of the Stability type, into something more like

struct TargetFeatureInfo {
  for_cfg: Stability,
  for_toggle: Stability,
}

That's a lot more work so I am not expecting / asking you to do it in this PR.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Sorry for the confusion, it has nothing to do with the particular diff you suggested. It was just for me to know where error/warning messages were triggered. I will keep discussing this in a separate comment.

if allow_unstable
|| (gate.in_cfg()
&& (sess.is_nightly_build() || gate.requires_nightly().is_none()))
&& (sess.is_nightly_build() || gate.requires_nightly(true).is_none()))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
&& (sess.is_nightly_build() || gate.requires_nightly(true).is_none()))
&& (sess.is_nightly_build() || gate.requires_nightly(/* in_cfg */ true).is_none()))

Comment thread compiler/rustc_target/src/target_features.rs
@rustbot rustbot 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-review Status: Awaiting review from the assignee but also interested parties. labels Apr 30, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 30, 2026

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@romancardenas romancardenas force-pushed the cfg-only-stable-target-feature branch from bb0826a to 109fc56 Compare May 4, 2026 08:11
@romancardenas romancardenas force-pushed the cfg-only-stable-target-feature branch from 109fc56 to df8d029 Compare May 4, 2026 08:13
@romancardenas
Copy link
Copy Markdown
Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 4, 2026
@romancardenas
Copy link
Copy Markdown
Author

I pushed a commit that includes a basic error handling for printing error and warning messages that explicitly mention a target feature that is cfg-stable but unstable otherwise. It is not as elaborate as should probably be, but maybe for this first PR is good enough.

Let me know if you don't like the approach and I will revert the latest commit.

@RalfJung
Copy link
Copy Markdown
Member

RalfJung commented May 4, 2026

I like it. :)

I'm a bit nervous about not having a test for this, but I am also not sure how a test could work. We'd need some sort of dummy feature that's guaranteed to always remain cfg_stable_toggle_unstable... but we don't actually want to have such a feature available on stable.^^

@bors r+ rollup

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented May 4, 2026

📌 Commit ee9a01a has been approved by RalfJung

It is now in the queue for this repository.

@rust-bors rust-bors Bot 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-review Status: Awaiting review from the assignee but also interested parties. labels May 4, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request May 4, 2026
…et-feature, r=RalfJung

`rustc`: `target_features`: allow for `cfg`-only stable `target_features`

This PR introduces a new stabilization level for `target_features`: `CfgOnlyStable`. The motivation is allowing the Rust compiler to expose `target_features` of targets so users can use `cfg(target_feature = "feature")` for conditional blocks depending on target features. However, `CfgOnlyStable` cannot be used for `#[target_feature(enable = "feature")]`, as this is still considered unstable. Accordingly, the compiler will still raise an error if these expressions are used on stable.

This PR relates partially to rust-lang#150257. As discussed, for RISC-V targets, having the `"d"`, `"e"`, and `"f"` target features exposed will allow baremetal developers to adapt the code depending on the target's properties.

r? @RalfJung
rust-bors Bot pushed a commit that referenced this pull request May 4, 2026
…uwer

Rollup of 10 pull requests

Successful merges:

 - #155848 ([doc]: Revert `core::io::ErrorKind` doc changes)
 - #155855 (Remove unnecessary `get_unchecked`)
 - #155543 (docs(unstable-book): Document const generics features)
 - #155962 (`rustc`: `target_features`: allow for `cfg`-only stable `target_features`)
 - #156043 (c-variadic: gate `va_arg` on `c_variadic_experimental_arch`)
 - #156082 (Move tests associated types)
 - #156092 (Clean up `TyCtxt::needs_crate_hash` usage and rename it to `needs_hir_hash`.)
 - #156104 (Relax `T: Sized` bound on `try_as_dyn` / `try_as_dyn_mut`)
 - #156128 (.mailmap: prefer matching just based on commit emails)
 - #156135 (Remove most uses of def_id_to_node_id)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants