Skip to content

Commit 16402de

Browse files
authored
Merge pull request #19223 from ChayimFriedman2/implied-target-feature
fix: Support target features implications in target_feature 1.1
2 parents e6bb047 + 5c654dc commit 16402de

5 files changed

Lines changed: 272 additions & 36 deletions

File tree

‎src/tools/rust-analyzer/.typos.toml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ extend-ignore-re = [
1818
"INOUT",
1919
"optin",
2020
"=Pn",
21+
# ignore `// spellchecker:off` until `// spellchecker:on`
22+
"(?s)(#|//)\\s*spellchecker:off.*?\\n\\s*(#|//)\\s*spellchecker:on",
2123
]
2224

2325
[default.extend-words]

‎src/tools/rust-analyzer/crates/hir-ty/src/lib.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ mod inhabitedness;
3636
mod interner;
3737
mod lower;
3838
mod mapping;
39+
mod target_feature;
3940
mod tls;
4041
mod utils;
4142

@@ -107,10 +108,9 @@ pub use mapping::{
107108
to_foreign_def_id, to_placeholder_idx,
108109
};
109110
pubuse method_resolution::check_orphan_rules;
111+
pubuse target_feature::TargetFeatures;
110112
pubuse traits::TraitEnvironment;
111-
pubuse utils::{
112-
all_super_traits, direct_super_traits, is_fn_unsafe_to_call,TargetFeatures,Unsafety,
113-
};
113+
pubuse utils::{all_super_traits, direct_super_traits, is_fn_unsafe_to_call,Unsafety};
114114
pubuse variance::Variance;
115115

