authorbors <bors@rust-lang.org> 2026-05-28 13:21:14 UTC
committerbors <bors@rust-lang.org> 2026-05-28 13:21:14 UTC
log8c1d72083bb2b7b9df8cbbf06a57d240a007bd85
treea0911da1789c269f999b277de0fcc4130f7e08d7
parentb5e038d7158c1af55a646027fdacf5ecd7c783c7
parent5cd06d184305e3e3fcaf9fee603e36dd2ab0b59f

Auto merge of #157064 - JonathanBrouwer:rollup-BDFNumV, r=JonathanBrouwer

Rollup of 7 pull requests Successful merges: - rust-lang/rust#157046 (file locking: clarify that double-locking is underspecified) - rust-lang/rust#156401 (rustdoc: deterministic sorting for `doc_cfg` badges) - rust-lang/rust#156746 (cg_llvm: Use `LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision`) - rust-lang/rust#156889 (Suggest function-local constructors without enclosing function path) - rust-lang/rust#157012 (Fix missing note of escaping `{` for braces including whitespaces) - rust-lang/rust#157056 (Update Xtensa target data layouts to match upstream LLVM) - rust-lang/rust#157062 (Add link to RFMF Sponsors page)

30 files changed, 520 insertions(+), 99 deletions(-)

