Skip to content

Commit eb2e928

Browse files
committed
target_features: control separately whether enabling and disabling a target feature is allowed
1 parent a1740a9 commit eb2e928

File tree

5 files changed

+63
-30
lines changed

5 files changed

+63
-30
lines changed

compiler/rustc_codegen_gcc/src/gcc_util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
9696
}
9797
Some((_, stability, _)) => {
9898
if let Err(reason) =
99-
stability.compute_toggleability(&sess.target).allow_toggle()
99+
stability.toggle_allowed(&sess.target, enable_disable == '+')
100100
{
101101
sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason });
102102
} else if stability.requires_nightly().is_some() {

compiler/rustc_codegen_gcc/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -483,9 +483,9 @@ fn target_features_cfg(
483483
.rust_target_features()
484484
.iter()
485485
.filter(|(_, gate, _)| gate.in_cfg())
486-
.filter_map(|&(feature, gate, _)| {
486+
.filter_map(|(feature, gate, _)| {
487487
if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() {
488-
Some(feature)
488+
Some(*feature)
489489
} else {
490490
None
491491
}

compiler/rustc_codegen_llvm/src/llvm_util.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -373,9 +373,9 @@ pub fn target_features_cfg(sess: &Session, allow_unstable: bool) -> Vec<Symbol>
373373
.rust_target_features()
374374
.iter()
375375
.filter(|(_, gate, _)| gate.in_cfg())
376-
.filter_map(|&(feature, gate, _)| {
376+
.filter_map(|(feature, gate, _)| {
377377
if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() {
378-
Some(feature)
378+
Some(*feature)
379379
} else {
380380
None
381381
}
@@ -718,7 +718,7 @@ pub(crate) fn global_llvm_features(
718718
}
719719
Some((_, stability, _)) => {
720720
if let Err(reason) =
721-
stability.compute_toggleability(&sess.target).allow_toggle()
721+
stability.toggle_allowed(&sess.target, enable_disable == '+')
722722
{
723723
sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason });
724724
} else if stability.requires_nightly().is_some() {

compiler/rustc_codegen_ssa/src/target_features.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ pub(crate) fn from_target_feature_attr(
6565

6666
// Only allow target features whose feature gates have been enabled
6767
// and which are permitted to be toggled.
68-
if let Err(reason) = stability.allow_toggle() {
68+
if let Err(reason) = stability.toggle_allowed(/*enable*/ true) {
6969
tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
7070
span: item.span(),
7171
feature,
@@ -160,7 +160,7 @@ pub(crate) fn provide(providers: &mut Providers) {
160160
.target
161161
.rust_target_features()
162162
.iter()
163-
.map(|&(a, b, _)| (a.to_string(), b.compute_toggleability(target)))
163+
.map(|(a, b, _)| (a.to_string(), b.compute_toggleability(target)))
164164
.collect()
165165
}
166166
},

compiler/rustc_target/src/target_features.rs

+55-22
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub const RUSTC_SPECIAL_FEATURES: &[&str] = &["backchain"];
2020
/// `Toggleability` is the type storing whether (un)stable features can be toggled:
2121
/// this is initially a function since it can depend on `Target`, but for stable hashing
2222
/// it needs to be something hashable to we have to make the type generic.
23-
#[derive(Debug, Clone, Copy)]
23+
#[derive(Debug, Clone)]
2424
pub enum Stability<Toggleability> {
2525
/// This target feature is stable, it can be used in `#[target_feature]` and
2626
/// `#[cfg(target_feature)]`.
@@ -44,11 +44,21 @@ pub enum Stability<Toggleability> {
4444
Forbidden { reason: &'static str },
4545
}
4646

47-
/// `Stability` where `allow_toggle` has not been computed yet.
4847
/// Returns `Ok` if the toggle is allowed, `Err` with an explanation of not.
49-
pub type StabilityUncomputed = Stability<fn(&Target) -> Result<(), &'static str>>;
48+
/// The `bool` indicates whether the feature is being enabled (`true`) or disabled.
49+
pub type AllowToggleUncomputed = fn(&Target, bool) -> Result<(), &'static str>;
50+
51+
/// The computed result of whether a feature can be enabled/disabled on the current target.
52+
#[derive(Debug, Clone)]
53+
pub struct AllowToggleComputed {
54+
enable: Result<(), &'static str>,
55+
disable: Result<(), &'static str>,
56+
}
57+
58+
/// `Stability` where `allow_toggle` has not been computed yet.
59+
pub type StabilityUncomputed = Stability<AllowToggleUncomputed>;
5060
/// `Stability` where `allow_toggle` has already been computed.
51-
pub type StabilityComputed = Stability<Result<(), &'static str>>;
61+
pub type StabilityComputed = Stability<AllowToggleComputed>;
5262

5363
impl<CTX, Toggleability: HashStable<CTX>> HashStable<CTX> for Stability<Toggleability> {
5464
#[inline]
@@ -69,11 +79,20 @@ impl<CTX, Toggleability: HashStable<CTX>> HashStable<CTX> for Stability<Toggleab
6979
}
7080
}
7181

82+
impl<CTX> HashStable<CTX> for AllowToggleComputed {
83+
#[inline]
84+
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
85+
let AllowToggleComputed { enable, disable } = self;
86+
enable.hash_stable(hcx, hasher);
87+
disable.hash_stable(hcx, hasher);
88+
}
89+
}
90+
7291
impl<Toggleability> Stability<Toggleability> {
7392
/// Returns whether the feature can be used in `cfg(target_feature)` ever.
7493
/// (It might still be nightly-only even if this returns `true`, so make sure to also check
7594
/// `requires_nightly`.)
76-
pub fn in_cfg(self) -> bool {
95+
pub fn in_cfg(&self) -> bool {
7796
!matches!(self, Stability::Forbidden { .. })
7897
}
7998

@@ -85,24 +104,37 @@ impl<Toggleability> Stability<Toggleability> {
85104
/// Before calling this, ensure the feature is even permitted for this use:
86105
/// - for `#[target_feature]`/`-Ctarget-feature`, check `allow_toggle()`
87106
/// - for `cfg(target_feature)`, check `in_cfg`
88-
pub fn requires_nightly(self) -> Option<Symbol> {
107+
pub fn requires_nightly(&self) -> Option<Symbol> {
89108
match self {
90-
Stability::Unstable { nightly_feature, .. } => Some(nightly_feature),
91-
Stability::Stable { .. } => None,
92-
Stability::Forbidden { .. } => panic!("forbidden features should not reach this far"),
109+
&Stability::Unstable { nightly_feature, .. } => Some(nightly_feature),
110+
&Stability::Stable { .. } => None,
111+
&Stability::Forbidden { .. } => panic!("forbidden features should not reach this far"),
93112
}
94113
}
95114
}
96115

97116
impl StabilityUncomputed {
98-
pub fn compute_toggleability(self, target: &Target) -> StabilityComputed {
117+
pub fn compute_toggleability(&self, target: &Target) -> StabilityComputed {
99118
use Stability::*;
119+
let compute = |f: AllowToggleUncomputed| AllowToggleComputed {
120+
enable: f(target, true),
121+
disable: f(target, false),
122+
};
100123
match self {
101-
Stable { allow_toggle } => Stable { allow_toggle: allow_toggle(target) },
102-
Unstable { nightly_feature, allow_toggle } => {
103-
Unstable { nightly_feature, allow_toggle: allow_toggle(target) }
124+
&Stable { allow_toggle } => Stable { allow_toggle: compute(allow_toggle) },
125+
&Unstable { nightly_feature, allow_toggle } => {
126+
Unstable { nightly_feature, allow_toggle: compute(allow_toggle) }
104127
}
105-
Forbidden { reason } => Forbidden { reason },
128+
&Forbidden { reason } => Forbidden { reason },
129+
}
130+
}
131+
132+
pub fn toggle_allowed(&self, target: &Target, enable: bool) -> Result<(), &'static str> {
133+
use Stability::*;
134+
match self {
135+
&Stable { allow_toggle } => allow_toggle(target, enable),
136+
&Unstable { allow_toggle, .. } => allow_toggle(target, enable),
137+
&Forbidden { reason } => Err(reason),
106138
}
107139
}
108140
}
@@ -111,19 +143,20 @@ impl StabilityComputed {
111143
/// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`.
112144
/// (It might still be nightly-only even if this returns `true`, so make sure to also check
113145
/// `requires_nightly`.)
114-
pub fn allow_toggle(self) -> Result<(), &'static str> {
115-
match self {
146+
pub fn toggle_allowed(&self, enable: bool) -> Result<(), &'static str> {
147+
let allow_toggle = match self {
116148
Stability::Stable { allow_toggle } => allow_toggle,
117149
Stability::Unstable { allow_toggle, .. } => allow_toggle,
118-
Stability::Forbidden { reason } => Err(reason),
119-
}
150+
Stability::Forbidden { reason } => return Err(reason),
151+
};
152+
if enable { allow_toggle.enable } else { allow_toggle.disable }
120153
}
121154
}
122155

123156
// Constructors for the list below, defaulting to "always allow toggle".
124-
const STABLE: StabilityUncomputed = Stability::Stable { allow_toggle: |_target| Ok(()) };
157+
const STABLE: StabilityUncomputed = Stability::Stable { allow_toggle: |_target, _enable| Ok(()) };
125158
const fn unstable(nightly_feature: Symbol) -> StabilityUncomputed {
126-
Stability::Unstable { nightly_feature, allow_toggle: |_target| Ok(()) }
159+
Stability::Unstable { nightly_feature, allow_toggle: |_target, _enable| Ok(()) }
127160
}
128161

129162
// Here we list target features that rustc "understands": they can be used in `#[target_feature]`
@@ -184,7 +217,7 @@ const ARM_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
184217
"fpregs",
185218
Stability::Unstable {
186219
nightly_feature: sym::arm_target_feature,
187-
allow_toggle: |target: &Target| {
220+
allow_toggle: |target: &Target, _enable| {
188221
// Only allow toggling this if the target has `soft-float` set. With `soft-float`,
189222
// `fpregs` isn't needed so changing it cannot affect the ABI.
190223
if target.has_feature("soft-float") {
@@ -481,7 +514,7 @@ const X86_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
481514
"x87",
482515
Stability::Unstable {
483516
nightly_feature: sym::x87_target_feature,
484-
allow_toggle: |target: &Target| {
517+
allow_toggle: |target: &Target, _enable| {
485518
// Only allow toggling this if the target has `soft-float` set. With `soft-float`,
486519
// `fpregs` isn't needed so changing it cannot affect the ABI.
487520
if target.has_feature("soft-float") {

0 commit comments

Comments
 (0)