116116
pubuse chalk_ir::{
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
//! Stuff for handling `#[target_feature]` (needed for unsafe check).
2+
3+
use std::sync::LazyLock;
4+
5+
use hir_def::attr::Attrs;
6+
use hir_def::tt;
7+
use intern::{sym,Symbol};
8+
use rustc_hash::{FxHashMap,FxHashSet};
9+
10+
#[derive(Debug,Default)]
11+
pubstructTargetFeatures{
12+
pub(crate)enabled:FxHashSet<Symbol>,
13+
}
14+
15+
implTargetFeatures{
16+
pubfnfrom_attrs(attrs:&Attrs) -> Self{
17+
letmut result = TargetFeatures::from_attrs_no_implications(attrs);
18+
result.expand_implications();
19+
result
20+
}
21+
22+
fnexpand_implications(&mutself){
23+
let all_implications = LazyLock::force(&TARGET_FEATURE_IMPLICATIONS);
24+
letmut queue = self.enabled.iter().cloned().collect::<Vec<_>>();
25+
whileletSome(feature) = queue.pop(){
26+
ifletSome(implications) = all_implications.get(&feature){
27+
for implication in implications {
28+
ifself.enabled.insert(implication.clone()){
29+
queue.push(implication.clone());
30+
}
31+
}
32+
}
33+
}
34+
}
35+
36+
/// Retrieves the target features from the attributes, and does not expand the target features implied by them.
37+
pub(crate)fnfrom_attrs_no_implications(attrs:&Attrs) -> Self{
38+
let enabled = attrs
39+
.by_key(&sym::target_feature)
40+
.tt_values()
41+
.filter_map(|tt| {
42+
match tt.token_trees().flat_tokens(){
43+
[
44+
tt::TokenTree::Leaf(tt::Leaf::Ident(enable_ident)),
45+
tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct{char:'=', .. })),
46+
tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal{kind: tt::LitKind::Str,symbol: features, .. })),
47+
]if enable_ident.sym == sym::enable => Some(features),
48+
_ => None,
49+
}
50+
})
51+
.flat_map(|features| features.as_str().split(',').map(Symbol::intern))
52+
.collect();
53+
Self{ enabled }
54+
}
55+
}
56+
57+
// List of the target features each target feature implies.
58+
// Ideally we'd depend on rustc for this, but rustc_target doesn't compile on stable,
59+
// and t-compiler prefers for it to stay this way.
60+
61+
staticTARGET_FEATURE_IMPLICATIONS:LazyLock<FxHashMap<Symbol,Box<[Symbol]>>> =
62+
LazyLock::new(|| {
63+
letmut result = FxHashMap::<Symbol,FxHashSet<Symbol>>::default();
64+
for&(feature_str, implications)inTARGET_FEATURE_IMPLICATIONS_RAW{
65+
let feature = Symbol::intern(feature_str);
66+
let implications = implications.iter().copied().map(Symbol::intern);
67+
// Some target features appear in two archs, e.g. Arm and x86.
68+
// Sometimes they contain different implications, e.g. `aes`.
69+
// We should probably choose by the active arch, but for now just merge them.
70+
result.entry(feature).or_default().extend(implications);
71+
}
72+
letmut result = result
73+
.into_iter()
74+
.map(|(feature, implications)| (feature,Box::from_iter(implications)))
75+
.collect::<FxHashMap<_,_>>();
76+
result.shrink_to_fit();
77+
result
78+
});
79+
80+
// spellchecker:off
81+
constTARGET_FEATURE_IMPLICATIONS_RAW:&[(&str,&[&str])] = &[
82+
// Arm
83+
("aes",&["neon"]),
84+
("dotprod",&["neon"]),
85+
("fp-armv8",&["vfp4"]),
86+
("fp16",&["neon"]),
87+
("i8mm",&["neon"]),
88+
("neon",&["vfp3"]),
89+
("sha2",&["neon"]),
90+
("v6",&["v5te"]),
91+
("v6k",&["v6"]),
92+
("v6t2",&["v6k","thumb2"]),
93+
("v7",&["v6t2"]),
94+
("v8",&["v7"]),
95+
("vfp3",&["vfp2","d32"]),
96+
("vfp4",&["vfp3"]),
97+
// Aarch64
98+
("aes",&["neon"]),
99+
("dotprod",&["neon"]),
100+
("dpb2",&["dpb"]),
101+
("f32mm",&["sve"]),
102+
("f64mm",&["sve"]),
103+
("fcma",&["neon"]),
104+
("fhm",&["fp16"]),
105+
("fp16",&["neon"]),
106+
("fp8",&["faminmax","lut","bf16"]),
107+
("fp8dot2",&["fp8dot4"]),
108+
("fp8dot4",&["fp8fma"]),
109+
("fp8fma",&["fp8"]),
110+
("jsconv",&["neon"]),
111+
("lse128",&["lse"]),
112+
("rcpc2",&["rcpc"]),
113+
("rcpc3",&["rcpc2"]),
114+
("rdm",&["neon"]),
115+
("sha2",&["neon"]),
116+
("sha3",&["sha2"]),
117+
("sm4",&["neon"]),
118+
("sme",&["bf16"]),
119+
("sme-b16b16",&["bf16","sme2","sve-b16b16"]),
120+
("sme-f16f16",&["sme2"]),
121+
("sme-f64f64",&["sme"]),
122+
("sme-f8f16",&["sme-f8f32"]),
123+
("sme-f8f32",&["sme2","fp8"]),
124+
("sme-fa64",&["sme","sve2"]),
125+
("sme-i16i64",&["sme"]),
126+
("sme2",&["sme"]),
127+
("sme2p1",&["sme2"]),
128+
("ssve-fp8dot2",&["ssve-fp8dot4"]),
129+
("ssve-fp8dot4",&["ssve-fp8fma"]),
130+
("ssve-fp8fma",&["sme2","fp8"]),
131+
("sve",&["neon"]),
132+
("sve-b16b16",&["bf16"]),
133+
("sve2",&["sve"]),
134+
("sve2-aes",&["sve2","aes"]),
135+
("sve2-bitperm",&["sve2"]),
136+
("sve2-sha3",&["sve2","sha3"]),
137+
("sve2-sm4",&["sve2","sm4"]),
138+
("sve2p1",&["sve2"]),
139+
("v8.1a",&["crc","lse","rdm","pan","lor","vh"]),
140+
("v8.2a",&["v8.1a","ras","dpb"]),
141+
("v8.3a",&["v8.2a","rcpc","paca","pacg","jsconv"]),
142+
("v8.4a",&["v8.3a","dotprod","dit","flagm"]),
143+
("v8.5a",&["v8.4a","ssbs","sb","dpb2","bti"]),
144+
("v8.6a",&["v8.5a","bf16","i8mm"]),
145+
("v8.7a",&["v8.6a","wfxt"]),
146+
("v8.8a",&["v8.7a","hbc","mops"]),
147+
("v8.9a",&["v8.8a","cssc"]),
148+
("v9.1a",&["v9a","v8.6a"]),
149+
("v9.2a",&["v9.1a","v8.7a"]),
150+
("v9.3a",&["v9.2a","v8.8a"]),
151+
("v9.4a",&["v9.3a","v8.9a"]),
152+
("v9.5a",&["v9.4a"]),
153+
("v9a",&["v8.5a","sve2"]),
154+
// x86
155+
("aes",&["sse2"]),
156+
("amx-bf16",&["amx-tile"]),
157+
("amx-complex",&["amx-tile"]),
158+
("amx-fp16",&["amx-tile"]),
159+
("amx-int8",&["amx-tile"]),
160+
("avx",&["sse4.2"]),
161+
("avx2",&["avx"]),
162+
("avx512bf16",&["avx512bw"]),
163+
("avx512bitalg",&["avx512bw"]),
164+
("avx512bw",&["avx512f"]),
165+
("avx512cd",&["avx512f"]),
166+
("avx512dq",&["avx512f"]),
167+
("avx512f",&["avx2","fma","f16c"]),
168+
("avx512fp16",&["avx512bw","avx512vl","avx512dq"]),
169+
("avx512ifma",&["avx512f"]),
170+
("avx512vbmi",&["avx512bw"]),
171+
("avx512vbmi2",&["avx512bw"]),
172+
("avx512vl",&["avx512f"]),
173+
("avx512vnni",&["avx512f"]),
174+
("avx512vp2intersect",&["avx512f"]),
175+
("avx512vpopcntdq",&["avx512f"]),
176+
("avxifma",&["avx2"]),
177+
("avxneconvert",&["avx2"]),
178+
("avxvnni",&["avx2"]),
179+
("avxvnniint16",&["avx2"]),
180+
("avxvnniint8",&["avx2"]),
181+
("f16c",&["avx"]),
182+
("fma",&["avx"]),
183+
("gfni",&["sse2"]),
184+
("kl",&["sse2"]),
185+
("pclmulqdq",&["sse2"]),
186+
("sha",&["sse2"]),
187+
("sha512",&["avx2"]),
188+
("sm3",&["avx"]),
189+
("sm4",&["avx2"]),
190+
("sse2",&["sse"]),
191+
("sse3",&["sse2"]),
192+
("sse4.1",&["ssse3"]),
193+
("sse4.2",&["sse4.1"]),
194+
("sse4a",&["sse3"]),
195+
("ssse3",&["sse3"]),
196+
("vaes",&["avx2","aes"]),
197+
("vpclmulqdq",&["avx","pclmulqdq"]),
198+
("widekl",&["kl"]),
199+
("xop",&[/*"fma4", */"avx","sse4a"]),
200+
("xsavec",&["xsave"]),
201+
("xsaveopt",&["xsave"]),
202+
("xsaves",&["xsave"]),
203+
// Hexagon
204+
("hvx-length128b",&["hvx"]),
205+
// PowerPC
206+
("power10-vector",&["power9-vector"]),
207+
("power8-altivec",&["altivec"]),
208+
("power8-crypto",&["power8-altivec"]),
209+
("power8-vector",&["vsx","power8-altivec"]),
210+
("power9-altivec",&["power8-altivec"]),
211+
("power9-vector",&["power8-vector","power9-altivec"]),
212+
("vsx",&["altivec"]),
213+
// MIPS
214+
// RISC-V
215+
("a",&["zaamo","zalrsc"]),
216+
("d",&["f"]),
217+
("zabha",&["zaamo"]),
218+
("zdinx",&["zfinx"]),
219+
("zfh",&["zfhmin"]),
220+
("zfhmin",&["f"]),
221+
("zhinx",&["zhinxmin"]),
222+
("zhinxmin",&["zfinx"]),
223+
("zk",&["zkn","zkr","zkt"]),
224+
("zkn",&["zbkb","zbkc","zbkx","zkne","zknd","zknh"]),
225+
("zks",&["zbkb","zbkc","zbkx","zksed","zksh"]),
226+
// WASM
227+
("relaxed-simd",&["simd128"]),
228+
// BPF
229+
("alu32",&[]),
230+
// CSKY
231+
("10e60",&["7e10"]),
232+
("2e3",&["e2"]),
233+
("3e3r2",&["3e3r1","doloop"]),
234+
("3e3r3",&["doloop"]),
235+
("3e7",&["2e3"]),
236+
("7e10",&["3e7"]),
237+
("e1",&["elrw"]),
238+
("e2",&["e2"]),
239+
("mp",&["2e3"]),
240+
("mp1e2",&["3e7"]),
241+
// LoongArch
242+
("d",&["f"]),
243+
("lasx",&["lsx"]),
244+
("lsx",&["d"]),
245+
// IBM Z
246+
("nnp-assist",&["vector"]),
247+
("vector-enhancements-1",&["vector"]),
248+
("vector-enhancements-2",&["vector-enhancements-1"]),
249+
("vector-packed-decimal",&["vector"]),
250+
("vector-packed-decimal-enhancement",&["vector-packed-decimal"]),
251+
("vector-packed-decimal-enhancement-2",&["vector-packed-decimal-enhancement"]),
252+
// SPARC
253+
// m68k
254+
("isa-68010",&["isa-68000"]),
255+
("isa-68020",&["isa-68010"]),
256+
("isa-68030",&["isa-68020"]),
257+
("isa-68040",&["isa-68030","isa-68882"]),
258+
("isa-68060",&["isa-68040"]),
259+
("isa-68882",&["isa-68881"]),
260+
];
261+
// spellchecker:on

