Skip to content

Commit 6df10f0

Browse files
borsgitbot
authored and
gitbot
committed
Auto merge of rust-lang#137290 - matthiaskrgr:rollup-a7xdbi4, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#120580 (Add `MAX_LEN_UTF8` and `MAX_LEN_UTF16` Constants) - rust-lang#132268 (Impl TryFrom<Vec<u8>> for String) - rust-lang#136093 (Match Ergonomics 2024: update old-edition behavior of feature gates) - rust-lang#136344 (Suggest replacing `.` with `::` in more error diagnostics.) - rust-lang#136690 (Use more explicit and reliable ptr select in sort impls) - rust-lang#136815 (CI: Stop /msys64/bin from being prepended to PATH in msys2 shell) - rust-lang#136923 (Lint `#[must_use]` attributes applied to methods in trait impls) - rust-lang#137155 (Organize `OsString`/`OsStr` shims) r? `@ghost` `@rustbot` modify labels: rollup
2 parents fd1c0eb + 1f0ce6c commit 6df10f0

File tree

23 files changed

+234
-170
lines changed

23 files changed

+234
-170
lines changed

alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
#![feature(box_uninit_write)]
106106
#![feature(bstr)]
107107
#![feature(bstr_internals)]
108+
#![feature(char_max_len)]
108109
#![feature(clone_to_uninit)]
109110
#![feature(coerce_unsized)]
110111
#![feature(const_eval_select)]

alloc/src/string.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -1419,7 +1419,9 @@ impl String {
14191419
pub fn push(&mut self, ch: char) {
14201420
match ch.len_utf8() {
14211421
1 => self.vec.push(ch as u8),
1422-
_ => self.vec.extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()),
1422+
_ => {
1423+
self.vec.extend_from_slice(ch.encode_utf8(&mut [0; char::MAX_LEN_UTF8]).as_bytes())
1424+
}
14231425
}
14241426
}
14251427

