@@ -20,7 +20,7 @@ pub const RUSTC_SPECIAL_FEATURES: &[&str] = &["backchain"];
20
20
/// `Toggleability` is the type storing whether (un)stable features can be toggled:
21
21
/// this is initially a function since it can depend on `Target`, but for stable hashing
22
22
/// it needs to be something hashable to we have to make the type generic.
23
- #[ derive( Debug , Clone , Copy ) ]
23
+ #[ derive( Debug , Clone ) ]
24
24
pub enum Stability < Toggleability > {
25
25
/// This target feature is stable, it can be used in `#[target_feature]` and
26
26
/// `#[cfg(target_feature)]`.
@@ -44,11 +44,21 @@ pub enum Stability<Toggleability> {
44
44
Forbidden { reason : & ' static str } ,
45
45
}
46
46
47
- /// `Stability` where `allow_toggle` has not been computed yet.
48
47
/// 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 > ;
50
60
/// `Stability` where `allow_toggle` has already been computed.
51
- pub type StabilityComputed = Stability < Result < ( ) , & ' static str > > ;
61
+ pub type StabilityComputed = Stability < AllowToggleComputed > ;
52
62
53
63
impl < CTX , Toggleability : HashStable < CTX > > HashStable < CTX > for Stability < Toggleability > {
54
64
#[ inline]
@@ -69,11 +79,20 @@ impl<CTX, Toggleability: HashStable<CTX>> HashStable<CTX> for Stability<Toggleab
69
79
}
70
80
}
71
81
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
+
72
91
impl < Toggleability > Stability < Toggleability > {
73
92
/// Returns whether the feature can be used in `cfg(target_feature)` ever.
74
93
/// (It might still be nightly-only even if this returns `true`, so make sure to also check
75
94
/// `requires_nightly`.)
76
- pub fn in_cfg ( self ) -> bool {
95
+ pub fn in_cfg ( & self ) -> bool {
77
96
!matches ! ( self , Stability :: Forbidden { .. } )
78
97
}
79
98
@@ -85,8 +104,8 @@ impl<Toggleability> Stability<Toggleability> {
85
104
/// Before calling this, ensure the feature is even permitted for this use:
86
105
/// - for `#[target_feature]`/`-Ctarget-feature`, check `allow_toggle()`
87
106
/// - for `cfg(target_feature)`, check `in_cfg`
88
- pub fn requires_nightly ( self ) -> Option < Symbol > {
89
- match self {
107
+ pub fn requires_nightly ( & self ) -> Option < Symbol > {
108
+ match * self {
90
109
Stability :: Unstable { nightly_feature, .. } => Some ( nightly_feature) ,
91
110
Stability :: Stable { .. } => None ,
92
111
Stability :: Forbidden { .. } => panic ! ( "forbidden features should not reach this far" ) ,
@@ -95,35 +114,49 @@ impl<Toggleability> Stability<Toggleability> {
95
114
}
96
115
97
116
impl StabilityUncomputed {
98
- pub fn compute_toggleability ( self , target : & Target ) -> StabilityComputed {
117
+ pub fn compute_toggleability ( & self , target : & Target ) -> StabilityComputed {
99
118
use Stability :: * ;
100
- match self {
101
- Stable { allow_toggle } => Stable { allow_toggle : allow_toggle ( target) } ,
119
+ let compute = |f : AllowToggleUncomputed | AllowToggleComputed {
120
+ enable : f ( target, true ) ,
121
+ disable : f ( target, false ) ,
122
+ } ;
123
+ match * self {
124
+ Stable { allow_toggle } => Stable { allow_toggle : compute ( allow_toggle) } ,
102
125
Unstable { nightly_feature, allow_toggle } => {
103
- Unstable { nightly_feature, allow_toggle : allow_toggle ( target ) }
126
+ Unstable { nightly_feature, allow_toggle : compute ( allow_toggle ) }
104
127
}
105
128
Forbidden { reason } => Forbidden { reason } ,
106
129
}
107
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) ,
138
+ }
139
+ }
108
140
}
109
141
110
142
impl StabilityComputed {
111
143
/// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`.
112
144
/// (It might still be nightly-only even if this returns `true`, so make sure to also check
113
145
/// `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 {
116
148
Stability :: Stable { allow_toggle } => allow_toggle,
117
149
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 }
120
153
}
121
154
}
122
155
123
156
// 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 ( ( ) ) } ;
125
158
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 ( ( ) ) }
127
160
}
128
161
129
162
// 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)] = &[
184
217
"fpregs" ,
185
218
Stability :: Unstable {
186
219
nightly_feature : sym:: arm_target_feature,
187
- allow_toggle : |target : & Target | {
220
+ allow_toggle : |target : & Target , _enable | {
188
221
// Only allow toggling this if the target has `soft-float` set. With `soft-float`,
189
222
// `fpregs` isn't needed so changing it cannot affect the ABI.
190
223
if target. has_feature ( "soft-float" ) {
@@ -257,6 +290,7 @@ const AARCH64_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
257
290
( "flagm" , STABLE , & [ ] ) ,
258
291
// FEAT_FLAGM2
259
292
( "flagm2" , unstable ( sym:: aarch64_unstable_target_feature) , & [ ] ) ,
293
+ ( "fp-armv8" , Stability :: Forbidden { reason : "Rust ties `fp-armv8` to `neon`" } , & [ ] ) ,
260
294
// FEAT_FP16
261
295
// Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608
262
296
( "fp16" , STABLE , & [ "neon" ] ) ,
@@ -292,7 +326,28 @@ const AARCH64_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
292
326
// FEAT_MTE & FEAT_MTE2
293
327
( "mte" , STABLE , & [ ] ) ,
294
328
// FEAT_AdvSimd & FEAT_FP
295
- ( "neon" , STABLE , & [ ] ) ,
329
+ (
330
+ "neon" ,
331
+ Stability :: Stable {
332
+ allow_toggle : |target, enable| {
333
+ if target. abi == "softfloat" {
334
+ // `neon` has no ABI implications for softfloat targets, we can allow this.
335
+ Ok ( ( ) )
336
+ } else if enable
337
+ && !target. has_neg_feature ( "fp-armv8" )
338
+ && !target. has_neg_feature ( "neon" )
339
+ {
340
+ // neon is enabled by default, and has not been disabled, so enabling it again
341
+ // is redundant and we can permit it. Forbidding this would be a breaking change
342
+ // since this feature is stable.
343
+ Ok ( ( ) )
344
+ } else {
345
+ Err ( "unsound on hard-float targets because it changes float ABI" )
346
+ }
347
+ } ,
348
+ } ,
349
+ & [ ] ,
350
+ ) ,
296
351
// FEAT_PAUTH (address authentication)
297
352
( "paca" , STABLE , & [ ] ) ,
298
353
// FEAT_PAUTH (generic authentication)
@@ -481,7 +536,7 @@ const X86_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
481
536
"x87" ,
482
537
Stability :: Unstable {
483
538
nightly_feature : sym:: x87_target_feature,
484
- allow_toggle : |target : & Target | {
539
+ allow_toggle : |target : & Target , _enable | {
485
540
// Only allow toggling this if the target has `soft-float` set. With `soft-float`,
486
541
// `fpregs` isn't needed so changing it cannot affect the ABI.
487
542
if target. has_feature ( "soft-float" ) {
0 commit comments