From 0276d9f1f41740d9757de9e0b0e3500a77f0cfb1 Mon Sep 17 00:00:00 2001 From: Haoran Wang Date: Mon, 25 May 2026 01:59:27 +0800 Subject: [PATCH 1/5] Suggest function-local constructors without enclosing function path --- .../src/fn_ctxt/suggestions.rs | 7 +- .../wrap-function-local-constructors.fixed | 63 ++++++++++++ .../wrap-function-local-constructors.rs | 63 ++++++++++++ .../wrap-function-local-constructors.stderr | 95 +++++++++++++++++++ 4 files changed, 225 insertions(+), 3 deletions(-) create mode 100644 tests/ui/suggestions/wrap-function-local-constructors.fixed create mode 100644 tests/ui/suggestions/wrap-function-local-constructors.rs create mode 100644 tests/ui/suggestions/wrap-function-local-constructors.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 323f0fb040d6b..6007c4ca9e359 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -18,7 +18,7 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_hir_analysis::suggest_impl_trait; use rustc_middle::middle::stability::EvalResult; use rustc_middle::span_bug; -use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::print::{with_no_trimmed_paths, with_types_for_suggestion}; use rustc_middle::ty::{ self, Article, Binder, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Unnormalized, Upcast, suggest_constraining_type_params, @@ -2679,8 +2679,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sole_field_ty = sole_field.ty(self.tcx, args).skip_norm_wip(); if self.may_coerce(expr_ty, sole_field_ty) { - let variant_path = - with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id)); + let variant_path = with_types_for_suggestion!(with_no_trimmed_paths!( + self.tcx.def_path_str(variant.def_id) + )); // FIXME #56861: DRYer prelude filtering if let Some(path) = variant_path.strip_prefix("std::prelude::") && let Some((_, path)) = path.split_once("::") diff --git a/tests/ui/suggestions/wrap-function-local-constructors.fixed b/tests/ui/suggestions/wrap-function-local-constructors.fixed new file mode 100644 index 0000000000000..bc71d874e3dc2 --- /dev/null +++ b/tests/ui/suggestions/wrap-function-local-constructors.fixed @@ -0,0 +1,63 @@ +//@ run-rustfix + +// Regression test for https://github.com/rust-lang/rust/issues/144319. +// Function-local constructors cannot be named through the enclosing function +// path. The suggestion must omit path segments that cannot be written in source, +// while preserving real path segments like local modules and enums. + +#![allow(dead_code)] + +fn direct_tuple_struct() { + struct Foo(bool); + struct Bar(Foo); + + _ = Bar(Foo(false)); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in `Foo` +} + +fn enum_variant() { + enum LocalResult { + Ok(T), + } + struct Bar(LocalResult); + + _ = Bar(LocalResult::Ok(false)); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in `LocalResult::Ok` +} + +fn local_module() { + mod inner { + pub struct Foo(pub bool); + } + struct Bar(inner::Foo); + + _ = Bar(inner::Foo(false)); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in `inner::Foo` +} + +fn closure_body() { + let _ = || { + struct Foo(bool); + struct Bar(Foo); + + _ = Bar(Foo(false)); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in `Foo` + }; +} + +fn inline_const_block() { + const { + struct Foo(bool); + struct Bar(Foo); + + _ = Bar(Foo(false)); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in `Foo` + }; +} + +pub fn main() {} diff --git a/tests/ui/suggestions/wrap-function-local-constructors.rs b/tests/ui/suggestions/wrap-function-local-constructors.rs new file mode 100644 index 0000000000000..88ba87edadcbf --- /dev/null +++ b/tests/ui/suggestions/wrap-function-local-constructors.rs @@ -0,0 +1,63 @@ +//@ run-rustfix + +// Regression test for https://github.com/rust-lang/rust/issues/144319. +// Function-local constructors cannot be named through the enclosing function +// path. The suggestion must omit path segments that cannot be written in source, +// while preserving real path segments like local modules and enums. + +#![allow(dead_code)] + +fn direct_tuple_struct() { + struct Foo(bool); + struct Bar(Foo); + + _ = Bar(false); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in `Foo` +} + +fn enum_variant() { + enum LocalResult { + Ok(T), + } + struct Bar(LocalResult); + + _ = Bar(false); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in `LocalResult::Ok` +} + +fn local_module() { + mod inner { + pub struct Foo(pub bool); + } + struct Bar(inner::Foo); + + _ = Bar(false); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in `inner::Foo` +} + +fn closure_body() { + let _ = || { + struct Foo(bool); + struct Bar(Foo); + + _ = Bar(false); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in `Foo` + }; +} + +fn inline_const_block() { + const { + struct Foo(bool); + struct Bar(Foo); + + _ = Bar(false); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in `Foo` + }; +} + +pub fn main() {} diff --git a/tests/ui/suggestions/wrap-function-local-constructors.stderr b/tests/ui/suggestions/wrap-function-local-constructors.stderr new file mode 100644 index 0000000000000..e883697721ca1 --- /dev/null +++ b/tests/ui/suggestions/wrap-function-local-constructors.stderr @@ -0,0 +1,95 @@ +error[E0308]: mismatched types + --> $DIR/wrap-function-local-constructors.rs:14:13 + | +LL | _ = Bar(false); + | --- ^^^^^ expected `Foo`, found `bool` + | | + | arguments to this struct are incorrect + | +note: tuple struct defined here + --> $DIR/wrap-function-local-constructors.rs:12:12 + | +LL | struct Bar(Foo); + | ^^^ +help: try wrapping the expression in `Foo` + | +LL | _ = Bar(Foo(false)); + | ++++ + + +error[E0308]: mismatched types + --> $DIR/wrap-function-local-constructors.rs:25:13 + | +LL | _ = Bar(false); + | --- ^^^^^ expected `LocalResult`, found `bool` + | | + | arguments to this struct are incorrect + | + = note: expected enum `LocalResult` + found type `bool` +note: tuple struct defined here + --> $DIR/wrap-function-local-constructors.rs:23:12 + | +LL | struct Bar(LocalResult); + | ^^^ +help: try wrapping the expression in `LocalResult::Ok` + | +LL | _ = Bar(LocalResult::Ok(false)); + | ++++++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/wrap-function-local-constructors.rs:36:13 + | +LL | _ = Bar(false); + | --- ^^^^^ expected `Foo`, found `bool` + | | + | arguments to this struct are incorrect + | +note: tuple struct defined here + --> $DIR/wrap-function-local-constructors.rs:34:12 + | +LL | struct Bar(inner::Foo); + | ^^^ +help: try wrapping the expression in `inner::Foo` + | +LL | _ = Bar(inner::Foo(false)); + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/wrap-function-local-constructors.rs:46:17 + | +LL | _ = Bar(false); + | --- ^^^^^ expected `Foo`, found `bool` + | | + | arguments to this struct are incorrect + | +note: tuple struct defined here + --> $DIR/wrap-function-local-constructors.rs:44:16 + | +LL | struct Bar(Foo); + | ^^^ +help: try wrapping the expression in `Foo` + | +LL | _ = Bar(Foo(false)); + | ++++ + + +error[E0308]: mismatched types + --> $DIR/wrap-function-local-constructors.rs:57:17 + | +LL | _ = Bar(false); + | --- ^^^^^ expected `Foo`, found `bool` + | | + | arguments to this struct are incorrect + | +note: tuple struct defined here + --> $DIR/wrap-function-local-constructors.rs:55:16 + | +LL | struct Bar(Foo); + | ^^^ +help: try wrapping the expression in `Foo` + | +LL | _ = Bar(Foo(false)); + | ++++ + + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. From e2521e694d3cf39ceff5a22a699ee7b29a3c9241 Mon Sep 17 00:00:00 2001 From: Kokoro2336 <2529677678@qq.com> Date: Wed, 27 May 2026 17:44:29 +0800 Subject: [PATCH 2/5] fix: missing note of escaping `{` for whitespaces. --- compiler/rustc_builtin_macros/src/format.rs | 14 +++++++++++++- tests/ui/fmt/format-string-error-2.rs | 11 +++++++++++ tests/ui/fmt/format-string-error-2.stderr | 19 ++++++++++++++++++- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 7c43693e15f84..6bb3fa884027e 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -987,6 +987,7 @@ fn report_invalid_references( // Collect all the implicit positions: let mut spans = Vec::new(); let mut num_placeholders = 0; + let mut has_white_space_only_missing_arg = false; for piece in template { let mut placeholder = None; // `{arg:.*}` @@ -1009,13 +1010,21 @@ fn report_invalid_references( } // `{}` if let FormatArgsPiece::Placeholder(FormatPlaceholder { - argument: FormatArgPosition { kind: FormatArgPositionKind::Implicit, .. }, + argument: FormatArgPosition { kind: FormatArgPositionKind::Implicit, index, .. }, span, .. }) = piece { placeholder = *span; num_placeholders += 1; + // Check whether there's any non-space whitespace in the placeholder. If so, we should emit a note suggesting an escaping `{`. + if index.is_err() + && let Some(span) = span + && let Ok(snippet) = ecx.source_map().span_to_snippet(*span) + && snippet.chars().any(|c| c.is_whitespace() && c != ' ') + { + has_white_space_only_missing_arg = true; + } } // For `{:.*}`, we only push one span. spans.extend(placeholder); @@ -1071,6 +1080,9 @@ fn report_invalid_references( if has_precision_star { e.note("positional arguments are zero-based"); } + if has_white_space_only_missing_arg { + e.note("if you intended to print `{`, you can escape it with `{{`"); + } } else { let mut indexes: Vec<_> = invalid_refs.iter().map(|&(index, _, _, _)| index).collect(); // Avoid `invalid reference to positional arguments 7 and 7 (there is 1 argument)` diff --git a/tests/ui/fmt/format-string-error-2.rs b/tests/ui/fmt/format-string-error-2.rs index c1d228bfbc9c4..d28885b58809b 100644 --- a/tests/ui/fmt/format-string-error-2.rs +++ b/tests/ui/fmt/format-string-error-2.rs @@ -91,4 +91,15 @@ raw { \n println!("{x=}"); //~^ ERROR invalid format string: python's f-string debug `=` is not supported in rust, use `dbg(x)` instead + + println!( + "fn main() {\n\ + \n\ + }" + //~^^^ ERROR 1 positional argument in format string + ); + + // Don't emit note suggesting an escaping `{` for `{ }`. + println!("{ }"); + //~^ ERROR 1 positional argument in format string } diff --git a/tests/ui/fmt/format-string-error-2.stderr b/tests/ui/fmt/format-string-error-2.stderr index b12e827853f80..7c440a25220a8 100644 --- a/tests/ui/fmt/format-string-error-2.stderr +++ b/tests/ui/fmt/format-string-error-2.stderr @@ -208,5 +208,22 @@ LL | println!("{x=}"); | = note: to print `{`, you can escape it using `{{` -error: aborting due to 21 previous errors +error: 1 positional argument in format string, but no arguments were given + --> $DIR/format-string-error-2.rs:96:20 + | +LL | "fn main() {\n\ + | ____________________^ +LL | | \n\ +LL | | }" + | |_________^ + | + = note: if you intended to print `{`, you can escape it with `{{` + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/format-string-error-2.rs:103:15 + | +LL | println!("{ }"); + | ^^^ + +error: aborting due to 23 previous errors From c8449aa9587325b8c4faa145e148dd1f23ec4d4c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 19 May 2026 15:37:54 +1000 Subject: [PATCH 3/5] Use `LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision` --- .../src/debuginfo/metadata/enums/mod.rs | 29 ++++++++++++------- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 24 +++++++-------- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 9 ------ 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 556158c286a84..f7fe0eb8cb3b8 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -21,8 +21,8 @@ use crate::debuginfo::metadata::{ file_metadata_from_def_id, type_di_node, unknown_file_metadata, }; use crate::debuginfo::utils::{DIB, create_DIArray, get_namespace_for_item}; -use crate::llvm; use crate::llvm::debuginfo::{DIFlags, DIType}; +use crate::llvm::{self, ToLlvmBool}; mod cpp_like; mod native; @@ -111,16 +111,23 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( let (size, align) = cx.size_and_align_of(base_type); let enumerator_di_nodes: SmallVec> = enumerators - .map(|(name, value)| unsafe { - let value = [value as u64, (value >> 64) as u64]; - Some(llvm::LLVMRustDIBuilderCreateEnumerator( - DIB(cx), - name.as_c_char_ptr(), - name.len(), - value.as_ptr(), - size.bits() as libc::c_uint, - is_unsigned, - )) + .map(|(name, value)| { + let value_words = [value as u64, (value >> 64) as u64]; + let size_in_bits = size.bits(); + // LLVM computes `NumWords = (SizeInBits + 63) / 64`. + assert!((size_in_bits + 63) / 64 <= value_words.len() as u64); + + let enumerator = unsafe { + llvm::LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision( + DIB(cx), + name.as_ptr(), + name.len(), + size_in_bits, + value_words.as_ptr(), + is_unsigned.to_llvm_bool(), + ) + }; + Some(enumerator) }) .collect(); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 2728152b5d209..27660ff2ed55c 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -22,9 +22,8 @@ use libc::{c_char, c_int, c_uchar, c_uint, c_ulonglong, c_void, size_t}; use super::RustString; use super::debuginfo::{ - DIArray, DIBuilder, DIDerivedType, DIDescriptor, DIEnumerator, DIFile, DIFlags, DILocation, - DISPFlags, DIScope, DISubprogram, DITemplateTypeParameter, DIType, DebugEmissionKind, - DebugNameTableKind, + DIArray, DIBuilder, DIDerivedType, DIDescriptor, DIFile, DIFlags, DILocation, DISPFlags, + DIScope, DISubprogram, DITemplateTypeParameter, DIType, DebugEmissionKind, DebugNameTableKind, }; use crate::llvm::MetadataKindId; use crate::{TryFromU32, llvm}; @@ -752,7 +751,6 @@ pub(crate) mod debuginfo { pub(crate) type DICompositeType = DIDerivedType; pub(crate) type DIVariable = DIDescriptor; pub(crate) type DIArray = DIDescriptor; - pub(crate) type DIEnumerator = DIDescriptor; pub(crate) type DITemplateTypeParameter = DIDescriptor; bitflags! { @@ -1794,6 +1792,15 @@ unsafe extern "C" { Flags: DIFlags, // (default is `DIFlags::DIFlagZero`) ) -> &'ll Metadata; + pub(crate) fn LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision<'ll>( + Builder: &DIBuilder<'ll>, + Name: *const c_uchar, // See "PTR_LEN_STR". + NameLen: size_t, + SizeInBits: u64, + Words: *const u64, // LLVM computes `NumWords = (SizeInBits + 63) / 64`. + IsUnsigned: llvm::Bool, + ) -> &'ll Metadata; + pub(crate) fn LLVMDIBuilderCreateUnionType<'ll>( Builder: &DIBuilder<'ll>, Scope: Option<&'ll Metadata>, @@ -2286,15 +2293,6 @@ unsafe extern "C" { Ty: &'a DIType, ) -> &'a DIType; - pub(crate) fn LLVMRustDIBuilderCreateEnumerator<'a>( - Builder: &DIBuilder<'a>, - Name: *const c_char, - NameLen: size_t, - Value: *const u64, - SizeInBits: c_uint, - IsUnsigned: bool, - ) -> &'a DIEnumerator; - pub(crate) fn LLVMRustDIBuilderCreateEnumerationType<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 63e3119ee96f7..28037d28fa44a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1198,15 +1198,6 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType( fromRust(Flags), unwrapDI(Ty))); } -extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateEnumerator(LLVMDIBuilderRef Builder, const char *Name, - size_t NameLen, const uint64_t Value[2], - unsigned SizeInBits, bool IsUnsigned) { - return wrap(unwrap(Builder)->createEnumerator( - StringRef(Name, NameLen), - APSInt(APInt(SizeInBits, ArrayRef(Value, 2)), IsUnsigned))); -} - extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType( LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, From 12ad5b7c525a826f2f353e07ccd689e0cb2a88d8 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 19 May 2026 20:15:33 +1000 Subject: [PATCH 4/5] Explain why the remaining debuginfo bindings don't use LLVM-C --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 27660ff2ed55c..3db3c498f87b5 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2215,6 +2215,9 @@ unsafe extern "C" { ValueLen: size_t, ); + /// We can't use LLVM-C's `LLVMDIBuilderCreateCompileUnit` because it hardcodes + /// `DICompileUnit::DebugNameTableKind::Default`, but we want to be able to + /// pass other values. pub(crate) fn LLVMRustDIBuilderCreateCompileUnit<'a>( Builder: &DIBuilder<'a>, Lang: c_uint, @@ -2232,6 +2235,8 @@ unsafe extern "C" { DebugNameTableKind: DebugNameTableKind, ) -> &'a DIDescriptor; + /// We can't use LLVM-C's `LLVMDIBuilderCreateFileWithChecksum` because it + /// _requires_ a checksum, but we sometimes don't provide one. pub(crate) fn LLVMRustDIBuilderCreateFile<'a>( Builder: &DIBuilder<'a>, Filename: *const c_char, @@ -2245,6 +2250,8 @@ unsafe extern "C" { SourceLen: size_t, ) -> &'a DIFile; + /// We can't use LLVM-C's `LLVMDIBuilderCreateFunction` because it only + /// supports a subset of `DISubprogram::DISPFlags`. pub(crate) fn LLVMRustDIBuilderCreateFunction<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIDescriptor, @@ -2263,6 +2270,7 @@ unsafe extern "C" { Decl: Option<&'a DIDescriptor>, ) -> &'a DISubprogram; + /// As of LLVM 22 there is no corresponding LLVM-C function. pub(crate) fn LLVMRustDIBuilderCreateMethod<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIDescriptor, @@ -2278,6 +2286,7 @@ unsafe extern "C" { TParam: &'a DIArray, ) -> &'a DISubprogram; + /// As of LLVM 22 there is no corresponding LLVM-C function. pub(crate) fn LLVMRustDIBuilderCreateVariantMemberType<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, @@ -2293,6 +2302,7 @@ unsafe extern "C" { Ty: &'a DIType, ) -> &'a DIType; + /// As of LLVM 22 there is no corresponding LLVM-C function. pub(crate) fn LLVMRustDIBuilderCreateEnumerationType<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, @@ -2307,6 +2317,7 @@ unsafe extern "C" { IsScoped: bool, ) -> &'a DIType; + /// As of LLVM 22 there is no corresponding LLVM-C function. pub(crate) fn LLVMRustDIBuilderCreateVariantPart<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, @@ -2323,6 +2334,7 @@ unsafe extern "C" { UniqueIdLen: size_t, ) -> &'a DIDerivedType; + /// As of LLVM 22 there is no corresponding LLVM-C function. pub(crate) fn LLVMRustDIBuilderCreateTemplateTypeParameter<'a>( Builder: &DIBuilder<'a>, Scope: Option<&'a DIScope>, @@ -2331,6 +2343,8 @@ unsafe extern "C" { Ty: &'a DIType, ) -> &'a DITemplateTypeParameter; + /// We can't use LLVM-C's `LLVMReplaceArrays` because it doesn't take a + /// `Params` argument. pub(crate) fn LLVMRustDICompositeTypeReplaceArrays<'a>( Builder: &DIBuilder<'a>, CompositeType: &'a DIType, @@ -2338,6 +2352,8 @@ unsafe extern "C" { Params: Option<&'a DIArray>, ); + /// We can't use LLVM-C's `LLVMDIBuilderGetOrCreateSubrange` because it doesn't + /// call the overload that takes a `Metadata` upper bound. pub(crate) fn LLVMRustDIGetOrCreateSubrange<'a>( Builder: &DIBuilder<'a>, CountNode: Option<&'a Metadata>, @@ -2346,6 +2362,8 @@ unsafe extern "C" { Stride: Option<&'a Metadata>, ) -> &'a Metadata; + /// We can't use LLVM-C's `LLVMDIBuilderCreateVectorType` because it doesn't + /// take a `BitStride` argument. pub(crate) fn LLVMRustDICreateVectorType<'a>( Builder: &DIBuilder<'a>, Size: u64, @@ -2355,6 +2373,7 @@ unsafe extern "C" { BitStride: Option<&'a Metadata>, ) -> &'a Metadata; + /// As of LLVM 22 there is no corresponding LLVM-C function. pub(crate) fn LLVMRustDILocationCloneWithBaseDiscriminator<'a>( Location: &'a DILocation, BD: c_uint, From d59cae8cf13fd548c0fa96b45bf04a7907c1ae86 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 28 May 2026 12:47:38 +1000 Subject: [PATCH 5/5] Note some bindings that can be replaced after dropping LLVM 21 support --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 3db3c498f87b5..eb9b2ab121296 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1996,6 +1996,7 @@ unsafe extern "C" { pub(crate) fn LLVMRustDisableSystemDialogsOnCrash(); // Operations on all values + /// FIXME: After dropping LLVM 21, migrate to LLVM-C's `LLVMGlobalAddMetadata`. pub(crate) fn LLVMRustGlobalAddMetadata<'a>( Val: &'a Value, KindID: MetadataKindId, @@ -2065,6 +2066,7 @@ unsafe extern "C" { ) -> &Attribute; // Operations on functions + /// FIXME: After dropping LLVM 21, migrate to LLVM-C's `LLVMGetOrInsertFunction`. pub(crate) fn LLVMRustGetOrInsertFunction<'a>( M: &'a Module, Name: *const c_char,