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 #128469

Merged
merged 15 commits into from
Aug 1, 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
50 changes: 23 additions & 27 deletions compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::mem::swap;

use ast::ptr::P;
use ast::HasAttrs;
use rustc_ast::mut_visit::MutVisitor;
Expand Down Expand Up @@ -154,13 +152,28 @@ pub fn expand_deriving_smart_ptr(
{
let pointee = &mut impl_generics.params[pointee_param_idx];
self_bounds = pointee.bounds.clone();
if !contains_maybe_sized_bound(&self_bounds)
&& !contains_maybe_sized_bound_on_pointee(
&generics.where_clause.predicates,
pointee_ty_ident.name,
)
{
cx.dcx()
.struct_span_err(
pointee_ty_ident.span,
format!(
"`derive(SmartPointer)` requires {} to be marked `?Sized`",
pointee_ty_ident.name
),
)
.emit();
return;
}
let arg = GenericArg::Type(s_ty.clone());
let unsize = cx.path_all(span, true, path!(span, core::marker::Unsize), vec![arg]);
pointee.bounds.push(cx.trait_bound(unsize, false));
let mut attrs = thin_vec![];
swap(&mut pointee.attrs, &mut attrs);
// Drop `#[pointee]` attribute since it should not be recognized outside `derive(SmartPointer)`
pointee.attrs = attrs.into_iter().filter(|attr| !attr.has_name(sym::pointee)).collect();
pointee.attrs.retain(|attr| !attr.has_name(sym::pointee));
}

// # Rewrite generic parameter bounds
Expand All @@ -169,14 +182,14 @@ pub fn expand_deriving_smart_ptr(
// ```
// struct<
// U: Trait<T>,
// #[pointee] T: Trait<T>,
// #[pointee] T: Trait<T> + ?Sized,
// V: Trait<T>> ...
// ```
// ... generates this `impl` generic parameters
// ```
// impl<
// U: Trait<T> + Trait<__S>,
// T: Trait<T> + Unsize<__S>, // (**)
// T: Trait<T> + ?Sized + Unsize<__S>, // (**)
// __S: Trait<__S> + ?Sized, // (*)
// V: Trait<T> + Trait<__S>> ...
// ```
Expand Down Expand Up @@ -218,23 +231,6 @@ pub fn expand_deriving_smart_ptr(
//
// We now insert `__S` with the missing bounds marked with (*) above.
// We should also write the bounds from `#[pointee]` to `__S` as required by `Unsize<__S>`.
let sized = cx.path_global(span, path!(span, core::marker::Sized));
// For some reason, we are not allowed to write `?Sized` bound twice like `__S: ?Sized + ?Sized`.
if !contains_maybe_sized_bound(&self_bounds)
&& !contains_maybe_sized_bound_on_pointee(
&generics.where_clause.predicates,
pointee_ty_ident.name,
)
{
self_bounds.push(GenericBound::Trait(
cx.poly_trait_ref(span, sized),
TraitBoundModifiers {
polarity: ast::BoundPolarity::Maybe(span),
constness: ast::BoundConstness::Never,
asyncness: ast::BoundAsyncness::Normal,
},
));
}
{
let mut substitution =
TypeSubstitution { from_name: pointee_ty_ident.name, to_ty: &s_ty, rewritten: false };
Expand All @@ -252,7 +248,7 @@ pub fn expand_deriving_smart_ptr(
// where
// U: Trait<V> + Trait<T>,
// Companion<T>: Trait<T>,
// T: Trait<T>,
// T: Trait<T> + ?Sized,
// { .. }
// ```
// ... will have a impl prelude like so
Expand All @@ -263,8 +259,8 @@ pub fn expand_deriving_smart_ptr(
// U: Trait<__S>,
// Companion<T>: Trait<T>,
// Companion<__S>: Trait<__S>,
// T: Trait<T>,
// __S: Trait<__S>,
// T: Trait<T> + ?Sized,
// __S: Trait<__S> + ?Sized,
// ```
//
// We should also write a few new `where` bounds from `#[pointee] T` to `__S`
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1306,6 +1306,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// No way to know whether it's diverging because
// of a `break` or an outer `break` or `return`.
self.diverges.set(Diverges::Maybe);
} else {
self.diverges.set(self.diverges.get() | Diverges::always(expr.span));
}

// If we permit break with a value, then result type is
Expand Down
54 changes: 33 additions & 21 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,30 +48,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Produces warning on the given node, if the current point in the
/// function is unreachable, and there hasn't been another warning.
pub(crate) fn warn_if_unreachable(&self, id: HirId, span: Span, kind: &str) {
// FIXME: Combine these two 'if' expressions into one once
// let chains are implemented
if let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() {
// If span arose from a desugaring of `if` or `while`, then it is the condition itself,
// which diverges, that we are about to lint on. This gives suboptimal diagnostics.
// Instead, stop here so that the `if`- or `while`-expression's block is linted instead.
if !span.is_desugaring(DesugaringKind::CondTemporary)
&& !span.is_desugaring(DesugaringKind::Async)
&& !orig_span.is_desugaring(DesugaringKind::Await)
{
self.diverges.set(Diverges::WarnedAlways);
// If span arose from a desugaring of `if` or `while`, then it is the condition itself,
// which diverges, that we are about to lint on. This gives suboptimal diagnostics.
// Instead, stop here so that the `if`- or `while`-expression's block is linted instead.
if span.is_desugaring(DesugaringKind::CondTemporary) {
return;
}

debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
// Don't lint if the result of an async block or async function is `!`.
// This does not affect the unreachable lints *within* the body.
if span.is_desugaring(DesugaringKind::Async) {
return;
}

let msg = format!("unreachable {kind}");
self.tcx().node_span_lint(lint::builtin::UNREACHABLE_CODE, id, span, |lint| {
lint.primary_message(msg.clone());
lint.span_label(span, msg).span_label(
orig_span,
custom_note.unwrap_or("any code following this expression is unreachable"),
);
})
}
// Don't lint *within* the `.await` operator, since that's all just desugaring junk.
// We only want to lint if there is a subsequent expression after the `.await`.
if span.is_desugaring(DesugaringKind::Await) {
return;
}

let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() else {
return;
};

// Don't warn twice.
self.diverges.set(Diverges::WarnedAlways);

debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);

let msg = format!("unreachable {kind}");
self.tcx().node_span_lint(lint::builtin::UNREACHABLE_CODE, id, span, |lint| {
lint.primary_message(msg.clone());
lint.span_label(span, msg).span_label(
orig_span,
custom_note.unwrap_or("any code following this expression is unreachable"),
);
})
}

/// Resolves type and const variables in `ty` if possible. Unlike the infcx
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_lint/src/precedence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ declare_lint! {
/// ### Example
///
/// ```rust,compile_fail
/// # #![deny(ambiguous_negative_literals)]
/// # #![allow(unused)]
/// -1i32.abs(); // equals -1, while `(-1i32).abs()` equals 1
/// ```
Expand All @@ -27,7 +28,7 @@ declare_lint! {
/// Method calls take precedence over unary precedence. Setting the
/// precedence explicitly makes the code clearer and avoid potential bugs.
pub AMBIGUOUS_NEGATIVE_LITERALS,
Deny,
Allow,
"ambiguous negative literals operations",
report_in_external_macro
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ pub fn target() -> Target {
Target {
llvm_target: "loongarch64-unknown-linux-musl".into(),
metadata: crate::spec::TargetMetadata {
description: Some("LoongArch64 Linux (LP64D ABI) with musl 1.2.3".into()),
tier: Some(3),
host_tools: Some(false),
std: None, // ?
description: Some("LoongArch64 Linux (LP64D ABI) with musl 1.2.5".into()),
tier: Some(2),
host_tools: Some(true),
std: Some(true),
},
pointer_width: 64,
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub fn target() -> Target {
Target {
llvm_target: "loongarch64-unknown-none".into(),
metadata: crate::spec::TargetMetadata {
description: None,
description: Some("Freestanding/bare-metal LoongArch64".into()),
tier: Some(2),
host_tools: Some(false),
std: Some(false),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub fn target() -> Target {
Target {
llvm_target: "loongarch64-unknown-none".into(),
metadata: crate::spec::TargetMetadata {
description: None,
description: Some("Freestanding/bare-metal LoongArch64 softfloat".into()),
tier: Some(2),
host_tools: Some(false),
std: Some(false),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::io::{Read, Write};
use crate::pipe::pipe;

#[test]
#[cfg(all(windows, unix, not(miri)))]
fn pipe_creation_clone_and_rw() {
let (rx, tx) = pipe().unwrap();

Expand Down
41 changes: 41 additions & 0 deletions library/std/src/sync/once.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,47 @@ impl Once {
self.inner.is_completed()
}

/// Blocks the current thread until initialization has completed.
///
/// # Example
///
/// ```rust
/// #![feature(once_wait)]
///
/// use std::sync::Once;
/// use std::thread;
///
/// static READY: Once = Once::new();
///
/// let thread = thread::spawn(|| {
/// READY.wait();
/// println!("everything is ready");
/// });
///
/// READY.call_once(|| println!("performing setup"));
/// ```
///
/// # Panics
///
/// If this [`Once`] has been poisoned because an initialization closure has
/// panicked, this method will also panic. Use [`wait_force`](Self::wait_force)
/// if this behaviour is not desired.
#[unstable(feature = "once_wait", issue = "127527")]
pub fn wait(&self) {
if !self.inner.is_completed() {
self.inner.wait(false);
}
}

/// Blocks the current thread until initialization has completed, ignoring
/// poisoning.
#[unstable(feature = "once_wait", issue = "127527")]
pub fn wait_force(&self) {
if !self.inner.is_completed() {
self.inner.wait(true);
}
}

/// Returns the current state of the `Once` instance.
///
/// Since this takes a mutable reference, no initialization can currently
Expand Down
47 changes: 47 additions & 0 deletions library/std/src/sync/once/tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use super::Once;
use crate::sync::atomic::AtomicBool;
use crate::sync::atomic::Ordering::Relaxed;
use crate::sync::mpsc::channel;
use crate::time::Duration;
use crate::{panic, thread};

#[test]
Expand Down Expand Up @@ -113,3 +116,47 @@ fn wait_for_force_to_finish() {
assert!(t1.join().is_ok());
assert!(t2.join().is_ok());
}

#[test]
fn wait() {
for _ in 0..50 {
let val = AtomicBool::new(false);
let once = Once::new();

thread::scope(|s| {
for _ in 0..4 {
s.spawn(|| {
once.wait();
assert!(val.load(Relaxed));
});
}

once.call_once(|| val.store(true, Relaxed));
});
}
}

#[test]
fn wait_on_poisoned() {
let once = Once::new();

panic::catch_unwind(|| once.call_once(|| panic!())).unwrap_err();
panic::catch_unwind(|| once.wait()).unwrap_err();
}

#[test]
fn wait_force_on_poisoned() {
let once = Once::new();

thread::scope(|s| {
panic::catch_unwind(|| once.call_once(|| panic!())).unwrap_err();

s.spawn(|| {
thread::sleep(Duration::from_millis(100));

once.call_once_force(|_| {});
});

once.wait_force();
})
}
28 changes: 28 additions & 0 deletions library/std/src/sync/once_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,34 @@ impl<T> OnceLock<T> {
}
}

/// Blocks the current thread until the cell is initialized.
///
/// # Example
///
/// Waiting for a computation on another thread to finish:
/// ```rust
/// #![feature(once_wait)]
///
/// use std::thread;
/// use std::sync::OnceLock;
///
/// let value = OnceLock::new();
///
/// thread::scope(|s| {
/// s.spawn(|| value.set(1 + 1));
///
/// let result = value.wait();
/// assert_eq!(result, &2);
/// })
/// ```
#[inline]
#[unstable(feature = "once_wait", issue = "127527")]
pub fn wait(&self) -> &T {
self.once.wait_force();

unsafe { self.get_unchecked() }
}

/// Sets the contents of this cell to `value`.
///
/// May block if another thread is currently attempting to initialize the cell. The cell is
Expand Down
14 changes: 5 additions & 9 deletions library/std/src/sys/anonymous_pipe/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
#![forbid(unsafe_op_in_unsafe_fn)]

cfg_if::cfg_if! {
if #[cfg(unix)] {
mod unix;
pub(crate) use unix::{AnonPipe, pipe};

#[cfg(all(test, not(miri)))]
mod tests;
pub use unix::{AnonPipe, pipe};
} else if #[cfg(windows)] {
mod windows;
pub(crate) use windows::{AnonPipe, pipe};

#[cfg(all(test, not(miri)))]
mod tests;
pub use windows::{AnonPipe, pipe};
} else {
mod unsupported;
pub(crate) use unsupported::{AnonPipe, pipe};
pub use unsupported::{AnonPipe, pipe};
}
}
Loading
Loading