Skip to content

Commit 404c53a

Browse files
committed
Auto merge of rust-lang#132616 - workingjubilee:rollup-0ykzbyb, r=workingjubilee
Rollup of 10 pull requests Successful merges: - rust-lang#129884 (mark some target features as 'forbidden' so they cannot be (un)set with -Ctarget-feature) - rust-lang#132153 (Stabilise `const_char_encode_utf16`.) - rust-lang#132473 ([core/fmt] Replace checked slice indexing by unchecked to support panic-free code) - rust-lang#132571 (add const_eval_select macro to reduce redundancy) - rust-lang#132587 (Revert "Avoid nested replacement ranges" from rust-lang#129346.) - rust-lang#132596 ([rustdoc] Fix `--show-coverage` when JSON output format is used) - rust-lang#132598 (Clippy: Move some attribute lints to be early pass (post expansion)) - rust-lang#132601 (Update books) - rust-lang#132606 (Improve example of `impl Pattern for &[char]`) - rust-lang#132609 (docs: fix grammar in doc comment at unix/process.rs) r? `@ghost` `@rustbot` modify labels: rollup
2 parents fbab782 + 56194e2 commit 404c53a

File tree

77 files changed

+1057
-751
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+1057
-751
lines changed

compiler/rustc_codegen_gcc/messages.ftl

+9-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ codegen_gcc_invalid_minimum_alignment =
88
codegen_gcc_lto_not_supported =
99
LTO is not supported. You may get a linker error.
1010
11+
codegen_gcc_forbidden_ctarget_feature =
12+
target feature `{$feature}` cannot be toggled with `-Ctarget-feature`
13+
1114
codegen_gcc_unwinding_inline_asm =
1215
GCC backend does not support unwinding from inline asm
1316
@@ -24,11 +27,15 @@ codegen_gcc_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdyl
2427
codegen_gcc_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$gcc_err})
2528
2629
codegen_gcc_unknown_ctarget_feature =
27-
unknown feature specified for `-Ctarget-feature`: `{$feature}`
28-
.note = it is still passed through to the codegen backend
30+
unknown and unstable feature specified for `-Ctarget-feature`: `{$feature}`
31+
.note = it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future
2932
.possible_feature = you might have meant: `{$rust_feature}`
3033
.consider_filing_feature_request = consider filing a feature request
3134
35+
codegen_gcc_unstable_ctarget_feature =
36+
unstable feature specified for `-Ctarget-feature`: `{$feature}`
37+
.note = this feature is not stably supported; its behavior can change in the future
38+
3239
codegen_gcc_missing_features =
3340
add the missing features in a `target_feature` attribute
3441

compiler/rustc_codegen_gcc/src/errors.rs

+13
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@ pub(crate) struct UnknownCTargetFeature<'a> {
1717
pub rust_feature: PossibleFeature<'a>,
1818
}
1919

20+
#[derive(Diagnostic)]
21+
#[diag(codegen_gcc_unstable_ctarget_feature)]
22+
#[note]
23+
pub(crate) struct UnstableCTargetFeature<'a> {
24+
pub feature: &'a str,
25+
}
26+
27+
#[derive(Diagnostic)]
28+
#[diag(codegen_gcc_forbidden_ctarget_feature)]
29+
pub(crate) struct ForbiddenCTargetFeature<'a> {
30+
pub feature: &'a str,
31+
}
32+
2033
#[derive(Subdiagnostic)]
2134
pub(crate) enum PossibleFeature<'a> {
2235
#[help(codegen_gcc_possible_feature)]

compiler/rustc_codegen_gcc/src/gcc_util.rs

+40-25
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ 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;
8+
use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability};
99
use smallvec::{SmallVec, smallvec};
1010

11-
use crate::errors::{PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix};
11+
use crate::errors::{
12+
ForbiddenCTargetFeature, PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix,
13+
UnstableCTargetFeature,
14+
};
1215

1316
/// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
1417
/// `--target` and similar).
@@ -43,7 +46,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
4346
);
4447

