Skip to content

Rollup of 6 pull requests #135584

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

Closed
wants to merge 19 commits into from
Closed
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
878a796
Add missing safety descriptions to Arc's 'from_raw','increment_strong…
DiuDiu777 Dec 19, 2024
c89f0dc
Adjust syntax
c410-f3r Dec 22, 2024
be23697
Detect overflow when the literal is larger than i128::MAX
s-cerevisiae Jan 8, 2025
330be17
Detect overflow when the literal is negative
s-cerevisiae Jan 8, 2025
1517a41
Add test cases and test for `HELP`
s-cerevisiae Jan 8, 2025
c04e65d
Extract integer conversion into a function
s-cerevisiae Jan 8, 2025
c994637
Only treat plain literal patterns as short
oli-obk Jan 8, 2025
4a85755
Minor simplification
s-cerevisiae Jan 11, 2025
f52724c
Add comment on case to mark the original issue
s-cerevisiae Jan 12, 2025
74e2e8b
Suggest the smallest fitting type instead
s-cerevisiae Jan 12, 2025
c4a5e12
Clarify note in `std::sync::LazyLock` example
Jan 15, 2025
bbeb5e3
Update `compiler-builtins` to 0.1.144
tgross35 Jan 16, 2025
48e671e
fix typo in library/alloc/src/sync.rs
DiuDiu777 Jan 16, 2025
79a1658
Rollup merge of #133720 - c410-f3r:cfg-match-foo-bar-baz, r=joshtriplett
matthiaskrgr Jan 16, 2025
663b35b
Rollup merge of #134496 - DiuDiu777:fix-doc, r=ibraheemdev
matthiaskrgr Jan 16, 2025
13c3759
Rollup merge of #135249 - s-cerevisiae:fix-overflowing-literals-help,…
matthiaskrgr Jan 16, 2025
2760486
Rollup merge of #135251 - oli-obk:push-lmpyvvyrtplk, r=ytmimi
matthiaskrgr Jan 16, 2025
b898de4
Rollup merge of #135556 - AeonSolstice:patch-1, r=tgross35
matthiaskrgr Jan 16, 2025
4dcc3f3
Rollup merge of #135560 - tgross35:update-builtins, r=tgross35
matthiaskrgr Jan 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644

[dependencies]
core = { path = "../core" }
-compiler_builtins = { version = "=0.1.143", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "=0.1.143", features = ['rustc-dep-of-std', 'no-f16-f128'] }
-compiler_builtins = { version = "=0.1.144", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "=0.1.144", features = ['rustc-dep-of-std', 'no-f16-f128'] }

[dev-dependencies]
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
25 changes: 25 additions & 0 deletions compiler/rustc_data_structures/src/flock.rs
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
//! green/native threading. This is just a bare-bones enough solution for
//! librustdoc, it is not production quality at all.