‎src/tools/rust-analyzer/crates/hir-ty/src/utils.rs‎

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,16 @@ use chalk_ir::{
99
DebruijnIndex,
1010
};
1111
use hir_def::{
12-
attr::Attrs,
1312
db::DefDatabase,
1413
generics::{WherePredicate,WherePredicateTypeTarget},
1514
lang_item::LangItem,
1615
resolver::{HasResolver,TypeNs},
17-
tt,
1816
type_ref::{TraitBoundModifier,TypeRef},
1917
EnumId,EnumVariantId,FunctionId,Lookup,OpaqueInternableThing,TraitId,TypeAliasId,
2018
TypeOrConstParamId,
2119
};
2220
use hir_expand::name::Name;
23-
use intern::{sym,Symbol};
21+
use intern::sym;
2422
use rustc_abi::TargetDataLayout;
2523
use rustc_hash::FxHashSet;
2624
use smallvec::{smallvec,SmallVec};
@@ -32,8 +30,8 @@ use crate::{
3230
db::HirDatabase,
3331
layout::{Layout,TagEncoding},
3432
mir::pad16,
35-
ChalkTraitId,Const,ConstScalar,GenericArg,Interner,Substitution,TraitRef,TraitRefExt,
36-
Ty,WhereClause,
33+
ChalkTraitId,Const,ConstScalar,GenericArg,Interner,Substitution,TargetFeatures,TraitRef,
34+
TraitRefExt,Ty,WhereClause,
3735
};
3836