4548
// -Ctarget-features
46-
let supported_features = sess.target.supported_target_features();
49+
let known_features = sess.target.rust_target_features();
4750
let mut featsmap = FxHashMap::default();
4851
let feats = sess
4952
.opts
@@ -62,37 +65,49 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
6265
}
6366
};
6467

68+
// Get the backend feature name, if any.
69+
// This excludes rustc-specific features, that do not get passed down to GCC.
6570
let feature = backend_feature_name(s)?;
6671
// Warn against use of GCC specific feature names on the CLI.
67-
if diagnostics && !supported_features.iter().any(|&(v, _, _)| v == feature) {
68-
let rust_feature = supported_features.iter().find_map(|&(rust_feature, _, _)| {
69-
let gcc_features = to_gcc_features(sess, rust_feature);
70-
if gcc_features.contains(&feature) && !gcc_features.contains(&rust_feature) {
71-
Some(rust_feature)
72-
} else {
73-
None
72+
if diagnostics {
73+
let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature);
74+
match feature_state {
75+
None => {
76+
let rust_feature =
77+
known_features.iter().find_map(|&(rust_feature, _, _)| {
78+
let gcc_features = to_gcc_features(sess, rust_feature);
79+
if gcc_features.contains(&feature)
80+
&& !gcc_features.contains(&rust_feature)
81+
{
82+
Some(rust_feature)
83+
} else {
84+
None
85+
}
86+
});
87+
let unknown_feature = if let Some(rust_feature) = rust_feature {
88+
UnknownCTargetFeature {
89+
feature,
90+
rust_feature: PossibleFeature::Some { rust_feature },
91+
}
92+
} else {
93+
UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
94+
};
95+
sess.dcx().emit_warn(unknown_feature);
7496
}
75-
});
76-
let unknown_feature = if let Some(rust_feature) = rust_feature {
77-
UnknownCTargetFeature {
78-
feature,
79-
rust_feature: PossibleFeature::Some { rust_feature },
97+
Some((_, Stability::Stable, _)) => {}
98+
Some((_, Stability::Unstable(_), _)) => {
99+
// An unstable feature. Warn about using it.
100+
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
80101
}
81-
} else {
82-
UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
83-
};
84-
sess.dcx().emit_warn(unknown_feature);
85-
}
102+
Some((_, Stability::Forbidden { .. }, _)) => {
103+
sess.dcx().emit_err(ForbiddenCTargetFeature { feature });
104+
}
105+
}
86106

87-
if diagnostics {
88107
// FIXME(nagisa): figure out how to not allocate a full hashset here.
89108
featsmap.insert(feature, enable_disable == '+');
90109
}
91110

92-
// rustc-specific features do not get passed down to GCC…
93-
if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
94-
return None;
95-
}
96111
// ... otherwise though we run through `to_gcc_features` when
97112
// passing requests down to GCC. This means that all in-language
98113
// features also work on the command line instead of having two

compiler/rustc_codegen_gcc/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,9 @@ pub fn target_features(
491491
) -> Vec<Symbol> {
492492
// TODO(antoyo): use global_gcc_features.
493493
sess.target
494-
.supported_target_features()
494+
.rust_target_features()
495495
.iter()
496+
.filter(|(_, gate, _)| gate.is_supported())
496497
.filter_map(|&(feature, gate, _)| {
497498
if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
498499
Some(feature)

compiler/rustc_codegen_llvm/messages.ftl

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ codegen_llvm_dynamic_linking_with_lto =
77
88
codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture
99
10+
codegen_llvm_forbidden_ctarget_feature =
11+
target feature `{$feature}` cannot be toggled with `-Ctarget-feature`: {$reason}
12+
.note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
13+
codegen_llvm_forbidden_ctarget_feature_issue = for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
14+
1015
codegen_llvm_from_llvm_diag = {$message}
1116
1217
codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}

compiler/rustc_codegen_llvm/src/errors.rs

+9
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ pub(crate) struct UnstableCTargetFeature<'a> {
3131
pub feature: &'a str,
3232
}
3333

34+
#[derive(Diagnostic)]
35+
#[diag(codegen_llvm_forbidden_ctarget_feature)]
36+
#[note]
37+
#[note(codegen_llvm_forbidden_ctarget_feature_issue)]
38+
pub(crate) struct ForbiddenCTargetFeature<'a> {
39+
pub feature: &'a str,
40+
pub reason: &'a str,
41+
}
42+
3443
#[derive(Subdiagnostic)]
3544
pub(crate) enum PossibleFeature<'a> {
3645
#[help(codegen_llvm_possible_feature)]

compiler/rustc_codegen_llvm/src/llvm_util.rs

+71-48
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ 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};
20+
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES, Stability};
2121

