Skip to content

Commit ca1e68b

Browse files
committed
Auto merge of rust-lang#98730 - matthiaskrgr:rollup-2c4d4x5, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - rust-lang#97629 ([core] add `Exclusive` to sync) - rust-lang#98503 (fix data race in thread::scope) - rust-lang#98670 (llvm-wrapper: adapt for LLVMConstExtractValue removal) - rust-lang#98671 (Fix source sidebar bugs) - rust-lang#98677 (For diagnostic information of Boolean, remind it as use the type: 'bool') - rust-lang#98684 (add test for 72793) - rust-lang#98688 (interpret: add From<&MplaceTy> for PlaceTy) - rust-lang#98695 (use "or pattern") - rust-lang#98709 (Remove unneeded methods declaration for old web browsers) - rust-lang#98717 (get rid of tidy 'unnecessarily ignored' warnings) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 7e2733b + 6e918b4 commit ca1e68b

File tree

26 files changed

+364
-79
lines changed

26 files changed

+364
-79
lines changed

compiler/rustc_codegen_llvm/src/common.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,7 @@ impl<'ll> CodegenCx<'ll, '_> {
109109
pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
110110
unsafe {
111111
assert_eq!(idx as c_uint as u64, idx);
112-
let us = &[idx as c_uint];
113-
let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
112+
let r = llvm::LLVMGetAggregateElement(v, idx as c_uint).unwrap();
114113

115114
debug!("const_get_elt(v={:?}, idx={}, r={:?})", v, idx, r);
116115

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -1134,11 +1134,7 @@ extern "C" {
11341134
pub fn LLVMConstIntToPtr<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
11351135
pub fn LLVMConstBitCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
11361136
pub fn LLVMConstPointerCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
1137-
pub fn LLVMConstExtractValue(
1138-
AggConstant: &Value,
1139-
IdxList: *const c_uint,
1140-
NumIdx: c_uint,
1141-
) -> &Value;
1137+
pub fn LLVMGetAggregateElement(ConstantVal: &Value, Idx: c_uint) -> Option<&Value>;
11421138

11431139
// Operations on global variables, functions, and aliases (globals)
11441140
pub fn LLVMIsDeclaration(Global: &Value) -> Bool;

compiler/rustc_const_eval/src/const_eval/valtrees.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ fn valtree_into_mplace<'tcx>(
346346
ty::FnDef(_, _) => {
347347
ecx.write_immediate(
348348
Immediate::Scalar(ScalarMaybeUninit::Scalar(Scalar::ZST)),
349-
&(*place).into(),
349+
&place.into(),
350350
)
351351
.unwrap();
352352
}
@@ -355,7 +355,7 @@ fn valtree_into_mplace<'tcx>(
355355
debug!("writing trivial valtree {:?} to place {:?}", scalar_int, place);
356356
ecx.write_immediate(
357357
Immediate::Scalar(ScalarMaybeUninit::Scalar(scalar_int.into())),
358-
&(*place).into(),
358+
&place.into(),
359359
)
360360
.unwrap();
361361
}
@@ -382,7 +382,7 @@ fn valtree_into_mplace<'tcx>(
382382
};
383383
debug!(?imm);
384384

385-
ecx.write_immediate(imm, &(*place).into()).unwrap();
385+
ecx.write_immediate(imm, &place.into()).unwrap();
386386
}
387387
ty::Adt(_, _) | ty::Tuple(_) | ty::Array(_, _) | ty::Str | ty::Slice(_) => {
388388
let branches = valtree.unwrap_branch();
@@ -464,11 +464,11 @@ fn valtree_into_mplace<'tcx>(
464464

465465
if let Some(variant_idx) = variant_idx {
466466
// don't forget filling the place with the discriminant of the enum
467-
ecx.write_discriminant(variant_idx, &(*place).into()).unwrap();
467+
ecx.write_discriminant(variant_idx, &place.into()).unwrap();
468468
}
469469

470470
debug!("dump of place after writing discriminant:");
471-
dump_place(ecx, (*place).into());
471+
dump_place(ecx, place.into());
472472
}
473473
_ => bug!("shouldn't have created a ValTree for {:?}", ty),
474474
}

