Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b15e23c

Browse files
committedApr 6, 2025
Add cfg_os_version_min feature
Based on in-progress RFC: rust-lang/rfcs#3750. Only implemented for Apple platforms for now, but written in a way that should be easily expandable to include other platforms.
1 parent f5c5102 commit b15e23c

File tree

16 files changed

+569
-2
lines changed

16 files changed

+569
-2
lines changed
 

‎Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3348,6 +3348,7 @@ dependencies = [
33483348
"rustc_macros",
33493349
"rustc_session",
33503350
"rustc_span",
3351+
"rustc_target",
33513352
"thin-vec",
33523353
]
33533354

‎compiler/rustc_attr_parsing/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ rustc_lexer = { path = "../rustc_lexer" }
1717
rustc_macros = { path = "../rustc_macros" }
1818
rustc_session = { path = "../rustc_session" }
1919
rustc_span = { path = "../rustc_span" }
20+
rustc_target = { path = "../rustc_target" }
2021
thin-vec = "0.2.12"
2122
# tidy-alphabetical-end

‎compiler/rustc_attr_parsing/messages.ftl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
attr_parsing_apple_version_invalid =
2+
failed parsing version: {$error}
3+
4+
attr_parsing_apple_version_unnecessarily_low =
5+
version is set unnecessarily low, the minimum supported by Rust on this platform is {$os_min}
6+
17
attr_parsing_cfg_predicate_identifier =
28
`cfg` predicate key must be an identifier
39
@@ -11,6 +17,12 @@ attr_parsing_empty_confusables =
1117
attr_parsing_expected_one_cfg_pattern =
1218
expected 1 cfg-pattern
1319
20+
attr_parsing_expected_platform_and_version_literals =
21+
expected two literals, a platform and a version
22+
23+
attr_parsing_expected_platform_literal =
24+
expected a platform literal
25+
1426
attr_parsing_expected_single_version_literal =
1527
expected single version literal
1628
@@ -108,6 +120,9 @@ attr_parsing_unknown_meta_item =
108120
unknown meta item '{$item}'
109121
.label = expected one of {$expected}
110122
123+
attr_parsing_unknown_platform_literal =
124+
unknown platform literal, expected values are: {$possibilities}
125+
111126
attr_parsing_unknown_version_literal =
112127
unknown version literal format, assuming it refers to a future version
113128

‎compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NodeId};
22
use rustc_ast_pretty::pprust;
33
use rustc_attr_data_structures::RustcVersion;
4+
use rustc_errors::Applicability;
45
use rustc_feature::{Features, GatedCfg, find_gated_cfg};
56
use rustc_session::Session;
67
use rustc_session::config::ExpectedValues;
@@ -9,6 +10,7 @@ use rustc_session::lint::builtin::UNEXPECTED_CFGS;
910
use rustc_session::parse::feature_err;
1011
use rustc_span::symbol::kw;
1112
use rustc_span::{Span, Symbol, sym};
13+
use rustc_target::spec::apple;
1214

1315
use crate::session_diagnostics::{self, UnsupportedLiteralReason};
1416
use crate::{fluent_generated, parse_version};
@@ -149,6 +151,129 @@ pub fn eval_condition(
149151
RustcVersion::CURRENT >= min_version
150152
}
151153
}
154+
MetaItemKind::List(mis) if cfg.name_or_empty() == sym::os_version_min => {
155+
try_gate_cfg(sym::os_version_min, cfg.span, sess, features);
156+
157+
let (platform, version) = match &mis[..] {
158+
[platform, version] => (platform, version),
159+
[..] => {
160+
dcx.emit_err(session_diagnostics::ExpectedPlatformAndVersionLiterals {
161+
span: cfg.span,
162+
});
163+
return false;
164+
}
165+
};
166+
167+
let (platform_sym, platform_span) = match platform {
168+
MetaItemInner::Lit(MetaItemLit {
169+
kind: LitKind::Str(platform_sym, ..),
170+
span: platform_span,
171+
..
172+
}) => (platform_sym, platform_span),
173+
MetaItemInner::Lit(MetaItemLit { span, .. })
174+
| MetaItemInner::MetaItem(MetaItem { span, .. }) => {
175+
dcx.emit_err(session_diagnostics::ExpectedPlatformLiteral { span: *span });
176+
return false;
177+
}
178+
};
179+
180+
let (version_sym, version_span) = match version {
181+
MetaItemInner::Lit(MetaItemLit {
182+
kind: LitKind::Str(version_sym, ..),
183+
span: version_span,
184+
..
185+
}) => (version_sym, version_span),
186+
MetaItemInner::Lit(MetaItemLit { span, .. })
187+
| MetaItemInner::MetaItem(MetaItem { span, .. }) => {
188+
dcx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: *span });
189+
return false;
190+
}
191+
};
192+
193+
// Always parse version, regardless of current target platform.
194+
let version = match *platform_sym {
195+
// Apple platforms follow the same versioning schema.
196+
sym::macos | sym::ios | sym::tvos | sym::watchos | sym::visionos => {
197+
match version_sym.as_str().parse() {
198+
Ok(version) => {
199+
let os_min = apple::OSVersion::os_minimum_deployment_target(
200+
&platform_sym.as_str(),
201+
);
202+
203+
// It's unnecessary to specify `cfg_target_os(...)` for a platform
204+
// version that is lower than the minimum targetted by `rustc` (instead,
205+
// make the item always available).
206+
//
207+
// This is correct _now_, but once we bump versions next time, we should
208+
// maybe make this a lint so that users can opt-in to supporting older
209+
// `rustc` versions? Or perhaps only fire the warning when Cargo's
210+
// `rust-version` field is above the version where the bump happened? Or
211+
// perhaps keep the version we check against low for a sufficiently long
212+
// time?
213+
if version <= os_min {
214+
sess.dcx()
215+
.create_warn(
216+
session_diagnostics::AppleVersionUnnecessarilyLow {
217+
span: *version_span,
218+
os_min: os_min.fmt_pretty().to_string(),
219+
},
220+
)
221+
.with_span_suggestion(
222+
cfg.span,
223+
"use `target_os` instead",
224+
format!("target_os = \"{platform_sym}\""),
225+
Applicability::MachineApplicable,
226+
)
227+
.emit();
228+
}
229+
230+
PlatformVersion::Apple { os: *platform_sym, version }
231+
}
232+
Err(error) => {
233+
sess.dcx().emit_err(session_diagnostics::AppleVersionInvalid {
234+
span: *version_span,
235+
error,
236+
});
237+
return false;
238+
}
239+
}
240+
}
241+
// FIXME(madsmtm): Handle further platforms as specified in the RFC.
242+
sym::windows | sym::libc => {
243+
#[allow(rustc::untranslatable_diagnostic)] // Temporary
244+
dcx.span_err(*platform_span, "unimplemented platform");
245+
return false;
246+
}
247+
_ => {
248+
// Unknown platform. This is intentionally a warning (and not an error) to be
249+
// future-compatible with later additions.
250+
let known_platforms = [
251+
sym::macos,
252+
sym::ios,
253+
sym::tvos,
254+
sym::watchos,
255+
sym::visionos,
256+
// sym::windows,
257+
// sym::libc,
258+
];
259+
dcx.emit_warn(session_diagnostics::UnknownPlatformLiteral {
260+
span: *platform_span,
261+
possibilities: known_platforms.into_iter().collect(),
262+
});
263+
return false;
264+
}
265+
};
266+
267+
// Figure out actual cfg-status based on current platform.
268+
match version {
269+
PlatformVersion::Apple { os, version } if os.as_str() == sess.target.os => {
270+
let deployment_target = sess.apple_deployment_target();
271+
version <= deployment_target
272+
}
273+
// If a `cfg`-value does not apply to a specific platform, assume
274+
_ => false,
275+
}
276+
}
152277
MetaItemKind::List(mis) => {
153278
for mi in mis.iter() {
154279
if mi.meta_item_or_bool().is_none() {
@@ -245,3 +370,8 @@ pub fn eval_condition(
245370
}
246371
}
247372
}
373+
374+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
375+
enum PlatformVersion {
376+
Apple { os: Symbol, version: apple::OSVersion },
377+
}

‎compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
use std::num::IntErrorKind;
1+
use std::num::{IntErrorKind, ParseIntError};
22

33
use rustc_ast as ast;
44
use rustc_errors::codes::*;
5-
use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level};
5+
use rustc_errors::{
6+
Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
7+
};
68
use rustc_macros::{Diagnostic, Subdiagnostic};
79
use rustc_span::{Span, Symbol};
810

