1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//! Data about Rust target features.
//!
//! Different versions of Rust support different [target
//! features](https://rust-lang.github.io/rfcs/2045-target-feature.html). Different Rust targets
//! automatically enable different target features. Different versions of Rust automatically enable
//! different target features _for the same target_. Enabling the same target feature implies
// enabling different target features in different versions of Rust.
//!
//! This crate provides target feature data for all targets covering Rust versions:
//!
//! * `"1.85.0"` (1.85.1 is identical)
//! * `"1.86.0"`
//! * `"1.87.0"` (from 1.87.0-beta.5)
//!
//! Rust 1.88.0 provides target feature data for the selected target [via `rustdoc`'s JSON output
//! format](https://docs.rs/rustdoc-types/latest/rustdoc_types/struct.TargetFeature.html), making
//! this crate obsolete going forward.
//!
//! # Example
//!
//! ```
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! use rust_target_feature_data::find;
//!
//! let features: Vec<_> = find("1.85.0", "i686-linux-android")?.collect();
//! let fxsr = features.iter().find(|f| f.name == "fxsr").unwrap();
//! assert_eq!(fxsr.globally_enabled, false);
//!
//! let features: Vec<_> = find("1.86.0", "i686-linux-android")?.collect();
//! let fxsr = features.iter().find(|f| f.name == "fxsr").unwrap();
//! assert_eq!(fxsr.globally_enabled, true);
//! # Ok(()) }
//! ```
use BTreeSet;
/// Information about a target feature.
///
/// Rust target features are used to influence code generation, especially around selecting
/// instructions which are not universally supported by the target architecture.
///
/// Target features are commonly enabled by the [`#[target_feature]` attribute][1] to influence code
/// generation for a particular function, and less commonly enabled by compiler options like
/// `-Ctarget-feature` or `-Ctarget-cpu`. Targets themselves automatically enable certain target
/// features by default, for example because the target's ABI specification requires saving specific
/// registers which only exist in an architectural extension.
///
/// Target features can imply other target features: for example, x86-64 `avx2` implies `avx`, and
/// aarch64 `sve2` implies `sve`, since both of these architectural extensions depend on their
/// predecessors.
///
/// Target features can be probed at compile time by [`#[cfg(target_feature)]`][2] or `cfg!(…)`
/// conditional compilation to determine whether a target feature is enabled in a particular
/// context.
///
/// [1]: https://doc.rust-lang.org/stable/reference/attributes/codegen.html#the-target_feature-attribute
/// [2]: https://doc.rust-lang.org/reference/conditional-compilation.html#target_feature
/// An error finding target feature data.
/// Find the target features applicable to a Rust version and target.
///
/// ```
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// use rust_target_feature_data::NotFoundError;
///
/// // Different versions return different features
/// for (version, count) in [
/// // ("1.83.0", 90),
/// // ("1.84.0", 91),
/// ("1.85.0", 92),
/// ("1.86.0", 92),
/// ("1.87.0", 92),
/// ] {
/// assert_eq!(
/// rust_target_feature_data::find(version, "aarch64-apple-darwin")?.count(),
/// count,
/// );
/// }
///
/// // 1.84.0 data is not included
/// assert_eq!(
/// rust_target_feature_data::find("1.84.0", "x86_64-unknown-linux-gnu").err().unwrap(),
/// NotFoundError::CompilerNotFound("1.84.0".into())
/// );
///
/// // i686-unknown-redox became i586-unknown-redox
/// assert!(
/// rust_target_feature_data::find("1.85.0", "i686-unknown-redox").is_ok()
/// );
/// assert_eq!(
/// rust_target_feature_data::find("1.86.0", "i686-unknown-redox").err().unwrap(),
/// NotFoundError::TargetNotFound("i686-unknown-redox".into())
/// );
/// # Ok(()) }
/// ```