Skip to content

Commit 0816929

Browse files
author
The Miri Cronjob Bot
committed
Merge from rustc
2 parents c00c18e + 35ffff2 commit 0816929

File tree

11 files changed

+793
-213
lines changed

11 files changed

+793
-213
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/src/fmt/rt.rs

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -183,38 +183,6 @@ impl Argument<'_> {
183183
ArgumentType::Placeholder { .. } => None,
184184
}
185185
}
186-
187-
/// Used by `format_args` when all arguments are gone after inlining,
188-
/// when using `&[]` would incorrectly allow for a bigger lifetime.
189-
///
190-
/// This fails without format argument inlining, and that shouldn't be different
191-
/// when the argument is inlined:
192-
///
193-
/// ```compile_fail,E0716
194-
/// let f = format_args!("{}", "a");
195-
/// println!("{f}");
196-
/// ```
197-
#[inline]
198-
pub const fn none() -> [Self; 0] {
199-
[]
200-
}
201-
}
202-
203-
/// This struct represents the unsafety of constructing an `Arguments`.
204-
/// It exists, rather than an unsafe function, in order to simplify the expansion
205-
/// of `format_args!(..)` and reduce the scope of the `unsafe` block.
206-
#[lang = "format_unsafe_arg"]
207-
pub struct UnsafeArg {
208-
_private: (),
209-
}
210-
211-
impl UnsafeArg {
212-
/// See documentation where `UnsafeArg` is required to know when it is safe to
213-
/// create and use `UnsafeArg`.
214-
#[inline]
215-
pub const unsafe fn new() -> Self {
216-
Self { _private: () }
217-
}
218186
}
219187

220188
/// Used by the format_args!() macro to create a fmt::Arguments object.
@@ -248,8 +216,7 @@ impl<'a> Arguments<'a> {
248216

249217
/// Specifies nonstandard formatting parameters.
250218
///
251-
/// An `rt::UnsafeArg` is required because the following invariants must be held
252-
/// in order for this function to be safe:
219+
/// SAFETY: the following invariants must be held:
253220
/// 1. The `pieces` slice must be at least as long as `fmt`.
254221
/// 2. Every `rt::Placeholder::position` value within `fmt` must be a valid index of `args`.
255222
/// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`.
@@ -261,11 +228,10 @@ impl<'a> Arguments<'a> {
261228
/// const _: () = if false { panic!("a {:1}", "a") };
262229
/// ```
263230
#[inline]
264-
pub fn new_v1_formatted(
231+
pub unsafe fn new_v1_formatted(
265232
pieces: &'a [&'static str],
266233
args: &'a [rt::Argument<'a>],
267234
fmt: &'a [rt::Placeholder],
268-
_unsafe_arg: rt::UnsafeArg,
269235
) -> Arguments<'a> {
270236
Arguments { pieces, fmt: Some(fmt), args }
271237
}

coretests/tests/fmt/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@ mod builders;
22
mod float;
33
mod num;
44