2222
use crate::back::write::create_informational_target_machine;
2323
use crate::errors::{
24-
FixedX18InvalidArch, InvalidTargetFeaturePrefix, PossibleFeature, UnknownCTargetFeature,
25-
UnknownCTargetFeaturePrefix, UnstableCTargetFeature,
24+
FixedX18InvalidArch, ForbiddenCTargetFeature, InvalidTargetFeaturePrefix, PossibleFeature,
25+
UnknownCTargetFeature, UnknownCTargetFeaturePrefix, UnstableCTargetFeature,
2626
};
2727
use crate::llvm;
2828

@@ -281,19 +281,29 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
281281
}
282282
}
283283

284-
/// Used to generate cfg variables and apply features
285-
/// Must express features in the way Rust understands them
284+
/// Used to generate cfg variables and apply features.
285+
/// Must express features in the way Rust understands them.
286+
///
287+
/// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled outside codegen.
286288
pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
287-
let mut features = vec![];
288-
289-
// Add base features for the target
289+
let mut features: FxHashSet<Symbol> = Default::default();
290+
291+
// Add base features for the target.
292+
// We do *not* add the -Ctarget-features there, and instead duplicate the logic for that below.
293+
// The reason is that if LLVM considers a feature implied but we do not, we don't want that to
294+
// show up in `cfg`. That way, `cfg` is entirely under our control -- except for the handling of
295+
// the target CPU, that is still expanded to target features (with all their implied features) by
296+
// LLVM.
290297
let target_machine = create_informational_target_machine(sess, true);
298+
// Compute which of the known target features are enabled in the 'base' target machine.
299+
// We only consider "supported" features; "forbidden" features are not reflected in `cfg` as of now.
291300
features.extend(
292301
sess.target
293-
.supported_target_features()
302+
.rust_target_features()
294303
.iter()
304+
.filter(|(_, gate, _)| gate.is_supported())
295305
.filter(|(feature, _, _)| {
296-
// skip checking special features, as LLVM may not understands them
306+
// skip checking special features, as LLVM may not understand them
297307
if RUSTC_SPECIAL_FEATURES.contains(feature) {
298308
return true;
299309
}
@@ -324,16 +334,22 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
324334
if enabled {
325335
features.extend(sess.target.implied_target_features(std::iter::once(feature)));
326336
} else {
337+
// We don't care about the order in `features` since the only thing we use it for is the
338+
// `features.contains` below.
339+
#[allow(rustc::potential_query_instability)]
327340
features.retain(|f| {
341+
// Keep a feature if it does not imply `feature`. Or, equivalently,
342+
// remove the reverse-dependencies of `feature`.
328343
!sess.target.implied_target_features(std::iter::once(*f)).contains(&feature)
329344
});
330345
}
331346
}
332347

333348
// Filter enabled features based on feature gates
334349
sess.target
335-
.supported_target_features()
350+
.rust_target_features()
336351
.iter()
352+
.filter(|(_, gate, _)| gate.is_supported())
337353
.filter_map(|&(feature, gate, _)| {
338354
if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
339355
Some(feature)
@@ -451,9 +467,13 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine, out: &mut Str
451467
let mut known_llvm_target_features = FxHashSet::<&'static str>::default();
452468
let mut rustc_target_features = sess
453469
.target
454-
.supported_target_features()
470+
.rust_target_features()
455471
.iter()
456-
.filter_map(|(feature, _gate, _implied)| {
472+
.filter_map(|(feature, gate, _implied)| {
473+
if !gate.is_supported() {
474+
// Only list (experimentally) supported features.
475+
return None;
476+
}
457477
// LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these
458478
// strings.
459479
let llvm_feature = to_llvm_features(sess, *feature)?.llvm_feature_name;
@@ -605,7 +625,7 @@ pub(crate) fn global_llvm_features(
605625

606626
// -Ctarget-features
607627
if !only_base_features {
608-
let supported_features = sess.target.supported_target_features();
628+
let known_features = sess.target.rust_target_features();
609629
let mut featsmap = FxHashMap::default();
610630

611631
// insert implied features
@@ -639,50 +659,53 @@ pub(crate) fn global_llvm_features(
639659
}
640660
};
641661

662+
// Get the backend feature name, if any.
663+
// This excludes rustc-specific features, which do not get passed to LLVM.
642664
let feature = backend_feature_name(sess, s)?;
643665
// Warn against use of LLVM specific feature names and unstable features on the CLI.
644666
if diagnostics {
645-
let feature_state = supported_features.iter().find(|&&(v, _, _)| v == feature);
646-
if feature_state.is_none() {
647-
let rust_feature =
648-
supported_features.iter().find_map(|&(rust_feature, _, _)| {
649-
let llvm_features = to_llvm_features(sess, rust_feature)?;
650-
if llvm_features.contains(feature)
651-
&& !llvm_features.contains(rust_feature)
652-
{
653-
Some(rust_feature)
654-
} else {
655-
None
667+
let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature);
668+
match feature_state {
669+
None => {
670+
let rust_feature =
671+
known_features.iter().find_map(|&(rust_feature, _, _)| {
672+
let llvm_features = to_llvm_features(sess, rust_feature)?;
673+
if llvm_features.contains(feature)
674+
&& !llvm_features.contains(rust_feature)
675+
{
676+
Some(rust_feature)
677+
} else {
678+
None
679+
}
680+
});
681+
let unknown_feature = if let Some(rust_feature) = rust_feature {
682+
UnknownCTargetFeature {
683+
feature,
684+
rust_feature: PossibleFeature::Some { rust_feature },
656685
}
657-
});
658-
let unknown_feature = if let Some(rust_feature) = rust_feature {
659-
UnknownCTargetFeature {
660-
feature,
661-
rust_feature: PossibleFeature::Some { rust_feature },
662-
}
663-
} else {
664-
UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
665-
};
666-
sess.dcx().emit_warn(unknown_feature);
667-
} else if feature_state
668-
.is_some_and(|(_name, feature_gate, _implied)| !feature_gate.is_stable())
669-
{
670-
// An unstable feature. Warn about using it.
671-
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
686+
} else {
687+
UnknownCTargetFeature {
688+
feature,
689+
rust_feature: PossibleFeature::None,
690+
}
691+
};
692+
sess.dcx().emit_warn(unknown_feature);
693+
}
694+
Some((_, Stability::Stable, _)) => {}
695+
Some((_, Stability::Unstable(_), _)) => {
696+
// An unstable feature. Warn about using it.
697+
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
698+
}
699+
Some((_, Stability::Forbidden { reason }, _)) => {
700+
sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason });
701+
}
672702
}
673-
}
674703

675-
if diagnostics {
676704
// FIXME(nagisa): figure out how to not allocate a full hashset here.
677705
featsmap.insert(feature, enable_disable == '+');
678706
}
679707

680-
// rustc-specific features do not get passed down to LLVM…
681-
if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
682-
return None;
683-
}
684-
685-
// ... otherwise though we run through `to_llvm_features` when
708+
// We run through `to_llvm_features` when
686709
// passing requests down to LLVM. This means that all in-language
687710
// features also work on the command line instead of having two
688711
// different names when the LLVM name and the Rust name differ.

compiler/rustc_codegen_ssa/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ codegen_ssa_failed_to_write = failed to write {$path}: {$error}
6464
6565
codegen_ssa_field_associated_value_expected = associated value expected for `{$name}`
6666
67+
codegen_ssa_forbidden_target_feature_attr =
68+
target feature `{$feature}` cannot be toggled with `#[target_feature]`: {$reason}
69+
6770
codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced
6871
6972
codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced

0 commit comments

Comments
 (0)