Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 3 pull requests #130541

Closed
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`.
Loading