Skip to content

Commit

Permalink
Auto merge of rust-lang#130541 - workingjubilee:rollup-26jmumi, r=wor…
Browse files Browse the repository at this point in the history
…kingjubilee

Rollup of 3 pull requests

Successful merges:

 - rust-lang#129755 (test: cross-edition metavar fragment specifiers)
 - rust-lang#130511 (Support `char::encode_utf8` in const scenarios.)
 - rust-lang#130531 (Check params for unsafety in THIR)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Sep 19, 2024
2 parents df7f778 + 05f8f46 commit a6d2ada
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 18 deletions.
14 changes: 14 additions & 0 deletions compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,13 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
warnings: self.warnings,
suggest_unsafe_block: self.suggest_unsafe_block,
};
// params in THIR may be unsafe, e.g. a union pattern.
for param in &inner_thir.params {
if let Some(param_pat) = param.pat.as_deref() {
inner_visitor.visit_pat(param_pat);
}
}
// Visit the body.
inner_visitor.visit_expr(&inner_thir[expr]);
// Unsafe blocks can be used in the inner body, make sure to take it into account
self.safety_context = inner_visitor.safety_context;
Expand Down Expand Up @@ -1032,6 +1039,13 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
warnings: &mut warnings,
suggest_unsafe_block: true,
};
// params in THIR may be unsafe, e.g. a union pattern.
for param in &thir.params {
if let Some(param_pat) = param.pat.as_deref() {
visitor.visit_pat(param_pat);
}
}
// Visit the body.
visitor.visit_expr(&thir[expr]);

warnings.sort_by_key(|w| w.block_span);
Expand Down
32 changes: 14 additions & 18 deletions library/core/src/char/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,8 +672,9 @@ impl char {
/// 'ß'.encode_utf8(&mut b);
/// ```
#[stable(feature = "unicode_encode_char", since = "1.15.0")]
#[rustc_const_unstable(feature = "const_char_encode_utf8", issue = "130512")]
#[inline]
pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
pub const fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
// SAFETY: `char` is not a surrogate, so this is valid UTF-8.
unsafe { from_utf8_unchecked_mut(encode_utf8_raw(self as u32, dst)) }
}
Expand Down Expand Up @@ -1735,14 +1736,11 @@ impl EscapeDebugExtArgs {

#[inline]
const fn len_utf8(code: u32) -> usize {
if code < MAX_ONE_B {
1
} else if code < MAX_TWO_B {
2
} else if code < MAX_THREE_B {
3
} else {
4
match code {
..MAX_ONE_B => 1,
..MAX_TWO_B => 2,
..MAX_THREE_B => 3,
_ => 4,
}
}

Expand All @@ -1760,11 +1758,12 @@ const fn len_utf8(code: u32) -> usize {
/// Panics if the buffer is not large enough.
/// A buffer of length four is large enough to encode any `char`.
#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
#[rustc_const_unstable(feature = "const_char_encode_utf8", issue = "130512")]
#[doc(hidden)]
#[inline]
pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] {
pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] {
let len = len_utf8(code);
match (len, &mut dst[..]) {
match (len, &mut *dst) {
(1, [a, ..]) => {
*a = code as u8;
}
Expand All @@ -1783,14 +1782,11 @@ pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] {
*c = (code >> 6 & 0x3F) as u8 | TAG_CONT;
*d = (code & 0x3F) as u8 | TAG_CONT;
}
_ => panic!(
"encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
len,
code,
dst.len(),
),
// Note that we cannot format in constant expressions.
_ => panic!("encode_utf8: buffer does not have enough bytes to encode code point"),
};
&mut dst[..len]
// SAFETY: `<&mut [u8]>::as_mut_ptr` is guaranteed to return a valid pointer and `len` has been tested to be within bounds.
unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr(), len) }
}

/// Encodes a raw u32 value as UTF-16 into the provided `u16` buffer,
Expand Down
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
#![feature(const_bigint_helper_methods)]
#![feature(const_black_box)]
#![feature(const_cell_into_inner)]
#![feature(const_char_encode_utf8)]
#![feature(const_eval_select)]
#![feature(const_exact_div)]
#![feature(const_float_classify)]
Expand Down
14 changes: 14 additions & 0 deletions tests/ui/macros/auxiliary/metavar_2018.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//@ edition: 2018
#[macro_export]
macro_rules! make_matcher {
($name:ident, $fragment_type:ident, $d:tt) => {
#[macro_export]
macro_rules! $name {
($d _:$fragment_type) => { true };
(const { 0 }) => { false };
(A | B) => { false };
}
};
}
make_matcher!(is_expr_from_2018, expr, $);
make_matcher!(is_pat_from_2018, pat, $);
38 changes: 38 additions & 0 deletions tests/ui/macros/metavar_cross_edition_recursive_macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//@ compile-flags: --edition=2024 -Z unstable-options
//@ aux-build: metavar_2018.rs
//@ known-bug: #130484
//@ run-pass

// This test captures the behavior of macro-generating-macros with fragment
// specifiers across edition boundaries.

#![feature(expr_fragment_specifier_2024)]
#![feature(macro_metavar_expr)]
#![allow(incomplete_features)]

extern crate metavar_2018;

use metavar_2018::{is_expr_from_2018, is_pat_from_2018, make_matcher};

make_matcher!(is_expr_from_2024, expr, $);
make_matcher!(is_pat_from_2024, pat, $);

fn main() {
// Check expr
let from_2018 = is_expr_from_2018!(const { 0 });
dbg!(from_2018);
let from_2024 = is_expr_from_2024!(const { 0 });
dbg!(from_2024);

assert!(!from_2018);
assert!(!from_2024); // from_2024 will be true once #130484 is fixed

// Check pat
let from_2018 = is_pat_from_2018!(A | B);
dbg!(from_2018);
let from_2024 = is_pat_from_2024!(A | B);
dbg!(from_2024);

assert!(!from_2018);
assert!(!from_2024); // from_2024 will be true once #130484 is fixed
}
19 changes: 19 additions & 0 deletions tests/ui/unsafe/union-pat-in-param.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
union U {
a: &'static i32,
b: usize,
}

fn fun(U { a }: U) {
//~^ ERROR access to union field is unsafe
dbg!(*a);
}

fn main() {
fun(U { b: 0 });

let closure = |U { a }| {
//~^ ERROR access to union field is unsafe
dbg!(*a);
};
closure(U { b: 0 });
}
19 changes: 19 additions & 0 deletions tests/ui/unsafe/union-pat-in-param.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-pat-in-param.rs:6:12
|
LL | fn fun(U { a }: U) {
| ^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-pat-in-param.rs:14:24
|
LL | let closure = |U { a }| {
| ^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0133`.

0 comments on commit a6d2ada

Please sign in to comment.