Skip to content

Commit 86f98f1

Browse files
committed
Auto merge of #139126 - jhpratt:rollup-tdceqkd, r=jhpratt
Rollup of 5 pull requests Successful merges: - #137836 (Set `target_vendor = "openwrt"` on `mips64-openwrt-linux-musl`) - #138206 ([AIX] Ignore linting on repr(C) structs with repr(packed) or repr(align(n))) - #139044 (bootstrap: Avoid cloning `change-id` list) - #139092 (Move `fd` into `std::sys`) - #139111 (Properly document FakeReads) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 85f518e + 4f7e9cb commit 86f98f1

File tree

27 files changed

+184
-79
lines changed

27 files changed

+184
-79
lines changed

compiler/rustc_lint/src/types.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1634,6 +1634,9 @@ impl ImproperCTypesDefinitions {
16341634
return true;
16351635
} else if let Adt(adt_def, _) = ty.kind()
16361636
&& adt_def.is_struct()
1637+
&& adt_def.repr().c()
1638+
&& !adt_def.repr().packed()
1639+
&& adt_def.repr().align.is_none()
16371640
{
16381641
let struct_variant = adt_def.variant(VariantIdx::ZERO);
16391642
// Within a nested struct, all fields are examined to correctly
@@ -1655,8 +1658,11 @@ impl ImproperCTypesDefinitions {
16551658
item: &'tcx hir::Item<'tcx>,
16561659
) {
16571660
let adt_def = cx.tcx.adt_def(item.owner_id.to_def_id());
1661+
// repr(C) structs also with packed or aligned representation
1662+
// should be ignored.
16581663
if adt_def.repr().c()
16591664
&& !adt_def.repr().packed()
1665+
&& adt_def.repr().align.is_none()
16601666
&& cx.tcx.sess.target.os == "aix"
16611667
&& !adt_def.all_fields().next().is_none()
16621668
{

compiler/rustc_middle/src/mir/syntax.rs

+84-28
Original file line numberDiff line numberDiff line change
@@ -334,14 +334,19 @@ pub enum StatementKind<'tcx> {
334334
/// See [`Rvalue`] documentation for details on each of those.
335335
Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>),
336336

337-
/// This represents all the reading that a pattern match may do (e.g., inspecting constants and
338-
/// discriminant values), and the kind of pattern it comes from. This is in order to adapt
339-
/// potential error messages to these specific patterns.
337+
/// When executed at runtime, this is a nop.
340338
///
341-
/// Note that this also is emitted for regular `let` bindings to ensure that locals that are
342-
/// never accessed still get some sanity checks for, e.g., `let x: ! = ..;`
339+
/// During static analysis, a fake read:
340+
/// - requires that the value being read is initialized (or, in the case
341+
/// of closures, that it was fully initialized at some point in the past)
342+
/// - constitutes a use of a value for the purposes of NLL (i.e. if the
343+
/// value being fake-read is a reference, the lifetime of that reference
344+
/// will be extended to cover the `FakeRead`)
345+
/// - but, unlike an actual read, does *not* invalidate any exclusive
346+
/// borrows.
343347
///
344-
/// When executed at runtime this is a nop.
348+
/// See [`FakeReadCause`] for more details on the situations in which a
349+
/// `FakeRead` is emitted.
345350
///
346351
/// Disallowed after drop elaboration.
347352
FakeRead(Box<(FakeReadCause, Place<'tcx>)>),
@@ -518,28 +523,59 @@ pub enum RetagKind {
518523
/// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists.
519524
#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, Hash, HashStable, PartialEq)]
520525
pub enum FakeReadCause {
521-
/// Inject a fake read of the borrowed input at the end of each guards
522-
/// code.
526+
/// A fake read injected into a match guard to ensure that the discriminants
527+
/// that are being matched on aren't modified while the match guard is being
528+
/// evaluated.
529+
///
530+
/// At the beginning of each match guard, a [fake borrow][FakeBorrowKind] is
531+
/// inserted for each discriminant accessed in the entire `match` statement.
532+
///
533+
/// Then, at the end of the match guard, a `FakeRead(ForMatchGuard)` is
534+
/// inserted to keep the fake borrows alive until that point.
523535
///
524536
/// This should ensure that you cannot change the variant for an enum while
525537
/// you are in the midst of matching on it.
526538
ForMatchGuard,
527539

528-
/// `let x: !; match x {}` doesn't generate any read of x so we need to
529-
/// generate a read of x to check that it is initialized and safe.
540+
/// Fake read of the scrutinee of a `match` or destructuring `let`
541+
/// (i.e. `let` with non-trivial pattern).
542+
///
543+
/// In `match x { ... }`, we generate a `FakeRead(ForMatchedPlace, x)`
544+
/// and insert it into the `otherwise_block` (which is supposed to be
545+
/// unreachable for irrefutable pattern-matches like `match` or `let`).
546+
///
547+
/// This is necessary because `let x: !; match x {}` doesn't generate any
548+
/// actual read of x, so we need to generate a `FakeRead` to check that it
549+
/// is initialized.
530550
///
531-
/// If a closure pattern matches a Place starting with an Upvar, then we introduce a
532-
/// FakeRead for that Place outside the closure, in such a case this option would be
533-
/// Some(closure_def_id).
534-
/// Otherwise, the value of the optional LocalDefId will be None.
551+
/// If the `FakeRead(ForMatchedPlace)` is being performed with a closure
552+
/// that doesn't capture the required upvars, the `FakeRead` within the
553+
/// closure is omitted entirely.
554+
///
555+
/// To make sure that this is still sound, if a closure matches against
556+
/// a Place starting with an Upvar, we hoist the `FakeRead` to the
557+
/// definition point of the closure.
558+
///
559+
/// If the `FakeRead` comes from being hoisted out of a closure like this,
560+
/// we record the `LocalDefId` of the closure. Otherwise, the `Option` will be `None`.
535561
//
536562
// We can use LocalDefId here since fake read statements are removed
537563
// before codegen in the `CleanupNonCodegenStatements` pass.
538564
ForMatchedPlace(Option<LocalDefId>),
539565

540-
/// A fake read of the RefWithinGuard version of a bind-by-value variable
541-
/// in a match guard to ensure that its value hasn't change by the time
542-
/// we create the OutsideGuard version.
566+
/// A fake read injected into a match guard to ensure that the places
567+
/// bound by the pattern are immutable for the duration of the match guard.
568+
///
569+
/// Within a match guard, references are created for each place that the
570+
/// pattern creates a binding for — this is known as the `RefWithinGuard`
571+
/// version of the variables. To make sure that the references stay
572+
/// alive until the end of the match guard, and properly prevent the
573+
/// places in question from being modified, a `FakeRead(ForGuardBinding)`
574+
/// is inserted at the end of the match guard.
575+
///
576+
/// For details on how these references are created, see the extensive
577+
/// documentation on `bind_matched_candidate_for_guard` in
578+
/// `rustc_mir_build`.
543579
ForGuardBinding,
544580

545581
/// Officially, the semantics of
@@ -552,22 +588,42 @@ pub enum FakeReadCause {
552588
/// However, if we see the simple pattern `let var = <expr>`, we optimize this to
553589
/// evaluate `<expr>` directly into the variable `var`. This is mostly unobservable,
554590
/// but in some cases it can affect the borrow checker, as in #53695.
555-
/// Therefore, we insert a "fake read" here to ensure that we get
556-
/// appropriate errors.
557591
///
558-
/// If a closure pattern matches a Place starting with an Upvar, then we introduce a
559-
/// FakeRead for that Place outside the closure, in such a case this option would be
560-
/// Some(closure_def_id).
561-
/// Otherwise, the value of the optional DefId will be None.
592+
/// Therefore, we insert a `FakeRead(ForLet)` immediately after each `let`
593+
/// with a trivial pattern.
594+
///
595+
/// FIXME: `ExprUseVisitor` has an entirely different opinion on what `FakeRead(ForLet)`
596+
/// is supposed to mean. If it was accurate to what MIR lowering does,
597+
/// would it even make sense to hoist these out of closures like
598+
/// `ForMatchedPlace`?
562599
ForLet(Option<LocalDefId>),
563600

564-
/// If we have an index expression like
601+
/// Currently, index expressions overloaded through the `Index` trait
602+
/// get lowered differently than index expressions with builtin semantics
603+
/// for arrays and slices — the latter will emit code to perform
604+
/// bound checks, and then return a MIR place that will only perform the
605+
/// indexing "for real" when it gets incorporated into an instruction.
606+
///
607+
/// This is observable in the fact that the following compiles:
608+
///
609+
/// ```
610+
/// fn f(x: &mut [&mut [u32]], i: usize) {
611+
/// x[i][x[i].len() - 1] += 1;
612+
/// }
613+
/// ```
614+
///
615+
/// However, we need to be careful to not let the user invalidate the
616+
/// bound check with an expression like
617+
///
618+
/// `(*x)[1][{ x = y; 4}]`
565619
///
566-
/// (*x)[1][{ x = y; 4}]
620+
/// Here, the first bounds check would be invalidated when we evaluate the
621+
/// second index expression. To make sure that this doesn't happen, we
622+
/// create a fake borrow of `x` and hold it while we evaluate the second
623+
/// index.
567624
///
568-
/// then the first bounds check is invalidated when we evaluate the second
569-
/// index expression. Thus we create a fake borrow of `x` across the second
570-
/// indexer, which will cause a borrow check error.
625+
/// This borrow is kept alive by a `FakeRead(ForIndex)` at the end of its
626+
/// scope.
571627
ForIndex,
572628
}
573629

compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub(crate) fn target() -> Target {
2323
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
2424
arch: "mips64".into(),
2525
options: TargetOptions {
26+
vendor: "openwrt".into(),
2627
abi: "abi64".into(),
2728
endian: Endian::Big,
2829
mcount: "_mcount".into(),

library/std/src/sys/pal/hermit/fd.rs library/std/src/sys/fd/hermit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#![unstable(reason = "not public", issue = "none", feature = "fd")]
22

3-
use super::hermit_abi;
43
use crate::cmp;
54
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, SeekFrom};
5+
use crate::os::hermit::hermit_abi;
66
use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
77
use crate::sys::{cvt, unsupported};
88
use crate::sys_common::{AsInner, FromInner, IntoInner};

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

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//! Platform-dependent file descriptor abstraction.
2+
3+
#![forbid(unsafe_op_in_unsafe_fn)]
4+
5+
cfg_if::cfg_if! {
6+
if #[cfg(target_family = "unix")] {
7+
mod unix;
8+
pub use unix::*;
9+
} else if #[cfg(target_os = "hermit")] {
10+
mod hermit;
11+
pub use hermit::*;
12+
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
13+
mod sgx;
14+
pub use sgx::*;
15+
} else if #[cfg(target_os = "wasi")] {
16+
mod wasi;
17+
pub use wasi::*;
18+
}
19+
}

library/std/src/sys/pal/sgx/fd.rs library/std/src/sys/fd/sgx.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use fortanix_sgx_abi::Fd;
22

3-
use super::abi::usercalls;
43
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
54
use crate::mem::ManuallyDrop;
5+
use crate::sys::pal::abi::usercalls;
66
use crate::sys::{AsInner, FromInner, IntoInner};
77

88
#[derive(Debug)]

library/std/src/sys/pal/unix/fd.rs library/std/src/sys/fd/unix.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ use crate::cmp;
2222
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read};
2323
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
2424
use crate::sys::cvt;
25+
#[cfg(all(target_os = "android", target_pointer_width = "64"))]
26+
use crate::sys::pal::weak::syscall;
27+
#[cfg(any(all(target_os = "android", target_pointer_width = "32"), target_vendor = "apple"))]
28+
use crate::sys::pal::weak::weak;
2529
use crate::sys_common::{AsInner, FromInner, IntoInner};
2630

2731
#[derive(Debug)]
@@ -232,7 +236,7 @@ impl FileDesc {
232236
// implementation if `preadv` is not available.
233237
#[cfg(all(target_os = "android", target_pointer_width = "64"))]
234238
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
235-
super::weak::syscall!(
239+
syscall!(
236240
fn preadv(
237241
fd: libc::c_int,
238242
iovec: *const libc::iovec,
@@ -257,7 +261,7 @@ impl FileDesc {
257261
// and its metadata from LLVM IR.
258262
#[no_sanitize(cfi)]
259263
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
260-
super::weak::weak!(
264+
weak!(
261265
fn preadv64(
262266
fd: libc::c_int,
263267
iovec: *const libc::iovec,
@@ -293,7 +297,7 @@ impl FileDesc {
293297
// use "weak" linking.
294298
#[cfg(target_vendor = "apple")]
295299
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
296-
super::weak::weak!(
300+
weak!(
297301
fn preadv(
298302
fd: libc::c_int,
299303
iovec: *const libc::iovec,
@@ -442,7 +446,7 @@ impl FileDesc {
442446
// implementation if `pwritev` is not available.
443447
#[cfg(all(target_os = "android", target_pointer_width = "64"))]
444448
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
445-
super::weak::syscall!(
449+
syscall!(
446450
fn pwritev(
447451
fd: libc::c_int,
448452
iovec: *const libc::iovec,
@@ -464,7 +468,7 @@ impl FileDesc {
464468

465469
#[cfg(all(target_os = "android", target_pointer_width = "32"))]
466470
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
467-
super::weak::weak!(
471+
weak!(
468472
fn pwritev64(
469473
fd: libc::c_int,
470474
iovec: *const libc::iovec,
@@ -500,7 +504,7 @@ impl FileDesc {
500504
// use "weak" linking.
501505
#[cfg(target_vendor = "apple")]
502506
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
503-
super::weak::weak!(
507+
weak!(
504508
fn pwritev(
505509
fd: libc::c_int,
506510
iovec: *const libc::iovec,
@@ -669,6 +673,6 @@ impl IntoRawFd for FileDesc {
669673

670674
impl FromRawFd for FileDesc {
671675
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
672-
Self(FromRawFd::from_raw_fd(raw_fd))
676+
Self(unsafe { FromRawFd::from_raw_fd(raw_fd) })
673677
}
674678
}

library/std/src/sys/pal/unix/fd/tests.rs library/std/src/sys/fd/unix/tests.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use core::mem::ManuallyDrop;
22

3-
use super::{FileDesc, IoSlice};
3+
use super::FileDesc;
4+
use crate::io::IoSlice;
45
use crate::os::unix::io::FromRawFd;
56

67
#[test]

library/std/src/sys/pal/wasi/fd.rs library/std/src/sys/fd/wasi.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
#![forbid(unsafe_op_in_unsafe_fn)]
2-
#![allow(dead_code)]
1+
#![expect(dead_code)]
32

4-
use super::err2io;
53
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
64
use crate::mem;
75
use crate::net::Shutdown;
86
use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
7+
use crate::sys::pal::err2io;
98
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
109

1110
#[derive(Debug)]

library/std/src/sys/fs/hermit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Raw
99
use crate::path::{Path, PathBuf};
1010
use crate::sync::Arc;
1111
use crate::sys::common::small_c_string::run_path_with_cstr;
12+
use crate::sys::fd::FileDesc;
1213
pub use crate::sys::fs::common::{copy, exists};
13-
use crate::sys::pal::fd::FileDesc;
1414
use crate::sys::time::SystemTime;
1515
use crate::sys::{cvt, unsupported};
1616
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};

library/std/src/sys/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub mod anonymous_pipe;
1212
pub mod backtrace;
1313
pub mod cmath;
1414
pub mod exit_guard;
15+
pub mod fd;
1516
pub mod fs;
1617
pub mod io;
1718
pub mod net;

library/std/src/sys/pal/hermit/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use crate::os::raw::c_char;
2020

2121
pub mod args;
2222
pub mod env;
23-
pub mod fd;
2423
pub mod futex;
2524
pub mod os;
2625
#[path = "../unsupported/pipe.rs"]

library/std/src/sys/pal/sgx/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use crate::sync::atomic::{AtomicBool, Ordering};
1111
pub mod abi;
1212
pub mod args;
1313
pub mod env;
14-
pub mod fd;
1514
mod libunwind_integration;
1615
pub mod os;
1716
#[path = "../unsupported/pipe.rs"]

library/std/src/sys/pal/unix/linux/pidfd.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::io;
22
use crate::os::fd::{AsRawFd, FromRawFd, RawFd};
33
use crate::sys::cvt;
4-
use crate::sys::pal::unix::fd::FileDesc;
4+
use crate::sys::fd::FileDesc;
55
use crate::sys::process::ExitStatus;
66
use crate::sys_common::{AsInner, FromInner, IntoInner};
77

library/std/src/sys/pal/unix/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ pub mod weak;
88

99
pub mod args;
1010
pub mod env;
11-
pub mod fd;
1211
#[cfg(target_os = "fuchsia")]
1312
pub mod fuchsia;
1413
pub mod futex;

0 commit comments

Comments
 (0)