3937
pub(crate)fnfn_traits(
@@ -267,32 +265,6 @@ impl<'a> ClosureSubst<'a> {
267265
}
268266
}
269267

270-
#[derive(Debug,Default)]
271-
pubstructTargetFeatures{
272-
enabled:FxHashSet<Symbol>,
273-
}
274-
275-
implTargetFeatures{
276-
pubfnfrom_attrs(attrs:&Attrs) -> Self{
277-
let enabled = attrs
278-
.by_key(&sym::target_feature)
279-
.tt_values()
280-
.filter_map(|tt| {
281-
match tt.token_trees().flat_tokens(){
282-
[
283-
tt::TokenTree::Leaf(tt::Leaf::Ident(enable_ident)),
284-
tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct{char:'=', .. })),
285-
tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal{kind: tt::LitKind::Str,symbol: features, .. })),
286-
]if enable_ident.sym == sym::enable => Some(features),
287-
_ => None,
288-
}
289-
})
290-
.flat_map(|features| features.as_str().split(',').map(Symbol::intern))
291-
.collect();
292-
Self{ enabled }
293-
}
294-
}
295-
296268
#[derive(Debug,Clone,Copy,PartialEq,Eq)]
297269
pubenumUnsafety{
298270
Safe,
@@ -314,7 +286,8 @@ pub fn is_fn_unsafe_to_call(
314286

315287
if data.has_target_feature(){
316288
// RFC 2396 <https://rust-lang.github.io/rfcs/2396-target-feature-1.1.html>.
317-
let callee_target_features = TargetFeatures::from_attrs(&db.attrs(func.into()));
289+
let callee_target_features =
290+
TargetFeatures::from_attrs_no_implications(&db.attrs(func.into()));
318291
if !caller_target_features.enabled.is_superset(&callee_target_features.enabled){
319292
returnUnsafety::Unsafe;
320293
}

‎src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,7 @@ fn main() {
854854
#[target_feature(enable = "avx")]
855855
fn foo() {}
856856
857-
#[target_feature(enable = "avx,avx2")]
857+
#[target_feature(enable = "avx2")]
858858
fn bar() {
859859
foo();
860860
}

0 commit comments

Comments
 (0)