compiler/rustc_const_eval/src/interpret/intern.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
195195
let tcx = self.ecx.tcx;
196196
let ty = mplace.layout.ty;
197197
if let ty::Ref(_, referenced_ty, ref_mutability) = *ty.kind() {
198-
let value = self.ecx.read_immediate(&(*mplace).into())?;
198+
let value = self.ecx.read_immediate(&mplace.into())?;
199199
let mplace = self.ecx.ref_to_mplace(&value)?;
200200
assert_eq!(mplace.layout.ty, referenced_ty);
201201
// Handle trait object vtables.

compiler/rustc_const_eval/src/interpret/operand.rs

+7
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,13 @@ impl<'tcx, Tag: Provenance> From<&'_ MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
204204
}
205205
}
206206

207+
impl<'tcx, Tag: Provenance> From<&'_ mut MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
208+
#[inline(always)]
209+
fn from(mplace: &mut MPlaceTy<'tcx, Tag>) -> Self {
210+
OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout }
211+
}
212+
}
213+
207214
impl<'tcx, Tag: Provenance> From<ImmTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
208215
#[inline(always)]
209216
fn from(val: ImmTy<'tcx, Tag>) -> Self {

compiler/rustc_const_eval/src/interpret/place.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,21 @@ impl<'tcx, Tag: Provenance> std::ops::Deref for MPlaceTy<'tcx, Tag> {
118118
impl<'tcx, Tag: Provenance> From<MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> {
119119
#[inline(always)]
120120
fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self {
121-
PlaceTy { place: Place::Ptr(mplace.mplace), layout: mplace.layout }
121+
PlaceTy { place: Place::Ptr(*mplace), layout: mplace.layout }
122+
}
123+
}
124+
125+
impl<'tcx, Tag: Provenance> From<&'_ MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> {
126+
#[inline(always)]
127+
fn from(mplace: &MPlaceTy<'tcx, Tag>) -> Self {
128+
PlaceTy { place: Place::Ptr(**mplace), layout: mplace.layout }
129+
}
130+
}
131+
132+
impl<'tcx, Tag: Provenance> From<&'_ mut MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> {
133+
#[inline(always)]
134+
fn from(mplace: &mut MPlaceTy<'tcx, Tag>) -> Self {
135+
PlaceTy { place: Place::Ptr(**mplace), layout: mplace.layout }
122136
}
123137
}
124138

compiler/rustc_const_eval/src/interpret/visitor.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M>
9292
&self,
9393
_ecx: &InterpCx<'mir, 'tcx, M>,
9494
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
95-
Ok((*self).into())
95+
Ok(self.into())
9696
}
9797

9898
#[inline(always)]

