Skip to content

Commit 71b2116

Browse files
committed
Auto merge of #128469 - matthiaskrgr:rollup-00svite, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #127567 (std: implement the `once_wait` feature) - #128162 (Cleanup sys module to match house style) - #128296 (Update target-spec metadata for loongarch64 targets) - #128443 (Properly mark loop as diverging if it has no breaks) - #128449 (Temporarily switch `ambiguous_negative_literals` lint to allow) - #128452 (derive(SmartPointer): require pointee to be maybe sized) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 28a58f2 + cf900ab commit 71b2116

26 files changed

+488
-212
lines changed

compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs

+23-27
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::mem::swap;
2-
31
use ast::ptr::P;
42
use ast::HasAttrs;
53
use rustc_ast::mut_visit::MutVisitor;
@@ -154,13 +152,28 @@ pub fn expand_deriving_smart_ptr(
154152
{
155153
let pointee = &mut impl_generics.params[pointee_param_idx];
156154
self_bounds = pointee.bounds.clone();
155+
if !contains_maybe_sized_bound(&self_bounds)
156+
&& !contains_maybe_sized_bound_on_pointee(
157+
&generics.where_clause.predicates,
158+
pointee_ty_ident.name,
159+
)
160+
{
161+
cx.dcx()
162+
.struct_span_err(
163+
pointee_ty_ident.span,
164+
format!(
165+
"`derive(SmartPointer)` requires {} to be marked `?Sized`",
166+
pointee_ty_ident.name
167+
),
168+
)
169+
.emit();
170+
return;
171+
}
157172
let arg = GenericArg::Type(s_ty.clone());
158173
let unsize = cx.path_all(span, true, path!(span, core::marker::Unsize), vec![arg]);
159174
pointee.bounds.push(cx.trait_bound(unsize, false));
160-
let mut attrs = thin_vec![];
161-
swap(&mut pointee.attrs, &mut attrs);
162175
// Drop `#[pointee]` attribute since it should not be recognized outside `derive(SmartPointer)`
163-
pointee.attrs = attrs.into_iter().filter(|attr| !attr.has_name(sym::pointee)).collect();
176+
pointee.attrs.retain(|attr| !attr.has_name(sym::pointee));
164177
}
165178

166179
// # Rewrite generic parameter bounds
@@ -169,14 +182,14 @@ pub fn expand_deriving_smart_ptr(
169182
// ```
170183
// struct<
171184
// U: Trait<T>,
172-
// #[pointee] T: Trait<T>,
185+
// #[pointee] T: Trait<T> + ?Sized,
173186
// V: Trait<T>> ...
174187
// ```
175188
// ... generates this `impl` generic parameters
176189
// ```
177190
// impl<
178191
// U: Trait<T> + Trait<__S>,
179-
// T: Trait<T> + Unsize<__S>, // (**)
192+
// T: Trait<T> + ?Sized + Unsize<__S>, // (**)
180193
// __S: Trait<__S> + ?Sized, // (*)
181194
// V: Trait<T> + Trait<__S>> ...
182195
// ```
@@ -218,23 +231,6 @@ pub fn expand_deriving_smart_ptr(
218231
//
219232
// We now insert `__S` with the missing bounds marked with (*) above.
220233
// We should also write the bounds from `#[pointee]` to `__S` as required by `Unsize<__S>`.
221-
let sized = cx.path_global(span, path!(span, core::marker::Sized));
222-
// For some reason, we are not allowed to write `?Sized` bound twice like `__S: ?Sized + ?Sized`.
223-
if !contains_maybe_sized_bound(&self_bounds)
224-
&& !contains_maybe_sized_bound_on_pointee(
225-
&generics.where_clause.predicates,
226-
pointee_ty_ident.name,
227-
)
228-
{
229-
self_bounds.push(GenericBound::Trait(
230-
cx.poly_trait_ref(span, sized),
231-
TraitBoundModifiers {
232-
polarity: ast::BoundPolarity::Maybe(span),
233-
constness: ast::BoundConstness::Never,
234-
asyncness: ast::BoundAsyncness::Normal,
235-
},
236-
));
237-
}
238234
{
239235
let mut substitution =
240236
TypeSubstitution { from_name: pointee_ty_ident.name, to_ty: &s_ty, rewritten: false };
@@ -252,7 +248,7 @@ pub fn expand_deriving_smart_ptr(
252248
// where
253249
// U: Trait<V> + Trait<T>,
254250
// Companion<T>: Trait<T>,
255-
// T: Trait<T>,
251+
// T: Trait<T> + ?Sized,
256252
// { .. }
257253
// ```
258254
// ... will have a impl prelude like so
@@ -263,8 +259,8 @@ pub fn expand_deriving_smart_ptr(
263259
// U: Trait<__S>,
264260
// Companion<T>: Trait<T>,
265261
// Companion<__S>: Trait<__S>,
266-
// T: Trait<T>,
267-
// __S: Trait<__S>,
262+
// T: Trait<T> + ?Sized,
263+
// __S: Trait<__S> + ?Sized,
268264
// ```
269265
//
270266
// We should also write a few new `where` bounds from `#[pointee] T` to `__S`

compiler/rustc_hir_typeck/src/expr.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13061306
// No way to know whether it's diverging because
13071307
// of a `break` or an outer `break` or `return`.
13081308
self.diverges.set(Diverges::Maybe);
1309+
} else {
1310+
self.diverges.set(self.diverges.get() | Diverges::always(expr.span));
13091311
}
13101312

13111313
// If we permit break with a value, then result type is

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+33-21
Original file line numberDiff line numberDiff line change
@@ -48,30 +48,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4848
/// Produces warning on the given node, if the current point in the
4949
/// function is unreachable, and there hasn't been another warning.
5050
pub(crate) fn warn_if_unreachable(&self, id: HirId, span: Span, kind: &str) {
51-
// FIXME: Combine these two 'if' expressions into one once
52-
// let chains are implemented
53-
if let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() {
54-
// If span arose from a desugaring of `if` or `while`, then it is the condition itself,
55-
// which diverges, that we are about to lint on. This gives suboptimal diagnostics.
56-
// Instead, stop here so that the `if`- or `while`-expression's block is linted instead.
57-
if !span.is_desugaring(DesugaringKind::CondTemporary)
58-
&& !span.is_desugaring(DesugaringKind::Async)
59-
&& !orig_span.is_desugaring(DesugaringKind::Await)
60-
{
61-
self.diverges.set(Diverges::WarnedAlways);
51+
// If span arose from a desugaring of `if` or `while`, then it is the condition itself,
52+
// which diverges, that we are about to lint on. This gives suboptimal diagnostics.
53+
// Instead, stop here so that the `if`- or `while`-expression's block is linted instead.
54+
if span.is_desugaring(DesugaringKind::CondTemporary) {
55+
return;
56+
}
6257

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

65-
let msg = format!("unreachable {kind}");
66-
self.tcx().node_span_lint(lint::builtin::UNREACHABLE_CODE, id, span, |lint| {
67-
lint.primary_message(msg.clone());
68-
lint.span_label(span, msg).span_label(
69-
orig_span,
70-
custom_note.unwrap_or("any code following this expression is unreachable"),
71-
);
72-
})
73-
}
64+
// Don't lint *within* the `.await` operator, since that's all just desugaring junk.
65+
// We only want to lint if there is a subsequent expression after the `.await`.
66+
if span.is_desugaring(DesugaringKind::Await) {
67+
return;
7468
}
69+
70+
let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() else {
71+
return;
72+
};
73+
74+
// Don't warn twice.
75+
self.diverges.set(Diverges::WarnedAlways);
76+
77+
debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
78+
79+
let msg = format!("unreachable {kind}");
80+
self.tcx().node_span_lint(lint::builtin::UNREACHABLE_CODE, id, span, |lint| {
81+
lint.primary_message(msg.clone());
82+
lint.span_label(span, msg).span_label(
83+
orig_span,
84+
custom_note.unwrap_or("any code following this expression is unreachable"),
85+
);
86+
})
7587
}
7688

7789
/// Resolves type and const variables in `ty` if possible. Unlike the infcx

compiler/rustc_lint/src/precedence.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ declare_lint! {
1616
/// ### Example
1717
///
1818
/// ```rust,compile_fail
19+
/// # #![deny(ambiguous_negative_literals)]
1920
/// # #![allow(unused)]
2021
/// -1i32.abs(); // equals -1, while `(-1i32).abs()` equals 1
2122
/// ```
@@ -27,7 +28,7 @@ declare_lint! {
2728
/// Method calls take precedence over unary precedence. Setting the
2829
/// precedence explicitly makes the code clearer and avoid potential bugs.
2930
pub AMBIGUOUS_NEGATIVE_LITERALS,
30-
Deny,
31+
Allow,
3132
"ambiguous negative literals operations",
3233
report_in_external_macro
3334
}

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ pub fn target() -> Target {
44
Target {
55
llvm_target: "loongarch64-unknown-linux-musl".into(),
66
metadata: crate::spec::TargetMetadata {
7-
description: Some("LoongArch64 Linux (LP64D ABI) with musl 1.2.3".into()),
8-
tier: Some(3),
9-
host_tools: Some(false),
10-
std: None, // ?
7+
description: Some("LoongArch64 Linux (LP64D ABI) with musl 1.2.5".into()),
8+
tier: Some(2),
9+
host_tools: Some(true),
10+
std: Some(true),
1111
},
1212
pointer_width: 64,
1313
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub fn target() -> Target {
66
Target {
77
llvm_target: "loongarch64-unknown-none".into(),
88
metadata: crate::spec::TargetMetadata {
9-
description: None,
9+
description: Some("Freestanding/bare-metal LoongArch64".into()),
1010
tier: Some(2),
1111
host_tools: Some(false),
1212
std: Some(false),

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub fn target() -> Target {
66
Target {
77
llvm_target: "loongarch64-unknown-none".into(),
88
metadata: crate::spec::TargetMetadata {
9-
description: None,
9+
description: Some("Freestanding/bare-metal LoongArch64 softfloat".into()),
1010
tier: Some(2),
1111
host_tools: Some(false),
1212
std: Some(false),

library/std/src/sys/anonymous_pipe/tests.rs library/std/src/pipe/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::io::{Read, Write};
22
use crate::pipe::pipe;
33

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

library/std/src/sync/once.rs

+41
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,47 @@ impl Once {
264264
self.inner.is_completed()
265265
}
266266

267+
/// Blocks the current thread until initialization has completed.
268+
///
269+
/// # Example
270+
///
271+
/// ```rust
272+
/// #![feature(once_wait)]
273+
///
274+
/// use std::sync::Once;
275+
/// use std::thread;
276+
///
277+
/// static READY: Once = Once::new();
278+
///
279+
/// let thread = thread::spawn(|| {
280+
/// READY.wait();
281+
/// println!("everything is ready");
282+
/// });
283+
///
284+
/// READY.call_once(|| println!("performing setup"));
285+
/// ```
286+
///
287+
/// # Panics
288+
///
289+
/// If this [`Once`] has been poisoned because an initialization closure has
290+
/// panicked, this method will also panic. Use [`wait_force`](Self::wait_force)
291+
/// if this behaviour is not desired.
292+
#[unstable(feature = "once_wait", issue = "127527")]
293+
pub fn wait(&self) {
294+
if !self.inner.is_completed() {
295+
self.inner.wait(false);
296+
}
297+
}
298+
299+
/// Blocks the current thread until initialization has completed, ignoring
300+
/// poisoning.
301+
#[unstable(feature = "once_wait", issue = "127527")]
302+
pub fn wait_force(&self) {
303+
if !self.inner.is_completed() {
304+
self.inner.wait(true);
305+
}
306+
}
307+
267308
/// Returns the current state of the `Once` instance.
268309
///
269310
/// Since this takes a mutable reference, no initialization can currently

library/std/src/sync/once/tests.rs

+47
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use super::Once;
2+
use crate::sync::atomic::AtomicBool;
3+
use crate::sync::atomic::Ordering::Relaxed;
24
use crate::sync::mpsc::channel;
5+
use crate::time::Duration;
36
use crate::{panic, thread};
47

58
#[test]
@@ -113,3 +116,47 @@ fn wait_for_force_to_finish() {
113116
assert!(t1.join().is_ok());
114117
assert!(t2.join().is_ok());
115118
}
119+
120+
#[test]
121+
fn wait() {
122+
for _ in 0..50 {
123+
let val = AtomicBool::new(false);
124+
let once = Once::new();
125+
126+
thread::scope(|s| {
127+
for _ in 0..4 {
128+
s.spawn(|| {
129+
once.wait();
130+
assert!(val.load(Relaxed));
131+
});
132+
}
133+
134+
once.call_once(|| val.store(true, Relaxed));
135+
});
136+
}
137+
}
138+
139+
#[test]
140+
fn wait_on_poisoned() {
141+
let once = Once::new();
142+
143+
panic::catch_unwind(|| once.call_once(|| panic!())).unwrap_err();
144+
panic::catch_unwind(|| once.wait()).unwrap_err();
145+
}
146+
147+
#[test]
148+
fn wait_force_on_poisoned() {
149+
let once = Once::new();
150+
151+
thread::scope(|s| {
152+
panic::catch_unwind(|| once.call_once(|| panic!())).unwrap_err();
153+
154+
s.spawn(|| {
155+
thread::sleep(Duration::from_millis(100));
156+
157+
once.call_once_force(|_| {});
158+
});
159+
160+
once.wait_force();
161+
})
162+
}

library/std/src/sync/once_lock.rs

+28
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,34 @@ impl<T> OnceLock<T> {
167167
}
168168
}
169169

170+
/// Blocks the current thread until the cell is initialized.
171+
///
172+
/// # Example
173+
///
174+
/// Waiting for a computation on another thread to finish:
175+
/// ```rust
176+
/// #![feature(once_wait)]
177+
///
178+
/// use std::thread;
179+
/// use std::sync::OnceLock;
180+
///
181+
/// let value = OnceLock::new();
182+
///
183+
/// thread::scope(|s| {
184+
/// s.spawn(|| value.set(1 + 1));
185+
///
186+
/// let result = value.wait();
187+
/// assert_eq!(result, &2);
188+
/// })
189+
/// ```
190+
#[inline]
191+
#[unstable(feature = "once_wait", issue = "127527")]
192+
pub fn wait(&self) -> &T {
193+
self.once.wait_force();
194+
195+
unsafe { self.get_unchecked() }
196+
}
197+
170198
/// Sets the contents of this cell to `value`.
171199
///
172200
/// May block if another thread is currently attempting to initialize the cell. The cell is
+5-9
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
1+
#![forbid(unsafe_op_in_unsafe_fn)]
2+
13
cfg_if::cfg_if! {
24
if #[cfg(unix)] {
35
mod unix;
4-
pub(crate) use unix::{AnonPipe, pipe};
5-
6-
#[cfg(all(test, not(miri)))]
7-
mod tests;
6+
pub use unix::{AnonPipe, pipe};
87
} else if #[cfg(windows)] {
98
mod windows;
10-
pub(crate) use windows::{AnonPipe, pipe};
11-
12-
#[cfg(all(test, not(miri)))]
13-
mod tests;
9+
pub use windows::{AnonPipe, pipe};
1410
} else {
1511
mod unsupported;
16-
pub(crate) use unsupported::{AnonPipe, pipe};
12+
pub use unsupported::{AnonPipe, pipe};
1713
}
1814
}

0 commit comments

Comments
 (0)