diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index 757fc1f58bd51..a56b753bda726 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -49,6 +49,8 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let Some((pat, arg)) = extract_for_loop(expr) else { return }; + let arg_span = arg.span.source_callsite(); + let ty = cx.typeck_results().expr_ty(arg); let (adt, args, ref_mutability) = match ty.kind() { @@ -78,27 +80,27 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles { && let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span) { ForLoopsOverFalliblesLoopSub::RemoveNext { - suggestion: recv.span.between(arg.span.shrink_to_hi()), + suggestion: recv.span.between(arg_span.shrink_to_hi()), recv_snip, } } else { ForLoopsOverFalliblesLoopSub::UseWhileLet { start_span: expr.span.with_hi(pat.span.lo()), - end_span: pat.span.between(arg.span), + end_span: pat.span.between(arg_span), var, } }; let question_mark = suggest_question_mark(cx, adt, args, expr.span) - .then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() }); + .then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg_span.shrink_to_hi() }); let suggestion = ForLoopsOverFalliblesSuggestion { var, start_span: expr.span.with_hi(pat.span.lo()), - end_span: pat.span.between(arg.span), + end_span: pat.span.between(arg_span), }; cx.emit_span_lint( FOR_LOOPS_OVER_FALLIBLES, - arg.span, + arg_span, ForLoopsOverFalliblesDiag { article, ref_prefix, ty, sub, question_mark, suggestion }, ); } diff --git a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs index 4aff127908eec..8da17a056e31b 100644 --- a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs +++ b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs @@ -55,18 +55,45 @@ impl<'a, 'tcx> UnnecessaryTransmuteChecker<'a, 'tcx> { }, // char → u32 (Char, Uint(UintTy::U32)) => err(format!("u32::from({arg})")), + // char (→ u32) → i32 + (Char, Int(IntTy::I32)) => err(format!("u32::from({arg}).cast_signed()")), // u32 → char (Uint(UintTy::U32), Char) => Error { sugg: format!("char::from_u32_unchecked({arg})"), help: Some("consider `char::from_u32(…).unwrap()`"), span, }, + // i32 → char + (Int(IntTy::I32), Char) => Error { + sugg: format!("char::from_u32_unchecked(i32::cast_unsigned({arg}))"), + help: Some("consider `char::from_u32(i32::cast_unsigned(…)).unwrap()`"), + span, + }, // uNN → iNN (Uint(ty), Int(_)) => err(format!("{}::cast_signed({arg})", ty.name_str())), // iNN → uNN (Int(ty), Uint(_)) => err(format!("{}::cast_unsigned({arg})", ty.name_str())), + // fNN → xsize + (Float(ty), Uint(UintTy::Usize)) => { + err(format!("{}::to_bits({arg}) as usize", ty.name_str())) + } + (Float(ty), Int(IntTy::Isize)) => { + err(format!("{}::to_bits({arg}) as isize", ty.name_str())) + } + // fNN (→ uNN) → iNN + (Float(ty), Int(..)) => err(format!("{}::to_bits({arg}).cast_signed()", ty.name_str())), // fNN → uNN (Float(ty), Uint(..)) => err(format!("{}::to_bits({arg})", ty.name_str())), + // xsize → fNN + (Uint(UintTy::Usize) | Int(IntTy::Isize), Float(ty)) => { + err(format!("{}::from_bits({arg} as _)", ty.name_str(),)) + } + // iNN (→ uNN) → fNN + (Int(int_ty), Float(ty)) => err(format!( + "{}::from_bits({}::cast_unsigned({arg}))", + ty.name_str(), + int_ty.name_str() + )), // uNN → fNN (Uint(_), Float(ty)) => err(format!("{}::from_bits({arg})", ty.name_str())), // bool → { x8 } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs index 0d25b19f3fcf3..c5704c574483f 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs @@ -1,10 +1,16 @@ -use crate::spec::{LinkerFlavor, Lld, Target, TargetMetadata, base}; +use crate::spec::{FramePointer, LinkerFlavor, Lld, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.max_atomic_width = Some(128); base.features = "+v8a,+neon,+fp-armv8".into(); + // Microsoft recommends enabling frame pointers on Arm64 Windows. + // From https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#integer-registers + // "The frame pointer (x29) is required for compatibility with fast stack walking used by ETW + // and other services. It must point to the previous {x29, x30} pair on the stack." + base.frame_pointer = FramePointer::NonLeaf; + // MSVC emits a warning about code that may trip "Cortex-A53 MPCore processor bug #843419" (see // https://developer.arm.com/documentation/epm048406/latest) which is sometimes emitted by LLVM. // Since Arm64 Windows 10+ isn't supported on that processor, it's safe to disable the warning. diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index cbfe00a757ce4..833f80279517a 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -163,7 +163,7 @@ fn check_version(config: &Config) -> Option { msg.push_str("WARNING: The `change-id` is missing in the `bootstrap.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n"); msg.push_str("NOTE: to silence this warning, "); msg.push_str(&format!( - "add `change-id = {latest_change_id}` or change-id = \"ignore\" at the top of `bootstrap.toml`" + "add `change-id = {latest_change_id}` or `change-id = \"ignore\"` at the top of `bootstrap.toml`" )); return Some(msg); } @@ -195,7 +195,7 @@ fn check_version(config: &Config) -> Option { msg.push_str("NOTE: to silence this warning, "); msg.push_str(&format!( - "update `bootstrap.toml` to use `change-id = {latest_change_id}` or change-id = \"ignore\" instead" + "update `bootstrap.toml` to use `change-id = {latest_change_id}` or `change-id = \"ignore\"` instead" )); if io::stdout().is_terminal() { diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs index 7aaf9c2624f9c..731d8b577637a 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs @@ -1,5 +1,6 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 +#![allow(unnecessary_transmutes)] #[cfg(target_arch = "x86")] use std::arch::x86::*; diff --git a/tests/ui/lint/for-loops-over-falibles/macro-issue-140747.rs b/tests/ui/lint/for-loops-over-falibles/macro-issue-140747.rs new file mode 100644 index 0000000000000..33a89ced963e9 --- /dev/null +++ b/tests/ui/lint/for-loops-over-falibles/macro-issue-140747.rs @@ -0,0 +1,10 @@ +#![forbid(for_loops_over_fallibles)] + +fn main() { + macro_rules! x { + () => { + None:: + }; + } + for _ in x! {} {} //~ ERROR for loop over an `Option`. This is more readably written as an `if let` statement [for_loops_over_fallibles] +} diff --git a/tests/ui/lint/for-loops-over-falibles/macro-issue-140747.stderr b/tests/ui/lint/for-loops-over-falibles/macro-issue-140747.stderr new file mode 100644 index 0000000000000..550d26045fbc9 --- /dev/null +++ b/tests/ui/lint/for-loops-over-falibles/macro-issue-140747.stderr @@ -0,0 +1,24 @@ +error: for loop over an `Option`. This is more readably written as an `if let` statement + --> $DIR/macro-issue-140747.rs:9:14 + | +LL | for _ in x! {} {} + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/macro-issue-140747.rs:1:11 + | +LL | #![forbid(for_loops_over_fallibles)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: to check pattern in a loop use `while let` + | +LL - for _ in x! {} {} +LL + while let Some(_) = x! {} {} + | +help: consider using `if let` to clear intent + | +LL - for _ in x! {} {} +LL + if let Some(_) = x! {} {} + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/transmute/unnecessary-transmutation.fixed b/tests/ui/transmute/unnecessary-transmutation.fixed index 1a0df143cc5ff..bf7d769348aaf 100644 --- a/tests/ui/transmute/unnecessary-transmutation.fixed +++ b/tests/ui/transmute/unnecessary-transmutation.fixed @@ -49,6 +49,10 @@ fn main() { //~^ ERROR let y: char = char::from_u32_unchecked(y); //~^ ERROR + let y: i32 = u32::from('🐱').cast_signed(); + //~^ ERROR + let y: char = char::from_u32_unchecked(i32::cast_unsigned(y)); + //~^ ERROR let x: u16 = i16::cast_unsigned(8i16); //~^ ERROR @@ -72,6 +76,11 @@ fn main() { let y: u64 = f64::to_bits(2.0); //~^ ERROR + let y: f64 = f64::from_bits(i64::cast_unsigned(1i64)); + //~^ ERROR + let y: i64 = f64::to_bits(1f64).cast_signed(); + //~^ ERROR + let z: bool = (1u8 == 1); //~^ ERROR let z: u8 = (z) as u8; diff --git a/tests/ui/transmute/unnecessary-transmutation.rs b/tests/ui/transmute/unnecessary-transmutation.rs index 6b979263c56ca..b9de529f1cccd 100644 --- a/tests/ui/transmute/unnecessary-transmutation.rs +++ b/tests/ui/transmute/unnecessary-transmutation.rs @@ -49,6 +49,10 @@ fn main() { //~^ ERROR let y: char = transmute(y); //~^ ERROR + let y: i32 = transmute('🐱'); + //~^ ERROR + let y: char = transmute(y); + //~^ ERROR let x: u16 = transmute(8i16); //~^ ERROR @@ -72,6 +76,11 @@ fn main() { let y: u64 = transmute(2.0); //~^ ERROR + let y: f64 = transmute(1i64); + //~^ ERROR + let y: i64 = transmute(1f64); + //~^ ERROR + let z: bool = transmute(1u8); //~^ ERROR let z: u8 = transmute(z); diff --git a/tests/ui/transmute/unnecessary-transmutation.stderr b/tests/ui/transmute/unnecessary-transmutation.stderr index b661aa13c985d..a19f1bebf16fd 100644 --- a/tests/ui/transmute/unnecessary-transmutation.stderr +++ b/tests/ui/transmute/unnecessary-transmutation.stderr @@ -154,82 +154,108 @@ LL | let y: char = transmute(y); = help: consider `char::from_u32(…).unwrap()` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:53:22 + --> $DIR/unnecessary-transmutation.rs:52:22 + | +LL | let y: i32 = transmute('🐱'); + | ^^^^^^^^^^^^^^^ help: replace this with: `u32::from('🐱').cast_signed()` + +error: unnecessary transmute + --> $DIR/unnecessary-transmutation.rs:54:23 + | +LL | let y: char = transmute(y); + | ^^^^^^^^^^^^ help: replace this with: `char::from_u32_unchecked(i32::cast_unsigned(y))` + | + = help: consider `char::from_u32(i32::cast_unsigned(…)).unwrap()` + +error: unnecessary transmute + --> $DIR/unnecessary-transmutation.rs:57:22 | LL | let x: u16 = transmute(8i16); | ^^^^^^^^^^^^^^^ help: replace this with: `i16::cast_unsigned(8i16)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:55:22 + --> $DIR/unnecessary-transmutation.rs:59:22 | LL | let x: i16 = transmute(x); | ^^^^^^^^^^^^ help: replace this with: `u16::cast_signed(x)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:57:22 + --> $DIR/unnecessary-transmutation.rs:61:22 | LL | let x: u32 = transmute(4i32); | ^^^^^^^^^^^^^^^ help: replace this with: `i32::cast_unsigned(4i32)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:59:22 + --> $DIR/unnecessary-transmutation.rs:63:22 | LL | let x: i32 = transmute(x); | ^^^^^^^^^^^^ help: replace this with: `u32::cast_signed(x)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:61:22 + --> $DIR/unnecessary-transmutation.rs:65:22 | LL | let x: u64 = transmute(7i64); | ^^^^^^^^^^^^^^^ help: replace this with: `i64::cast_unsigned(7i64)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:63:22 + --> $DIR/unnecessary-transmutation.rs:67:22 | LL | let x: i64 = transmute(x); | ^^^^^^^^^^^^ help: replace this with: `u64::cast_signed(x)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:66:22 + --> $DIR/unnecessary-transmutation.rs:70:22 | LL | let y: f32 = transmute(1u32); | ^^^^^^^^^^^^^^^ help: replace this with: `f32::from_bits(1u32)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:68:22 + --> $DIR/unnecessary-transmutation.rs:72:22 | LL | let y: u32 = transmute(y); | ^^^^^^^^^^^^ help: replace this with: `f32::to_bits(y)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:70:22 + --> $DIR/unnecessary-transmutation.rs:74:22 | LL | let y: f64 = transmute(3u64); | ^^^^^^^^^^^^^^^ help: replace this with: `f64::from_bits(3u64)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:72:22 + --> $DIR/unnecessary-transmutation.rs:76:22 | LL | let y: u64 = transmute(2.0); | ^^^^^^^^^^^^^^ help: replace this with: `f64::to_bits(2.0)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:75:23 + --> $DIR/unnecessary-transmutation.rs:79:22 + | +LL | let y: f64 = transmute(1i64); + | ^^^^^^^^^^^^^^^ help: replace this with: `f64::from_bits(i64::cast_unsigned(1i64))` + +error: unnecessary transmute + --> $DIR/unnecessary-transmutation.rs:81:22 + | +LL | let y: i64 = transmute(1f64); + | ^^^^^^^^^^^^^^^ help: replace this with: `f64::to_bits(1f64).cast_signed()` + +error: unnecessary transmute + --> $DIR/unnecessary-transmutation.rs:84:23 | LL | let z: bool = transmute(1u8); | ^^^^^^^^^^^^^^ help: replace this with: `(1u8 == 1)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:77:21 + --> $DIR/unnecessary-transmutation.rs:86:21 | LL | let z: u8 = transmute(z); | ^^^^^^^^^^^^ help: replace this with: `(z) as u8` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:82:21 + --> $DIR/unnecessary-transmutation.rs:91:21 | LL | let z: i8 = transmute(z); | ^^^^^^^^^^^^ help: replace this with: `(z) as i8` -error: aborting due to 32 previous errors +error: aborting due to 36 previous errors diff --git a/triagebot.toml b/triagebot.toml index b3a319037bd39..1f0afdc44425d 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1002,7 +1002,7 @@ message = "This PR changes a file inside `tests/crashes`. If a crash was fixed, [mentions."tests/rustdoc-json"] message = """ -These commits modify `test/rustdoc-json`. +These commits modify `tests/rustdoc-json`. rustdoc-json is a **public** (but unstable) interface. Please ensure that if you've changed the output: