Skip to content

Commit 5ff104c

Browse files
Rollup merge of #153196 - MikkelPaulson:const-path-separators, r=joboet
Update path separators to be available in const context Tracking issue: #153106 This makes platform-dependent secondary path separators available in const context (ie. at compile time). The platform definitions have also been consolidated behind a common macro to prevent transcription errors, whereas previously they were defined 3-4 times per platform. ### Questions I've manually verified that this compiles against each platform. It seems like no unit tests should be required for this change; is that correct?
2 parents 552b316 + 098b1b9 commit 5ff104c

8 files changed

Lines changed: 62 additions & 62 deletions

File tree

library/std/src/path.rs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ use crate::ops::{self, Deref};
9393
use crate::rc::Rc;
9494
use crate::str::FromStr;
9595
use crate::sync::Arc;
96-
use crate::sys::path::{HAS_PREFIXES, MAIN_SEP_STR, is_sep_byte, is_verbatim_sep, parse_prefix};
96+
use crate::sys::path::{HAS_PREFIXES, is_sep_byte, is_verbatim_sep, parse_prefix};
9797
use crate::{cmp, fmt, fs, io, sys};
9898

9999
////////////////////////////////////////////////////////////////////////////////
@@ -266,22 +266,33 @@ impl<'a> Prefix<'a> {
266266
/// ```
267267
#[must_use]
268268
#[stable(feature = "rust1", since = "1.0.0")]
269-
pub fn is_separator(c: char) -> bool {
269+
#[rustc_const_unstable(feature = "const_path_separators", issue = "153106")]
270+
pub const fn is_separator(c: char) -> bool {
270271
c.is_ascii() && is_sep_byte(c as u8)
271272
}
272273

273-
/// The primary separator of path components for the current platform.
274-
///
275-
/// For example, `/` on Unix and `\` on Windows.
274+
/// All path separators recognized on the current platform, represented as [`char`]s; for example,
275+
/// this is `&['/'][..]` on Unix and `&['\\', '/'][..]` on Windows. The [primary
276+
/// separator](MAIN_SEPARATOR) is always element 0 of the slice.
277+
#[unstable(feature = "const_path_separators", issue = "153106")]
278+
pub const SEPARATORS: &[char] = crate::sys::path::SEPARATORS;
279+
280+
/// All path separators recognized on the current platform, represented as [`&str`]s; for example,
281+
/// this is `&["/"][..]` on Unix and `&["\\", "/"][..]` on Windows. The [primary
282+
/// separator](MAIN_SEPARATOR_STR) is always element 0 of the slice.
283+
#[unstable(feature = "const_path_separators", issue = "153106")]
284+
pub const SEPARATORS_STR: &[&str] = crate::sys::path::SEPARATORS_STR;
285+
286+
/// The primary separator of path components for the current platform, represented as a [`char`];
287+
/// for example, this is `'/'` on Unix and `'\\'` on Windows.
276288
#[stable(feature = "rust1", since = "1.0.0")]
277289
#[cfg_attr(not(test), rustc_diagnostic_item = "path_main_separator")]
278-
pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP;
290+
pub const MAIN_SEPARATOR: char = SEPARATORS[0];
279291

280-
/// The primary separator of path components for the current platform.
281-
///
282-
/// For example, `/` on Unix and `\` on Windows.
292+
/// The primary separator of path components for the current platform, represented as a [`&str`];
293+
/// for example, this is `"/"` on Unix and `"\\"` on Windows.
283294
#[stable(feature = "main_separator_str", since = "1.68.0")]
284-
pub const MAIN_SEPARATOR_STR: &str = crate::sys::path::MAIN_SEP_STR;
295+
pub const MAIN_SEPARATOR_STR: &str = SEPARATORS_STR[0];
285296

286297
////////////////////////////////////////////////////////////////////////////////
287298
// Misc helpers
@@ -562,7 +573,7 @@ impl<'a> Component<'a> {
562573
pub fn as_os_str(self) -> &'a OsStr {
563574
match self {
564575
Component::Prefix(p) => p.as_os_str(),
565-
Component::RootDir => OsStr::new(MAIN_SEP_STR),
576+
Component::RootDir => OsStr::new(MAIN_SEPARATOR_STR),
566577
Component::CurDir => OsStr::new("."),
567578
Component::ParentDir => OsStr::new(".."),
568579
Component::Normal(path) => path,
@@ -1379,7 +1390,7 @@ impl PathBuf {
13791390

13801391
for c in buf {
13811392
if need_sep && c != Component::RootDir {
1382-
res.push(MAIN_SEP_STR);
1393+
res.push(MAIN_SEPARATOR_STR);
13831394
}
13841395
res.push(c.as_os_str());
13851396

@@ -1402,7 +1413,7 @@ impl PathBuf {
14021413

14031414
// `path` is a pure relative path
14041415
} else if need_sep {
1405-
self.inner.push(MAIN_SEP_STR);
1416+
self.inner.push(MAIN_SEPARATOR_STR);
14061417
}
14071418

14081419
self.inner.push(path);

library/std/src/sys/path/cygwin.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,20 @@ use crate::sys::cvt;
55
use crate::sys::helpers::run_path_with_cstr;
66
use crate::{io, ptr};
77

8-
#[inline]
9-
pub fn is_sep_byte(b: u8) -> bool {
10-
b == b'/' || b == b'\\'
11-
}
8+
path_separator_bytes!(b'/', b'\\');
129

1310
/// Cygwin always prefers `/` over `\`, and it always converts all `/` to `\`
1411
/// internally when calling Win32 APIs. Therefore, the server component of path
1512
/// `\\?\UNC\localhost/share` is `localhost/share` on Win32, but `localhost`
1613
/// on Cygwin.
1714
#[inline]
18-
pub fn is_verbatim_sep(b: u8) -> bool {
19-
b == b'/' || b == b'\\'
15+
pub const fn is_verbatim_sep(b: u8) -> bool {
16+
is_sep_byte(b)
2017
}
2118

2219
pub use super::windows_prefix::parse_prefix;
2320

2421
pub const HAS_PREFIXES: bool = true;
25-
pub const MAIN_SEP_STR: &str = "/";
26-
pub const MAIN_SEP: char = '/';
2722

2823
unsafe extern "C" {
2924
// Doc: https://cygwin.com/cygwin-api/func-cygwin-conv-path.html

library/std/src/sys/path/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
// There's a lot of necessary redundancy in separator definition. Consolidated into a macro to
2+
// prevent transcription errors.
3+
macro_rules! path_separator_bytes {
4+
($($sep:literal),+) => (
5+
pub const SEPARATORS: &[char] = &[$($sep as char,)+];
6+
pub const SEPARATORS_STR: &[&str] = &[$(
7+
match str::from_utf8(&[$sep]) {
8+
Ok(s) => s,
9+
Err(_) => panic!("path_separator_bytes must be ASCII bytes"),
10+
}
11+
),+];
12+
13+
#[inline]
14+
pub const fn is_sep_byte(b: u8) -> bool {
15+
$(b == $sep) ||+
16+
}
17+
)
18+
}
19+
120
cfg_select! {
221
target_os = "windows" => {
322
mod windows;

library/std/src/sys/path/sgx.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,18 @@ use crate::io;
33
use crate::path::{Path, PathBuf, Prefix};
44
use crate::sys::unsupported;
55

6-
#[inline]
7-
pub fn is_sep_byte(b: u8) -> bool {
8-
b == b'/'
9-
}
6+
path_separator_bytes!(b'/');
107

118
#[inline]
12-
pub fn is_verbatim_sep(b: u8) -> bool {
13-
b == b'/'
9+
pub const fn is_verbatim_sep(b: u8) -> bool {
10+
is_sep_byte(b)
1411
}
1512

1613
pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
1714
None
1815
}
1916

2017
pub const HAS_PREFIXES: bool = false;
21-
pub const MAIN_SEP_STR: &str = "/";
22-
pub const MAIN_SEP: char = '/';
2318

2419
pub(crate) fn absolute(_path: &Path) -> io::Result<PathBuf> {
2520
unsupported()

library/std/src/sys/path/uefi.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,21 @@ use crate::path::{Path, PathBuf, Prefix};
55
use crate::sys::pal::helpers;
66
use crate::sys::unsupported_err;
77

8+
path_separator_bytes!(b'\\');
9+
810
const FORWARD_SLASH: u8 = b'/';
911
const COLON: u8 = b':';
1012

1113
#[inline]
12-
pub fn is_sep_byte(b: u8) -> bool {
13-
b == b'\\'
14-
}
15-
16-
#[inline]
17-
pub fn is_verbatim_sep(b: u8) -> bool {
18-
b == b'\\'
14+
pub const fn is_verbatim_sep(b: u8) -> bool {
15+
is_sep_byte(b)
1916
}
2017

2118
pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
2219
None
2320
}
2421

2522
pub const HAS_PREFIXES: bool = true;
26-
pub const MAIN_SEP_STR: &str = "\\";
27-
pub const MAIN_SEP: char = '\\';
2823

2924
/// UEFI paths can be of 4 types:
3025
///

library/std/src/sys/path/unix.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,11 @@ use crate::ffi::OsStr;
22
use crate::path::{Path, PathBuf, Prefix};
33
use crate::{env, io};
44

5-
#[inline]
6-
pub fn is_sep_byte(b: u8) -> bool {
7-
b == b'/'
8-
}
5+
path_separator_bytes!(b'/');
96

107
#[inline]
11-
pub fn is_verbatim_sep(b: u8) -> bool {
12-
b == b'/'
8+
pub const fn is_verbatim_sep(b: u8) -> bool {
9+
is_sep_byte(b)
1310
}
1411

1512
#[inline]
@@ -18,8 +15,6 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
1815
}
1916

2017
pub const HAS_PREFIXES: bool = false;
21-
pub const MAIN_SEP_STR: &str = "/";
22-
pub const MAIN_SEP: char = '/';
2318

2419
/// Make a POSIX path absolute without changing its semantics.
2520
pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {

library/std/src/sys/path/unsupported_backslash.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,18 @@ use crate::io;
44
use crate::path::{Path, PathBuf, Prefix};
55
use crate::sys::unsupported;
66

7-
#[inline]
8-
pub fn is_sep_byte(b: u8) -> bool {
9-
b == b'\\'
10-
}
7+
path_separator_bytes!(b'\\');
118

129
#[inline]
13-
pub fn is_verbatim_sep(b: u8) -> bool {
14-
b == b'\\'
10+
pub const fn is_verbatim_sep(b: u8) -> bool {
11+
is_sep_byte(b)
1512
}
1613

1714
pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
1815
None
1916
}
2017

2118
pub const HAS_PREFIXES: bool = true;
22-
pub const MAIN_SEP_STR: &str = "\\";
23-
pub const MAIN_SEP: char = '\\';
2419

2520
pub(crate) fn absolute(_path: &Path) -> io::Result<PathBuf> {
2621
unsupported()

library/std/src/sys/path/windows.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ mod tests;
99

1010
pub use super::windows_prefix::parse_prefix;
1111

12+
path_separator_bytes!(b'\\', b'/');
13+
1214
pub const HAS_PREFIXES: bool = true;
13-
pub const MAIN_SEP_STR: &str = "\\";
14-
pub const MAIN_SEP: char = '\\';
1515

1616
/// A null terminated wide string.
1717
#[repr(transparent)]
@@ -48,12 +48,7 @@ pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&WCStr) -> io::Result<T>) ->
4848
}
4949

5050
#[inline]
51-
pub fn is_sep_byte(b: u8) -> bool {
52-
b == b'/' || b == b'\\'
53-
}
54-
55-
#[inline]
56-
pub fn is_verbatim_sep(b: u8) -> bool {
51+
pub const fn is_verbatim_sep(b: u8) -> bool {
5752
b == b'\\'
5853
}
5954

0 commit comments

Comments
 (0)