compiler/rustc_errors/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,7 @@ impl HandlerInner {
14471447
self.flags.treat_err_as_bug.map(|c| c.get()).unwrap_or(0),
14481448
) {
14491449
(1, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"),
1450-
(0, _) | (1, _) => {}
1450+
(0 | 1, _) => {}
14511451
(count, as_bug) => panic!(
14521452
"aborting after {} errors due to `-Z treat-err-as-bug={}`",
14531453
count, as_bug,

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -1865,3 +1865,11 @@ extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
18651865
GlobalValue *GV = unwrap<GlobalValue>(V);
18661866
Mangler().getNameWithPrefix(OS, GV, true);
18671867
}
1868+
1869+
// LLVMGetAggregateElement was added in LLVM 15. For earlier LLVM versions just
1870+
// use its implementation.
1871+
#if LLVM_VERSION_LT(15, 0)
1872+
extern "C" LLVMValueRef LLVMGetAggregateElement(LLVMValueRef C, unsigned Idx) {
1873+
return wrap(unwrap<Constant>(C)->getAggregateElement(Idx));
1874+
}
1875+
#endif

compiler/rustc_resolve/src/late/diagnostics.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1503,6 +1503,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
15031503
Some(match name {
15041504
"byte" => sym::u8, // In Java, bytes are signed, but in practice one almost always wants unsigned bytes.
15051505
"short" => sym::i16,
1506+
"Bool" => sym::bool,
1507+
"Boolean" => sym::bool,
15061508
"boolean" => sym::bool,
15071509
"int" => sym::i32,
15081510
"long" => sym::i64,

library/core/src/sync/exclusive.rs

+173
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
//! Defines [`Exclusive`].
2+
3+
use core::fmt;
4+
use core::future::Future;
5+
use core::pin::Pin;
6+
use core::task::{Context, Poll};
7+
8+
/// `Exclusive` provides only _mutable_ access, also referred to as _exclusive_
9+
/// access to the underlying value. It provides no _immutable_, or _shared_
10+
/// access to the underlying value.
11+
///
12+
/// While this may seem not very useful, it allows `Exclusive` to _unconditionally_
13+
/// implement [`Sync`]. Indeed, the safety requirements of `Sync` state that for `Exclusive`
14+
/// to be `Sync`, it must be sound to _share_ across threads, that is, it must be sound
15+
/// for `&Exclusive` to cross thread boundaries. By design, a `&Exclusive` has no API
16+
/// whatsoever, making it useless, thus harmless, thus memory safe.
17+
///
18+
/// Certain constructs like [`Future`]s can only be used with _exclusive_ access,
19+
/// and are often `Send` but not `Sync`, so `Exclusive` can be used as hint to the
20+
/// rust compiler that something is `Sync` in practice.
21+
///
22+
/// ## Examples
23+
/// Using a non-`Sync` future prevents the wrapping struct from being `Sync`
24+
/// ```compile_fail
25+
/// use core::cell::Cell;
26+
///
27+
/// async fn other() {}
28+
/// fn assert_sync<T: Sync>(t: T) {}
29+
/// struct State<F> {
30+
/// future: F
31+
/// }
32+
///
33+
/// assert_sync(State {
34+
/// future: async {
35+
/// let cell = Cell::new(1);
36+
/// let cell_ref = &cell;
37+
/// other().await;
38+
/// let value = cell_ref.get();
39+
/// }
40+
/// });
41+
/// ```
42+
///
43+
/// `Exclusive` ensures the struct is `Sync` without stripping the future of its
44+
/// functionality.
45+
/// ```
46+
/// #![feature(exclusive_wrapper)]
47+
/// use core::cell::Cell;
48+
/// use core::sync::Exclusive;
49+
///
50+
/// async fn other() {}
51+
/// fn assert_sync<T: Sync>(t: T) {}
52+
/// struct State<F> {
53+
/// future: Exclusive<F>
54+
/// }
55+
///
56+
/// assert_sync(State {
57+
/// future: Exclusive::new(async {
58+
/// let cell = Cell::new(1);
59+
/// let cell_ref = &cell;
60+
/// other().await;
61+
/// let value = cell_ref.get();
62+
/// })
63+
/// });
64+
/// ```
65+
///
66+
/// ## Parallels with a mutex
67+
/// In some sense, `Exclusive` can be thought of as a _compile-time_ version of
68+
/// a mutex, as the borrow-checker guarantees that only one `&mut` can exist
69+
/// for any value. This is a parallel with the fact that
70+
/// `&` and `&mut` references together can be thought of as a _compile-time_
71+
/// version of a read-write lock.
72+
///
73+
///
74+
/// [`Sync`]: core::marker::Sync
75+
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
76+
#[doc(alias = "SyncWrapper")]
77+
#[doc(alias = "SyncCell")]
78+
#[doc(alias = "Unique")]
79+
// `Exclusive` can't have `PartialOrd`, `Clone`, etc. impls as they would
80+
// use `&` access to the inner value, violating the `Sync` impl's safety
81+
// requirements.
82+
#[derive(Default)]
83+
#[repr(transparent)]
84+
pub struct Exclusive<T: ?Sized> {
85+
inner: T,
86+
}
87+
88+
// See `Exclusive`'s docs for justification.
89+
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
90+
unsafe impl<T: ?Sized> Sync for Exclusive<T> {}
91+
92+
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
93+
impl<T: ?Sized> fmt::Debug for Exclusive<T> {
94+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
95+
f.debug_struct("Exclusive").finish_non_exhaustive()
96+
}
97+
}
98+
99+
impl<T: Sized> Exclusive<T> {
100+
/// Wrap a value in an `Exclusive`
101+
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
102+
#[must_use]
103+
pub const fn new(t: T) -> Self {
104+
Self { inner: t }
105+
}
106+
107+
/// Unwrap the value contained in the `Exclusive`
108+
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
109+
#[must_use]
110+
pub const fn into_inner(self) -> T {
111+
self.inner
112+
}
113+
}
114+
115+
impl<T: ?Sized> Exclusive<T> {
116+
/// Get exclusive access to the underlying value.
117+
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
118+
#[must_use]
119+
pub const fn get_mut(&mut self) -> &mut T {
120+
&mut self.inner
121+
}
122+
123+
/// Get pinned exclusive access to the underlying value.
124+
///
125+
/// `Exclusive` is considered to _structurally pin_ the underlying
126+
/// value, which means _unpinned_ `Exclusive`s can produce _unpinned_
127+
/// access to the underlying value, but _pinned_ `Exclusive`s only
128+
/// produce _pinned_ access to the underlying value.
129+
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
130+
#[must_use]
131+
pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
132+
// SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned
133+
// `Pin::map_unchecked_mut` is not const, so we do this conversion manually
134+
unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
135+
}
136+
137+
/// Build a _mutable_ references to an `Exclusive<T>` from
138+
/// a _mutable_ reference to a `T`. This allows you to skip
139+
/// building an `Exclusive` with [`Exclusive::new`].
140+
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
141+
#[must_use]
142+
pub const fn from_mut(r: &'_ mut T) -> &'_ mut Exclusive<T> {
143+
// SAFETY: repr is ≥ C, so refs have the same layout; and `Exclusive` properties are `&mut`-agnostic
144+
unsafe { &mut *(r as *mut T as *mut Exclusive<T>) }
145+
}
146+
147+
/// Build a _pinned mutable_ references to an `Exclusive<T>` from
148+
/// a _pinned mutable_ reference to a `T`. This allows you to skip
149+
/// building an `Exclusive` with [`Exclusive::new`].
150+
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
151+
#[must_use]
152+
pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut Exclusive<T>> {
153+
// SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned
154+
// `Pin::map_unchecked_mut` is not const, so we do this conversion manually
155+
unsafe { Pin::new_unchecked(Self::from_mut(r.get_unchecked_mut())) }
156+
}
157+
}
158+
159+
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
160+
impl<T> From<T> for Exclusive<T> {
161+
fn from(t: T) -> Self {
162+
Self::new(t)
163+
}
164+
}
165+
166+
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
167+
impl<T: Future + ?Sized> Future for Exclusive<T> {
168+
type Output = T::Output;
169+
170+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
171+
self.get_pin_mut().poll(cx)
172+
}
173+
}

library/core/src/sync/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
#![stable(feature = "rust1", since = "1.0.0")]
44

55
pub mod atomic;
6+
mod exclusive;
7+
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
8+
pub use exclusive::Exclusive;

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@
270270
#![feature(duration_checked_float)]
271271
#![feature(duration_constants)]
272272
#![feature(exact_size_is_empty)]
273+
#![feature(exclusive_wrapper)]
273274
#![feature(extend_one)]
274275
#![feature(float_minimum_maximum)]
275276
#![feature(hasher_prefixfree_extras)]

library/std/src/sync/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@
155155
pub use alloc_crate::sync::{Arc, Weak};
156156
#[stable(feature = "rust1", since = "1.0.0")]
157157
pub use core::sync::atomic;
158+
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
159+
pub use core::sync::Exclusive;
158160

159161
#[stable(feature = "rust1", since = "1.0.0")]
160162
pub use self::barrier::{Barrier, BarrierWaitResult};

0 commit comments

Comments
 (0)