5+
#[test]
6+
fn test_lifetime() {
7+
// Trigger all different forms of expansion,
8+
// and check that each of them can be stored as a variable.
9+
let a = format_args!("hello");
10+
let a = format_args!("hello {a}");
11+
let a = format_args!("hello {a:1}");
12+
let a = format_args!("hello {a} {a:?}");
13+
assert_eq!(a.to_string(), "hello hello hello hello hello hello hello");
14+
15+
// Without arguments, it should also work in consts.
16+
const A: std::fmt::Arguments<'static> = format_args!("hello");
17+
assert_eq!(A.to_string(), "hello");
18+
}
19+
520
#[test]
621
fn test_format_flags() {
722
// No residual flags left by pointer formatting

std/src/path.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1316,8 +1316,17 @@ impl PathBuf {
13161316
need_sep = false
13171317
}
13181318

1319+
let need_clear = if cfg!(target_os = "cygwin") {
1320+
// If path is absolute and its prefix is none, it is like `/foo`,
1321+
// and will be handled below.
1322+
path.prefix().is_some()
1323+
} else {
1324+
// On Unix: prefix is always None.
1325+
path.is_absolute() || path.prefix().is_some()
1326+
};
1327+
13191328
// absolute `path` replaces `self`
1320-
if path.is_absolute() || path.prefix().is_some() {
1329+
if need_clear {
13211330
self.inner.truncate(0);
13221331

13231332
// verbatim paths need . and .. removed
@@ -3643,6 +3652,11 @@ impl Error for NormalizeError {}
36433652
/// paths, this is currently equivalent to calling
36443653
/// [`GetFullPathNameW`][windows-path].
36453654
///
3655+
/// On Cygwin, this is currently equivalent to calling [`cygwin_conv_path`][cygwin-path]
3656+
/// with mode `CCP_WIN_A_TO_POSIX`, and then being processed like other POSIX platforms.
3657+
/// If a Windows path is given, it will be converted to an absolute POSIX path without
3658+
/// keeping `..`.
3659+
///
36463660
/// Note that these [may change in the future][changes].
36473661
///
36483662
/// # Errors
@@ -3700,6 +3714,7 @@ impl Error for NormalizeError {}
37003714
/// [changes]: io#platform-specific-behavior
37013715
/// [posix-semantics]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
37023716
/// [windows-path]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew
3717+
/// [cygwin-path]: https://cygwin.com/cygwin-api/func-cygwin-conv-path.html
37033718
#[stable(feature = "absolute_path", since = "1.79.0")]
37043719
pub fn absolute<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
37053720
let path = path.as_ref();

std/src/sys/path/cygwin.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
use crate::ffi::OsString;
2+
use crate::os::unix::ffi::OsStringExt;
3+
use crate::path::{Path, PathBuf};
4+
use crate::sys::common::small_c_string::run_path_with_cstr;
5+
use crate::sys::cvt;
6+
use crate::{io, ptr};
7+
8+
#[inline]
9+
pub fn is_sep_byte(b: u8) -> bool {
10+
b == b'/' || b == b'\\'
11+
}
12+
13+
/// Cygwin allways prefers `/` over `\`, and it always converts all `/` to `\`
14+
/// internally when calling Win32 APIs. Therefore, the server component of path
15+
/// `\\?\UNC\localhost/share` is `localhost/share` on Win32, but `localhost`
16+
/// on Cygwin.
17+
#[inline]
18+
pub fn is_verbatim_sep(b: u8) -> bool {
19+
b == b'/' || b == b'\\'
20+
}
21+
22+
pub use super::windows_prefix::parse_prefix;
23+
24+
pub const MAIN_SEP_STR: &str = "/";
25+
pub const MAIN_SEP: char = '/';
26+
27+
unsafe extern "C" {
28+
// Doc: https://cygwin.com/cygwin-api/func-cygwin-conv-path.html
29+
// Src: https://github.com/cygwin/cygwin/blob/718a15ba50e0d01c79800bd658c2477f9a603540/winsup/cygwin/path.cc#L3902
30+
// Safety:
31+
// * `what` should be `CCP_WIN_A_TO_POSIX` here
32+
// * `from` is null-terminated UTF-8 path
33+
// * `to` is buffer, the buffer size is `size`.
34+
//
35+
// Converts a path to an absolute POSIX path, no matter the input is Win32 path or POSIX path.
36+
fn cygwin_conv_path(
37+
what: libc::c_uint,
38+
from: *const libc::c_char,
39+
to: *mut u8,
40+
size: libc::size_t,
41+
) -> libc::ssize_t;
42+
}
43+
44+
const CCP_WIN_A_TO_POSIX: libc::c_uint = 2;
45+
46+
/// Make a POSIX path absolute.
47+
pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
48+
run_path_with_cstr(path, &|path| {
49+
let conv = CCP_WIN_A_TO_POSIX;
50+
let size = cvt(unsafe { cygwin_conv_path(conv, path.as_ptr(), ptr::null_mut(), 0) })?;
51+
// If success, size should not be 0.
52+
debug_assert!(size >= 1);
53+
let size = size as usize;
54+
let mut buffer = Vec::with_capacity(size);
55+
cvt(unsafe { cygwin_conv_path(conv, path.as_ptr(), buffer.as_mut_ptr(), size) })?;
56+
unsafe {
57+
buffer.set_len(size - 1);
58+
}
59+
Ok(PathBuf::from(OsString::from_vec(buffer)))
60+
})
61+
.map(|path| {
62+
if path.prefix().is_some() {
63+
return path;
64+
}
65+
66+
// From unix.rs
67+
let mut components = path.components();
68+
let path_os = path.as_os_str().as_encoded_bytes();
69+
70+
let mut normalized = if path_os.starts_with(b"//") && !path_os.starts_with(b"///") {
71+
components.next();
72+
PathBuf::from("//")
73+
} else {
74+
PathBuf::new()
75+
};
76+
normalized.extend(components);
77+
78+
if path_os.ends_with(b"/") {
79+
normalized.push("");
80+
}
81+
82+
normalized
83+
})
84+
}
85+
86+
pub(crate) fn is_absolute(path: &Path) -> bool {
87+
if path.as_os_str().as_encoded_bytes().starts_with(b"\\") {
88+
path.has_root() && path.prefix().is_some()
89+
} else {
90+
path.has_root()
91+
}
92+
}

std/src/sys/path/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
cfg_if::cfg_if! {
22
if #[cfg(target_os = "windows")] {
33
mod windows;
4+
mod windows_prefix;
45
pub use windows::*;
56
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
67
mod sgx;
@@ -11,6 +12,10 @@ cfg_if::cfg_if! {
1112
} else if #[cfg(target_os = "uefi")] {
1213
mod uefi;
1314
pub use uefi::*;
15+
} else if #[cfg(target_os = "cygwin")] {
16+
mod cygwin;
17+
mod windows_prefix;
18+
pub use cygwin::*;
1419
} else {
1520
mod unix;
1621
pub use unix::*;

0 commit comments

Comments
 (0)