#[cfg(bootstrap)]
cfg_match! {
cfg(target_os = "linux") => {
mod linux;
@@ -27,4 +28,28 @@ cfg_match! {
}
}

#[cfg(not(bootstrap))]
cfg_match! {
target_os = "linux" => {
mod linux;
use linux as imp;
}
target_os = "redox" => {
mod linux;
use linux as imp;
}
unix => {
mod unix;
use unix as imp;
}
windows => {
mod windows;
use self::windows as imp;
}
_ => {
mod unsupported;
use unsupported as imp;
}
}

pub use imp::Lock;
63 changes: 63 additions & 0 deletions compiler/rustc_data_structures/src/profiling.rs
Original file line number Diff line number Diff line change
@@ -860,6 +860,7 @@ fn get_thread_id() -> u32 {
}

// Memory reporting
#[cfg(bootstrap)]
cfg_match! {
cfg(windows) => {
pub fn get_resident_set_size() -> Option<usize> {
@@ -921,5 +922,67 @@ cfg_match! {
}
}

#[cfg(not(bootstrap))]
cfg_match! {
windows => {
pub fn get_resident_set_size() -> Option<usize> {
use std::mem;

use windows::{
Win32::System::ProcessStatus::{K32GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS},
Win32::System::Threading::GetCurrentProcess,
};

let mut pmc = PROCESS_MEMORY_COUNTERS::default();
let pmc_size = mem::size_of_val(&pmc);
unsafe {
K32GetProcessMemoryInfo(
GetCurrentProcess(),
&mut pmc,
pmc_size as u32,
)
}
.ok()
.ok()?;

Some(pmc.WorkingSetSize)
}
}
target_os = "macos" => {
pub fn get_resident_set_size() -> Option<usize> {
use libc::{c_int, c_void, getpid, proc_pidinfo, proc_taskinfo, PROC_PIDTASKINFO};
use std::mem;
const PROC_TASKINFO_SIZE: c_int = mem::size_of::<proc_taskinfo>() as c_int;

unsafe {
let mut info: proc_taskinfo = mem::zeroed();
let info_ptr = &mut info as *mut proc_taskinfo as *mut c_void;
let pid = getpid() as c_int;
let ret = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, info_ptr, PROC_TASKINFO_SIZE);
if ret == PROC_TASKINFO_SIZE {
Some(info.pti_resident_size as usize)
} else {
None
}
}
}
}
unix => {
pub fn get_resident_set_size() -> Option<usize> {
let field = 1;
let contents = fs::read("/proc/self/statm").ok()?;
let contents = String::from_utf8(contents).ok()?;
let s = contents.split_whitespace().nth(field)?;
let npages = s.parse::<usize>().ok()?;
Some(npages * 4096)
}
}
_ => {
pub fn get_resident_set_size() -> Option<usize> {
None
}
}
}

#[cfg(test)]
mod tests;
31 changes: 23 additions & 8 deletions compiler/rustc_lint/src/types/literal.rs
Original file line number Diff line number Diff line change
@@ -204,20 +204,35 @@ fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static
match t.kind() {
ty::Uint(ty::UintTy::Usize) | ty::Int(ty::IntTy::Isize) => None,
ty::Uint(_) => Some(Integer::fit_unsigned(val).uint_ty_str()),
ty::Int(_) if negative => Some(Integer::fit_signed(-(val as i128)).int_ty_str()),
ty::Int(int) => {
let signed = Integer::fit_signed(val as i128);
let unsigned = Integer::fit_unsigned(val);
Some(if Some(unsigned.size().bits()) == int.bit_width() {
unsigned.uint_ty_str()
ty::Int(_) => {
let signed = literal_to_i128(val, negative).map(Integer::fit_signed);
if negative {
signed.map(Integer::int_ty_str)
} else {
signed.int_ty_str()
})
let unsigned = Integer::fit_unsigned(val);
Some(if let Some(signed) = signed {
if unsigned.size() < signed.size() {
unsigned.uint_ty_str()
} else {
signed.int_ty_str()
}
} else {
unsigned.uint_ty_str()
})
}
}
_ => None,
}
}

fn literal_to_i128(val: u128, negative: bool) -> Option<i128> {
if negative {
(val <= i128::MAX as u128 + 1).then(|| val.wrapping_neg() as i128)
} else {
val.try_into().ok()
}
}

fn lint_int_literal<'tcx>(
cx: &LateContext<'tcx>,
type_limits: &TypeLimits,
160 changes: 160 additions & 0 deletions compiler/rustc_span/src/analyze_source_file.rs
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ pub(crate) fn analyze_source_file(src: &str) -> (Vec<RelativeBytePos>, Vec<Multi
(lines, multi_byte_chars)
}

#[cfg(bootstrap)]
cfg_match! {
cfg(any(target_arch = "x86", target_arch = "x86_64")) => {
fn analyze_source_file_dispatch(
@@ -185,6 +186,165 @@ cfg_match! {
}
}
}

#[cfg(not(bootstrap))]
cfg_match! {
any(target_arch = "x86", target_arch = "x86_64") => {
fn analyze_source_file_dispatch(
src: &str,
lines: &mut Vec<RelativeBytePos>,
multi_byte_chars: &mut Vec<MultiByteChar>,
) {
if is_x86_feature_detected!("sse2") {
unsafe {
analyze_source_file_sse2(src, lines, multi_byte_chars);
}
} else {
analyze_source_file_generic(
src,
src.len(),
RelativeBytePos::from_u32(0),
lines,
multi_byte_chars,
);
}
}

/// Checks 16 byte chunks of text at a time. If the chunk contains
/// something other than printable ASCII characters and newlines, the
/// function falls back to the generic implementation. Otherwise it uses
/// SSE2 intrinsics to quickly find all newlines.
#[target_feature(enable = "sse2")]
unsafe fn analyze_source_file_sse2(
src: &str,
lines: &mut Vec<RelativeBytePos>,
multi_byte_chars: &mut Vec<MultiByteChar>,
) {
#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;

const CHUNK_SIZE: usize = 16;

let src_bytes = src.as_bytes();

let chunk_count = src.len() / CHUNK_SIZE;

// This variable keeps track of where we should start decoding a
// chunk. If a multi-byte character spans across chunk boundaries,
// we need to skip that part in the next chunk because we already
// handled it.
let mut intra_chunk_offset = 0;

for chunk_index in 0..chunk_count {
let ptr = src_bytes.as_ptr() as *const __m128i;
// We don't know if the pointer is aligned to 16 bytes, so we
// use `loadu`, which supports unaligned loading.
let chunk = unsafe { _mm_loadu_si128(ptr.add(chunk_index)) };

// For character in the chunk, see if its byte value is < 0, which
// indicates that it's part of a UTF-8 char.
let multibyte_test = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(0)) };
// Create a bit mask from the comparison results.
let multibyte_mask = unsafe { _mm_movemask_epi8(multibyte_test) };

// If the bit mask is all zero, we only have ASCII chars here:
if multibyte_mask == 0 {
assert!(intra_chunk_offset == 0);

// Check if there are any control characters in the chunk. All
// control characters that we can encounter at this point have a
// byte value less than 32 or ...
let control_char_test0 = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(32)) };
let control_char_mask0 = unsafe { _mm_movemask_epi8(control_char_test0) };

// ... it's the ASCII 'DEL' character with a value of 127.
let control_char_test1 = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127)) };
let control_char_mask1 = unsafe { _mm_movemask_epi8(control_char_test1) };

let control_char_mask = control_char_mask0 | control_char_mask1;

if control_char_mask != 0 {
// Check for newlines in the chunk
let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) };
let newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) };