@@ -1716,7 +1718,7 @@ impl String {
17161718
#[rustc_confusables("set")]
17171719
pub fn insert(&mut self, idx: usize, ch: char) {
17181720
assert!(self.is_char_boundary(idx));
1719-
let mut bits = [0; 4];
1721+
let mut bits = [0; char::MAX_LEN_UTF8];
17201722
let bits = ch.encode_utf8(&mut bits).as_bytes();
17211723

17221724
unsafe {
@@ -2797,7 +2799,7 @@ impl SpecToString for core::ascii::Char {
27972799
impl SpecToString for char {
27982800
#[inline]
27992801
fn spec_to_string(&self) -> String {
2800-
String::from(self.encode_utf8(&mut [0; 4]))
2802+
String::from(self.encode_utf8(&mut [0; char::MAX_LEN_UTF8]))
28012803
}
28022804
}
28032805

@@ -3155,6 +3157,24 @@ impl From<String> for Vec<u8> {
31553157
}
31563158
}
31573159

3160+
#[stable(feature = "try_from_vec_u8_for_string", since = "CURRENT_RUSTC_VERSION")]
3161+
impl TryFrom<Vec<u8>> for String {
3162+
type Error = FromUtf8Error;
3163+
/// Converts the given [`Vec<u8>`] into a [`String`] if it contains valid UTF-8 data.
3164+
///
3165+
/// # Examples
3166+
///
3167+
/// ```
3168+
/// let s1 = b"hello world".to_vec();
3169+
/// let v1 = String::try_from(s1).unwrap();
3170+
/// assert_eq!(v1, "hello world");
3171+
///
3172+
/// ```
3173+
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
3174+
Self::from_utf8(bytes)
3175+
}
3176+
}
3177+
31583178
#[cfg(not(no_global_oom_handling))]
31593179
#[stable(feature = "rust1", since = "1.0.0")]
31603180
impl fmt::Write for String {

alloc/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#![feature(iter_array_chunks)]
44
#![feature(assert_matches)]
55
#![feature(btree_extract_if)]
6+
#![feature(char_max_len)]
67
#![feature(cow_is_borrowed)]
78
#![feature(core_intrinsics)]
89
#![feature(downcast_unchecked)]

alloc/tests/str.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
use std::assert_matches::assert_matches;
44
use std::borrow::Cow;
5+
use std::char::MAX_LEN_UTF8;
56
use std::cmp::Ordering::{Equal, Greater, Less};
67
use std::str::{from_utf8, from_utf8_unchecked};
78

@@ -1231,7 +1232,7 @@ fn test_to_uppercase_rev_iterator() {
12311232
#[test]
12321233
#[cfg_attr(miri, ignore)] // Miri is too slow
12331234
fn test_chars_decoding() {
1234-
let mut bytes = [0; 4];
1235+
let mut bytes = [0; MAX_LEN_UTF8];
12351236
for c in (0..0x110000).filter_map(std::char::from_u32) {
12361237
let s = c.encode_utf8(&mut bytes);
12371238
if Some(c) != s.chars().next() {
@@ -1243,7 +1244,7 @@ fn test_chars_decoding() {
12431244
#[test]
12441245
#[cfg_attr(miri, ignore)] // Miri is too slow
12451246
fn test_chars_rev_decoding() {
1246-
let mut bytes = [0; 4];
1247+
let mut bytes = [0; MAX_LEN_UTF8];
12471248
for c in (0..0x110000).filter_map(std::char::from_u32) {
12481249
let s = c.encode_utf8(&mut bytes);
12491250
if Some(c) != s.chars().rev().next() {

core/src/char/methods.rs

+10
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ impl char {
7171
#[stable(feature = "assoc_char_consts", since = "1.52.0")]
7272
pub const MAX: char = '\u{10FFFF}';
7373

74+
/// The maximum number of bytes required to [encode](char::encode_utf8) a `char` to
75+
/// UTF-8 encoding.
76+
#[unstable(feature = "char_max_len", issue = "121714")]
77+
pub const MAX_LEN_UTF8: usize = 4;
78+
79+
/// The maximum number of two-byte units required to [encode](char::encode_utf16) a `char`
80+
/// to UTF-16 encoding.
81+
#[unstable(feature = "char_max_len", issue = "121714")]
82+
pub const MAX_LEN_UTF16: usize = 2;
83+
7484
/// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
7585
/// decoding error.
7686
///

core/src/char/mod.rs

+10
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,16 @@ const MAX_THREE_B: u32 = 0x10000;
9595
#[stable(feature = "rust1", since = "1.0.0")]
9696
pub const MAX: char = char::MAX;
9797

98+
/// The maximum number of bytes required to [encode](char::encode_utf8) a `char` to
99+
/// UTF-8 encoding.
100+
#[unstable(feature = "char_max_len", issue = "121714")]
101+
pub const MAX_LEN_UTF8: usize = char::MAX_LEN_UTF8;
102+
103+
/// The maximum number of two-byte units required to [encode](char::encode_utf16) a `char`
104+
/// to UTF-16 encoding.
105+
#[unstable(feature = "char_max_len", issue = "121714")]
106+
pub const MAX_LEN_UTF16: usize = char::MAX_LEN_UTF16;
107+
98108
/// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
99109
/// decoding error. Use [`char::REPLACEMENT_CHARACTER`] instead.
100110
#[stable(feature = "decode_utf16", since = "1.9.0")]

core/src/fmt/mod.rs

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

55
use crate::cell::{Cell, Ref, RefCell, RefMut, SyncUnsafeCell, UnsafeCell};
6-
use crate::char::EscapeDebugExtArgs;
6+
use crate::char::{EscapeDebugExtArgs, MAX_LEN_UTF8};
77
use crate::marker::PhantomData;
88
use crate::num::fmt as numfmt;
99
use crate::ops::Deref;
@@ -187,7 +187,7 @@ pub trait Write {
187187
/// ```
188188
#[stable(feature = "fmt_write_char", since = "1.1.0")]
189189
fn write_char(&mut self, c: char) -> Result {
190-
self.write_str(c.encode_utf8(&mut [0; 4]))
190+
self.write_str(c.encode_utf8(&mut [0; MAX_LEN_UTF8]))
191191
}
192192

193193
/// Glue for usage of the [`write!`] macro with implementors of this trait.
@@ -2768,7 +2768,7 @@ impl Display for char {
27682768
if f.options.width.is_none() && f.options.precision.is_none() {
27692769
f.write_char(*self)
27702770
} else {
2771-
f.pad(self.encode_utf8(&mut [0; 4]))
2771+
f.pad(self.encode_utf8(&mut [0; MAX_LEN_UTF8]))
27722772
}
27732773
}
27742774
}

core/src/slice/sort/shared/smallsort.rs

+13-18
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ unsafe fn swap_if_less<T, F>(v_base: *mut T, a_pos: usize, b_pos: usize, is_less
387387
where
388388
F: FnMut(&T, &T) -> bool,
389389
{
390-
// SAFETY: the caller must guarantee that `a` and `b` each added to `v_base` yield valid
390+
// SAFETY: the caller must guarantee that `a_pos` and `b_pos` each added to `v_base` yield valid
391391
// pointers into `v_base`, and are properly aligned, and part of the same allocation.
392392
unsafe {
393393
let v_a = v_base.add(a_pos);
@@ -404,16 +404,16 @@ where
404404
// The equivalent code with a branch would be:
405405
//
406406
// if should_swap {
407-
// ptr::swap(left, right, 1);
407+
// ptr::swap(v_a, v_b, 1);
408408
// }
409409

410410
// The goal is to generate cmov instructions here.
411-
let left_swap = if should_swap { v_b } else { v_a };
412-
let right_swap = if should_swap { v_a } else { v_b };
411+
let v_a_swap = should_swap.select_unpredictable(v_b, v_a);
412+
let v_b_swap = should_swap.select_unpredictable(v_a, v_b);
413413

414-
let right_swap_tmp = ManuallyDrop::new(ptr::read(right_swap));
415-
ptr::copy(left_swap, v_a, 1);
416-
ptr::copy_nonoverlapping(&*right_swap_tmp, v_b, 1);
414+
let v_b_swap_tmp = ManuallyDrop::new(ptr::read(v_b_swap));
415+
ptr::copy(v_a_swap, v_a, 1);
416+
ptr::copy_nonoverlapping(&*v_b_swap_tmp, v_b, 1);
417417
}
418418
}
419419

@@ -640,26 +640,21 @@ pub unsafe fn sort4_stable<T, F: FnMut(&T, &T) -> bool>(
640640
// 1, 1 | c b a d
641641
let c3 = is_less(&*c, &*a);
642642
let c4 = is_less(&*d, &*b);
643-
let min = select(c3, c, a);
644-
let max = select(c4, b, d);
645-
let unknown_left = select(c3, a, select(c4, c, b));
646-
let unknown_right = select(c4, d, select(c3, b, c));
643+
let min = c3.select_unpredictable(c, a);
644+
let max = c4.select_unpredictable(b, d);
645+
let unknown_left = c3.select_unpredictable(a, c4.select_unpredictable(c, b));
646+
let unknown_right = c4.select_unpredictable(d, c3.select_unpredictable(b, c));
647647

648648
// Sort the last two unknown elements.
649649
let c5 = is_less(&*unknown_right, &*unknown_left);
650-
let lo = select(c5, unknown_right, unknown_left);
651-
let hi = select(c5, unknown_left, unknown_right);
650+
let lo = c5.select_unpredictable(unknown_right, unknown_left);
651+
let hi = c5.select_unpredictable(unknown_left, unknown_right);
652652

653653
ptr::copy_nonoverlapping(min, dst, 1);
654654
ptr::copy_nonoverlapping(lo, dst.add(1), 1);
655655
ptr::copy_nonoverlapping(hi, dst.add(2), 1);
656656
ptr::copy_nonoverlapping(max, dst.add(3), 1);
657657
}
658-
659-
#[inline(always)]
660-
fn select<T>(cond: bool, if_true: *const T, if_false: *const T) -> *const T {
661-
if cond { if_true } else { if_false }
662-
}
663658
}
664659

665660
/// SAFETY: The caller MUST guarantee that `v_base` is valid for 8 reads and

core/src/str/pattern.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
issue = "27721"
3939
)]
4040

41+
use crate::char::MAX_LEN_UTF8;
4142
use crate::cmp::Ordering;
4243
use crate::convert::TryInto as _;
4344
use crate::slice::memchr;
@@ -561,8 +562,8 @@ impl Pattern for char {
561562
type Searcher<'a> = CharSearcher<'a>;
562563

563564
#[inline]
564-
fn into_searcher(self, haystack: &str) -> Self::Searcher<'_> {
565-
let mut utf8_encoded = [0; 4];
565+
fn into_searcher<'a>(self, haystack: &'a str) -> Self::Searcher<'a> {
566+
let mut utf8_encoded = [0; MAX_LEN_UTF8];
566567
let utf8_size = self
567568
.encode_utf8(&mut utf8_encoded)
568569
.len()

coretests/tests/char.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::char::MAX_LEN_UTF8;
12
use std::str::FromStr;
23
use std::{char, str};
34

@@ -259,7 +260,7 @@ fn test_escape_unicode() {
259260
#[test]
260261
fn test_encode_utf8() {
261262
fn check(input: char, expect: &[u8]) {
262-
let mut buf = [0; 4];
263+
let mut buf = [0; MAX_LEN_UTF8];
263264
let ptr = buf.as_ptr();
264265
let s = input.encode_utf8(&mut buf);
265266
assert_eq!(s.as_ptr() as usize, ptr as usize);

coretests/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#![feature(bigint_helper_methods)]
1414
#![feature(bstr)]
1515
#![feature(cell_update)]
16+
#![feature(char_max_len)]
1617
#![feature(clone_to_uninit)]
1718
#![feature(const_eval_select)]
1819
#![feature(const_swap_nonoverlapping)]

portable-simd/crates/core_simd/src/masks.rs

-13
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,6 @@ where
401401
LaneCount<N>: SupportedLaneCount,
402402
{
403403
#[inline]
404-
#[must_use = "method returns a defaulted mask with all elements set to false (0)"]
405404
fn default() -> Self {
406405
Self::splat(false)
407406
}
@@ -413,7 +412,6 @@ where
413412
LaneCount<N>: SupportedLaneCount,
414413
{
415414
#[inline]
416-
#[must_use = "method returns a new bool and does not mutate the original value"]
417415
fn eq(&self, other: &Self) -> bool {
418416
self.0 == other.0
419417
}
@@ -425,7 +423,6 @@ where
425423
LaneCount<N>: SupportedLaneCount,
426424
{
427425
#[inline]
428-
#[must_use = "method returns a new Ordering and does not mutate the original value"]
429426
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
430427
self.0.partial_cmp(&other.0)
431428
}
@@ -451,7 +448,6 @@ where
451448
{
452449
type Output = Self;
453450
#[inline]
454-
#[must_use = "method returns a new mask and does not mutate the original value"]
455451
fn bitand(self, rhs: Self) -> Self {
456452
Self(self.0 & rhs.0)
457453
}
@@ -464,7 +460,6 @@ where
464460
{
465461
type Output = Self;
466462
#[inline]
467-
#[must_use = "method returns a new mask and does not mutate the original value"]
468463
fn bitand(self, rhs: bool) -> Self {
469464
self & Self::splat(rhs)
470465
}
@@ -477,7 +472,6 @@ where
477472
{
478473
type Output = Mask<T, N>;
479474
#[inline]
480-
#[must_use = "method returns a new mask and does not mutate the original value"]
481475
fn bitand(self, rhs: Mask<T, N>) -> Mask<T, N> {
482476
Mask::splat(self) & rhs
483477
}
@@ -490,7 +484,6 @@ where
490484
{
491485
type Output = Self;
492486
#[inline]
493-
#[must_use = "method returns a new mask and does not mutate the original value"]
494487
fn bitor(self, rhs: Self) -> Self {
495488
Self(self.0 | rhs.0)
496489
}
@@ -503,7 +496,6 @@ where
503496
{
504497
type Output = Self;
505498
#[inline]
506-
#[must_use = "method returns a new mask and does not mutate the original value"]
507499
fn bitor(self, rhs: bool) -> Self {
508500
self | Self::splat(rhs)
509501
}
@@ -516,7 +508,6 @@ where
516508
{
517509
type Output = Mask<T, N>;
518510
#[inline]
519-
#[must_use = "method returns a new mask and does not mutate the original value"]
520511
fn bitor(self, rhs: Mask<T, N>) -> Mask<T, N> {
521512
Mask::splat(self) | rhs
522513
}
@@ -529,7 +520,6 @@ where
529520
{
530521
type Output = Self;
531522
#[inline]
532-
#[must_use = "method returns a new mask and does not mutate the original value"]
533523
fn bitxor(self, rhs: Self) -> Self::Output {
534524
Self(self.0 ^ rhs.0)
535525
}
@@ -542,7 +532,6 @@ where
542532
{
543533
type Output = Self;
544534
#[inline]
545-
#[must_use = "method returns a new mask and does not mutate the original value"]
546535
fn bitxor(self, rhs: bool) -> Self::Output {
547536
self ^ Self::splat(rhs)
548537
}
@@ -555,7 +544,6 @@ where
555544
{
556545
type Output = Mask<T, N>;
557546
#[inline]
558-
#[must_use = "method returns a new mask and does not mutate the original value"]
559547
fn bitxor(self, rhs: Mask<T, N>) -> Self::Output {
560548
Mask::splat(self) ^ rhs
561549
}
@@ -568,7 +556,6 @@ where
568556
{
569557
type Output = Mask<T, N>;
570558
#[inline]
571-
#[must_use = "method returns a new mask and does not mutate the original value"]
572559
fn not(self) -> Self::Output {
573560
Self(!self.0)
574561
}

0 commit comments

Comments
 (0)