Skip to content

Commit 16402de

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

File tree

5 files changed

+272
-36
lines changed

5 files changed

+272
-36
lines changed

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

+2
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

+3-3
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
pub use method_resolution::check_orphan_rules;
111+
pub use target_feature::TargetFeatures;
110112
pub use traits::TraitEnvironment;
111-
pub use utils::{
112-
all_super_traits, direct_super_traits, is_fn_unsafe_to_call, TargetFeatures, Unsafety,
113-
};
113+
pub use utils::{all_super_traits, direct_super_traits, is_fn_unsafe_to_call, Unsafety};
114114
pub use variance::Variance;
115115

116116
pub use chalk_ir::{
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+
pub struct TargetFeatures {
12+
pub(crate) enabled: FxHashSet<Symbol>,
13+
}
14+
15+
impl TargetFeatures {
16+
pub fn from_attrs(attrs: &Attrs) -> Self {
17+
let mut result = TargetFeatures::from_attrs_no_implications(attrs);
18+
result.expand_implications();
19+
result
20+
}
21+
22+
fn expand_implications(&mut self) {
23+
let all_implications = LazyLock::force(&TARGET_FEATURE_IMPLICATIONS);
24+
let mut queue = self.enabled.iter().cloned().collect::<Vec<_>>();
25+
while let Some(feature) = queue.pop() {
26+
if let Some(implications) = all_implications.get(&feature) {
27+
for implication in implications {
28+
if self.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) fn from_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+
static TARGET_FEATURE_IMPLICATIONS: LazyLock<FxHashMap<Symbol, Box<[Symbol]>>> =
62+
LazyLock::new(|| {
63+
let mut result = FxHashMap::<Symbol, FxHashSet<Symbol>>::default();
64+
for &(feature_str, implications) in TARGET_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+
let mut 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+
const TARGET_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

+5-32
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) fn fn_traits(
@@ -267,32 +265,6 @@ impl<'a> ClosureSubst<'a> {
267265
}
268266
}
269267

270-
#[derive(Debug, Default)]
271-
pub struct TargetFeatures {
272-
enabled: FxHashSet<Symbol>,
273-
}
274-
275-
impl TargetFeatures {
276-
pub fn from_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
pub enum Unsafety {
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
return Unsafety::Unsafe;
320293
}

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

+1-1
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)