Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c3c1757

Browse files
committedJun 14, 2024
Auto merge of rust-lang#126473 - matthiaskrgr:rollup-8w2xm09, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#123769 (Improve escaping of byte, byte str, and c str proc-macro literals) - rust-lang#126054 (`E0229`: Suggest Moving Type Constraints to Type Parameter Declaration) - rust-lang#126135 (add HermitOS support for vectored read/write operations) - rust-lang#126266 (Unify guarantees about the default allocator) - rust-lang#126285 (`UniqueRc`: support allocators and `T: ?Sized`.) - rust-lang#126399 (extend the check for LLVM build) - rust-lang#126426 (const validation: fix ICE on dangling ZST reference) r? `@ghost` `@rustbot` modify labels: rollup
2 parents ca52a2c + a135342 commit c3c1757

File tree

16 files changed

+369
-137
lines changed

16 files changed

+369
-137
lines changed
 

‎alloc/src/rc.rs

+65-30
Original file line numberDiff line numberDiff line change
@@ -3516,7 +3516,7 @@ fn data_offset_align(align: usize) -> usize {
35163516
layout.size() + layout.padding_needed_for(align)
35173517
}
35183518

3519-
/// A uniquely owned `Rc`
3519+
/// A uniquely owned [`Rc`].
35203520
///
35213521
/// This represents an `Rc` that is known to be uniquely owned -- that is, have exactly one strong
35223522
/// reference. Multiple weak pointers can be created, but attempts to upgrade those to strong
@@ -3554,13 +3554,24 @@ fn data_offset_align(align: usize) -> usize {
35543554
/// including fallible or async constructors.
35553555
#[unstable(feature = "unique_rc_arc", issue = "112566")]
35563556
#[derive(Debug)]
3557-
pub struct UniqueRc<T> {
3557+
pub struct UniqueRc<
3558+
T: ?Sized,
3559+
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
3560+
> {
35583561
ptr: NonNull<RcBox<T>>,
35593562
phantom: PhantomData<RcBox<T>>,
3563+
alloc: A,
35603564
}
35613565

3566+
#[unstable(feature = "unique_rc_arc", issue = "112566")]
3567+
impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<UniqueRc<U, A>>
3568+
for UniqueRc<T, A>
3569+
{
3570+
}
3571+
3572+
// Depends on A = Global
35623573
impl<T> UniqueRc<T> {
3563-
/// Creates a new `UniqueRc`
3574+
/// Creates a new `UniqueRc`.
35643575
///
35653576
/// Weak references to this `UniqueRc` can be created with [`UniqueRc::downgrade`]. Upgrading
35663577
/// these weak references will fail before the `UniqueRc` has been converted into an [`Rc`].
@@ -3569,54 +3580,78 @@ impl<T> UniqueRc<T> {
35693580
#[cfg(not(no_global_oom_handling))]
35703581
#[unstable(feature = "unique_rc_arc", issue = "112566")]
35713582
pub fn new(value: T) -> Self {
3572-
Self {
3573-
ptr: Box::leak(Box::new(RcBox {
3583+
Self::new_in(value, Global)
3584+
}
3585+
}
3586+
3587+
impl<T, A: Allocator> UniqueRc<T, A> {
3588+
/// Creates a new `UniqueRc` in the provided allocator.
3589+
///
3590+
/// Weak references to this `UniqueRc` can be created with [`UniqueRc::downgrade`]. Upgrading
3591+
/// these weak references will fail before the `UniqueRc` has been converted into an [`Rc`].
3592+
/// After converting the `UniqueRc` into an [`Rc`], any weak references created beforehand will
3593+
/// point to the new [`Rc`].
3594+
#[cfg(not(no_global_oom_handling))]
3595+
#[unstable(feature = "unique_rc_arc", issue = "112566")]
3596+
pub fn new_in(value: T, alloc: A) -> Self {
3597+
let (ptr, alloc) = Box::into_unique(Box::new_in(
3598+
RcBox {
35743599
strong: Cell::new(0),
35753600
// keep one weak reference so if all the weak pointers that are created are dropped
35763601
// the UniqueRc still stays valid.
35773602
weak: Cell::new(1),
35783603
value,
3579-
}))
3580-
.into(),
3581-
phantom: PhantomData,
3582-
}
3583-
}
3584-
3585-
/// Creates a new weak reference to the `UniqueRc`
3586-
///
3587-
/// Attempting to upgrade this weak reference will fail before the `UniqueRc` has been converted
3588-
/// to a [`Rc`] using [`UniqueRc::into_rc`].
3589-
#[unstable(feature = "unique_rc_arc", issue = "112566")]
3590-
pub fn downgrade(this: &Self) -> Weak<T> {
3591-
// SAFETY: This pointer was allocated at creation time and we guarantee that we only have
3592-
// one strong reference before converting to a regular Rc.
3593-
unsafe {
3594-
this.ptr.as_ref().inc_weak();
3595-
}
3596-
Weak { ptr: this.ptr, alloc: Global }
3604+
},
3605+
alloc,
3606+
));
3607+
Self { ptr: ptr.into(), phantom: PhantomData, alloc }
35973608
}
3609+
}
35983610

3599-
/// Converts the `UniqueRc` into a regular [`Rc`]
3611+
impl<T: ?Sized, A: Allocator> UniqueRc<T, A> {
3612+
/// Converts the `UniqueRc` into a regular [`Rc`].
36003613
///
36013614
/// This consumes the `UniqueRc` and returns a regular [`Rc`] that contains the `value` that
36023615
/// is passed to `into_rc`.
36033616
///
36043617
/// Any weak references created before this method is called can now be upgraded to strong
36053618
/// references.
36063619
#[unstable(feature = "unique_rc_arc", issue = "112566")]
3607-
pub fn into_rc(this: Self) -> Rc<T> {
3620+
pub fn into_rc(this: Self) -> Rc<T, A> {
36083621
let mut this = ManuallyDrop::new(this);
3622+
3623+
// Move the allocator out.
3624+
// SAFETY: `this.alloc` will not be accessed again, nor dropped because it is in
3625+
// a `ManuallyDrop`.
3626+
let alloc: A = unsafe { ptr::read(&this.alloc) };
3627+
36093628
// SAFETY: This pointer was allocated at creation time so we know it is valid.
36103629
unsafe {
36113630
// Convert our weak reference into a strong reference
36123631
this.ptr.as_mut().strong.set(1);
3613-
Rc::from_inner(this.ptr)
3632+
Rc::from_inner_in(this.ptr, alloc)
3633+
}
3634+
}
3635+
}
3636+
3637+
impl<T: ?Sized, A: Allocator + Clone> UniqueRc<T, A> {
3638+
/// Creates a new weak reference to the `UniqueRc`.
3639+
///
3640+
/// Attempting to upgrade this weak reference will fail before the `UniqueRc` has been converted
3641+
/// to a [`Rc`] using [`UniqueRc::into_rc`].
3642+
#[unstable(feature = "unique_rc_arc", issue = "112566")]
3643+
pub fn downgrade(this: &Self) -> Weak<T, A> {
3644+
// SAFETY: This pointer was allocated at creation time and we guarantee that we only have
3645+
// one strong reference before converting to a regular Rc.
3646+
unsafe {
3647+
this.ptr.as_ref().inc_weak();
36143648
}
3649+
Weak { ptr: this.ptr, alloc: this.alloc.clone() }
36153650
}
36163651
}
36173652

36183653
#[unstable(feature = "unique_rc_arc", issue = "112566")]
3619-
impl<T> Deref for UniqueRc<T> {
3654+
impl<T: ?Sized, A: Allocator> Deref for UniqueRc<T, A> {
36203655
type Target = T;
36213656

36223657
fn deref(&self) -> &T {
@@ -3626,7 +3661,7 @@ impl<T> Deref for UniqueRc<T> {
36263661
}
36273662

36283663
#[unstable(feature = "unique_rc_arc", issue = "112566")]
3629-
impl<T> DerefMut for UniqueRc<T> {
3664+
impl<T: ?Sized, A: Allocator> DerefMut for UniqueRc<T, A> {
36303665
fn deref_mut(&mut self) -> &mut T {
36313666
// SAFETY: This pointer was allocated at creation time so we know it is valid. We know we
36323667
// have unique ownership and therefore it's safe to make a mutable reference because
@@ -3636,7 +3671,7 @@ impl<T> DerefMut for UniqueRc<T> {
36363671
}
36373672

36383673
#[unstable(feature = "unique_rc_arc", issue = "112566")]
3639-
unsafe impl<#[may_dangle] T> Drop for UniqueRc<T> {
3674+
unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueRc<T, A> {
36403675
fn drop(&mut self) {
36413676
unsafe {
36423677
// destroy the contained object
@@ -3646,7 +3681,7 @@ unsafe impl<#[may_dangle] T> Drop for UniqueRc<T> {
36463681
self.ptr.as_ref().dec_weak();
36473682

36483683
if self.ptr.as_ref().weak() == 0 {
3649-
Global.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr()));
3684+
self.alloc.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr()));
36503685
}
36513686
}
36523687
}

‎alloc/src/rc/tests.rs

+26
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,23 @@ fn test_unique_rc_drops_contents() {
606606
assert!(dropped);
607607
}
608608

609+
/// Exercise the non-default allocator usage.
610+
#[test]
611+
fn test_unique_rc_with_alloc_drops_contents() {
612+
let mut dropped = false;
613+
struct DropMe<'a>(&'a mut bool);
614+
impl Drop for DropMe<'_> {
615+
fn drop(&mut self) {
616+
*self.0 = true;
617+
}
618+
}
619+
{
620+
let rc = UniqueRc::new_in(DropMe(&mut dropped), std::alloc::System);
621+
drop(rc);
622+
}
623+
assert!(dropped);
624+
}
625+
609626
#[test]
610627
fn test_unique_rc_weak_clone_holding_ref() {
611628
let mut v = UniqueRc::new(0u8);
@@ -614,3 +631,12 @@ fn test_unique_rc_weak_clone_holding_ref() {
614631
let _ = w.clone(); // touch weak count
615632
*r = 123;
616633
}
634+
635+
#[test]
636+
fn test_unique_rc_unsizing_coercion() {
637+
let mut rc: UniqueRc<[u8]> = UniqueRc::new([0u8; 3]);
638+
assert_eq!(rc.len(), 3);
639+
rc[0] = 123;
640+
let rc: Rc<[u8]> = UniqueRc::into_rc(rc);
641+
assert_eq!(*rc, [123, 0, 0]);
642+
}

‎proc_macro/src/escape.rs

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#[derive(Copy, Clone)]
2+
pub(crate) struct EscapeOptions {
3+
/// Produce \'.
4+
pub escape_single_quote: bool,
5+
/// Produce \".
6+
pub escape_double_quote: bool,
7+
/// Produce \x escapes for non-ASCII, and use \x rather than \u for ASCII
8+
/// control characters.
9+
pub escape_nonascii: bool,
10+
}
11+
12+
pub(crate) fn escape_bytes(bytes: &[u8], opt: EscapeOptions) -> String {
13+
let mut repr = String::new();
14+
15+
if opt.escape_nonascii {
16+
for &byte in bytes {
17+
escape_single_byte(byte, opt, &mut repr);
18+
}
19+
} else {
20+
let mut chunks = bytes.utf8_chunks();
21+
while let Some(chunk) = chunks.next() {
22+
for ch in chunk.valid().chars() {
23+
escape_single_char(ch, opt, &mut repr);
24+
}
25+
for &byte in chunk.invalid() {
26+
escape_single_byte(byte, opt, &mut repr);
27+
}
28+
}
29+
}
30+
31+
repr
32+
}
33+
34+
fn escape_single_byte(byte: u8, opt: EscapeOptions, repr: &mut String) {
35+
if byte == b'\0' {
36+
repr.push_str("\\0");
37+
} else if (byte == b'\'' && !opt.escape_single_quote)
38+
|| (byte == b'"' && !opt.escape_double_quote)
39+
{
40+
repr.push(byte as char);
41+
} else {
42+
// Escapes \t, \r, \n, \\, \', \", and uses \x## for non-ASCII and
43+
// for ASCII control characters.
44+
repr.extend(byte.escape_ascii().map(char::from));
45+
}
46+
}
47+
48+
fn escape_single_char(ch: char, opt: EscapeOptions, repr: &mut String) {
49+
if (ch == '\'' && !opt.escape_single_quote) || (ch == '"' && !opt.escape_double_quote) {
50+
repr.push(ch);
51+
} else {
52+
// Escapes \0, \t, \r, \n, \\, \', \", and uses \u{...} for
53+
// non-printable characters and for Grapheme_Extend characters, which
54+
// includes things like U+0300 "Combining Grave Accent".
55+
repr.extend(ch.escape_debug());
56+
}
57+
}

‎proc_macro/src/lib.rs

+37-14
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@
4343
pub mod bridge;
4444

4545
mod diagnostic;
46+
mod escape;
4647

4748
#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
4849
pub use diagnostic::{Diagnostic, Level, MultiSpan};
4950

51+
use crate::escape::{escape_bytes, EscapeOptions};
5052
use std::ffi::CStr;
5153
use std::ops::{Range, RangeBounds};
5254
use std::path::PathBuf;
@@ -1356,40 +1358,61 @@ impl Literal {
13561358
/// String literal.
13571359
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
13581360
pub fn string(string: &str) -> Literal {
1359-
let quoted = format!("{:?}", string);
1360-
assert!(quoted.starts_with('"') && quoted.ends_with('"'));
1361-
let symbol = &quoted[1..quoted.len() - 1];
1362-
Literal::new(bridge::LitKind::Str, symbol, None)
1361+
let escape = EscapeOptions {
1362+
escape_single_quote: false,
1363+
escape_double_quote: true,
1364+
escape_nonascii: false,
1365+
};
1366+
let repr = escape_bytes(string.as_bytes(), escape);
1367+
Literal::new(bridge::LitKind::Str, &repr, None)
13631368
}
13641369

13651370
/// Character literal.
13661371
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
13671372
pub fn character(ch: char) -> Literal {
1368-
let quoted = format!("{:?}", ch);
1369-
assert!(quoted.starts_with('\'') && quoted.ends_with('\''));
1370-
let symbol = &quoted[1..quoted.len() - 1];
1371-
Literal::new(bridge::LitKind::Char, symbol, None)
1373+
let escape = EscapeOptions {
1374+
escape_single_quote: true,
1375+
escape_double_quote: false,
1376+
escape_nonascii: false,
1377+
};
1378+
let repr = escape_bytes(ch.encode_utf8(&mut [0u8; 4]).as_bytes(), escape);
1379+
Literal::new(bridge::LitKind::Char, &repr, None)
13721380
}
13731381

13741382
/// Byte character literal.
13751383
#[stable(feature = "proc_macro_byte_character", since = "1.79.0")]
13761384
pub fn byte_character(byte: u8) -> Literal {
1377-
let string = [byte].escape_ascii().to_string();
1378-
Literal::new(bridge::LitKind::Byte, &string, None)
1385+
let escape = EscapeOptions {
1386+
escape_single_quote: true,
1387+
escape_double_quote: false,
1388+
escape_nonascii: true,
1389+
};
1390+
let repr = escape_bytes(&[byte], escape);
1391+
Literal::new(bridge::LitKind::Byte, &repr, None)
13791392
}
13801393

13811394
/// Byte string literal.
13821395
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
13831396
pub fn byte_string(bytes: &[u8]) -> Literal {
1384-
let string = bytes.escape_ascii().to_string();
1385-
Literal::new(bridge::LitKind::ByteStr, &string, None)
1397+
let escape = EscapeOptions {
1398+
escape_single_quote: false,
1399+
escape_double_quote: true,
1400+
escape_nonascii: true,
1401+
};
1402+
let repr = escape_bytes(bytes, escape);
1403+
Literal::new(bridge::LitKind::ByteStr, &repr, None)
13861404
}
13871405

13881406
/// C string literal.
13891407
#[stable(feature = "proc_macro_c_str_literals", since = "1.79.0")]
13901408
pub fn c_string(string: &CStr) -> Literal {
1391-
let string = string.to_bytes().escape_ascii().to_string();
1392-
Literal::new(bridge::LitKind::CStr, &string, None)
1409+
let escape = EscapeOptions {
1410+
escape_single_quote: false,
1411+
escape_double_quote: true,
1412+
escape_nonascii: false,
1413+
};
1414+
let repr = escape_bytes(string.to_bytes(), escape);
1415+
Literal::new(bridge::LitKind::CStr, &repr, None)
13931416
}
13941417

13951418
/// Returns the span encompassing this literal.

‎std/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ dlmalloc = { version = "0.2.4", features = ['rustc-dep-of-std'] }
5050
fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'], public = true }
5151

5252
[target.'cfg(target_os = "hermit")'.dependencies]
53-
hermit-abi = { version = "0.3.9", features = ['rustc-dep-of-std'], public = true }
53+
hermit-abi = { version = "0.4.0", features = ['rustc-dep-of-std'], public = true }
5454

5555
[target.'cfg(target_os = "wasi")'.dependencies]
5656
wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }

‎std/src/alloc.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ pub use alloc_crate::alloc::*;
7373
/// work, such as to serve alignment requests greater than the alignment
7474
/// provided directly by the backing system allocator.
7575
///
76-
/// This type implements the `GlobalAlloc` trait and Rust programs by default
76+
/// This type implements the [`GlobalAlloc`] trait. Currently the default
77+
/// global allocator is unspecified. Libraries, however, like `cdylib`s and
78+
/// `staticlib`s are guaranteed to use the [`System`] by default and as such
7779
/// work as if they had this definition:
7880
///
7981
/// ```rust
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.