Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c1caaa3

Browse files
committedNov 28, 2024
generalize 'forbidden feature' concept so that even (un)stable feature can be invalid to toggle
Also rename some things for extra clarity
1 parent 9b4d7c6 commit c1caaa3

File tree

13 files changed

+467
-400
lines changed

13 files changed

+467
-400
lines changed
 

‎compiler/rustc_codegen_cranelift/src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,11 @@ impl CodegenBackend for CraneliftCodegenBackend {
185185
}
186186
}
187187

188-
fn target_features(&self, sess: &Session, _allow_unstable: bool) -> Vec<rustc_span::Symbol> {
188+
fn target_features_cfg(
189+
&self,
190+
sess: &Session,
191+
_allow_unstable: bool,
192+
) -> Vec<rustc_span::Symbol> {
189193
// FIXME return the actually used target features. this is necessary for #[cfg(target_feature)]
190194
if sess.target.arch == "x86_64" && sess.target.os != "none" {
191195
// x86_64 mandates SSE2 support

‎compiler/rustc_codegen_gcc/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ codegen_gcc_lto_not_supported =
99
LTO is not supported. You may get a linker error.
1010
1111
codegen_gcc_forbidden_ctarget_feature =
12-
target feature `{$feature}` cannot be toggled with `-Ctarget-feature`
12+
target feature `{$feature}` cannot be toggled with `-Ctarget-feature`: {$reason}
1313
1414
codegen_gcc_unwinding_inline_asm =
1515
GCC backend does not support unwinding from inline asm

‎compiler/rustc_codegen_gcc/src/errors.rs

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub(crate) struct UnstableCTargetFeature<'a> {
2828
#[diag(codegen_gcc_forbidden_ctarget_feature)]
2929
pub(crate) struct ForbiddenCTargetFeature<'a> {
3030
pub feature: &'a str,
31+
pub reason: &'a str,
3132
}
3233

3334
#[derive(Subdiagnostic)]

‎compiler/rustc_codegen_gcc/src/gcc_util.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable;
55
use rustc_data_structures::fx::FxHashMap;
66
use rustc_middle::bug;
77
use rustc_session::Session;
8-
use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability};
8+
use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
99
use smallvec::{SmallVec, smallvec};
1010

1111
use crate::errors::{
@@ -94,13 +94,15 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
9494
};
9595
sess.dcx().emit_warn(unknown_feature);
9696
}
97-
Some((_, Stability::Stable, _)) => {}
98-
Some((_, Stability::Unstable(_), _)) => {
99-
// An unstable feature. Warn about using it.
100-
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
101-
}
102-
Some((_, Stability::Forbidden { .. }, _)) => {
103-
sess.dcx().emit_err(ForbiddenCTargetFeature { feature });
97+
Some((_, stability, _)) => {
98+
if let Err(reason) = stability.compute(&sess.target).allow_toggle() {
99+
sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason });
100+
} else if stability.requires_nightly().is_some() {
101+
// An unstable feature. Warn about using it. (It makes little sense
102+
// to hard-error here since we just warn about fully unknown
103+
// features above).
104+
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
105+
}
104106
}
105107
}
106108

‎compiler/rustc_codegen_gcc/src/lib.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,8 @@ impl CodegenBackend for GccCodegenBackend {
260260
.join(sess)
261261
}
262262

263-
fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
264-
target_features(sess, allow_unstable, &self.target_info)
263+
fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
264+
target_features_cfg(sess, allow_unstable, &self.target_info)
265265
}
266266
}
267267

@@ -472,7 +472,8 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
472472
}
473473
}
474474