if control_char_mask == newlines_mask {
// All control characters are newlines, record them
let mut newlines_mask = 0xFFFF0000 | newlines_mask as u32;
let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1);

loop {
let index = newlines_mask.trailing_zeros();

if index >= CHUNK_SIZE as u32 {
// We have arrived at the end of the chunk.
break;
}

lines.push(RelativeBytePos(index) + output_offset);

// Clear the bit, so we can find the next one.
newlines_mask &= (!1) << index;
}

// We are done for this chunk. All control characters were
// newlines and we took care of those.
continue;
} else {
// Some of the control characters are not newlines,
// fall through to the slow path below.
}
} else {
// No control characters, nothing to record for this chunk
continue;
}
}

// The slow path.
// There are control chars in here, fallback to generic decoding.
let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset;
intra_chunk_offset = analyze_source_file_generic(
&src[scan_start..],
CHUNK_SIZE - intra_chunk_offset,
RelativeBytePos::from_usize(scan_start),
lines,
multi_byte_chars,
);
}

// There might still be a tail left to analyze
let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset;
if tail_start < src.len() {
analyze_source_file_generic(
&src[tail_start..],
src.len() - tail_start,
RelativeBytePos::from_usize(tail_start),
lines,
multi_byte_chars,
);
}
}
}
_ => {
// The target (or compiler version) does not support SSE2 ...
fn analyze_source_file_dispatch(
src: &str,
lines: &mut Vec<RelativeBytePos>,
multi_byte_chars: &mut Vec<MultiByteChar>,
) {
analyze_source_file_generic(
src,
src.len(),
RelativeBytePos::from_u32(0),
lines,
multi_byte_chars,
);
}
}
}

