@@ -12,13 +12,16 @@ use rustc_middle::ty::TyCtxt;
1212use rustc_session:: parse:: feature_err;
1313use rustc_span:: symbol:: { sym, Symbol } ;
1414use rustc_span:: Span ;
15+ use rustc_target:: target_features:: { self , Stability } ;
1516
1617use crate :: errors;
1718
18- pub fn from_target_feature (
19+ /// Compute the enabled target features from the `#[target_feature]` function attribute.
20+ /// Enabled target features are added to `target_features`.
21+ pub fn from_target_feature_attr (
1922 tcx : TyCtxt < ' _ > ,
2023 attr : & ast:: Attribute ,
21- supported_target_features : & UnordMap < String , Option < Symbol > > ,
24+ known_target_features : & UnordMap < String , target_features :: Stability > ,
2225 target_features : & mut Vec < TargetFeature > ,
2326) {
2427 let Some ( list) = attr. meta_item_list ( ) else { return } ;
@@ -47,12 +50,12 @@ pub fn from_target_feature(
4750
4851 // We allow comma separation to enable multiple features.
4952 added_target_features. extend ( value. as_str ( ) . split ( ',' ) . filter_map ( |feature| {
50- let Some ( feature_gate ) = supported_target_features . get ( feature) else {
53+ let Some ( stability ) = known_target_features . get ( feature) else {
5154 let msg = format ! ( "the feature named `{feature}` is not valid for this target" ) ;
5255 let mut err = tcx. dcx ( ) . struct_span_err ( item. span ( ) , msg) ;
5356 err. span_label ( item. span ( ) , format ! ( "`{feature}` is not valid for this target" ) ) ;
5457 if let Some ( stripped) = feature. strip_prefix ( '+' ) {
55- let valid = supported_target_features . contains_key ( stripped) ;
58+ let valid = known_target_features . contains_key ( stripped) ;
5659 if valid {
5760 err. help ( "consider removing the leading `+` in the feature name" ) ;
5861 }
@@ -62,39 +65,73 @@ pub fn from_target_feature(
6265 } ;
6366
6467 // Only allow features whose feature gates have been enabled.
65- let allowed = match feature_gate. as_ref ( ) . copied ( ) {
66- Some ( sym:: arm_target_feature) => rust_features. arm_target_feature ,
67- Some ( sym:: hexagon_target_feature) => rust_features. hexagon_target_feature ,
68- Some ( sym:: powerpc_target_feature) => rust_features. powerpc_target_feature ,
69- Some ( sym:: mips_target_feature) => rust_features. mips_target_feature ,
70- Some ( sym:: riscv_target_feature) => rust_features. riscv_target_feature ,
71- Some ( sym:: avx512_target_feature) => rust_features. avx512_target_feature ,
72- Some ( sym:: sse4a_target_feature) => rust_features. sse4a_target_feature ,
73- Some ( sym:: tbm_target_feature) => rust_features. tbm_target_feature ,
74- Some ( sym:: wasm_target_feature) => rust_features. wasm_target_feature ,
75- Some ( sym:: rtm_target_feature) => rust_features. rtm_target_feature ,
76- Some ( sym:: ermsb_target_feature) => rust_features. ermsb_target_feature ,
77- Some ( sym:: bpf_target_feature) => rust_features. bpf_target_feature ,
78- Some ( sym:: aarch64_ver_target_feature) => rust_features. aarch64_ver_target_feature ,
79- Some ( sym:: csky_target_feature) => rust_features. csky_target_feature ,
80- Some ( sym:: loongarch_target_feature) => rust_features. loongarch_target_feature ,
81- Some ( sym:: lahfsahf_target_feature) => rust_features. lahfsahf_target_feature ,
82- Some ( sym:: prfchw_target_feature) => rust_features. prfchw_target_feature ,
83- Some ( sym:: sha512_sm_x86) => rust_features. sha512_sm_x86 ,
84- Some ( sym:: x86_amx_intrinsics) => rust_features. x86_amx_intrinsics ,
85- Some ( sym:: xop_target_feature) => rust_features. xop_target_feature ,
86- Some ( sym:: s390x_target_feature) => rust_features. s390x_target_feature ,
87- Some ( name) => bug ! ( "unknown target feature gate {}" , name) ,
88- None => true ,
68+ let allowed = match stability {
69+ Stability :: Forbidden => false ,
70+ Stability :: Stable => true ,
71+ Stability :: Unstable ( sym:: arm_target_feature) => rust_features. arm_target_feature ,
72+ Stability :: Unstable ( sym:: hexagon_target_feature) => {
73+ rust_features. hexagon_target_feature
74+ }
75+ Stability :: Unstable ( sym:: powerpc_target_feature) => {
76+ rust_features. powerpc_target_feature
77+ }
78+ Stability :: Unstable ( sym:: mips_target_feature) => rust_features. mips_target_feature ,
79+ Stability :: Unstable ( sym:: riscv_target_feature) => {
80+ rust_features. riscv_target_feature
81+ }
82+ Stability :: Unstable ( sym:: avx512_target_feature) => {
83+ rust_features. avx512_target_feature
84+ }
85+ Stability :: Unstable ( sym:: sse4a_target_feature) => {
86+ rust_features. sse4a_target_feature
87+ }
88+ Stability :: Unstable ( sym:: tbm_target_feature) => rust_features. tbm_target_feature ,
89+ Stability :: Unstable ( sym:: wasm_target_feature) => rust_features. wasm_target_feature ,
90+ Stability :: Unstable ( sym:: rtm_target_feature) => rust_features. rtm_target_feature ,
91+ Stability :: Unstable ( sym:: ermsb_target_feature) => {
92+ rust_features. ermsb_target_feature
93+ }
94+ Stability :: Unstable ( sym:: bpf_target_feature) => rust_features. bpf_target_feature ,
95+ Stability :: Unstable ( sym:: aarch64_ver_target_feature) => {
96+ rust_features. aarch64_ver_target_feature
97+ }
98+ Stability :: Unstable ( sym:: csky_target_feature) => rust_features. csky_target_feature ,
99+ Stability :: Unstable ( sym:: loongarch_target_feature) => {
100+ rust_features. loongarch_target_feature
101+ }
102+ Stability :: Unstable ( sym:: lahfsahf_target_feature) => {
103+ rust_features. lahfsahf_target_feature
104+ }
105+ Stability :: Unstable ( sym:: prfchw_target_feature) => {
106+ rust_features. prfchw_target_feature
107+ }
108+ Stability :: Unstable ( sym:: sha512_sm_x86) => rust_features. sha512_sm_x86 ,
109+ Stability :: Unstable ( sym:: x86_amx_intrinsics) => rust_features. x86_amx_intrinsics ,
110+ Stability :: Unstable ( sym:: xop_target_feature) => rust_features. xop_target_feature ,
111+ Stability :: Unstable ( sym:: s390x_target_feature) => {
112+ rust_features. s390x_target_feature
113+ }
114+ Stability :: Unstable ( name) => bug ! ( "unknown target feature gate {}" , name) ,
89115 } ;
90116 if !allowed {
91- feature_err (
92- & tcx. sess ,
93- feature_gate. unwrap ( ) ,
94- item. span ( ) ,
95- format ! ( "the target feature `{feature}` is currently unstable" ) ,
96- )
97- . emit ( ) ;
117+ match stability {
118+ Stability :: Stable => unreachable ! ( ) ,
119+ & Stability :: Unstable ( lang_feature_name) => {
120+ feature_err (
121+ & tcx. sess ,
122+ lang_feature_name,
123+ item. span ( ) ,
124+ format ! ( "the target feature `{feature}` is currently unstable" ) ,
125+ )
126+ . emit ( ) ;
127+ }
128+ Stability :: Forbidden => {
129+ tcx. dcx ( ) . emit_err ( errors:: ForbiddenTargetFeature {
130+ span : item. span ( ) ,
131+ feature,
132+ } ) ;
133+ }
134+ }
98135 }
99136 Some ( Symbol :: intern ( feature) )
100137 } ) ) ;
@@ -160,20 +197,20 @@ pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_s
160197
161198pub ( crate ) fn provide ( providers : & mut Providers ) {
162199 * providers = Providers {
163- supported_target_features : |tcx, cnum| {
200+ known_target_features : |tcx, cnum| {
164201 assert_eq ! ( cnum, LOCAL_CRATE ) ;
165202 if tcx. sess . opts . actually_rustdoc {
166203 // rustdoc needs to be able to document functions that use all the features, so
167204 // whitelist them all
168205 rustc_target:: target_features:: all_known_features ( )
169- . map ( |( a, b) | ( a. to_string ( ) , b. as_feature_name ( ) ) )
206+ . map ( |( a, b) | ( a. to_string ( ) , b) )
170207 . collect ( )
171208 } else {
172209 tcx. sess
173210 . target
174- . supported_target_features ( )
211+ . known_target_features ( )
175212 . iter ( )
176- . map ( |& ( a, b, _) | ( a. to_string ( ) , b. as_feature_name ( ) ) )
213+ . map ( |& ( a, b, _) | ( a. to_string ( ) , b) )
177214 . collect ( )
178215 }
179216 } ,
0 commit comments