475-
pub fn target_features(
475+
/// Returns the features that should be set in `cfg(target_feature)`.
476+
fn target_features_cfg(
476477
sess: &Session,
477478
allow_unstable: bool,
478479
target_info: &LockedTargetInfo,
@@ -481,9 +482,9 @@ pub fn target_features(
481482
sess.target
482483
.rust_target_features()
483484
.iter()
484-
.filter(|(_, gate, _)| gate.is_supported())
485+
.filter(|(_, gate, _)| gate.in_cfg())
485486
.filter_map(|&(feature, gate, _)| {
486-
if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
487+
if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() {
487488
Some(feature)
488489
} else {
489490
None

‎compiler/rustc_codegen_llvm/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use std::mem::ManuallyDrop;
2828
use back::owned_target_machine::OwnedTargetMachine;
2929
use back::write::{create_informational_target_machine, create_target_machine};
3030
use errors::ParseTargetMachineConfig;
31-
pub use llvm_util::target_features;
31+
pub use llvm_util::target_features_cfg;
3232
use rustc_ast::expand::allocator::AllocatorKind;
3333
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
3434
use rustc_codegen_ssa::back::write::{
@@ -331,8 +331,8 @@ impl CodegenBackend for LlvmCodegenBackend {
331331
llvm_util::print_version();
332332
}
333333

334-
fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
335-
target_features(sess, allow_unstable)
334+
fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
335+
target_features_cfg(sess, allow_unstable)
336336
}
337337

338338
fn codegen_crate<'tcx>(

‎compiler/rustc_codegen_llvm/src/llvm_util.rs

+15-13
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_session::Session;
1717
use rustc_session::config::{PrintKind, PrintRequest};
1818
use rustc_span::symbol::Symbol;
1919
use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
20-
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES, Stability};
20+
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
2121

2222
use crate::back::write::create_informational_target_machine;
2323
use crate::errors::{
@@ -297,7 +297,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
297297
/// Must express features in the way Rust understands them.
298298
///
299299
/// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled outside codegen.
300-
pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
300+
pub fn target_features_cfg(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
301301
let mut features: FxHashSet<Symbol> = Default::default();
302302

303303
// Add base features for the target.
@@ -313,7 +313,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
313313
sess.target
314314
.rust_target_features()
315315
.iter()
316-
.filter(|(_, gate, _)| gate.is_supported())
316+
.filter(|(_, gate, _)| gate.in_cfg())
317317
.filter(|(feature, _, _)| {
318318
// skip checking special features, as LLVM may not understand them
319319
if RUSTC_SPECIAL_FEATURES.contains(feature) {
@@ -369,9 +369,9 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
369369
sess.target
370370
.rust_target_features()
371371
.iter()
372-
.filter(|(_, gate, _)| gate.is_supported())
372+
.filter(|(_, gate, _)| gate.in_cfg())
373373
.filter_map(|&(feature, gate, _)| {
374-
if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
374+
if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() {
375375
Some(feature)
376376
} else {
377377
None
@@ -490,7 +490,7 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine, out: &mut Str
490490
.rust_target_features()
491491
.iter()
492492
.filter_map(|(feature, gate, _implied)| {
493-
if !gate.is_supported() {
493+
if !gate.in_cfg() {
494494
// Only list (experimentally) supported features.
495495
return None;
496496
}
@@ -713,13 +713,15 @@ pub(crate) fn global_llvm_features(
713713
};
714714
sess.dcx().emit_warn(unknown_feature);
715715
}
716-
Some((_, Stability::Stable, _)) => {}
717-
Some((_, Stability::Unstable(_), _)) => {
718-
// An unstable feature. Warn about using it.
719-
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
720-
}
721-
Some((_, Stability::Forbidden { reason }, _)) => {
722-
sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason });
716+
Some((_, stability, _)) => {
717+
if let Err(reason) = stability.compute(&sess.target).allow_toggle() {
718+
sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason });
719+
} else if stability.requires_nightly().is_some() {
720+
// An unstable feature. Warn about using it. (It makes little sense
721+
// to hard-error here since we just warn about fully unknown
722+
// features above).
723+
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
724+
}
723725
}
724726
}
725727

‎compiler/rustc_codegen_ssa/src/target_features.rs

+23-30
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_middle::ty::TyCtxt;
1111
use rustc_session::parse::feature_err;
1212
use rustc_span::Span;
1313
use rustc_span::symbol::{Symbol, sym};
14-
use rustc_target::target_features::{self, Stability};
14+
use rustc_target::target_features;
1515

1616
use crate::errors;
1717

@@ -20,7 +20,7 @@ use crate::errors;
2020
pub(crate) fn from_target_feature_attr(
2121
tcx: TyCtxt<'_>,
2222
attr: &ast::Attribute,
23-
rust_target_features: &UnordMap<String, target_features::Stability>,
23+
rust_target_features: &UnordMap<String, target_features::StabilityComputed>,
2424
target_features: &mut Vec<TargetFeature>,
2525
) {
2626
let Some(list) = attr.meta_item_list() else { return };
@@ -63,32 +63,24 @@ pub(crate) fn from_target_feature_attr(
6363
return None;
6464
};
6565

66-
// Only allow target features whose feature gates have been enabled.
67-
let allowed = match stability {
68-
Stability::Forbidden { .. } => false,
69-
Stability::Stable => true,
70-
Stability::Unstable(name) => rust_features.enabled(*name),
71-
};
72-
if !allowed {
73-
match stability {
74-
Stability::Stable => unreachable!(),
75-
&Stability::Unstable(lang_feature_name) => {
76-
feature_err(
77-
&tcx.sess,
78-
lang_feature_name,
79-
item.span(),
80-
format!("the target feature `{feature}` is currently unstable"),
81-
)
82-
.emit();
83-
}
84-
Stability::Forbidden { reason } => {
85-
tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
86-
span: item.span(),
87-
feature,
88-
reason,
89-
});
90-
}
91-
}
66+
// Only allow target features whose feature gates have been enabled
67+
// and which are permitted to be toggled.
68+
if let Err(reason) = stability.allow_toggle() {
69+
tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
70+
span: item.span(),
71+
feature,
72+
reason,
73+
});
74+
} else if let Some(nightly_feature) = stability.requires_nightly()
75+
&& !rust_features.enabled(nightly_feature)
76+
{
77+
feature_err(
78+
&tcx.sess,
79+
nightly_feature,
80+
item.span(),
81+
format!("the target feature `{feature}` is currently unstable"),
82+
)
83+
.emit();
9284
}
9385
Some(Symbol::intern(feature))
9486
}));
@@ -156,18 +148,19 @@ pub(crate) fn provide(providers: &mut Providers) {
156148
*providers = Providers {
157149
rust_target_features: |tcx, cnum| {
158150
assert_eq!(cnum, LOCAL_CRATE);
151+
let target = &tcx.sess.target;
159152
if tcx.sess.opts.actually_rustdoc {
160153
// rustdoc needs to be able to document functions that use all the features, so
161154
// whitelist them all
162155
rustc_target::target_features::all_rust_features()
163-
.map(|(a, b)| (a.to_string(), b))
156+
.map(|(a, b)| (a.to_string(), b.compute(target)))
164157
.collect()
165158
} else {
166159
tcx.sess
167160
.target
168161
.rust_target_features()
169162
.iter()
170-
.map(|&(a, b, _)| (a.to_string(), b))
163+
.map(|&(a, b, _)| (a.to_string(), b.compute(target)))
171164
.collect()
172165
}
173166
},

‎compiler/rustc_codegen_ssa/src/traits/backend.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ pub trait CodegenBackend {
4646

4747
fn print(&self, _req: &PrintRequest, _out: &mut String, _sess: &Session) {}
4848

49-
fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> {
49+
/// Returns the features that should be set in `cfg(target_features)`.
50+
/// RUSTC_SPECIFIC_FEATURES should be skipped here, those are handled outside codegen.
51+
fn target_features_cfg(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> {
5052
vec![]
5153
}
5254

‎compiler/rustc_interface/src/util.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
3535
pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dyn CodegenBackend) {
3636
let tf = sym::target_feature;
3737

38-
let unstable_target_features = codegen_backend.target_features(sess, true);
38+
let unstable_target_features = codegen_backend.target_features_cfg(sess, true);
3939
sess.unstable_target_features.extend(unstable_target_features.iter().cloned());
4040

41-
let target_features = codegen_backend.target_features(sess, false);
41+
let target_features = codegen_backend.target_features_cfg(sess, false);
4242
sess.target_features.extend(target_features.iter().cloned());
4343

4444
cfg.extend(target_features.into_iter().map(|feat| (tf, Some(feat))));

‎compiler/rustc_middle/src/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2236,7 +2236,7 @@ rustc_queries! {
22362236
}
22372237

22382238
/// Returns the Rust target features for the current target. These are not always the same as LLVM target features!
2239-
query rust_target_features(_: CrateNum) -> &'tcx UnordMap<String, rustc_target::target_features::Stability> {
2239+
query rust_target_features(_: CrateNum) -> &'tcx UnordMap<String, rustc_target::target_features::StabilityComputed> {
22402240
arena_cache
22412241
eval_always
22422242
desc { "looking up Rust target features" }

‎compiler/rustc_session/src/config/cfg.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ impl CheckCfg {
371371

372372
ins!(sym::target_feature, empty_values).extend(
373373
rustc_target::target_features::all_rust_features()
374-
.filter(|(_, s)| s.is_supported())
374+
.filter(|(_, s)| s.in_cfg())
375375
.map(|(f, _s)| f)
376376
.chain(rustc_target::target_features::RUSTC_SPECIFIC_FEATURES.iter().cloned())
377377
.map(Symbol::intern),

‎compiler/rustc_target/src/target_features.rs

+396-334
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.