@@ -16,6 +18,22 @@ pub(crate) enum UnsupportedLiteralReason {
1618
DeprecatedKvPair,
1719
}
1820

21+
#[derive(Diagnostic)]
22+
#[diag(attr_parsing_apple_version_invalid)]
23+
pub(crate) struct AppleVersionInvalid {
24+
#[primary_span]
25+
pub span: Span,
26+
pub error: ParseIntError,
27+
}
28+
29+
#[derive(Diagnostic)]
30+
#[diag(attr_parsing_apple_version_unnecessarily_low)]
31+
pub(crate) struct AppleVersionUnnecessarilyLow {
32+
#[primary_span]
33+
pub span: Span,
34+
pub os_min: String,
35+
}
36+
1937
#[derive(Diagnostic)]
2038
#[diag(attr_parsing_expected_one_cfg_pattern, code = E0536)]
2139
pub(crate) struct ExpectedOneCfgPattern {
@@ -386,6 +404,20 @@ pub(crate) struct DeprecatedItemSuggestion {
386404
pub details: (),
387405
}
388406

407+
#[derive(Diagnostic)]
408+
#[diag(attr_parsing_expected_platform_and_version_literals)]
409+
pub(crate) struct ExpectedPlatformAndVersionLiterals {
410+
#[primary_span]
411+
pub span: Span,
412+
}
413+
414+
#[derive(Diagnostic)]
415+
#[diag(attr_parsing_expected_platform_literal)]
416+
pub(crate) struct ExpectedPlatformLiteral {
417+
#[primary_span]
418+
pub span: Span,
419+
}
420+
389421
#[derive(Diagnostic)]
390422
#[diag(attr_parsing_expected_single_version_literal)]
391423
pub(crate) struct ExpectedSingleVersionLiteral {
@@ -432,6 +464,14 @@ pub(crate) struct SoftNoArgs {
432464
pub span: Span,
433465
}
434466

467+
#[derive(Diagnostic)]
468+
#[diag(attr_parsing_unknown_platform_literal)]
469+
pub(crate) struct UnknownPlatformLiteral {
470+
#[primary_span]
471+
pub span: Span,
472+
pub possibilities: DiagSymbolList,
473+
}
474+
435475
#[derive(Diagnostic)]
436476
#[diag(attr_parsing_unknown_version_literal)]
437477
pub(crate) struct UnknownVersionLiteral {

‎compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const GATED_CFGS: &[GatedCfg] = &[
3333
),
3434
(sym::sanitize, sym::cfg_sanitize, Features::cfg_sanitize),
3535
(sym::version, sym::cfg_version, Features::cfg_version),
36+
(sym::os_version_min, sym::cfg_os_version_min, Features::cfg_os_version_min),
3637
(sym::relocation_model, sym::cfg_relocation_model, Features::cfg_relocation_model),
3738
(sym::sanitizer_cfi_generalize_pointers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi),
3839
(sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi),

‎compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,8 @@ declare_features! (
395395
(unstable, cfg_boolean_literals, "1.83.0", Some(131204)),
396396
/// Allows the use of `#[cfg(contract_checks)` to check if contract checks are enabled.
397397
(unstable, cfg_contract_checks, "1.86.0", Some(128044)),
398+
/// Allow conditional compilation depending on target platform version.
399+
(unstable, cfg_os_version_min, "CURRENT_RUSTC_VERSION", Some(136866)),
398400
/// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
399401
(unstable, cfg_overflow_checks, "1.71.0", Some(111466)),
400402
/// Provides the relocation model information as cfg entry

‎compiler/rustc_span/src/symbol.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,7 @@ symbols! {
611611
cfg_eval,
612612
cfg_fmt_debug,
613613
cfg_hide,
614+
cfg_os_version_min,
614615
cfg_overflow_checks,
615616
cfg_panic,
616617
cfg_relocation_model,
@@ -1194,6 +1195,7 @@ symbols! {
11941195
intrinsics_unaligned_volatile_store,
11951196
io_stderr,
11961197
io_stdout,
1198+
ios,
11971199
irrefutable_let_patterns,
11981200
is,
11991201
is_val_statically_known,
@@ -1279,6 +1281,7 @@ symbols! {
12791281
loop_break_value,
12801282
lt,
12811283
m68k_target_feature,
1284+
macos,
12821285
macro_at_most_once_rep,
12831286
macro_attributes_in_derive_output,
12841287
macro_escape,
@@ -1502,6 +1505,7 @@ symbols! {
15021505
ord_cmp_method,
15031506
os_str_to_os_string,
15041507
os_string_as_os_str,
1508+
os_version_min,
15051509
other,
15061510
out,
15071511
overflow_checks,
@@ -2124,6 +2128,7 @@ symbols! {
21242128
tuple,
21252129
tuple_indexing,
21262130
tuple_trait,
2131+
tvos,
21272132
two_phase,
21282133
ty,
21292134
type_alias_enum_variants,
@@ -2270,6 +2275,7 @@ symbols! {
22702275
vfp2,
22712276
vis,
22722277
visible_private_types,
2278+
visionos,
22732279
volatile,
22742280
volatile_copy_memory,
22752281
volatile_copy_nonoverlapping_memory,
@@ -2286,6 +2292,7 @@ symbols! {
22862292
wasm_abi,
22872293
wasm_import_module,
22882294
wasm_target_feature,
2295+
watchos,
22892296
where_clause_attrs,
22902297
while_let,
22912298
width,
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# `cfg_os_version_min`
2+
3+
The tracking issue for this feature is: [#136866]
4+
5+
[#136866]: https://github.com/rust-lang/rust/issues/136866
6+
7+
------------------------
8+
9+
The `cfg_os_version_min` feature makes it possible to conditionally compile
10+
code depending on the target platform version(s).
11+
12+
As `cfg(os_version_min("platform", "version"))` is platform-specific, it
13+
internally contains relevant `cfg(target_os = "platform")`. So specifying
14+
`cfg(os_version_min("macos", "1.0"))` is equivalent to
15+
`cfg(target_os = "macos")`.
16+
17+
Note that this only concerns the compile-time configured version; at runtime,
18+
the version may be higher.
19+
20+
21+
## Changing the version
22+
23+
Each Rust target has a default set of targetted platform versions. Examples
24+
include the operating system version (`windows`, `macos`, Linux `kernel`) and
25+
system library version (`libc`).
26+
27+
The mechanism for changing a targetted platform version is currently
28+
target-specific (a more general mechanism may be created in the future):
29+
- On macOS, you can select the minimum OS version using the
30+
`MACOSX_DEPLOYMENT_TARGET` environment variable. Similarly for iOS, tvOS,
31+
watchOS and visionOS, see the relevant [platform docs] for details.
32+
- Others: Unknown.
33+
34+
[platform docs]: https://doc.rust-lang.org/nightly/rustc/platform-support.html
35+
36+
37+
## Examples
38+
39+
Statically link the `preadv` symbol if available, or fall back to weak linking if not.
40+
41+
```rust
42+
#![feature(cfg_os_version_min)]
43+
use libc;
44+
45+
// Always available under these conditions.
46+
#[cfg(any(
47+
os_version_min("macos", "11.0"),
48+
os_version_min("ios", "14.0"),
49+
os_version_min("tvos", "14.0"),
50+
os_version_min("watchos", "7.0"),
51+
os_version_min("visionos", "1.0")
52+
))]
53+
let preadv = {
54+
extern "C" {
55+
fn preadv(libc::c_int, *const libc::iovec, libc::c_int, libc::off64_t) -> libc::ssize_t;
56+
}
57+
Some(preadv)
58+
};
59+
60+
// Otherwise `preadv` needs to be weakly linked.
61+
// We do that using a `weak!` macro, defined elsewhere.
62+
#[cfg(not(any(
63+
os_version_min("macos", "11.0"),
64+
os_version_min("ios", "14.0"),
65+
os_version_min("tvos", "14.0"),
66+
os_version_min("watchos", "7.0"),
67+
os_version_min("visionos", "1.0")
68+
)))]
69+
weak!(fn preadv(libc::c_int, *const libc::iovec, libc::c_int, libc::off64_t) -> libc::ssize_t);
70+
71+
if let Some(preadv) = preadv {
72+
preadv(...) // Use preadv, it's available
73+
} else {
74+
// ... fallback impl
75+
}
76+
```
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//! Test the semantics of `cfg(os_version_min)` while setting deployment target.
2+
3+
//@ only-macos
4+
//@ revisions: no_env env_low env_mid env_high
5+
//@[no_env] unset-rustc-env:MACOSX_DEPLOYMENT_TARGET
6+
//@[env_low] rustc-env:MACOSX_DEPLOYMENT_TARGET=10.14
7+
//@[env_mid] rustc-env:MACOSX_DEPLOYMENT_TARGET=14.0
8+
//@[env_high] rustc-env:MACOSX_DEPLOYMENT_TARGET=17.0
9+
//@ run-pass
10+
11+
#![feature(cfg_os_version_min)]
12+
13+
fn main() {
14+
assert_eq!(cfg!(os_version_min("macos", "14.0")), cfg!(any(env_mid, env_high)));
15+
16+
// Aarch64 minimum is macOS 11.0, even if a lower env is requested.
17+
assert_eq!(
18+
cfg!(os_version_min("macos", "11.0")),
19+
cfg!(any(env_mid, env_high, target_arch = "aarch64"))
20+
);
21+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//! Test low and high version with `cfg(os_version_min)`.
2+
//@ run-pass
3+
#![feature(cfg_os_version_min)]
4+
5+
fn main() {
6+
// Always available on macOS
7+
assert_eq!(cfg!(os_version_min("macos", "10.0")), cfg!(target_os = "macos"));
8+
//~^ WARNING: version is set unnecessarily low
9+
10+
// Never available
11+
assert!(cfg!(not(os_version_min("macos", "9999.99.99"))));
12+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
warning: version is set unnecessarily low, the minimum supported by Rust on this platform is 10.12
2+
--> $DIR/cfg-os-version-min-edges.rs:7:45
3+
|
4+
LL | assert_eq!(cfg!(os_version_min("macos", "10.0")), cfg!(target_os = "macos"));
5+
| ------------------------^^^^^^- help: use `target_os` instead: `target_os = "macos"`
6+
7+
warning: 1 warning emitted
8+
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//! Test invalid syntax for `cfg(os_version_min)`.
2+
#![feature(cfg_os_version_min)]
3+
4+
#[cfg(os_version_min = "macos")] //~ WARNING: unexpected `cfg` condition name: `os_version_min`
5+
fn foo() {}
6+
7+
#[cfg(os_version_min("macos"))] //~ ERROR: expected two literals, a platform and a version
8+
fn foo() {}
9+
#[cfg(os_version_min("1", "2", "3"))] //~ ERROR: expected two literals, a platform and a version
10+
fn foo() {}
11+
12+
#[cfg(os_version_min(macos, "1.0.0"))] //~ ERROR: expected a platform literal
13+
fn foo() {}
14+
#[cfg(os_version_min(42, "1.0.0"))] //~ ERROR: expected a platform literal
15+
fn foo() {}
16+
17+
#[cfg(os_version_min("macos", 42))] //~ ERROR: expected a version literal
18+
fn foo() {}
19+
#[cfg(os_version_min("macos", 10.10))] //~ ERROR: expected a version literal
20+
fn foo() {}
21+
#[cfg(os_version_min("macos", false))] //~ ERROR: expected a version literal
22+
fn foo() {}
23+
24+
#[cfg(os_version_min("11.0", "macos"))] //~ WARNING: unknown platform literal
25+
fn foo() {}
26+
#[cfg(os_version_min("linux", "5.3"))] //~ WARNING: unknown platform literal
27+
fn foo() {}
28+
29+
#[cfg(os_version_min("windows", "10.0.10240"))] //~ ERROR: unimplemented platform
30+
fn foo() {}
31+
32+
#[cfg(os_version_min("macos", "99999"))] //~ ERROR: failed parsing version
33+
fn foo() {}
34+
#[cfg(os_version_min("macos", "-1"))] //~ ERROR: failed parsing version
35+
fn foo() {}
36+
#[cfg(os_version_min("macos", "65536"))] //~ ERROR: failed parsing version
37+
fn foo() {}
38+
#[cfg(os_version_min("macos", "1.2.3.4"))] //~ ERROR: failed parsing version
39+
fn foo() {}
40+
41+
#[cfg(os_version_min("macos", "10.0"))] //~ WARNING: version is set unnecessarily low
42+
fn bar1() {}
43+
#[cfg(os_version_min("macos", "0"))] //~ WARNING: version is set unnecessarily low
44+
fn bar2() {}
45+
46+
#[cfg(os_version_min("macos", "10.12"))] //~ WARNING: version is set unnecessarily low
47+
fn bar3() {}
48+
#[cfg(os_version_min("ios", "10.0"))] //~ WARNING: version is set unnecessarily low
49+
fn bar4() {}
50+
#[cfg(os_version_min("tvos", "10.0"))] //~ WARNING: version is set unnecessarily low
51+
fn bar5() {}
52+
#[cfg(os_version_min("watchos", "5.0"))] //~ WARNING: version is set unnecessarily low
53+
fn bar6() {}
54+
#[cfg(os_version_min("visionos", "1.0"))] //~ WARNING: version is set unnecessarily low
55+
fn bar7() {}
56+
57+
fn main() {}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
error: expected two literals, a platform and a version
2+
--> $DIR/cfg-os-version-min-invalid.rs:7:7
3+
|
4+
LL | #[cfg(os_version_min("macos"))]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: expected two literals, a platform and a version
8+
--> $DIR/cfg-os-version-min-invalid.rs:9:7
9+
|
10+
LL | #[cfg(os_version_min("1", "2", "3"))]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: expected a platform literal
14+
--> $DIR/cfg-os-version-min-invalid.rs:12:22
15+
|
16+
LL | #[cfg(os_version_min(macos, "1.0.0"))]
17+
| ^^^^^
18+
19+
error: expected a platform literal
20+
--> $DIR/cfg-os-version-min-invalid.rs:14:22
21+
|
22+
LL | #[cfg(os_version_min(42, "1.0.0"))]
23+
| ^^
24+
25+
error: expected a version literal
26+
--> $DIR/cfg-os-version-min-invalid.rs:17:31
27+
|
28+
LL | #[cfg(os_version_min("macos", 42))]
29+
| ^^
30+
31+
error: expected a version literal
32+
--> $DIR/cfg-os-version-min-invalid.rs:19:31
33+
|
34+
LL | #[cfg(os_version_min("macos", 10.10))]
35+
| ^^^^^
36+
37+
error: expected a version literal
38+
--> $DIR/cfg-os-version-min-invalid.rs:21:31
39+
|
40+
LL | #[cfg(os_version_min("macos", false))]
41+
| ^^^^^
42+
43+
warning: unknown platform literal, expected values are: `macos`, `ios`, `tvos`, `watchos`, and `visionos`
44+
--> $DIR/cfg-os-version-min-invalid.rs:24:22
45+
|
46+
LL | #[cfg(os_version_min("11.0", "macos"))]
47+
| ^^^^^^
48+
49+
warning: unknown platform literal, expected values are: `macos`, `ios`, `tvos`, `watchos`, and `visionos`
50+
--> $DIR/cfg-os-version-min-invalid.rs:26:22
51+
|
52+
LL | #[cfg(os_version_min("linux", "5.3"))]
53+
| ^^^^^^^
54+
55+
error: unimplemented platform
56+
--> $DIR/cfg-os-version-min-invalid.rs:29:22
57+
|
58+
LL | #[cfg(os_version_min("windows", "10.0.10240"))]
59+
| ^^^^^^^^^
60+
61+
error: failed parsing version: number too large to fit in target type
62+
--> $DIR/cfg-os-version-min-invalid.rs:32:31
63+
|
64+
LL | #[cfg(os_version_min("macos", "99999"))]
65+
| ^^^^^^^
66+
67+
error: failed parsing version: invalid digit found in string
68+
--> $DIR/cfg-os-version-min-invalid.rs:34:31
69+
|
70+
LL | #[cfg(os_version_min("macos", "-1"))]
71+
| ^^^^
72+
73+
error: failed parsing version: number too large to fit in target type
74+
--> $DIR/cfg-os-version-min-invalid.rs:36:31
75+
|
76+
LL | #[cfg(os_version_min("macos", "65536"))]
77+
| ^^^^^^^
78+
79+
error: failed parsing version: invalid digit found in string
80+
--> $DIR/cfg-os-version-min-invalid.rs:38:31
81+
|
82+
LL | #[cfg(os_version_min("macos", "1.2.3.4"))]
83+
| ^^^^^^^^^
84+
85+
warning: version is set unnecessarily low, the minimum supported by Rust on this platform is 10.12
86+
--> $DIR/cfg-os-version-min-invalid.rs:41:31
87+
|
88+
LL | #[cfg(os_version_min("macos", "10.0"))]
89+
| ------------------------^^^^^^- help: use `target_os` instead: `target_os = "macos"`
90+
91+
warning: version is set unnecessarily low, the minimum supported by Rust on this platform is 10.12
92+
--> $DIR/cfg-os-version-min-invalid.rs:43:31
93+
|
94+
LL | #[cfg(os_version_min("macos", "0"))]
95+
| ------------------------^^^- help: use `target_os` instead: `target_os = "macos"`
96+
97+
warning: version is set unnecessarily low, the minimum supported by Rust on this platform is 10.12
98+
--> $DIR/cfg-os-version-min-invalid.rs:46:31
99+
|
100+
LL | #[cfg(os_version_min("macos", "10.12"))]
101+
| ------------------------^^^^^^^- help: use `target_os` instead: `target_os = "macos"`
102+
103+
warning: version is set unnecessarily low, the minimum supported by Rust on this platform is 10.0
104+
--> $DIR/cfg-os-version-min-invalid.rs:48:29
105+
|
106+
LL | #[cfg(os_version_min("ios", "10.0"))]
107+
| ----------------------^^^^^^- help: use `target_os` instead: `target_os = "ios"`
108+
109+
warning: version is set unnecessarily low, the minimum supported by Rust on this platform is 10.0
110+
--> $DIR/cfg-os-version-min-invalid.rs:50:30
111+
|
112+
LL | #[cfg(os_version_min("tvos", "10.0"))]
113+
| -----------------------^^^^^^- help: use `target_os` instead: `target_os = "tvos"`
114+
115+
warning: version is set unnecessarily low, the minimum supported by Rust on this platform is 5.0
116+
--> $DIR/cfg-os-version-min-invalid.rs:52:33
117+
|
118+
LL | #[cfg(os_version_min("watchos", "5.0"))]
119+
| --------------------------^^^^^- help: use `target_os` instead: `target_os = "watchos"`
120+
121+
warning: version is set unnecessarily low, the minimum supported by Rust on this platform is 1.0
122+
--> $DIR/cfg-os-version-min-invalid.rs:54:34
123+
|
124+
LL | #[cfg(os_version_min("visionos", "1.0"))]
125+
| ---------------------------^^^^^- help: use `target_os` instead: `target_os = "visionos"`
126+
127+
warning: unexpected `cfg` condition name: `os_version_min`
128+
--> $DIR/cfg-os-version-min-invalid.rs:4:7
129+
|
130+
LL | #[cfg(os_version_min = "macos")]
131+
| ^^^^^^^^^^^^^^^^^^^^^^^^
132+
|
133+
= help: expected names are: `FALSE` and `test` and 31 more
134+
= help: to expect this configuration use `--check-cfg=cfg(os_version_min, values("macos"))`
135+
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
136+
= note: `#[warn(unexpected_cfgs)]` on by default
137+
138+
error: aborting due to 12 previous errors; 10 warnings emitted
139+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![feature(cfg_boolean_literals)]
2+
3+
#[cfg(os_version_min("macos", "11.0"))]
4+
//~^ ERROR `cfg(os_version_min)` is experimental and subject to change
5+
fn foo1() {}
6+
7+
#[cfg(os_version_min("macos", 1.20))] //~ ERROR: expected a version literal
8+
//~^ ERROR `cfg(os_version_min)` is experimental and subject to change
9+
fn foo2() {}
10+
11+
// No warning if cfg'd away.
12+
#[cfg_attr(false, cfg(os_version_min("macos", false)))]
13+
fn foo3() {}
14+
15+
fn main() {
16+
if cfg!(os_version_min("macos", "11.0")) {}
17+
//~^ ERROR `cfg(os_version_min)` is experimental and subject to change
18+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error[E0658]: `cfg(os_version_min)` is experimental and subject to change
2+
--> $DIR/feature-gate-cfg-os-version-min.rs:3:7
3+
|
4+
LL | #[cfg(os_version_min("macos", "11.0"))]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #136866 <https://github.com/rust-lang/rust/issues/136866> for more information
8+
= help: add `#![feature(cfg_os_version_min)]` to the crate attributes to enable
9+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
10+
11+
error[E0658]: `cfg(os_version_min)` is experimental and subject to change
12+
--> $DIR/feature-gate-cfg-os-version-min.rs:7:7
13+
|
14+
LL | #[cfg(os_version_min("macos", 1.20))]
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
|
17+
= note: see issue #136866 <https://github.com/rust-lang/rust/issues/136866> for more information
18+
= help: add `#![feature(cfg_os_version_min)]` to the crate attributes to enable
19+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
20+
21+
error: expected a version literal
22+
--> $DIR/feature-gate-cfg-os-version-min.rs:7:31
23+
|
24+
LL | #[cfg(os_version_min("macos", 1.20))]
25+
| ^^^^
26+
27+
error[E0658]: `cfg(os_version_min)` is experimental and subject to change
28+
--> $DIR/feature-gate-cfg-os-version-min.rs:16:13
29+
|
30+
LL | if cfg!(os_version_min("macos", "11.0")) {}
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32+
|
33+
= note: see issue #136866 <https://github.com/rust-lang/rust/issues/136866> for more information
34+
= help: add `#![feature(cfg_os_version_min)]` to the crate attributes to enable
35+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
36+
37+
error: aborting due to 4 previous errors
38+
39+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)
Please sign in to comment.