mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
suggest valid features when target feature is invalid
This commit is contained in:
@@ -8,7 +8,8 @@
|
||||
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{
|
||||
Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, msg,
|
||||
Diag, DiagArgValue, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, IntoDiagArg,
|
||||
Level, msg,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::layout::LayoutError;
|
||||
@@ -1249,20 +1250,29 @@ pub(crate) struct FeatureNotValid<'a> {
|
||||
#[label("`{$feature}` is not valid for this target")]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub plus_hint: Option<RemovePlusFromFeatureName<'a>>,
|
||||
pub hint: FeatureNotValidHint<'a>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
"consider removing the leading `+` in the feature name",
|
||||
code = "enable = \"{stripped}\"",
|
||||
applicability = "maybe-incorrect",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub struct RemovePlusFromFeatureName<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub stripped: &'a str,
|
||||
pub(crate) enum FeatureNotValidHint<'a> {
|
||||
#[suggestion(
|
||||
"consider removing the leading `+` in the feature name",
|
||||
code = "enable = \"{stripped}\"",
|
||||
applicability = "maybe-incorrect",
|
||||
style = "verbose"
|
||||
)]
|
||||
RemovePlusFromFeatureName {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
stripped: &'a str,
|
||||
},
|
||||
#[help(
|
||||
"valid names are: {$possibilities}{$and_more ->
|
||||
[0] {\"\"}
|
||||
*[other] {\" \"}and {$and_more} more
|
||||
}"
|
||||
)]
|
||||
ValidFeatureNames { possibilities: DiagSymbolList<&'a str>, and_more: usize },
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::builtin::AARCH64_SOFTFLOAT_NEON;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_span::{Span, Symbol, edit_distance, sym};
|
||||
use rustc_target::spec::Arch;
|
||||
use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::errors::{FeatureNotValid, RemovePlusFromFeatureName};
|
||||
use crate::errors::{FeatureNotValid, FeatureNotValidHint};
|
||||
use crate::{errors, target_features};
|
||||
|
||||
/// Compute the enabled target features from the `#[target_feature]` function attribute.
|
||||
@@ -32,15 +32,25 @@ pub(crate) fn from_target_feature_attr(
|
||||
for &(feature, feature_span) in features {
|
||||
let feature_str = feature.as_str();
|
||||
let Some(stability) = rust_target_features.get(feature_str) else {
|
||||
let plus_hint = feature_str
|
||||
.strip_prefix('+')
|
||||
.filter(|stripped| rust_target_features.contains_key(*stripped))
|
||||
.map(|stripped| RemovePlusFromFeatureName { span: feature_span, stripped });
|
||||
tcx.dcx().emit_err(FeatureNotValid {
|
||||
feature: feature_str,
|
||||
span: feature_span,
|
||||
plus_hint,
|
||||
});
|
||||
let hint = if let Some(stripped) = feature_str.strip_prefix('+')
|
||||
&& rust_target_features.contains_key(stripped)
|
||||
{
|
||||
FeatureNotValidHint::RemovePlusFromFeatureName { span: feature_span, stripped }
|
||||
} else {
|
||||
// Show the 5 feature names that are most similar to the input.
|
||||
let mut valid_names: Vec<_> =
|
||||
rust_target_features.keys().map(|name| name.as_str()).into_sorted_stable_ord();
|
||||
valid_names.sort_by_key(|name| {
|
||||
edit_distance::edit_distance(name, feature.as_str(), 5).unwrap_or(usize::MAX)
|
||||
});
|
||||
valid_names.truncate(5);
|
||||
|
||||
FeatureNotValidHint::ValidFeatureNames {
|
||||
possibilities: valid_names.into(),
|
||||
and_more: rust_target_features.len().saturating_sub(5),
|
||||
}
|
||||
};
|
||||
tcx.dcx().emit_err(FeatureNotValid { feature: feature_str, span: feature_span, hint });
|
||||
continue;
|
||||
};
|
||||
|
||||
|
||||
@@ -119,7 +119,12 @@ fn main() {
|
||||
//~| NOTE `+sse2` is not valid for this target
|
||||
unsafe fn hey() {}
|
||||
|
||||
#[target_feature(enable = "+sse5")]
|
||||
//~^ ERROR `+sse5` is not valid for this target
|
||||
//~| NOTE `+sse5` is not valid for this target
|
||||
unsafe fn typo() {}
|
||||
#[target_feature(enable = "sse5")]
|
||||
//~^ ERROR `sse5` is not valid for this target
|
||||
//~| NOTE `sse5` is not valid for this target
|
||||
unsafe fn typo_sse() {}
|
||||
|
||||
#[target_feature(enable = "avx512")]
|
||||
//~^ ERROR `avx512` is not valid for this target
|
||||
//~| NOTE `avx512` is not valid for this target
|
||||
unsafe fn typo_avx512() {}
|
||||
|
||||
@@ -160,6 +160,8 @@ error: the feature named `foo` is not valid for this target
|
||||
|
|
||||
LL | #[target_feature(enable = "foo")]
|
||||
| ^^^^^^^^^^^^^^ `foo` is not valid for this target
|
||||
|
|
||||
= help: valid names are: `fma`, `xop`, `adx`, `aes`, and `avx` and 74 more
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `foo`
|
||||
--> $DIR/invalid-attribute.rs:81:1
|
||||
@@ -205,13 +207,23 @@ LL - #[target_feature(enable = "+sse2")]
|
||||
LL + #[target_feature(enable = "sse2")]
|
||||
|
|
||||
|
||||
error: the feature named `+sse5` is not valid for this target
|
||||
error: the feature named `sse5` is not valid for this target
|
||||
--> $DIR/invalid-attribute.rs:122:18
|
||||
|
|
||||
LL | #[target_feature(enable = "+sse5")]
|
||||
| ^^^^^^^^^^^^^^^^ `+sse5` is not valid for this target
|
||||
LL | #[target_feature(enable = "sse5")]
|
||||
| ^^^^^^^^^^^^^^^ `sse5` is not valid for this target
|
||||
|
|
||||
= help: valid names are: `sse`, `sse2`, `sse3`, `sse4a`, and `ssse3` and 74 more
|
||||
|
||||
error: aborting due to 25 previous errors
|
||||
error: the feature named `avx512` is not valid for this target
|
||||
--> $DIR/invalid-attribute.rs:127:18
|
||||
|
|
||||
LL | #[target_feature(enable = "avx512")]
|
||||
| ^^^^^^^^^^^^^^^^^ `avx512` is not valid for this target
|
||||
|
|
||||
= help: valid names are: `avx512f`, `avx2`, `avx512bw`, `avx512cd`, and `avx512dq` and 74 more
|
||||
|
||||
error: aborting due to 26 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0046, E0053, E0539, E0658.
|
||||
For more information about an error, try `rustc --explain E0046`.
|
||||
|
||||
Reference in New Issue
Block a user