Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
acd02b8
document that `!` does bitwise and logical negation
evan-dickinson Sep 9, 2026
6fc1dc1
lint: suggest fXX::is_nan for unsuffixed NaN comparisons
caelyreth Oct 13, 2026
4f9916a
lint: use UFCS for NaN comparison suggestions
caelyreth Oct 13, 2026
ed4718f
lint: preserve qualified paths in NaN suggestions
caelyreth Oct 13, 2026
62cf356
lint: fix NaN suggestions for nested operands and macros
caelyreth Oct 14, 2026
142d509
Don't try to skip anything in `Skip::advance_by(0)`
cuviper Oct 17, 2026
abce4dc
Don't ignore unknown LLVM diagnostics
nikic Oct 19, 2026
2c2a5e9
test: re-organize ui test case
caelyreth Oct 19, 2026
d201932
test: cover shadowing in qualified NaN suggestions
caelyreth Oct 19, 2026
3b9350a
lint: skip NaN diagnostics for custom comparisons
caelyreth Oct 19, 2026
8735b14
Improve bit permutation codegen
ywxt Oct 20, 2026
fcc7978
Don't distinguish diagnostic kinds without special treatment
nikic Oct 20, 2026
b95ad06
Don't downgrade linker error to warning
nikic Oct 20, 2026
0370417
emit usize and isize as typedefs
Walnut356 Oct 20, 2026
1effc4d
Rollup merge of #163104 - Walnut356:i_usize_typedef, r=mati865
JonathanBrouwer Oct 20, 2026
14903bd
Rollup merge of #164488 - cuviper:skip0, r=JohnTitor
JonathanBrouwer Oct 20, 2026
6463723
Rollup merge of #164578 - nikic:llvm-diags, r=mati865
JonathanBrouwer Oct 20, 2026
9576fca
Rollup merge of #164611 - ywxt:int_bits, r=Amanieu
JonathanBrouwer Oct 20, 2026
d8eef7d
Rollup merge of #162668 - evan-dickinson:bitwise-not, r=JohnTitor
JonathanBrouwer Oct 20, 2026
157c2cb
Rollup merge of #164264 - caelyreth:fix-invalid-nan-float, r=jieyouxu
JonathanBrouwer Oct 20, 2026
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
33 changes: 17 additions & 16 deletions compiler/rustc_codegen_llvm/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ impl<'a> Drop for DiagnosticHandlers<'a> {
fn report_inline_asm(
cgcx: &CodegenContext,
msg: String,
level: llvm::DiagnosticLevel,
severity: llvm::DiagnosticSeverity,
cookie: u64,
source: Option<(String, Vec<InnerSpan>)>,
) -> InlineAsmError {
Expand All @@ -422,10 +422,10 @@ fn report_inline_asm(
let hi = BytePos::from_u32((cookie >> 32) as u32);
(lo, hi)
};
let level = match level {
llvm::DiagnosticLevel::Error => Level::Error,
llvm::DiagnosticLevel::Warning => Level::Warning(None),
llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
let level = match severity {
llvm::DiagnosticSeverity::Error => Level::Error,
llvm::DiagnosticSeverity::Warning => Level::Warning(None),
llvm::DiagnosticSeverity::Note | llvm::DiagnosticSeverity::Remark => Level::Note,
};
let msg = msg.trim_prefix("error: ").to_string();
InlineAsmError { lo, hi, msg, level, source }
Expand Down Expand Up @@ -456,7 +456,7 @@ fn diagnostic_handler_callback_inner(
shared_emitter.inline_asm_error(report_inline_asm(
cgcx,
inline.message,
inline.level,
inline.severity,
inline.cookie,
inline.source,
));
Expand All @@ -479,21 +479,22 @@ fn diagnostic_handler_callback_inner(
message: &opt.message,
});
}
llvm::diagnostic::PGO(diagnostic_ref) | llvm::diagnostic::Linker(diagnostic_ref) => {
let message = llvm::build_string(|s| unsafe {
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
})
.expect("non-UTF8 diagnostic");
dcx.emit_warn(FromLlvmDiag { message });
}
llvm::diagnostic::Unsupported(diagnostic_ref) => {

llvm::diagnostic::Other(diagnostic_ref) => {
let message = llvm::build_string(|s| unsafe {
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
})
.expect("non-UTF8 diagnostic");
dcx.emit_err(FromLlvmDiag { message });
match diagnostic_ref.severity() {
llvm::DiagnosticSeverity::Error => {
dcx.emit_err(FromLlvmDiag { message });
}
llvm::DiagnosticSeverity::Warning => {
dcx.emit_warn(FromLlvmDiag { message });
}
_ => {}
};
}
llvm::diagnostic::UnknownDiagnostic(..) => {}
}
}

Expand Down
46 changes: 44 additions & 2 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{assert_matches, iter, ptr};

use libc::{c_longlong, c_uint};
use rustc_abi::{Align, Endian, Layout, NumScalableVectors, Size};
use rustc_ast::{IntTy, UintTy};
use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo};
use rustc_codegen_ssa::traits::*;
use rustc_hir::def::{CtorKind, DefKind};
Expand Down Expand Up @@ -794,9 +795,50 @@ fn build_basic_type_di_node<'ll, 'tcx>(
_ => bug!("debuginfo::build_basic_type_di_node - `t` is invalid type"),
};

