Skip to content

Commit 4407527

Browse files
committed
Auto merge of #149104 - matthiaskrgr:rollup-shexlc8, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #146341 (minimal dirfd implementation (1/4)) - #146925 (Add doc for va_list APIs) - #147035 (alloc: fix `Debug` implementation of `ExtractIf`) - #147173 (Add support for hexagon-unknown-qurt target) - #149041 (ignore unsized types in mips64 and sparc64 callconvs) - #149056 (fix the fragment_in_dst_padding_gets_overwritten test on s390x) - #149095 (rustc-dev-guide subtree update) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 07bdbae + 7322d98 commit 4407527

File tree

49 files changed

+1289
-324
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1289
-324
lines changed

compiler/rustc_target/src/callconv/mips64.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,12 @@ where
148148
Ty: TyAbiInterface<'a, C> + Copy,
149149
C: HasDataLayout,
150150
{
151-
if !fn_abi.ret.is_ignore() {
151+
if !fn_abi.ret.is_ignore() && fn_abi.ret.layout.is_sized() {
152152
classify_ret(cx, &mut fn_abi.ret);
153153
}
154154

155155
for arg in fn_abi.args.iter_mut() {
156-
if arg.is_ignore() {
156+
if arg.is_ignore() || !arg.layout.is_sized() {
157157
continue;
158158
}
159159
classify_arg(cx, arg);

compiler/rustc_target/src/callconv/sparc64.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,11 +216,14 @@ where
216216
Ty: TyAbiInterface<'a, C> + Copy,
217217
C: HasDataLayout + HasTargetSpec,
218218
{
219-
if !fn_abi.ret.is_ignore() {
219+
if !fn_abi.ret.is_ignore() && fn_abi.ret.layout.is_sized() {
220220
classify_arg(cx, &mut fn_abi.ret, Size::from_bytes(32));
221221
}
222222

223223
for arg in fn_abi.args.iter_mut() {
224+
if !arg.layout.is_sized() {
225+
continue;
226+
}
224227
if arg.is_ignore() {
225228
// sparc64-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs.
226229
if cx.target_spec().os == Os::Linux

compiler/rustc_target/src/spec/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,6 +1490,7 @@ supported_targets! {
14901490
("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
14911491
("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
14921492
("hexagon-unknown-none-elf", hexagon_unknown_none_elf),
1493+
("hexagon-unknown-qurt", hexagon_unknown_qurt),
14931494

14941495
("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
14951496
("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
@@ -1958,6 +1959,7 @@ crate::target_spec_enum! {
19581959
OpenBsd = "openbsd",
19591960
Psp = "psp",
19601961
Psx = "psx",
1962+
Qurt = "qurt",
19611963
Redox = "redox",
19621964
Rtems = "rtems",
19631965
Solaris = "solaris",
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use crate::spec::{Arch, Cc, LinkerFlavor, Lld, Os, Target, TargetMetadata, TargetOptions, cvs};
2+
3+
pub(crate) fn target() -> Target {
4+
let mut base = TargetOptions::default();
5+
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &["-G0"]);
6+
7+
Target {
8+
llvm_target: "hexagon-unknown-elf".into(),
9+
metadata: TargetMetadata {
10+
description: Some("Hexagon QuRT".into()),
11+
tier: Some(3),
12+
host_tools: Some(false),
13+
std: Some(false),
14+
},
15+
pointer_width: 32,
16+
data_layout: "\
17+
e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32\
18+
:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32\
19+
:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048\
20+
:2048:2048"
21+
.into(),
22+
arch: Arch::Hexagon,
23+
options: TargetOptions {
24+
os: Os::Qurt,
25+
vendor: "unknown".into(),
26+
cpu: "hexagonv69".into(),
27+
linker: Some("rust-lld".into()),
28+
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
29+
exe_suffix: ".elf".into(),
30+
dynamic_linking: true,
31+
executables: true,
32+
families: cvs!["unix"],
33+
has_thread_local: true,
34+
has_rpath: false,
35+
crt_static_default: false,
36+
crt_static_respected: true,
37+
crt_static_allows_dylibs: true,
38+
no_default_libraries: false,
39+
max_atomic_width: Some(32),
40+
features: "-small-data,+hvx-length128b".into(),
41+
c_enum_min_bits: Some(8),
42+
..base
43+
},
44+
}
45+
}

library/alloc/src/vec/extract_if.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,20 @@ where
130130
A: Allocator,
131131
{
132132
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133-
let peek = if self.idx < self.end { self.vec.get(self.idx) } else { None };
133+
let peek = if self.idx < self.end {
134+
// This has to use pointer arithmetic as `self.vec[self.idx]` or
135+
// `self.vec.get_unchecked(self.idx)` wouldn't work since we
136+
// temporarily set the length of `self.vec` to zero.
137+
//
138+
// SAFETY:
139+
// Since `self.idx` is smaller than `self.end` and `self.end` is
140+
// smaller than `self.old_len`, `idx` is valid for indexing the
141+
// buffer. Also, per the invariant of `self.idx`, this element
142+
// has not been inspected/moved out yet.
143+
Some(unsafe { &*self.vec.as_ptr().add(self.idx) })
144+
} else {
145+
None
146+
};
134147
f.debug_struct("ExtractIf").field("peek", &peek).finish_non_exhaustive()
135148
}
136149
}

library/alloctests/tests/vec.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,6 +1650,17 @@ fn extract_if_unconsumed() {
16501650
assert_eq!(vec, [1, 2, 3, 4]);
16511651
}
16521652

1653+
#[test]
1654+
fn extract_if_debug() {
1655+
let mut vec = vec![1, 2];
1656+
let mut drain = vec.extract_if(.., |&mut x| x % 2 != 0);
1657+
assert!(format!("{drain:?}").contains("Some(1)"));
1658+
drain.next();
1659+
assert!(format!("{drain:?}").contains("Some(2)"));
1660+
drain.next();
1661+
assert!(format!("{drain:?}").contains("None"));
1662+
}
1663+
16531664
#[test]
16541665
fn test_reserve_exact() {
16551666
// This is all the same as test_reserve

library/core/src/ffi/va_list.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,11 @@ impl<'f> VaListImpl<'f> {
243243
///
244244
/// # Safety
245245
///
246-
/// This function is only sound to call when the next variable argument:
246+
/// This function is only sound to call when:
247247
///
248-
/// - has a type that is ABI-compatible with the type `T`
249-
/// - has a value that is a properly initialized value of type `T`
248+
/// - there is a next variable argument available.
249+
/// - the next argument's type must be ABI-compatible with the type `T`.
250+
/// - the next argument must have a properly initialized value of type `T`.
250251
///
251252
/// Calling this function with an incompatible type, an invalid value, or when there
252253
/// are no more variable arguments, is unsound.

library/core/src/intrinsics/mod.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3350,22 +3350,41 @@ pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize
33503350

33513351
/// Copies the current location of arglist `src` to the arglist `dst`.
33523352
///
3353-
/// FIXME: document safety requirements
3353+
/// # Safety
3354+
///
3355+
/// You must check the following invariants before you call this function:
3356+
///
3357+
/// - `dest` must be non-null and point to valid, writable memory.
3358+
/// - `dest` must not alias `src`.
3359+
///
33543360
#[rustc_intrinsic]
33553361
#[rustc_nounwind]
33563362
pub unsafe fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>);
33573363

33583364
/// Loads an argument of type `T` from the `va_list` `ap` and increment the
33593365
/// argument `ap` points to.
33603366
///
3361-
/// FIXME: document safety requirements
3367+
/// # Safety
3368+
///
3369+
/// This function is only sound to call when:
3370+
///
3371+
/// - there is a next variable argument available.
3372+
/// - the next argument's type must be ABI-compatible with the type `T`.
3373+
/// - the next argument must have a properly initialized value of type `T`.
3374+
///
3375+
/// Calling this function with an incompatible type, an invalid value, or when there
3376+
/// are no more variable arguments, is unsound.
3377+
///
33623378
#[rustc_intrinsic]
33633379
#[rustc_nounwind]
33643380
pub unsafe fn va_arg<T: VaArgSafe>(ap: &mut VaListImpl<'_>) -> T;
33653381

33663382
/// Destroy the arglist `ap` after initialization with `va_start` or `va_copy`.
33673383
///
3368-
/// FIXME: document safety requirements
3384+
/// # Safety
3385+
///
3386+
/// `ap` must not be used to access variable arguments after this call.
3387+
///
33693388
#[rustc_intrinsic]
33703389
#[rustc_nounwind]
33713390
pub unsafe fn va_end(ap: &mut VaListImpl<'_>);

library/std/src/fs.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,43 @@ pub enum TryLockError {
153153
WouldBlock,
154154
}
155155

156+
/// An object providing access to a directory on the filesystem.
157+
///
158+
/// Directories are automatically closed when they go out of scope. Errors detected
159+
/// on closing are ignored by the implementation of `Drop`.
160+
///
161+
/// # Platform-specific behavior
162+
///
163+
/// On supported systems (including Windows and some UNIX-based OSes), this function acquires a
164+
/// handle/file descriptor for the directory. This allows functions like [`Dir::open_file`] to
165+
/// avoid [TOCTOU] errors when the directory itself is being moved.
166+
///
167+
/// On other systems, it stores an absolute path (see [`canonicalize()`]). In the latter case, no
168+
/// [TOCTOU] guarantees are made.
169+
///
170+
/// # Examples
171+
///
172+
/// Opens a directory and then a file inside it.
173+
///
174+
/// ```no_run
175+
/// #![feature(dirfd)]
176+
/// use std::{fs::Dir, io};
177+
///
178+
/// fn main() -> std::io::Result<()> {
179+
/// let dir = Dir::open("foo")?;
180+
/// let mut file = dir.open_file("bar.txt")?;
181+
/// let contents = io::read_to_string(file)?;
182+
/// assert_eq!(contents, "Hello, world!");
183+
/// Ok(())
184+
/// }
185+
/// ```
186+
///
187+
/// [TOCTOU]: self#time-of-check-to-time-of-use-toctou
188+
#[unstable(feature = "dirfd", issue = "120426")]
189+
pub struct Dir {
190+
inner: fs_imp::Dir,
191+
}
192+
156193
/// Metadata information about a file.
157194
///
158195
/// This structure is returned from the [`metadata`] or
@@ -1555,6 +1592,87 @@ impl Seek for Arc<File> {
15551592
}
15561593
}
15571594

1595+
impl Dir {
1596+
/// Attempts to open a directory at `path` in read-only mode.
1597+
///
1598+
/// # Errors
1599+
///
1600+
/// This function will return an error if `path` does not point to an existing directory.
1601+
/// Other errors may also be returned according to [`OpenOptions::open`].
1602+
///
1603+
/// # Examples
1604+
///
1605+
/// ```no_run
1606+
/// #![feature(dirfd)]
1607+
/// use std::{fs::Dir, io};
1608+
///
1609+
/// fn main() -> std::io::Result<()> {
1610+
/// let dir = Dir::open("foo")?;
1611+
/// let mut f = dir.open_file("bar.txt")?;
1612+
/// let contents = io::read_to_string(f)?;
1613+
/// assert_eq!(contents, "Hello, world!");
1614+
/// Ok(())
1615+
/// }
1616+
/// ```
1617+
#[unstable(feature = "dirfd", issue = "120426")]
1618+
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<Self> {
1619+
fs_imp::Dir::open(path.as_ref(), &OpenOptions::new().read(true).0)
1620+
.map(|inner| Self { inner })
1621+
}
1622+
1623+
/// Attempts to open a file in read-only mode relative to this directory.
1624+
///
1625+
/// # Errors
1626+
///
1627+
/// This function will return an error if `path` does not point to an existing file.
1628+
/// Other errors may also be returned according to [`OpenOptions::open`].
1629+
///
1630+
/// # Examples
1631+
///
1632+
/// ```no_run
1633+
/// #![feature(dirfd)]
1634+
/// use std::{fs::Dir, io};
1635+
///
1636+
/// fn main() -> std::io::Result<()> {
1637+
/// let dir = Dir::open("foo")?;
1638+
/// let mut f = dir.open_file("bar.txt")?;
1639+
/// let contents = io::read_to_string(f)?;
1640+
/// assert_eq!(contents, "Hello, world!");
1641+
/// Ok(())
1642+
/// }
1643+
/// ```
1644+
#[unstable(feature = "dirfd", issue = "120426")]
1645+
pub fn open_file<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
1646+
self.inner
1647+
.open_file(path.as_ref(), &OpenOptions::new().read(true).0)
1648+
.map(|f| File { inner: f })
1649+
}
1650+
}
1651+
1652+
impl AsInner<fs_imp::Dir> for Dir {
1653+
#[inline]
1654+
fn as_inner(&self) -> &fs_imp::Dir {
1655+
&self.inner
1656+
}
1657+
}
1658+
impl FromInner<fs_imp::Dir> for Dir {
1659+
fn from_inner(f: fs_imp::Dir) -> Dir {
1660+
Dir { inner: f }
1661+
}
1662+
}
1663+
impl IntoInner<fs_imp::Dir> for Dir {
1664+
fn into_inner(self) -> fs_imp::Dir {
1665+
self.inner
1666+
}
1667+
}
1668+
1669+
#[unstable(feature = "dirfd", issue = "120426")]
1670+
impl fmt::Debug for Dir {
1671+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1672+
self.inner.fmt(f)
1673+
}
1674+
}
1675+
15581676
impl OpenOptions {
15591677
/// Creates a blank new set of options ready for configuration.
15601678
///

library/std/src/fs/tests.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use rand::RngCore;
22

3+
#[cfg(not(miri))]
4+
use super::Dir;
35
#[cfg(any(
46
windows,
57
target_os = "freebsd",
@@ -19,6 +21,8 @@ use crate::assert_matches::assert_matches;
1921
))]
2022
use crate::fs::TryLockError;
2123
use crate::fs::{self, File, FileTimes, OpenOptions};
24+
#[cfg(not(miri))]
25+
use crate::io;
2226
use crate::io::prelude::*;
2327
use crate::io::{BorrowedBuf, ErrorKind, SeekFrom};
2428
use crate::mem::MaybeUninit;
@@ -2450,3 +2454,30 @@ fn test_fs_set_times_nofollow() {
24502454
assert_ne!(target_metadata.accessed().unwrap(), accessed);
24512455
assert_ne!(target_metadata.modified().unwrap(), modified);
24522456
}
2457+
2458+
#[test]
2459+
// FIXME: libc calls fail on miri
2460+
#[cfg(not(miri))]
2461+
fn test_dir_smoke_test() {
2462+
let tmpdir = tmpdir();
2463+
let dir = Dir::open(tmpdir.path());
2464+
check!(dir);
2465+
}
2466+
2467+
#[test]
2468+
// FIXME: libc calls fail on miri
2469+
#[cfg(not(miri))]
2470+
fn test_dir_read_file() {
2471+
let tmpdir = tmpdir();
2472+
let mut f = check!(File::create(tmpdir.join("foo.txt")));
2473+
check!(f.write(b"bar"));
2474+
check!(f.flush());
2475+
drop(f);
2476+
let dir = check!(Dir::open(tmpdir.path()));
2477+
let f = check!(dir.open_file("foo.txt"));
2478+
let buf = check!(io::read_to_string(f));
2479+
assert_eq!("bar", &buf);
2480+
let f = check!(dir.open_file(tmpdir.join("foo.txt")));
2481+
let buf = check!(io::read_to_string(f));
2482+
assert_eq!("bar", &buf);
2483+
}

0 commit comments

Comments
 (0)