// `scan_len` determines the number of bytes in `src` to scan. Note that the
// function can read past `scan_len` if a multi-byte character start within the
// range but extends past it. The overflow is returned by the function.
4 changes: 2 additions & 2 deletions library/Cargo.lock
Original file line number Diff line number Diff line change
@@ -61,9 +61,9 @@ dependencies = [

[[package]]
name = "compiler_builtins"
version = "0.1.143"
version = "0.1.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c85ba2077e3eab3dd81be4ece6b7fb2ad0887c1fb813e9a45400baf75c6c7c29"
checksum = "d18a7b7b5a56aa131e62314b4d862c9f6aa2860f615f3770094ec9064d7ec572"
dependencies = [
"cc",
"rustc-std-workspace-core",
2 changes: 1 addition & 1 deletion library/alloc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ edition = "2021"

[dependencies]
core = { path = "../core" }
compiler_builtins = { version = "=0.1.143", features = ['rustc-dep-of-std'] }
compiler_builtins = { version = "=0.1.144", features = ['rustc-dep-of-std'] }

[dev-dependencies]
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
8 changes: 6 additions & 2 deletions library/alloc/src/sync.rs
Original file line number Diff line number Diff line change
@@ -1397,6 +1397,8 @@ impl<T: ?Sized> Arc<T> {
/// different types. See [`mem::transmute`][transmute] for more information
/// on what restrictions apply in this case.
///
/// The raw pointer must point to a block of memory allocated by the global allocator.
///
/// The user of `from_raw` has to make sure a specific value of `T` is only
/// dropped once.
///
@@ -1452,7 +1454,8 @@ impl<T: ?Sized> Arc<T> {
///
/// The pointer must have been obtained through `Arc::into_raw`, and the
/// associated `Arc` instance must be valid (i.e. the strong count must be at
/// least 1) for the duration of this method.
/// least 1) for the duration of this method, and `ptr` must point to a block of memory
/// allocated by the global allocator.
///
/// # Examples
///
@@ -1486,7 +1489,8 @@ impl<T: ?Sized> Arc<T> {
///
/// The pointer must have been obtained through `Arc::into_raw`, and the
/// associated `Arc` instance must be valid (i.e. the strong count must be at
/// least 1) when invoking this method. This method can be used to release the final
/// least 1) when invoking this method, and `ptr` must point to a block of memory
/// allocated by the global allocator. This method can be used to release the final
/// `Arc` and backing storage, but **should not** be called after the final `Arc` has been
/// released.
///
52 changes: 52 additions & 0 deletions library/core/src/macros/mod.rs
Original file line number Diff line number Diff line change
@@ -224,6 +224,7 @@ pub macro assert_matches {
/// }
/// }
/// ```
#[cfg(bootstrap)]
#[unstable(feature = "cfg_match", issue = "115585")]
#[rustc_diagnostic_item = "cfg_match"]
pub macro cfg_match {
@@ -284,6 +285,57 @@ pub macro cfg_match {
}
}

/// A macro for defining `#[cfg]` match-like statements.
///
/// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of
/// `#[cfg]` cases, emitting the implementation which matches first.
///
/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
/// without having to rewrite each clause multiple times.
///
/// Trailing `_` wildcard match arms are **optional** and they indicate a fallback branch when
/// all previous declarations do not evaluate to true.
///
/// # Example
///
/// ```
/// #![feature(cfg_match)]
///
/// cfg_match! {
/// unix => {
/// fn foo() { /* unix specific functionality */ }
/// }
/// target_pointer_width = "32" => {
/// fn foo() { /* non-unix, 32-bit functionality */ }
/// }
/// _ => {
/// fn foo() { /* fallback implementation */ }
/// }
/// }
/// ```
#[cfg(not(bootstrap))]
#[unstable(feature = "cfg_match", issue = "115585")]
#[rustc_diagnostic_item = "cfg_match"]
pub macro cfg_match {
({ $($tt:tt)* }) => {{
cfg_match! { $($tt)* }
}},
(_ => { $($output:tt)* }) => {
$($output)*
},
(
$cfg:meta => $output:tt
$($( $rest:tt )+)?
) => {
#[cfg($cfg)]
cfg_match! { _ => $output }
$(
#[cfg(not($cfg))]
cfg_match! { $($rest)+ }
)?
},
}

/// Asserts that a boolean expression is `true` at runtime.
///
/// This will invoke the [`panic!`] macro if the provided expression cannot be
3 changes: 3 additions & 0 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
@@ -153,7 +153,10 @@ mod intrinsics;
mod io;
mod iter;
mod lazy;
#[cfg(not(bootstrap))]
mod macros;
#[cfg(bootstrap)]
mod macros_bootstrap;
mod manually_drop;
mod mem;
mod net;
53 changes: 32 additions & 21 deletions library/core/tests/macros.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ struct Struct;

impl Trait for Struct {
cfg_match! {
cfg(feature = "blah") => {
feature = "blah" => {
fn blah(&self) {
unimplemented!();
}
@@ -47,21 +47,21 @@ fn matches_leading_pipe() {
#[test]
fn cfg_match_basic() {
cfg_match! {
cfg(target_pointer_width = "64") => { fn f0_() -> bool { true }}
target_pointer_width = "64" => { fn f0_() -> bool { true }}
}

cfg_match! {
cfg(unix) => { fn f1_() -> bool { true }}
cfg(any(target_os = "macos", target_os = "linux")) => { fn f1_() -> bool { false }}
unix => { fn f1_() -> bool { true } }
any(target_os = "macos", target_os = "linux") => { fn f1_() -> bool { false }}
}

cfg_match! {
cfg(target_pointer_width = "32") => { fn f2_() -> bool { false }}
cfg(target_pointer_width = "64") => { fn f2_() -> bool { true }}
target_pointer_width = "32" => { fn f2_() -> bool { false } }
target_pointer_width = "64" => { fn f2_() -> bool { true } }
}

cfg_match! {
cfg(target_pointer_width = "16") => { fn f3_() -> i32 { 1 }}
target_pointer_width = "16" => { fn f3_() -> i32 { 1 } }
_ => { fn f3_() -> i32 { 2 }}
}

@@ -83,7 +83,7 @@ fn cfg_match_basic() {
#[test]
fn cfg_match_debug_assertions() {
cfg_match! {
cfg(debug_assertions) => {
debug_assertions => {
assert!(cfg!(debug_assertions));
assert_eq!(4, 2+2);
}
@@ -98,13 +98,13 @@ fn cfg_match_debug_assertions() {
#[test]
fn cfg_match_no_duplication_on_64() {
cfg_match! {
cfg(windows) => {
windows => {
fn foo() {}
}
cfg(unix) => {
unix => {
fn foo() {}
}
cfg(target_pointer_width = "64") => {
target_pointer_width = "64" => {
fn foo() {}
}
}
@@ -114,34 +114,34 @@ fn cfg_match_no_duplication_on_64() {
#[test]
fn cfg_match_options() {
cfg_match! {
cfg(test) => {
test => {
use core::option::Option as Option2;
fn works1() -> Option2<u32> { Some(1) }
}
_ => { fn works1() -> Option<u32> { None } }
}

cfg_match! {
cfg(feature = "foo") => { fn works2() -> bool { false } }
cfg(test) => { fn works2() -> bool { true } }
feature = "foo" => { fn works2() -> bool { false } }
test => { fn works2() -> bool { true } }
_ => { fn works2() -> bool { false } }
}

cfg_match! {
cfg(feature = "foo") => { fn works3() -> bool { false } }
feature = "foo" => { fn works3() -> bool { false } }
_ => { fn works3() -> bool { true } }
}

cfg_match! {
cfg(test) => {
test => {
use core::option::Option as Option3;
fn works4() -> Option3<u32> { Some(1) }
}
}

cfg_match! {
cfg(feature = "foo") => { fn works5() -> bool { false } }
cfg(test) => { fn works5() -> bool { true } }
feature = "foo" => { fn works5() -> bool { false } }
test => { fn works5() -> bool { true } }
}

assert!(works1().is_some());
@@ -154,7 +154,7 @@ fn cfg_match_options() {
#[test]
fn cfg_match_two_functions() {
cfg_match! {
cfg(target_pointer_width = "64") => {
target_pointer_width = "64" => {
fn foo1() {}
fn bar1() {}
}
@@ -178,7 +178,7 @@ fn cfg_match_two_functions() {

fn _accepts_expressions() -> i32 {
cfg_match! {
cfg(unix) => { 1 }
unix => { 1 }
_ => { 2 }
}
}
@@ -189,7 +189,18 @@ fn _allows_stmt_expr_attributes() {
let one = 1;
let two = 2;
cfg_match! {
cfg(unix) => { one * two; }
unix => { one * two; }
_ => { one + two; }
}
}

fn _expression() {
let _ = cfg_match!({
windows => {
" XP"
}
_ => {
""
}
});
}
193 changes: 193 additions & 0 deletions library/core/tests/macros_bootstrap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#![allow(unused_must_use)]

#[allow(dead_code)]
trait Trait {
fn blah(&self);
}

#[allow(dead_code)]
struct Struct;

impl Trait for Struct {
cfg_match! {
cfg(feature = "blah") => {
fn blah(&self) {
unimplemented!();
}
}
_ => {
fn blah(&self) {
unimplemented!();
}
}
}
}

#[test]
fn assert_eq_trailing_comma() {
assert_eq!(1, 1,);
}

#[test]
fn assert_escape() {
assert!(r#"☃\backslash"#.contains("\\"));
}

#[test]
fn assert_ne_trailing_comma() {
assert_ne!(1, 2,);
}

#[rustfmt::skip]
#[test]
fn matches_leading_pipe() {
matches!(1, | 1 | 2 | 3);
}

#[test]
fn cfg_match_basic() {
cfg_match! {
cfg(target_pointer_width = "64") => { fn f0_() -> bool { true }}
}

cfg_match! {
cfg(unix) => { fn f1_() -> bool { true }}
cfg(any(target_os = "macos", target_os = "linux")) => { fn f1_() -> bool { false }}
}

cfg_match! {
cfg(target_pointer_width = "32") => { fn f2_() -> bool { false }}
cfg(target_pointer_width = "64") => { fn f2_() -> bool { true }}
}

cfg_match! {
cfg(target_pointer_width = "16") => { fn f3_() -> i32 { 1 }}
_ => { fn f3_() -> i32 { 2 }}
}

#[cfg(target_pointer_width = "64")]
assert!(f0_());

#[cfg(unix)]
assert!(f1_());

#[cfg(target_pointer_width = "32")]
assert!(!f2_());
#[cfg(target_pointer_width = "64")]
assert!(f2_());

#[cfg(not(target_pointer_width = "16"))]
assert_eq!(f3_(), 2);
}

#[test]
fn cfg_match_debug_assertions() {
cfg_match! {
cfg(debug_assertions) => {
assert!(cfg!(debug_assertions));
assert_eq!(4, 2+2);
}
_ => {
assert!(cfg!(not(debug_assertions)));
assert_eq!(10, 5+5);
}
}
}

#[cfg(target_pointer_width = "64")]
#[test]
fn cfg_match_no_duplication_on_64() {
cfg_match! {
cfg(windows) => {
fn foo() {}
}
cfg(unix) => {
fn foo() {}
}
cfg(target_pointer_width = "64") => {
fn foo() {}
}
}
foo();
}

#[test]
fn cfg_match_options() {
cfg_match! {
cfg(test) => {
use core::option::Option as Option2;
fn works1() -> Option2<u32> { Some(1) }
}
_ => { fn works1() -> Option<u32> { None } }
}

cfg_match! {
cfg(feature = "foo") => { fn works2() -> bool { false } }
cfg(test) => { fn works2() -> bool { true } }
_ => { fn works2() -> bool { false } }
}

cfg_match! {
cfg(feature = "foo") => { fn works3() -> bool { false } }
_ => { fn works3() -> bool { true } }
}

cfg_match! {
cfg(test) => {
use core::option::Option as Option3;
fn works4() -> Option3<u32> { Some(1) }
}
}

cfg_match! {
cfg(feature = "foo") => { fn works5() -> bool { false } }
cfg(test) => { fn works5() -> bool { true } }
}

assert!(works1().is_some());
assert!(works2());
assert!(works3());
assert!(works4().is_some());
assert!(works5());
}

#[test]
fn cfg_match_two_functions() {
cfg_match! {
cfg(target_pointer_width = "64") => {
fn foo1() {}
fn bar1() {}
}
_ => {
fn foo2() {}
fn bar2() {}
}
}

#[cfg(target_pointer_width = "64")]
{
foo1();
bar1();
}
#[cfg(not(target_pointer_width = "64"))]
{
foo2();
bar2();
}
}

fn _accepts_expressions() -> i32 {
cfg_match! {
cfg(unix) => { 1 }
_ => { 2 }
}
}

fn _allows_stmt_expr_attributes() {
let one = 1;
let two = 2;
cfg_match! {
cfg(unix) => { one * two; }
_ => { one + two; }
}
}
2 changes: 1 addition & 1 deletion library/std/Cargo.toml
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core", public = true }
compiler_builtins = { version = "=0.1.143" }
compiler_builtins = { version = "=0.1.144" }
unwind = { path = "../unwind" }
hashbrown = { version = "0.15", default-features = false, features = [
'rustc-dep-of-std',
2 changes: 1 addition & 1 deletion library/std/src/sync/lazy_lock.rs
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ union Data<T, F> {
/// ```
/// use std::sync::LazyLock;
///
/// // n.b. static items do not call [`Drop`] on program termination, so this won't be deallocated.
/// // Note: static items do not call [`Drop`] on program termination, so this won't be deallocated.
/// // this is fine, as the OS can deallocate the terminated program faster than we can free memory
/// // but tools like valgrind might report "memory leaks" as it isn't obvious this is intentional.
/// static DEEP_THOUGHT: LazyLock<String> = LazyLock::new(|| {
26 changes: 26 additions & 0 deletions tests/ui/lint/type-overflow.rs
Original file line number Diff line number Diff line change
@@ -3,20 +3,46 @@

fn main() {
let error = 255i8; //~WARNING literal out of range for `i8`
//~^ HELP consider using the type `u8` instead

let ok = 0b1000_0001; // should be ok -> i32
let ok = 0b0111_1111i8; // should be ok -> 127i8

let fail = 0b1000_0001i8; //~WARNING literal out of range for `i8`
//~^ HELP consider using the type `u8` instead
//~| HELP consider using the type `u8` for the literal and cast it to `i8`

let fail = 0x8000_0000_0000_0000i64; //~WARNING literal out of range for `i64`
//~^ HELP consider using the type `u64` instead
//~| HELP consider using the type `u64` for the literal and cast it to `i64`

let fail = 0x1_FFFF_FFFFu32; //~WARNING literal out of range for `u32`
//~^ HELP consider using the type `u64` instead

let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
//~^ WARNING literal out of range for `i128`
//~| HELP consider using the type `u128` instead
//~| HELP consider using the type `u128` for the literal and cast it to `i128`

let fail = 0x8000_0000_0000_0000_0000_0000_0000_0000;
//~^ WARNING literal out of range for `i32`
//~| HELP consider using the type `u128` instead

let fail = -0x8000_0000_0000_0000_0000_0000_0000_0000; // issue #131849
//~^ WARNING literal out of range for `i32`
//~| HELP consider using the type `i128` instead

let fail = -0x8000_0000_0000_0000_0000_0000_0000_0001i128;
//~^ WARNING literal out of range for `i128`

let fail = 340282366920938463463374607431768211455i8;
//~^ WARNING literal out of range for `i8`
//~| HELP consider using the type `u128` instead

let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for `i32`
//~| HELP consider using the type `u64` instead
//~| HELP

let fail = -0b1111_1111i8; //~WARNING literal out of range for `i8`
//~| HELP consider using the type `i16` instead
}
53 changes: 45 additions & 8 deletions tests/ui/lint/type-overflow.stderr
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ LL | #![warn(overflowing_literals)]
| ^^^^^^^^^^^^^^^^^^^^

warning: literal out of range for `i8`
--> $DIR/type-overflow.rs:10:16
--> $DIR/type-overflow.rs:11:16
|
LL | let fail = 0b1000_0001i8;
| ^^^^^^^^^^^^^
@@ -29,7 +29,7 @@ LL | let fail = 0b1000_0001u8 as i8;
| ~~~~~~~~~~~~~~~~~~~

warning: literal out of range for `i64`
--> $DIR/type-overflow.rs:12:16
--> $DIR/type-overflow.rs:15:16
|
LL | let fail = 0x8000_0000_0000_0000i64;
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -45,15 +45,15 @@ LL | let fail = 0x8000_0000_0000_0000u64 as i64;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

warning: literal out of range for `u32`
--> $DIR/type-overflow.rs:14:16
--> $DIR/type-overflow.rs:19:16
|
LL | let fail = 0x1_FFFF_FFFFu32;
| ^^^^^^^^^^^^^^^^ help: consider using the type `u64` instead: `0x1_FFFF_FFFFu64`
|
= note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into the type `u32` and will become `4294967295u32`

warning: literal out of range for `i128`
--> $DIR/type-overflow.rs:16:22
--> $DIR/type-overflow.rs:22:22
|
LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -66,26 +66,63 @@ LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000u128 as i128;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

warning: literal out of range for `i32`
--> $DIR/type-overflow.rs:19:16
--> $DIR/type-overflow.rs:27:16
|
LL | let fail = 0x8000_0000_0000_0000_0000_0000_0000_0000;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i32` and will become `0i32`
= help: consider using the type `u128` instead

warning: literal out of range for `i32`
--> $DIR/type-overflow.rs:31:17
|
LL | let fail = -0x8000_0000_0000_0000_0000_0000_0000_0000; // issue #131849
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i32`
= note: and the value `-0x8000_0000_0000_0000_0000_0000_0000_0000` will become `0i32`
= help: consider using the type `i128` instead

warning: literal out of range for `i128`
--> $DIR/type-overflow.rs:35:17
|
LL | let fail = -0x8000_0000_0000_0000_0000_0000_0000_0001i128;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0001i128` (decimal `170141183460469231731687303715884105729`) does not fit into the type `i128`
= note: and the value `-0x8000_0000_0000_0000_0000_0000_0000_0001i128` will become `170141183460469231731687303715884105727i128`

warning: literal out of range for `i8`
--> $DIR/type-overflow.rs:38:16
|
LL | let fail = 340282366920938463463374607431768211455i8;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the literal `340282366920938463463374607431768211455i8` does not fit into the type `i8` whose range is `-128..=127`
= help: consider using the type `u128` instead

warning: literal out of range for `i32`
--> $DIR/type-overflow.rs:42:16
|
LL | let fail = 0x8FFF_FFFF_FFFF_FFFE;
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into the type `i32` and will become `-2i32`
= help: consider using the type `i128` instead
= help: consider using the type `u64` instead
help: to use as a negative number (decimal `-2`), consider using the type `u32` for the literal and cast it to `i32`
|
LL | let fail = 0x8FFF_FFFF_FFFF_FFFEu32 as i32;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

warning: literal out of range for `i8`
--> $DIR/type-overflow.rs:21:17
--> $DIR/type-overflow.rs:46:17
|
LL | let fail = -0b1111_1111i8;
| ^^^^^^^^^^^^^ help: consider using the type `i16` instead: `0b1111_1111i16`
|
= note: the literal `0b1111_1111i8` (decimal `255`) does not fit into the type `i8`
= note: and the value `-0b1111_1111i8` will become `1i8`

warning: 7 warnings emitted
warning: 11 warnings emitted