let ty_di_node = create_basic_type(cx, name, cx.size_of(t), encoding);
// Around LLDB 21 or 22, LLDB started using prebuilt Clang type nodes for primitives rather than
// reading the full DWARF data. These nodes are based on the size and signedness of the
// primitive, and ignore pretty much all other fields. This causes 2 issues:
// 1. type names get normalized to C-style names which isn't ideal. The normalization occurs
// even in generic args.
// 2. if you have a generic type `S<T>`, and 2 instantiations are `S<u64>`
// and `S<usize>` (on a 64-bit target), the use of prebuilt nodes causes a name collision.
// Whichever instantiation is interacted with first will work fine, all others will break a
// bunch of stuff in the LLDB pipeline. To avoid this, we explicitly treat `usize` and `isize`
// as typedefs of their equivalent types. For more info see: llvm/llvm-project#196812

let mut needs_typedef = cpp_like_debuginfo;

let ty_di_node = match t.kind() {
ty::Uint(UintTy::Usize) => {
needs_typedef = true;

let equivalent = match t.primitive_size(cx.tcx).bits() {
8 => cx.tcx.types.u8,
16 => cx.tcx.types.u16,
32 => cx.tcx.types.u32,
64 => cx.tcx.types.u64,
128 => cx.tcx.types.u128,
x => bug!("Unexpected signed int size {x}"),
};
type_di_node(cx, equivalent)
}
ty::Int(IntTy::Isize) => {
needs_typedef = true;

let equivalent = match t.primitive_size(cx.tcx).bits() {
8 => cx.tcx.types.i8,
16 => cx.tcx.types.i16,
32 => cx.tcx.types.i32,
64 => cx.tcx.types.i64,
128 => cx.tcx.types.i128,
x => bug!("Unexpected signed int size: {x}"),
};
type_di_node(cx, equivalent)
}
_ => create_basic_type(cx, name, cx.size_of(t), encoding),
};