.github/FUNDING.yml+1
......@@ -1 +1,2 @@
1github: rustfoundation
12custom: ["rust-lang.org/funding"]
compiler/rustc_builtin_macros/src/format.rs+13-1
......@@ -987,6 +987,7 @@ fn report_invalid_references(
987987 // Collect all the implicit positions:
988988 let mut spans = Vec::new();
989989 let mut num_placeholders = 0;
990 let mut has_white_space_only_missing_arg = false;
990991 for piece in template {
991992 let mut placeholder = None;
992993 // `{arg:.*}`
......@@ -1009,13 +1010,21 @@ fn report_invalid_references(
10091010 }
10101011 // `{}`
10111012 if let FormatArgsPiece::Placeholder(FormatPlaceholder {
1012 argument: FormatArgPosition { kind: FormatArgPositionKind::Implicit, .. },
1013 argument: FormatArgPosition { kind: FormatArgPositionKind::Implicit, index, .. },
10131014 span,
10141015 ..
10151016 }) = piece
10161017 {
10171018 placeholder = *span;
10181019 num_placeholders += 1;
1020 // Check whether there's any non-space whitespace in the placeholder. If so, we should emit a note suggesting an escaping `{`.
1021 if index.is_err()
1022 && let Some(span) = span
1023 && let Ok(snippet) = ecx.source_map().span_to_snippet(*span)
1024 && snippet.chars().any(|c| c.is_whitespace() && c != ' ')
1025 {
1026 has_white_space_only_missing_arg = true;
1027 }
10191028 }
10201029 // For `{:.*}`, we only push one span.
10211030 spans.extend(placeholder);
......@@ -1071,6 +1080,9 @@ fn report_invalid_references(
10711080 if has_precision_star {
10721081 e.note("positional arguments are zero-based");
10731082 }
1083 if has_white_space_only_missing_arg {
1084 e.note("if you intended to print `{`, you can escape it with `{{`");
1085 }
10741086 } else {
10751087 let mut indexes: Vec<_> = invalid_refs.iter().map(|&(index, _, _, _)| index).collect();
10761088 // Avoid `invalid reference to positional arguments 7 and 7 (there is 1 argument)`
compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs+18-11
......@@ -21,8 +21,8 @@ use crate::debuginfo::metadata::{
2121 file_metadata_from_def_id, type_di_node, unknown_file_metadata,
2222};
2323use crate::debuginfo::utils::{DIB, create_DIArray, get_namespace_for_item};
24use crate::llvm;
2524use crate::llvm::debuginfo::{DIFlags, DIType};
25use crate::llvm::{self, ToLlvmBool};
2626
2727mod cpp_like;
2828mod native;
......@@ -111,16 +111,23 @@ fn build_enumeration_type_di_node<'ll, 'tcx>(
111111 let (size, align) = cx.size_and_align_of(base_type);
112112
113113 let enumerator_di_nodes: SmallVec<Option<&'ll DIType>> = enumerators
114 .map(|(name, value)| unsafe {
115 let value = [value as u64, (value >> 64) as u64];
116 Some(llvm::LLVMRustDIBuilderCreateEnumerator(
117 DIB(cx),
118 name.as_c_char_ptr(),
119 name.len(),
120 value.as_ptr(),
121 size.bits() as libc::c_uint,
122 is_unsigned,
123 ))
114 .map(|(name, value)| {
115 let value_words = [value as u64, (value >> 64) as u64];
116 let size_in_bits = size.bits();
117 // LLVM computes `NumWords = (SizeInBits + 63) / 64`.
118 assert!((size_in_bits + 63) / 64 <= value_words.len() as u64);
119
120 let enumerator = unsafe {
121 llvm::LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision(
122 DIB(cx),
123 name.as_ptr(),
124 name.len(),
125 size_in_bits,
126 value_words.as_ptr(),
127 is_unsigned.to_llvm_bool(),
128 )
129 };
130 Some(enumerator)
124131 })
125132 .collect();
126133
compiler/rustc_codegen_llvm/src/llvm/ffi.rs+32-13
......@@ -22,9 +22,8 @@ use libc::{c_char, c_int, c_uchar, c_uint, c_ulonglong, c_void, size_t};
2222
2323use super::RustString;
2424use super::debuginfo::{
25 DIArray, DIBuilder, DIDerivedType, DIDescriptor, DIEnumerator, DIFile, DIFlags, DILocation,
26 DISPFlags, DIScope, DISubprogram, DITemplateTypeParameter, DIType, DebugEmissionKind,
27 DebugNameTableKind,
25 DIArray, DIBuilder, DIDerivedType, DIDescriptor, DIFile, DIFlags, DILocation, DISPFlags,
26 DIScope, DISubprogram, DITemplateTypeParameter, DIType, DebugEmissionKind, DebugNameTableKind,
2827};
2928use crate::llvm::MetadataKindId;
3029use crate::{TryFromU32, llvm};
......@@ -752,7 +751,6 @@ pub(crate) mod debuginfo {
752751 pub(crate) type DICompositeType = DIDerivedType;
753752 pub(crate) type DIVariable = DIDescriptor;
754753 pub(crate) type DIArray = DIDescriptor;
755 pub(crate) type DIEnumerator = DIDescriptor;
756754 pub(crate) type DITemplateTypeParameter = DIDescriptor;
757755
758756 bitflags! {
......@@ -1794,6 +1792,15 @@ unsafe extern "C" {
17941792 Flags: DIFlags, // (default is `DIFlags::DIFlagZero`)
17951793 ) -> &'ll Metadata;
17961794
1795 pub(crate) fn LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision<'ll>(
1796 Builder: &DIBuilder<'ll>,
1797 Name: *const c_uchar, // See "PTR_LEN_STR".
1798 NameLen: size_t,
1799 SizeInBits: u64,
1800 Words: *const u64, // LLVM computes `NumWords = (SizeInBits + 63) / 64`.
1801 IsUnsigned: llvm::Bool,
1802 ) -> &'ll Metadata;
1803
17971804 pub(crate) fn LLVMDIBuilderCreateUnionType<'ll>(
17981805 Builder: &DIBuilder<'ll>,
17991806 Scope: Option<&'ll Metadata>,
......@@ -1989,6 +1996,7 @@ unsafe extern "C" {
19891996 pub(crate) fn LLVMRustDisableSystemDialogsOnCrash();
19901997
19911998 // Operations on all values
1999 /// FIXME: After dropping LLVM 21, migrate to LLVM-C's `LLVMGlobalAddMetadata`.
19922000 pub(crate) fn LLVMRustGlobalAddMetadata<'a>(
19932001 Val: &'a Value,
19942002 KindID: MetadataKindId,
......@@ -2058,6 +2066,7 @@ unsafe extern "C" {
20582066 ) -> &Attribute;
20592067
20602068 // Operations on functions
2069 /// FIXME: After dropping LLVM 21, migrate to LLVM-C's `LLVMGetOrInsertFunction`.
20612070 pub(crate) fn LLVMRustGetOrInsertFunction<'a>(
20622071 M: &'a Module,
20632072 Name: *const c_char,
......@@ -2208,6 +2217,9 @@ unsafe extern "C" {
22082217 ValueLen: size_t,
22092218 );
22102219
2220 /// We can't use LLVM-C's `LLVMDIBuilderCreateCompileUnit` because it hardcodes
2221 /// `DICompileUnit::DebugNameTableKind::Default`, but we want to be able to
2222 /// pass other values.
22112223 pub(crate) fn LLVMRustDIBuilderCreateCompileUnit<'a>(
22122224 Builder: &DIBuilder<'a>,
22132225 Lang: c_uint,
......@@ -2225,6 +2237,8 @@ unsafe extern "C" {
22252237 DebugNameTableKind: DebugNameTableKind,
22262238 ) -> &'a DIDescriptor;
22272239
2240 /// We can't use LLVM-C's `LLVMDIBuilderCreateFileWithChecksum` because it
2241 /// _requires_ a checksum, but we sometimes don't provide one.
22282242 pub(crate) fn LLVMRustDIBuilderCreateFile<'a>(
22292243 Builder: &DIBuilder<'a>,
22302244 Filename: *const c_char,
......@@ -2238,6 +2252,8 @@ unsafe extern "C" {
22382252 SourceLen: size_t,
22392253 ) -> &'a DIFile;
22402254
2255 /// We can't use LLVM-C's `LLVMDIBuilderCreateFunction` because it only
2256 /// supports a subset of `DISubprogram::DISPFlags`.
22412257 pub(crate) fn LLVMRustDIBuilderCreateFunction<'a>(
22422258 Builder: &DIBuilder<'a>,
22432259 Scope: &'a DIDescriptor,
......@@ -2256,6 +2272,7 @@ unsafe extern "C" {
22562272 Decl: Option<&'a DIDescriptor>,
22572273 ) -> &'a DISubprogram;
22582274
2275 /// As of LLVM 22 there is no corresponding LLVM-C function.
22592276 pub(crate) fn LLVMRustDIBuilderCreateMethod<'a>(
22602277 Builder: &DIBuilder<'a>,
22612278 Scope: &'a DIDescriptor,
......@@ -2271,6 +2288,7 @@ unsafe extern "C" {
22712288 TParam: &'a DIArray,
22722289 ) -> &'a DISubprogram;
22732290
2291 /// As of LLVM 22 there is no corresponding LLVM-C function.
22742292 pub(crate) fn LLVMRustDIBuilderCreateVariantMemberType<'a>(
22752293 Builder: &DIBuilder<'a>,
22762294 Scope: &'a DIScope,
......@@ -2286,15 +2304,7 @@ unsafe extern "C" {
22862304 Ty: &'a DIType,
22872305 ) -> &'a DIType;
22882306
2289 pub(crate) fn LLVMRustDIBuilderCreateEnumerator<'a>(
2290 Builder: &DIBuilder<'a>,
2291 Name: *const c_char,
2292 NameLen: size_t,
2293 Value: *const u64,
2294 SizeInBits: c_uint,
2295 IsUnsigned: bool,
2296 ) -> &'a DIEnumerator;
2297
2307 /// As of LLVM 22 there is no corresponding LLVM-C function.
22982308 pub(crate) fn LLVMRustDIBuilderCreateEnumerationType<'a>(
22992309 Builder: &DIBuilder<'a>,
23002310 Scope: &'a DIScope,
......@@ -2309,6 +2319,7 @@ unsafe extern "C" {
23092319 IsScoped: bool,
23102320 ) -> &'a DIType;
23112321
2322 /// As of LLVM 22 there is no corresponding LLVM-C function.
23122323 pub(crate) fn LLVMRustDIBuilderCreateVariantPart<'a>(
23132324 Builder: &DIBuilder<'a>,
23142325 Scope: &'a DIScope,
......@@ -2325,6 +2336,7 @@ unsafe extern "C" {
23252336 UniqueIdLen: size_t,
23262337 ) -> &'a DIDerivedType;
23272338
2339 /// As of LLVM 22 there is no corresponding LLVM-C function.
23282340 pub(crate) fn LLVMRustDIBuilderCreateTemplateTypeParameter<'a>(
23292341 Builder: &DIBuilder<'a>,
23302342 Scope: Option<&'a DIScope>,
......@@ -2333,6 +2345,8 @@ unsafe extern "C" {
23332345 Ty: &'a DIType,
23342346 ) -> &'a DITemplateTypeParameter;
23352347
2348 /// We can't use LLVM-C's `LLVMReplaceArrays` because it doesn't take a
2349 /// `Params` argument.
23362350 pub(crate) fn LLVMRustDICompositeTypeReplaceArrays<'a>(
23372351 Builder: &DIBuilder<'a>,
23382352 CompositeType: &'a DIType,
......@@ -2340,6 +2354,8 @@ unsafe extern "C" {
23402354 Params: Option<&'a DIArray>,
23412355 );
23422356
2357 /// We can't use LLVM-C's `LLVMDIBuilderGetOrCreateSubrange` because it doesn't
2358 /// call the overload that takes a `Metadata` upper bound.
23432359 pub(crate) fn LLVMRustDIGetOrCreateSubrange<'a>(
23442360 Builder: &DIBuilder<'a>,
23452361 CountNode: Option<&'a Metadata>,
......@@ -2348,6 +2364,8 @@ unsafe extern "C" {
23482364 Stride: Option<&'a Metadata>,
23492365 ) -> &'a Metadata;
23502366
2367 /// We can't use LLVM-C's `LLVMDIBuilderCreateVectorType` because it doesn't
2368 /// take a `BitStride` argument.
23512369 pub(crate) fn LLVMRustDICreateVectorType<'a>(
23522370 Builder: &DIBuilder<'a>,
23532371 Size: u64,
......@@ -2357,6 +2375,7 @@ unsafe extern "C" {
23572375 BitStride: Option<&'a Metadata>,
23582376 ) -> &'a Metadata;
23592377
2378 /// As of LLVM 22 there is no corresponding LLVM-C function.
23602379 pub(crate) fn LLVMRustDILocationCloneWithBaseDiscriminator<'a>(
23612380 Location: &'a DILocation,
23622381 BD: c_uint,
compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs+4-3
......@@ -18,7 +18,7 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
1818use rustc_hir_analysis::suggest_impl_trait;
1919use rustc_middle::middle::stability::EvalResult;
2020use rustc_middle::span_bug;
21use rustc_middle::ty::print::with_no_trimmed_paths;
21use rustc_middle::ty::print::{with_no_trimmed_paths, with_types_for_suggestion};
2222use rustc_middle::ty::{
2323 self, Article, Binder, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Unnormalized, Upcast,
2424 suggest_constraining_type_params,
......@@ -2679,8 +2679,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26792679
26802680 let sole_field_ty = sole_field.ty(self.tcx, args).skip_norm_wip();
26812681 if self.may_coerce(expr_ty, sole_field_ty) {
2682 let variant_path =
2683 with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
2682 let variant_path = with_types_for_suggestion!(with_no_trimmed_paths!(
2683 self.tcx.def_path_str(variant.def_id)
2684 ));
26842685 // FIXME #56861: DRYer prelude filtering
26852686 if let Some(path) = variant_path.strip_prefix("std::prelude::")
26862687 && let Some((_, path)) = path.split_once("::")
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp-9
......@@ -1198,15 +1198,6 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
11981198 fromRust(Flags), unwrapDI<DIType>(Ty)));
11991199}
12001200
1201extern "C" LLVMMetadataRef
1202LLVMRustDIBuilderCreateEnumerator(LLVMDIBuilderRef Builder, const char *Name,
1203 size_t NameLen, const uint64_t Value[2],
1204 unsigned SizeInBits, bool IsUnsigned) {
1205 return wrap(unwrap(Builder)->createEnumerator(
1206 StringRef(Name, NameLen),
1207 APSInt(APInt(SizeInBits, ArrayRef<uint64_t>(Value, 2)), IsUnsigned)));
1208}
1209
12101201extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
12111202 LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
12121203 size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs+1-1
......@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
77 Target {
88 llvm_target: "xtensa-none-elf".into(),
99 pointer_width: 32,
10 data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(),
10 data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32".into(),
1111 arch: Arch::Xtensa,
1212 metadata: TargetMetadata { description: None, tier: Some(3), host_tools: None, std: None },
1313
compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs+1-1
......@@ -5,7 +5,7 @@ pub(crate) fn target() -> Target {
55 Target {
66 llvm_target: "xtensa-none-elf".into(),
77 pointer_width: 32,
8 data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(),
8 data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32".into(),
99 arch: Arch::Xtensa,
1010 metadata: TargetMetadata {
1111 description: Some("Xtensa ESP32".into()),
compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs+1-1
......@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
77 Target {
88 llvm_target: "xtensa-none-elf".into(),
99 pointer_width: 32,
10 data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(),
10 data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32".into(),
1111 arch: Arch::Xtensa,
1212 metadata: TargetMetadata { description: None, tier: Some(3), host_tools: None, std: None },
1313
compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs+1-1
......@@ -5,7 +5,7 @@ pub(crate) fn target() -> Target {
55 Target {
66 llvm_target: "xtensa-none-elf".into(),
77 pointer_width: 32,
8 data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(),
8 data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32".into(),
99 arch: Arch::Xtensa,
1010 metadata: TargetMetadata {
1111 description: Some("Xtensa ESP32-S2".into()),
compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs+1-1
......@@ -7,7 +7,7 @@ pub(crate) fn target() -> Target {
77 Target {
88 llvm_target: "xtensa-none-elf".into(),
99 pointer_width: 32,
10 data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(),
10 data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32".into(),
1111 arch: Arch::Xtensa,
1212 metadata: TargetMetadata { description: None, tier: Some(3), host_tools: None, std: None },
1313
compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs+1-1
......@@ -5,7 +5,7 @@ pub(crate) fn target() -> Target {
55 Target {
66 llvm_target: "xtensa-none-elf".into(),
77 pointer_width: 32,
8 data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(),
8 data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32".into(),
99 arch: Arch::Xtensa,
1010 metadata: TargetMetadata {
1111 description: Some("Xtensa ESP32-S3".into()),
library/std/src/fs.rs+10-11
......@@ -815,18 +815,17 @@ impl File {
815815
816816 /// Acquire an exclusive lock on the file. Blocks until the lock can be acquired.
817817 ///
818 /// This acquires an exclusive lock; no other file handle to this file, in this or any other
818 /// This acquires an exclusive lock. No *other* file handle to this file, in this or any other
819819 /// process, may acquire another lock.
820 /// If this file handle/descriptor, or a clone of it, already holds a lock, the exact behavior
821 /// is unspecified and platform dependent, including the possibility that it will deadlock.
822 /// However, if this method returns, then an exclusive lock is held.
820823 ///
821824 /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`],
822825 /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with
823826 /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not
824827 /// cause non-lockholders to block.
825828 ///
826 /// If this file handle/descriptor, or a clone of it, already holds a lock the exact behavior
827 /// is unspecified and platform dependent, including the possibility that it will deadlock.
828 /// However, if this method returns, then an exclusive lock is held.
829 ///
830829 /// If the file is not open for writing, it is unspecified whether this function returns an error.
831830 ///
832831 /// The lock will be released when this file (along with any other file descriptors/handles
......@@ -869,18 +868,18 @@ impl File {
869868
870869 /// Acquire a shared (non-exclusive) lock on the file. Blocks until the lock can be acquired.
871870 ///
872 /// This acquires a shared lock; more than one file handle, in this or any other process, may
873 /// hold a shared lock, but none may hold an exclusive lock at the same time.
871 /// This acquires a shared lock. More than one file handle to this file, in this or any other
872 /// process, may hold a shared lock, but no *other* file handle may hold an exclusive lock at
873 /// the same time.
874 /// If this file handle/descriptor, or a clone of it, already holds a lock, the exact
875 /// behavior is unspecified and platform dependent, including the possibility that it will
876 /// deadlock. However, if this method returns, then a shared lock is held.
874877 ///
875878 /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`],
876879 /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with
877880 /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not
878881 /// cause non-lockholders to block.
879882 ///
880 /// If this file handle/descriptor, or a clone of it, already holds a lock, the exact behavior
881 /// is unspecified and platform dependent, including the possibility that it will deadlock.
882 /// However, if this method returns, then a shared lock is held.
883 ///
884883 /// The lock will be released when this file (along with any other file descriptors/handles
885884 /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.
886885 ///
library/std/src/fs/tests.rs+29-5
......@@ -305,18 +305,42 @@ fn file_lock_dup() {
305305}
306306
307307#[test]
308#[cfg(windows)]
309fn file_lock_double_unlock() {
308#[cfg_attr(
309 not(any(
310 windows,
311 target_os = "aix",
312 target_os = "cygwin",
313 target_os = "freebsd",
314 target_os = "fuchsia",
315 target_os = "hurd",
316 target_os = "illumos",
317 target_os = "linux",
318 target_os = "netbsd",
319 target_os = "openbsd",
320 target_os = "solaris",
321 target_vendor = "apple",
322 )),
323 should_panic
324)]
325fn file_lock_double() {
310326 let tmpdir = tmpdir();
311 let filename = &tmpdir.join("file_lock_double_unlock_test.txt");
327 let filename = &tmpdir.join("file_lock_double_test.txt");
312328 let f1 = check!(File::create(filename));
313329 let f2 = check!(OpenOptions::new().write(true).open(filename));
314330
315 // On Windows a file handle may acquire both a shared and exclusive lock.
316 // Check that both are released by unlock()
331 // A file handle may acquire both a shared and exclusive lock.
317332 check!(f1.lock());
318333 check!(f1.lock_shared());
334 // The behavior here differs between Windows and Unix: on Windows, f1 holds both locks;
335 // on Unix, the lock got downgraded so f1 only holds the shared lock.
319336 assert_matches!(f2.try_lock(), Err(TryLockError::WouldBlock));
337 if cfg!(windows) {
338 assert_matches!(f2.try_lock_shared(), Err(TryLockError::WouldBlock));
339 } else {
340 check!(f2.try_lock_shared());
341 check!(f2.unlock());
342 }
343 // Check that both are released by unlock().
320344 check!(f1.unlock());
321345 check!(f2.try_lock());
322346}
src/librustdoc/clean/cfg.rs+46-2
......@@ -187,6 +187,44 @@ impl Cfg {
187187 }
188188 }
189189
190 /// Recursively sorts the configuration tree to ensure deterministic rendering.
191 ///
192 /// Sorting groups predicates logically: Targets first, then Target Features,
193 /// then Crate Features, and finally nested Any/All/Not groupings.
194 /// Within each group, a fallback alphabetical sort is applied.
195 pub(crate) fn sort_for_rendering(&mut self) {
196 fn sort_cfg_entry(cfg: &mut CfgEntry) {
197 match cfg {
198 CfgEntry::Any(sub_cfgs, _) | CfgEntry::All(sub_cfgs, _) => {
199 for sub_cfg in sub_cfgs.iter_mut() {
200 sort_cfg_entry(sub_cfg);
201 }
202
203 sub_cfgs.sort_by_cached_key(|a| {
204 (
205 cfg_category(a),
206 Display(a, Format::LongPlain).to_string().to_ascii_lowercase(),
207 )
208 });
209 }
210 CfgEntry::Not(box_cfg, _) => sort_cfg_entry(box_cfg),
211 _ => {}
212 }
213 }
214
215 fn cfg_category(cfg: &CfgEntry) -> u8 {
216 match cfg {
217 CfgEntry::NameValue { name, .. } if *name == sym::feature => 2,
218 CfgEntry::NameValue { name, .. } if *name == sym::target_feature => 1,
219 CfgEntry::NameValue { .. } | CfgEntry::Bool(..) => 0,
220 CfgEntry::Any(..) | CfgEntry::All(..) | CfgEntry::Not(..) => 3,
221 _ => 4,
222 }
223 }
224
225 sort_cfg_entry(&mut self.0);
226 }
227
190228 fn omit_preposition(&self) -> bool {
191229 matches!(self.0, CfgEntry::Bool(..))
192230 }
......@@ -843,14 +881,20 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
843881 if matches!(cfg_info.current_cfg.0, CfgEntry::Bool(true, _)) {
844882 None
845883 } else {
846 Some(Arc::new(cfg_info.current_cfg.clone()))
884 let mut cfg = cfg_info.current_cfg.clone();
885 cfg.sort_for_rendering();
886 Some(Arc::new(cfg))
847887 }
848888 } else {
849889 // If `doc(auto_cfg)` feature is enabled, we want to collect all `cfg` items, we remove the
850890 // hidden ones afterward.
851891 match strip_hidden(&cfg_info.current_cfg.0, &cfg_info.hidden_cfg) {
852892 None | Some(CfgEntry::Bool(true, _)) => None,
853 Some(cfg) => Some(Arc::new(Cfg(cfg))),
893 Some(cfg_entry) => {
894 let mut cfg = Cfg(cfg_entry);
895 cfg.sort_for_rendering();
896 Some(Arc::new(cfg))
897 }
854898 }
855899 }
856900}
src/librustdoc/clean/cfg/tests.rs+31
......@@ -418,3 +418,34 @@ fn test_simplify_with() {
418418 assert_eq!(foobar.simplify_with(&foobarbaz), None);
419419 });
420420}
421
422#[test]
423fn test_sort_for_rendering() {
424 create_default_session_globals_then(|| {
425 let mut cfg = cfg_any(thin_vec![
426 name_value_cfg_e("feature", "sync"),
427 name_value_cfg_e("target_os", "linux"),
428 cfg_all_e(thin_vec![word_cfg_e("unix")]),
429 name_value_cfg_e("target_feature", "sse2"),
430 name_value_cfg_e("target_os", "android"),
431 name_value_cfg_e("feature", "alloc"),
432 ]);
433
434 cfg.sort_for_rendering();
435
436 let expected = cfg_any(thin_vec![
437 // Category 0: Targets (Sorted Alphabetically: Android -> Linux)
438 name_value_cfg_e("target_os", "android"),
439 name_value_cfg_e("target_os", "linux"),
440 // Category 1: Target Features
441 name_value_cfg_e("target_feature", "sse2"),
442 // Category 2: Crate Features (Sorted Alphabetically: alloc -> sync)
443 name_value_cfg_e("feature", "alloc"),
444 name_value_cfg_e("feature", "sync"),
445 // Category 3: Nested logic pushed to the end
446 cfg_all_e(thin_vec![word_cfg_e("unix")]),
447 ]);
448
449 assert_eq!(cfg, expected);
450 });
451}
tests/rustdoc-gui/item-info-overflow.goml+2-2
......@@ -8,7 +8,7 @@ assert-property: (".item-info", {"scrollWidth": "940"})
88// Just to be sure we're comparing the correct "item-info":
99assert-text: (
1010 ".item-info",
11 "Available on Android or Linux or Emscripten or DragonFly BSD or FreeBSD or NetBSD or OpenBSD",
11 "Available on Android or DragonFly BSD or Emscripten or FreeBSD or Linux or NetBSD or OpenBSD",
1212 STARTS_WITH,
1313)
1414
......@@ -26,6 +26,6 @@ assert-property: (
2626// Just to be sure we're comparing the correct "item-info":
2727assert-text: (
2828 "#impl-SimpleTrait-for-LongItemInfo2 .item-info",
29 "Available on Android or Linux or Emscripten or DragonFly BSD or FreeBSD or NetBSD or OpenBSD",
29 "Available on Android or DragonFly BSD or Emscripten or FreeBSD or Linux or NetBSD or OpenBSD",
3030 STARTS_WITH,
3131)
tests/rustdoc-gui/item-info.goml+2-2
......@@ -19,8 +19,8 @@ store-position: (
1919 "//*[@class='stab portability']//code[normalize-space()='Win32_System_Diagnostics']",
2020 {"x": second_line_x, "y": second_line_y},
2121)
22assert: |first_line_x| != |second_line_x| && |first_line_x| == 521 && |second_line_x| == 277
23assert: |first_line_y| != |second_line_y| && |first_line_y| == 676 && |second_line_y| == 699
22assert: |first_line_x| != |second_line_x| && |first_line_x| == 509 && |second_line_x| == 277
23assert: |first_line_y| == |second_line_y| && |first_line_y| == 699
2424
2525// Now we ensure that they're not rendered on the same line.
2626set-window-size: (1100, 800)
tests/rustdoc-html/doc-cfg/all-targets.rs+20-19
......@@ -2,10 +2,10 @@
22
33//@ has all_targets/fn.foo.html \
44// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
5// 'Available on GNU or Catalyst or Managarm C Library or MSVC or musl or Newlib or \
6// Neutrino 7.0 or Neutrino 7.1 or Neutrino 7.1 with io-sock or Neutrino 8.0 or \
7// OpenHarmony or relibc or SGX or Simulator or WASIp1 or WASIp2 or WASIp3 or \
8// uClibc or V5 or target_env=fake_env only.'
5// 'Available on target_env=fake_env or Catalyst or GNU or Managarm C Library \
6// or MSVC or musl or Neutrino 7.0 or Neutrino 7.1 or Neutrino 7.1 with io-sock \
7// or Neutrino 8.0 or Newlib or OpenHarmony or relibc or SGX or Simulator or \
8// uClibc or V5 or WASIp1 or WASIp2 or WASIp3 only.'
99#[doc(cfg(any(
1010 target_env = "gnu",
1111 target_env = "macabi",
......@@ -32,12 +32,12 @@ pub fn foo() {}
3232
3333//@ has all_targets/fn.bar.html \
3434// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
35// 'Available on AArch64 or AMD GPU or ARM or ARM64EC or AVR or BPF or C-SKY or \
36// Hexagon or LoongArch32 or LoongArch64 or Motorola 680x0 or MIPS or MIPS release \
37// 6 or MIPS-64 or MIPS-64 release 6 or MSP430 or NVidia GPU or PowerPC or \
38// PowerPC64 or RISC-V RV32 or RISC-V RV64 or s390x or SPARC or SPARC-64 or SPIR-V \
39// or WebAssembly or WebAssembly or x86 or x86-64 or Xtensa or \
40// target_arch=fake_arch only.'
35// 'Available on target_arch=fake_arch or AArch64 or AMD GPU or ARM or \
36// ARM64EC or AVR or BPF or C-SKY or Hexagon or LoongArch32 or LoongArch64 \
37// or MIPS or MIPS release 6 or MIPS-64 or MIPS-64 release 6 or Motorola 680x0 \
38// or MSP430 or NVidia GPU or PowerPC or PowerPC64 or RISC-V RV32 or RISC-V RV64 \
39// or s390x or SPARC or SPARC-64 or SPIR-V or WebAssembly or WebAssembly or x86 \
40// or x86-64 or Xtensa only.'
4141#[doc(cfg(any(
4242 target_arch = "aarch64",
4343 target_arch = "amdgpu",
......@@ -75,15 +75,16 @@ pub fn bar() {}
7575
7676//@ has all_targets/fn.baz.html \
7777// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
78// 'Available on AIX and AMD HSA and Android and CUDA and Cygwin and DragonFly \
79// BSD and Emscripten and ESP-IDF and FreeBSD and Fuchsia and Haiku and HelenOS \
80// and Hermit and Horizon and GNU/Hurd and illumos and iOS and L4Re and Linux \
81// and LynxOS-178 and macOS and Managarm and Motor OS and NetBSD and bare-metal \
82// and QNX Neutrino and NuttX and OpenBSD and Play Station Portable and Play \
83// Station 1 and QuRT and Redox OS and RTEMS OS and Solaris and SOLID ASP3 and \
84// TEEOS and Trusty and tvOS and UEFI and VEXos and visionOS and Play Station \
85// Vita and VxWorks and WASI and watchOS and Windows and Xous and zero knowledge \
86// Virtual Machine and target_os=unknown and target_os=fake_os only.'
78// 'Available on target_os=fake_os and target_os=unknown and AIX and AMD HSA \
79// and Android and bare-metal and CUDA and Cygwin and DragonFly BSD and \
80// Emscripten and ESP-IDF and FreeBSD and Fuchsia and GNU/Hurd and Haiku \
81// and HelenOS and Hermit and Horizon and illumos and iOS and L4Re and Linux \
82// and LynxOS-178 and macOS and Managarm and Motor OS and NetBSD and NuttX \
83// and OpenBSD and Play Station 1 and Play Station Portable and Play Station Vita \
84// and QNX Neutrino and QuRT and Redox OS and RTEMS OS and Solaris and \
85// SOLID ASP3 and TEEOS and Trusty and tvOS and UEFI and VEXos and visionOS \
86// and VxWorks and WASI and watchOS and Windows and Xous and zero knowledge \
87// Virtual Machine only.'
8788#[doc(cfg(all(
8889 target_os = "aix",
8990 target_os = "amdhsa",
tests/rustdoc-html/doc-cfg/doc-cfg-simplification.rs+3-3
......@@ -46,7 +46,7 @@ pub mod ratel {
4646
4747 //@ has 'globuliferous/ratel/static.NUNCIATIVE.html'
4848 //@ count - '//*[@class="stab portability"]' 1
49 //@ matches - '//*[@class="stab portability"]' 'crate features ratel and nunciative'
49 //@ matches - '//*[@class="stab portability"]' 'crate features nunciative and ratel'
5050 #[doc(cfg(feature = "nunciative"))]
5151 pub static NUNCIATIVE: () = ();
5252
......@@ -80,7 +80,7 @@ pub mod ratel {
8080
8181 //@ has 'globuliferous/ratel/enum.Cosmotellurian.html'
8282 //@ count - '//*[@class="stab portability"]' 10
83 //@ matches - '//*[@class="stab portability"]' 'crate features ratel and cosmotellurian'
83 //@ matches - '//*[@class="stab portability"]' 'crate features cosmotellurian and ratel'
8484 //@ matches - '//*[@class="stab portability"]' 'crate feature biotaxy'
8585 //@ matches - '//*[@class="stab portability"]' 'crate feature xiphopagus'
8686 //@ matches - '//*[@class="stab portability"]' 'crate feature juxtapositive'
......@@ -158,7 +158,7 @@ pub mod ratel {
158158
159159 //@ has 'globuliferous/ratel/trait.Aposiopesis.html'
160160 //@ count - '//*[@class="stab portability"]' 4
161 //@ matches - '//*[@class="stab portability"]' 'crate features ratel and aposiopesis'
161 //@ matches - '//*[@class="stab portability"]' 'crate features aposiopesis and ratel'
162162 //@ matches - '//*[@class="stab portability"]' 'crate feature umbracious'
163163 //@ matches - '//*[@class="stab portability"]' 'crate feature uakari'
164164 //@ matches - '//*[@class="stab portability"]' 'crate feature rotograph'
tests/rustdoc-html/doc-cfg/doc-cfg.rs+2-2
......@@ -3,7 +3,7 @@
33//@ has doc_cfg/struct.Portable.html
44//@ !has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' ''
55//@ has - '//*[@id="method.unix_and_arm_only_function"]' 'fn unix_and_arm_only_function()'
6//@ has - '//*[@class="stab portability"]' 'Available on Unix and ARM only.'
6//@ has - '//*[@class="stab portability"]' 'Available on ARM and Unix only.'
77//@ has - '//*[@id="method.wasi_and_wasm32_only_function"]' 'fn wasi_and_wasm32_only_function()'
88//@ has - '//*[@class="stab portability"]' 'Available on WASI and WebAssembly only.'
99pub struct Portable;
......@@ -25,7 +25,7 @@ pub mod unix_only {
2525
2626 //@ has doc_cfg/unix_only/trait.ArmOnly.html \
2727 // '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
28 // 'Available on Unix and ARM only.'
28 // 'Available on ARM and Unix only.'
2929 //@ count - '//*[@class="stab portability"]' 1
3030 #[doc(cfg(target_arch = "arm"))]
3131 pub trait ArmOnly {
tests/rustdoc-html/doc-cfg/duplicate-cfg.rs+5-5
......@@ -23,11 +23,11 @@ pub mod bar {
2323}
2424
2525//@ has 'foo/baz/index.html'
26//@ has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.'
26//@ has '-' '//*[@class="stab portability"]' 'Available on crate features send and sync only.'
2727#[doc(cfg(all(feature = "sync", feature = "send")))]
2828pub mod baz {
2929 //@ has 'foo/baz/struct.Baz.html'
30 //@ has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.'
30 //@ has '-' '//*[@class="stab portability"]' 'Available on crate features send and sync only.'
3131 #[doc(cfg(feature = "sync"))]
3232 pub struct Baz;
3333}
......@@ -37,17 +37,17 @@ pub mod baz {
3737#[doc(cfg(feature = "sync"))]
3838pub mod qux {
3939 //@ has 'foo/qux/struct.Qux.html'
40 //@ has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.'
40 //@ has '-' '//*[@class="stab portability"]' 'Available on crate features send and sync only.'
4141 #[doc(cfg(all(feature = "sync", feature = "send")))]
4242 pub struct Qux;
4343}
4444
4545//@ has 'foo/quux/index.html'
46//@ has '-' '//*[@class="stab portability"]' 'Available on crate feature sync and crate feature send and foo only.'
46//@ has '-' '//*[@class="stab portability"]' 'Available on foo and crate feature send and crate feature sync only.'
4747#[doc(cfg(all(feature = "sync", feature = "send", foo)))]
4848pub mod quux {
4949 //@ has 'foo/quux/struct.Quux.html'
50 //@ has '-' '//*[@class="stab portability"]' 'Available on crate feature sync and crate feature send and foo and bar only.'
50 //@ has '-' '//*[@class="stab portability"]' 'Available on bar and foo and crate feature send and crate feature sync only.'
5151 #[doc(cfg(all(feature = "send", feature = "sync", bar)))]
5252 pub struct Quux;
5353}
tests/rustdoc-html/doc-cfg/sort.rs created+42
......@@ -0,0 +1,42 @@
1// Tests that `doc(cfg)` badges and auto-detected `cfg` badges are sorted deterministically.
2//@ edition:2021
3//@ compile-flags: --cfg target_os="linux"
4
5#![crate_name = "foo"]
6#![feature(doc_cfg)]
7
8// TEST 1: Explicit `#[doc(cfg(...))]`
9// Tests that OS targets are sorted alphabetically.
10//@ has 'foo/fn.foo.html'
11//@ has - '//*[@class="stab portability"]' 'Available on Android or Apple or Cygwin \
12// or DragonFly BSD or FreeBSD or Linux or NetBSD or OpenBSD or QNX Neutrino only.'
13#[doc(cfg(any(
14 target_os = "android",
15 target_os = "linux",
16 target_os = "dragonfly",
17 target_os = "freebsd",
18 target_os = "netbsd",
19 target_os = "openbsd",
20 target_os = "nto",
21 target_vendor = "apple",
22 target_os = "cygwin"
23)))]
24pub fn foo() {}
25
26// TEST 2: Implicit `#[cfg(...)]` via auto-detection
27// Tests that targets are sorted alphabetically just like explicit `doc(cfg)`.
28//@ has 'foo/fn.bar.html'
29//@ has - '//*[@class="stab portability"]' 'Available on Android or Apple or Cygwin \
30// or DragonFly BSD or FreeBSD or Linux or NetBSD or OpenBSD or QNX Neutrino only.'
31#[cfg(any(
32 target_os = "android",
33 target_os = "linux",
34 target_os = "dragonfly",
35 target_os = "freebsd",
36 target_os = "netbsd",
37 target_os = "openbsd",
38 target_os = "nto",
39 target_vendor = "apple",
40 target_os = "cygwin"
41))]
42pub fn bar() {}
tests/rustdoc-html/inline_cross/doc-auto-cfg.rs+2-2
......@@ -37,11 +37,11 @@ pub mod pre {
3737pub mod post {
3838 // issue: <https://github.com/rust-lang/rust/issues/113982>
3939 //@ has 'it/post/index.html' '//*[@class="stab portability"]' 'extra'
40 //@ has - '//*[@class="stab portability"]' 'extra and extension'
40 //@ has - '//*[@class="stab portability"]' 'extension and extra'
4141 //@ has 'it/post/struct.Type.html' '//*[@class="stab portability"]' \
4242 // 'Available on crate feature extra only.'
4343 //@ has 'it/post/fn.compute.html' '//*[@class="stab portability"]' \
44 // 'Available on crate feature extra and extension only.'
44 // 'Available on extension and crate feature extra only.'
4545 #[cfg(feature = "extra")]
4646 pub use doc_auto_cfg::*;
4747
tests/rustdoc-html/target-feature.rs+2-2
......@@ -28,13 +28,13 @@ pub unsafe fn f2_not_safe() {}
2828
2929//@ has 'foo/fn.f3_multifeatures_in_attr.html'
3030//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
31// 'Available on target features popcnt and avx2 only.'
31// 'Available on target features avx2 and popcnt only.'
3232#[target_feature(enable = "popcnt", enable = "avx2")]
3333pub fn f3_multifeatures_in_attr() {}
3434
3535//@ has 'foo/fn.f4_multi_attrs.html'
3636//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
37// 'Available on target features popcnt and avx2 only.'
37// 'Available on target features avx2 and popcnt only.'
3838#[target_feature(enable = "popcnt")]
3939#[target_feature(enable = "avx2")]
4040pub fn f4_multi_attrs() {}
tests/ui/fmt/format-string-error-2.rs+11
......@@ -91,4 +91,15 @@ raw { \n
9191
9292 println!("{x=}");
9393 //~^ ERROR invalid format string: python's f-string debug `=` is not supported in rust, use `dbg(x)` instead
94
95 println!(
96 "fn main() {\n\
97 \n\
98 }"
99 //~^^^ ERROR 1 positional argument in format string
100 );
101
102 // Don't emit note suggesting an escaping `{` for `{ }`.
103 println!("{ }");
104 //~^ ERROR 1 positional argument in format string
94105}
tests/ui/fmt/format-string-error-2.stderr+18-1
......@@ -208,5 +208,22 @@ LL | println!("{x=}");
208208 |
209209 = note: to print `{`, you can escape it using `{{`
210210
211error: aborting due to 21 previous errors
211error: 1 positional argument in format string, but no arguments were given
212 --> $DIR/format-string-error-2.rs:96:20
213 |
214LL | "fn main() {\n\
215 | ____________________^
216LL | | \n\
217LL | | }"
218 | |_________^
219 |
220 = note: if you intended to print `{`, you can escape it with `{{`
221
222error: 1 positional argument in format string, but no arguments were given
223 --> $DIR/format-string-error-2.rs:103:15
224 |
225LL | println!("{ }");
226 | ^^^
227
228error: aborting due to 23 previous errors
212229
tests/ui/suggestions/wrap-function-local-constructors.fixed created+63
......@@ -0,0 +1,63 @@
1//@ run-rustfix
2
3// Regression test for https://github.com/rust-lang/rust/issues/144319.
4// Function-local constructors cannot be named through the enclosing function
5// path. The suggestion must omit path segments that cannot be written in source,
6// while preserving real path segments like local modules and enums.
7
8#![allow(dead_code)]
9
10fn direct_tuple_struct() {
11 struct Foo(bool);
12 struct Bar(Foo);
13
14 _ = Bar(Foo(false));
15 //~^ ERROR mismatched types
16 //~| HELP try wrapping the expression in `Foo`
17}
18
19fn enum_variant() {
20 enum LocalResult<T> {
21 Ok(T),
22 }
23 struct Bar(LocalResult<bool>);
24
25 _ = Bar(LocalResult::Ok(false));
26 //~^ ERROR mismatched types
27 //~| HELP try wrapping the expression in `LocalResult::Ok`
28}
29
30fn local_module() {
31 mod inner {
32 pub struct Foo(pub bool);
33 }
34 struct Bar(inner::Foo);
35
36 _ = Bar(inner::Foo(false));
37 //~^ ERROR mismatched types
38 //~| HELP try wrapping the expression in `inner::Foo`
39}
40
41fn closure_body() {
42 let _ = || {
43 struct Foo(bool);
44 struct Bar(Foo);
45
46 _ = Bar(Foo(false));
47 //~^ ERROR mismatched types
48 //~| HELP try wrapping the expression in `Foo`
49 };
50}
51
52fn inline_const_block() {
53 const {
54 struct Foo(bool);
55 struct Bar(Foo);
56
57 _ = Bar(Foo(false));
58 //~^ ERROR mismatched types
59 //~| HELP try wrapping the expression in `Foo`
60 };
61}
62
63pub fn main() {}
tests/ui/suggestions/wrap-function-local-constructors.rs created+63
......@@ -0,0 +1,63 @@
1//@ run-rustfix
2
3// Regression test for https://github.com/rust-lang/rust/issues/144319.
4// Function-local constructors cannot be named through the enclosing function
5// path. The suggestion must omit path segments that cannot be written in source,
6// while preserving real path segments like local modules and enums.
7
8#![allow(dead_code)]
9
10fn direct_tuple_struct() {
11 struct Foo(bool);
12 struct Bar(Foo);
13
14 _ = Bar(false);
15 //~^ ERROR mismatched types
16 //~| HELP try wrapping the expression in `Foo`
17}
18
19fn enum_variant() {
20 enum LocalResult<T> {
21 Ok(T),
22 }
23 struct Bar(LocalResult<bool>);
24
25 _ = Bar(false);
26 //~^ ERROR mismatched types
27 //~| HELP try wrapping the expression in `LocalResult::Ok`
28}
29
30fn local_module() {
31 mod inner {
32 pub struct Foo(pub bool);
33 }
34 struct Bar(inner::Foo);
35
36 _ = Bar(false);
37 //~^ ERROR mismatched types
38 //~| HELP try wrapping the expression in `inner::Foo`
39}
40
41fn closure_body() {
42 let _ = || {
43 struct Foo(bool);
44 struct Bar(Foo);
45
46 _ = Bar(false);
47 //~^ ERROR mismatched types
48 //~| HELP try wrapping the expression in `Foo`
49 };
50}
51
52fn inline_const_block() {
53 const {
54 struct Foo(bool);
55 struct Bar(Foo);
56
57 _ = Bar(false);
58 //~^ ERROR mismatched types
59 //~| HELP try wrapping the expression in `Foo`
60 };
61}
62
63pub fn main() {}
tests/ui/suggestions/wrap-function-local-constructors.stderr created+95
......@@ -0,0 +1,95 @@
1error[E0308]: mismatched types
2 --> $DIR/wrap-function-local-constructors.rs:14:13
3 |
4LL | _ = Bar(false);
5 | --- ^^^^^ expected `Foo`, found `bool`
6 | |
7 | arguments to this struct are incorrect
8 |
9note: tuple struct defined here
10 --> $DIR/wrap-function-local-constructors.rs:12:12
11 |
12LL | struct Bar(Foo);
13 | ^^^
14help: try wrapping the expression in `Foo`
15 |
16LL | _ = Bar(Foo(false));
17 | ++++ +
18
19error[E0308]: mismatched types
20 --> $DIR/wrap-function-local-constructors.rs:25:13
21 |
22LL | _ = Bar(false);
23 | --- ^^^^^ expected `LocalResult<bool>`, found `bool`
24 | |
25 | arguments to this struct are incorrect
26 |
27 = note: expected enum `LocalResult<bool>`
28 found type `bool`
29note: tuple struct defined here
30 --> $DIR/wrap-function-local-constructors.rs:23:12
31 |
32LL | struct Bar(LocalResult<bool>);
33 | ^^^
34help: try wrapping the expression in `LocalResult::Ok`
35 |
36LL | _ = Bar(LocalResult::Ok(false));
37 | ++++++++++++++++ +
38
39error[E0308]: mismatched types
40 --> $DIR/wrap-function-local-constructors.rs:36:13
41 |
42LL | _ = Bar(false);
43 | --- ^^^^^ expected `Foo`, found `bool`
44 | |
45 | arguments to this struct are incorrect
46 |
47note: tuple struct defined here
48 --> $DIR/wrap-function-local-constructors.rs:34:12
49 |
50LL | struct Bar(inner::Foo);
51 | ^^^
52help: try wrapping the expression in `inner::Foo`
53 |
54LL | _ = Bar(inner::Foo(false));
55 | +++++++++++ +
56
57error[E0308]: mismatched types
58 --> $DIR/wrap-function-local-constructors.rs:46:17
59 |
60LL | _ = Bar(false);
61 | --- ^^^^^ expected `Foo`, found `bool`
62 | |
63 | arguments to this struct are incorrect
64 |
65note: tuple struct defined here
66 --> $DIR/wrap-function-local-constructors.rs:44:16
67 |
68LL | struct Bar(Foo);
69 | ^^^
70help: try wrapping the expression in `Foo`
71 |
72LL | _ = Bar(Foo(false));
73 | ++++ +
74
75error[E0308]: mismatched types
76 --> $DIR/wrap-function-local-constructors.rs:57:17
77 |
78LL | _ = Bar(false);
79 | --- ^^^^^ expected `Foo`, found `bool`
80 | |
81 | arguments to this struct are incorrect
82 |
83note: tuple struct defined here
84 --> $DIR/wrap-function-local-constructors.rs:55:16
85 |
86LL | struct Bar(Foo);
87 | ^^^
88help: try wrapping the expression in `Foo`
89 |
90LL | _ = Bar(Foo(false));
91 | ++++ +
92
93error: aborting due to 5 previous errors
94
95For more information about this error, try `rustc --explain E0308`.