Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 6 pull requests #124330

Merged
merged 13 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1139,7 +1139,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// are the same function and their parameters have a LUB.
match self.commit_if_ok(|_| {
self.at(cause, self.param_env).lub(
DefineOpaqueTypes::No,
DefineOpaqueTypes::Yes,
prev_ty,
new_ty,
)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ symbols! {
Duration,
Encodable,
Encoder,
Enumerate,
Eq,
Equal,
Err,
Expand Down
1 change: 1 addition & 0 deletions library/core/src/iter/adapters/enumerate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::ops::Try;
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "Enumerate")]
pub struct Enumerate<I> {
iter: I,
count: usize,
Expand Down
17 changes: 12 additions & 5 deletions library/std/src/sys/pal/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,14 +201,21 @@ pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> crate::io::Result<Vec<u16>> {
// currently reside in the buffer. This function is an abstraction over these
// functions by making them easier to call.
//
// The first callback, `f1`, is yielded a (pointer, len) pair which can be
// The first callback, `f1`, is passed a (pointer, len) pair which can be
// passed to a syscall. The `ptr` is valid for `len` items (u16 in this case).
// The closure is expected to return what the syscall returns which will be
// interpreted by this function to determine if the syscall needs to be invoked
// again (with more buffer space).
// The closure is expected to:
// - On success, return the actual length of the written data *without* the null terminator.
// This can be 0. In this case the last_error must be left unchanged.
// - On insufficient buffer space,
// - either return the required length *with* the null terminator,
// - or set the last-error to ERROR_INSUFFICIENT_BUFFER and return `len`.
// - On other failure, return 0 and set last_error.
//
// This is how most but not all syscalls indicate the required buffer space.
// Other syscalls may need translation to match this protocol.
//
// Once the syscall has completed (errors bail out early) the second closure is
// yielded the data which has been read from the syscall. The return value
// passed the data which has been read from the syscall. The return value
// from this closure is then the return value of the function.
pub fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> crate::io::Result<T>
where
Expand Down
2 changes: 2 additions & 0 deletions library/std/src/sys/pal/windows/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ fn home_dir_crt() -> Option<PathBuf> {

super::fill_utf16_buf(
|buf, mut sz| {
// GetUserProfileDirectoryW does not quite use the usual protocol for
// negotiating the buffer size, so we have to translate.
match c::GetUserProfileDirectoryW(
ptr::without_provenance_mut(CURRENT_PROCESS_TOKEN),
buf,
Expand Down
26 changes: 22 additions & 4 deletions library/std/src/sys/pal/windows/thread_local_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,15 @@ impl StaticKey {
panic!("out of TLS indexes");
}

self.key.store(key + 1, Release);
register_dtor(self);

// Release-storing the key needs to be the last thing we do.
// This is because in `fn key()`, other threads will do an acquire load of the key,
// and if that sees this write then it will entirely bypass the `InitOnce`. We thus
// need to establish synchronization through `key`. In particular that acquire load
// must happen-after the register_dtor above, to ensure the dtor actually runs!
self.key.store(key + 1, Release);

let r = c::InitOnceComplete(self.once.get(), 0, ptr::null_mut());
debug_assert_eq!(r, c::TRUE);

Expand Down Expand Up @@ -313,17 +319,29 @@ unsafe fn run_dtors() {
// Use acquire ordering to observe key initialization.
let mut cur = DTORS.load(Acquire);
while !cur.is_null() {
let key = (*cur).key.load(Relaxed) - 1;
let pre_key = (*cur).key.load(Acquire);
let dtor = (*cur).dtor.unwrap();
cur = (*cur).next.load(Relaxed);

// In StaticKey::init, we register the dtor before setting `key`.
// So if one thread's `run_dtors` races with another thread executing `init` on the same
// `StaticKey`, we can encounter a key of 0 here. That means this key was never
// initialized in this thread so we can safely skip it.
if pre_key == 0 {
continue;
}
// If this is non-zero, then via the `Acquire` load above we synchronized with
// everything relevant for this key. (It's not clear that this is needed, since the
// release-acquire pair on DTORS also establishes synchronization, but better safe than
// sorry.)
let key = pre_key - 1;

let ptr = c::TlsGetValue(key);
if !ptr.is_null() {
c::TlsSetValue(key, ptr::null_mut());
dtor(ptr as *mut _);
any_run = true;
}

cur = (*cur).next.load(Relaxed);
}

if !any_run {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

set -euf -o pipefail

INTEGRATION_SHA=56310bca298872ffb5ea02e665956d9b6dc41171
INTEGRATION_SHA=1011e3298775ee7cdf6f6dc73e808d6a86e33bd6
PICK_REFS=()

checkout=fuchsia
Expand Down
8 changes: 4 additions & 4 deletions src/ci/docker/scripts/build-fuchsia-toolchain.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ set -ex
source shared.sh

FUCHSIA_SDK_URL=https://chrome-infra-packages.appspot.com/dl/fuchsia/sdk/core/linux-amd64
FUCHSIA_SDK_ID=MrhQwtmP8CpZre-i_PNOREcThbUcrX3bA-45d6WQr-cC
FUCHSIA_SDK_SHA256=32b850c2d98ff02a59adefa2fcf34e44471385b51cad7ddb03ee3977a590afe7
FUCHSIA_SDK_ID=version:20.20240412.3.1
FUCHSIA_SDK_SHA256=cc52f3497487dd813c89d9316e6967efcea89c7759edccf3e40fcf3662e53f19
FUCHSIA_SDK_USR_DIR=/usr/local/core-linux-amd64-fuchsia-sdk
CLANG_DOWNLOAD_URL=\
https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/linux-amd64
CLANG_DOWNLOAD_ID=Tpc85d1ZwSlZ6UKl2d96GRUBGNA5JKholOKe24sRDr0C
CLANG_DOWNLOAD_SHA256=4e973ce5dd59c12959e942a5d9df7a19150118d03924a86894e29edb8b110ebd
CLANG_DOWNLOAD_ID=git_revision:c777c011a709dffd4fa5e79cad7947b7c3405d02
CLANG_DOWNLOAD_SHA256=779167422ad73c292f049dcea5569f84577af9292189ed2749518b966a4d0844

install_clang() {
mkdir -p clang_download
Expand Down
2 changes: 1 addition & 1 deletion src/ci/docker/scripts/fuchsia-test-runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ def start(self):
# Look up the product bundle transfer manifest.
self.log_info("Looking up the product bundle transfer manifest...")
product_name = "minimal." + self.triple_to_arch(self.target)
fuchsia_version = "14.20230811.2.1"
fuchsia_version = "20.20240412.3.1"

# FIXME: We should be able to replace this with the machine parsable
# `ffx --machine json product lookup ...` once F15 is released.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//@ aux-crate: sigpipe_utils=sigpipe-utils.rs

#![feature(unix_sigpipe)]

#[unix_sigpipe = "inherit"]
fn main() {
sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//@ aux-crate: sigpipe_utils=sigpipe-utils.rs

#![feature(unix_sigpipe)]

#[unix_sigpipe = "inherit"]
fn main() {
sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
}
31 changes: 23 additions & 8 deletions tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
//@ ignore-cross-compile because aux-bin does not yet support it
//@ only-unix because SIGPIPE is a unix thing
//@ aux-bin: assert-inherit-sig_dfl.rs
//@ aux-bin: assert-inherit-sig_ign.rs
//@ run-pass
//@ aux-build:sigpipe-utils.rs

#![feature(unix_sigpipe)]
#![feature(rustc_private, unix_sigpipe)]

#[unix_sigpipe = "inherit"]
extern crate libc;

// By default the Rust runtime resets SIGPIPE to SIG_DFL before exec:ing child
// processes so opt-out of that with `#[unix_sigpipe = "sig_dfl"]`. See
// https://github.com/rust-lang/rust/blob/bf4de3a874753bbee3323081c8b0c133444fed2d/library/std/src/sys/pal/unix/process/process_unix.rs#L359-L384
#[unix_sigpipe = "sig_dfl"]
fn main() {
extern crate sigpipe_utils;
// First expect SIG_DFL in a child process with #[unix_sigpipe = "inherit"].
assert_inherit_sigpipe_disposition("auxiliary/bin/assert-inherit-sig_dfl");

// With SIG_IGN we expect #[unix_sigpipe = "inherit"] to also get SIG_IGN.
unsafe {
libc::signal(libc::SIGPIPE, libc::SIG_IGN);
}
assert_inherit_sigpipe_disposition("auxiliary/bin/assert-inherit-sig_ign");
}

// #[unix_sigpipe = "inherit"] is active, so SIGPIPE shall NOT be ignored,
// instead the default handler shall be installed. (We assume that the
// process that runs these tests have the default handler.)
sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
fn assert_inherit_sigpipe_disposition(aux_bin: &str) {
let mut cmd = std::process::Command::new(aux_bin);
assert!(cmd.status().unwrap().success());
}
58 changes: 58 additions & 0 deletions tests/ui/fn/fn_def_coercion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//! Test that coercing between function items of the same function,
//! but with different generic args succeeds in typeck, but then fails
//! in borrowck when the lifetimes can't actually be merged.

fn foo<T>(t: T) -> T {
t
}

fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
let mut x = foo::<&'a ()>; //~ ERROR: lifetime may not live long enough
x = foo::<&'b ()>; //~ ERROR: lifetime may not live long enough
x = foo::<&'c ()>;
x(a);
x(b);
x(c);
}

fn g<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
let x = foo::<&'c ()>;
let _: &'c () = x(a); //~ ERROR lifetime may not live long enough
}

fn h<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
let x = foo::<&'a ()>;
let _: &'a () = x(c);
}

fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
let mut x = foo::<&'c ()>;
x = foo::<&'b ()>; //~ ERROR lifetime may not live long enough
x = foo::<&'a ()>; //~ ERROR lifetime may not live long enough
x(a);
x(b);
x(c);
}

fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
let x = match true {
true => foo::<&'b ()>, //~ ERROR lifetime may not live long enough
false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough
};
x(a);
x(b);
x(c);
}

fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
let x = match true {
true => foo::<&'c ()>,
false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough
};

x(a);
x(b); //~ ERROR lifetime may not live long enough
x(c);
}

fn main() {}
Loading
Loading