if !cpp_like_debuginfo {
if !needs_typedef {
return DINodeCreationResult::new(ty_di_node, false);
}

Expand Down
33 changes: 13 additions & 20 deletions compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ impl<'ll> OptimizationDiagnostic<'ll> {
}

pub(crate) struct SrcMgrDiagnostic {
pub level: super::DiagnosticLevel,
pub message: String,
pub source: Option<(String, Vec<InnerSpan>)>,
}
Expand All @@ -86,7 +85,6 @@ impl SrcMgrDiagnostic {
// diagnostics.
let mut have_source = false;
let mut buffer = String::new();
let mut level = super::DiagnosticLevel::Error;
let mut loc = 0;
let mut ranges = [0; 8];
let mut num_ranges = ranges.len() / 2;
Expand All @@ -96,7 +94,6 @@ impl SrcMgrDiagnostic {
diag,
message,
buffer,
&mut level,
&mut loc,
ranges.as_mut_ptr(),
&mut num_ranges,
Expand All @@ -108,7 +105,6 @@ impl SrcMgrDiagnostic {

SrcMgrDiagnostic {
message,
level,
source: have_source.then(|| {
let mut spans = vec![InnerSpan::new(loc as usize, loc as usize)];
for i in 0..num_ranges {
Expand All @@ -122,7 +118,7 @@ impl SrcMgrDiagnostic {

#[derive(Clone)]
pub(crate) struct InlineAsmDiagnostic {
pub level: super::DiagnosticLevel,
pub severity: super::DiagnosticSeverity,
pub cookie: u64,
pub message: String,
pub source: Option<(String, Vec<InnerSpan>)>,
Expand All @@ -132,14 +128,13 @@ impl InlineAsmDiagnostic {
unsafe fn unpackInlineAsm(di: &DiagnosticInfo) -> Self {
let mut cookie = 0;
let mut message = None;
let mut level = super::DiagnosticLevel::Error;

unsafe {
super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message);
super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut cookie, &mut message);
}

InlineAsmDiagnostic {
level,
severity: di.severity(),
cookie,
message: super::twine_to_string(message.unwrap()),
source: None,
Expand All @@ -151,7 +146,7 @@ impl InlineAsmDiagnostic {
let smdiag =
unsafe { SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie)) };
InlineAsmDiagnostic {
level: smdiag.level,
severity: di.severity(),
cookie,
message: smdiag.message,
source: smdiag.source,
Expand All @@ -162,13 +157,9 @@ impl InlineAsmDiagnostic {
pub(crate) enum Diagnostic<'ll> {
Optimization(OptimizationDiagnostic<'ll>),
InlineAsm(InlineAsmDiagnostic),
PGO(&'ll DiagnosticInfo),
Linker(&'ll DiagnosticInfo),
Unsupported(&'ll DiagnosticInfo),

/// LLVM has other types that we do not wrap here.
#[expect(dead_code)]
UnknownDiagnostic(&'ll DiagnosticInfo),
/// LLVM has other types that we do not distinguish here.
Other(&'ll DiagnosticInfo),
}

impl<'ll> Diagnostic<'ll> {
Expand Down Expand Up @@ -206,14 +197,16 @@ impl<'ll> Diagnostic<'ll> {
Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di))
}

Dk::PGOProfile => PGO(di),
Dk::Linker => Linker(di),
Dk::Unsupported => Unsupported(di),

Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)),

_ => UnknownDiagnostic(di),
_ => Other(di),
}
}
}
}

impl DiagnosticInfo {
pub(crate) fn severity(&self) -> super::DiagnosticSeverity {
unsafe { super::LLVMGetDiagInfoSeverity(self) }
}
}
9 changes: 4 additions & 5 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,15 +551,15 @@ pub(crate) enum DiagnosticKind {
SrcMgr,
}

/// LLVMRustDiagnosticLevel
/// LLVMDiagnosticSeverity
#[derive(Copy, Clone)]
#[repr(C)]
#[allow(dead_code)] // Variants constructed by C++.
pub(crate) enum DiagnosticLevel {
pub(crate) enum DiagnosticSeverity {
Error,
Warning,
Note,
Remark,
Note,
}

unsafe extern "C" {
Expand Down Expand Up @@ -2502,13 +2502,13 @@ unsafe extern "C" {

pub(crate) fn LLVMRustUnpackInlineAsmDiagnostic<'a>(
DI: &'a DiagnosticInfo,
level_out: &mut DiagnosticLevel,
cookie_out: &mut u64,
message_out: &mut Option<&'a Twine>,
);

pub(crate) fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString);
pub(crate) fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind;
pub(crate) fn LLVMGetDiagInfoSeverity(DI: &DiagnosticInfo) -> DiagnosticSeverity;

pub(crate) fn LLVMRustGetSMDiagnostic<'a>(
DI: &'a DiagnosticInfo,
Expand All @@ -2519,7 +2519,6 @@ unsafe extern "C" {
d: &SMDiagnostic,
message_out: &RustString,
buffer_out: &RustString,
level_out: &mut DiagnosticLevel,
loc_out: &mut c_uint,
ranges_out: *mut c_uint,
num_ranges: &mut usize,
Expand Down
18 changes: 10 additions & 8 deletions compiler/rustc_lint/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2299,19 +2299,21 @@ pub(crate) enum InvalidNanComparisons {
#[derive(Subdiagnostic)]
pub(crate) enum InvalidNanComparisonsSuggestion {
#[multipart_suggestion(
"use `f32::is_nan()` or `f64::is_nan()` instead",
"use the `is_nan` method instead",
style = "verbose",
applicability = "machine-applicable"
)]
Spanful {
#[suggestion_part(code = "!")]
neg: Option<Span>,
#[suggestion_part(code = ".is_nan()")]
float: Span,
Ufcs {
prefix: String,
#[suggestion_part(code = "{prefix}")]
prefix_span: Span,
suffix: &'static str,
#[suggestion_part(code = "{suffix}")]
close_span: Span,
#[suggestion_part(code = "")]
nan_plus_binop: Span,
remove_nan: Span,
},
#[help("use `f32::is_nan()` or `f64::is_nan()` instead")]
#[help("use the `is_nan` method instead")]
Spanless,
}

Expand Down
Loading
Loading