From 3cd065d3d358c0124368f21a7deb0e75712c286b Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Fri, 2 May 2025 21:28:11 +0500 Subject: [PATCH 01/18] macro expansion issue --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 27 +++--- tests/ui/auxiliary/delegate_macro.rs | 6 ++ tests/ui/not-enough-arguments.rs | 52 +++++++--- tests/ui/not-enough-arguments.stderr | 94 ++++++++++++++----- 4 files changed, 124 insertions(+), 55 deletions(-) create mode 100644 tests/ui/auxiliary/delegate_macro.rs diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 8b2d9ab297905..0a0967941aab3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1546,25 +1546,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { SuggestionText::Reorder => Some("reorder these arguments".to_string()), SuggestionText::DidYouMean => Some("did you mean".to_string()), }; - if let Some(suggestion_text) = suggestion_text { + if let Some(suggestion_text) = suggestion_text + && !full_call_span.in_external_macro(self.sess().source_map()) + { let source_map = self.sess().source_map(); - let (mut suggestion, suggestion_span) = if let Some(call_span) = - full_call_span.find_ancestor_inside_same_ctxt(error_span) - { - ("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi())) + let suggestion_span = if let Some(args_span) = error_span.trim_start(full_call_span) { + // Span of the braces, e.g. `(a, b, c)`. + args_span } else { - ( - format!( - "{}(", - source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| { - fn_def_id.map_or("".to_string(), |fn_def_id| { - tcx.item_name(fn_def_id).to_string() - }) - }) - ), - error_span, - ) + // The arg span of a function call that wasn't even given braces + // like what might happen with delegation reuse. + // e.g. `reuse HasSelf::method;` should suggest `reuse HasSelf::method($args);`. + full_call_span.shrink_to_hi() }; + let mut suggestion = "(".to_owned(); let mut needs_comma = false; for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() { if needs_comma { diff --git a/tests/ui/auxiliary/delegate_macro.rs b/tests/ui/auxiliary/delegate_macro.rs new file mode 100644 index 0000000000000..0d752e1203955 --- /dev/null +++ b/tests/ui/auxiliary/delegate_macro.rs @@ -0,0 +1,6 @@ +#[macro_export] +macro_rules! delegate { + ($method:ident) => { + ::$method(8) + }; +} diff --git a/tests/ui/not-enough-arguments.rs b/tests/ui/not-enough-arguments.rs index 4a2ea5e44c71a..ec660a1de81be 100644 --- a/tests/ui/not-enough-arguments.rs +++ b/tests/ui/not-enough-arguments.rs @@ -1,20 +1,16 @@ +//@ aux-build: delegate_macro.rs +extern crate delegate_macro; +use delegate_macro::delegate; + // Check that the only error msg we report is the // mismatch between the # of params, and not other // unrelated errors. - -fn foo(a: isize, b: isize, c: isize, d:isize) { - panic!(); +fn foo(a: isize, b: isize, c: isize, d: isize) { + panic!(); } // Check that all arguments are shown in the error message, even if they're across multiple lines. -fn bar( - a: i32, - b: i32, - c: i32, - d: i32, - e: i32, - f: i32, -) { +fn bar(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) { println!("{}", a); println!("{}", b); println!("{}", c); @@ -23,9 +19,35 @@ fn bar( println!("{}", f); } +macro_rules! delegate_local { + ($method:ident) => { + ::$method(8) + //~^ ERROR function takes 2 arguments but 1 + }; +} + +macro_rules! delegate_from { + ($from:ident, $method:ident) => { + <$from>::$method(8) + //~^ ERROR function takes 2 arguments but 1 + }; +} + +struct Bar; + +impl Bar { + fn foo(a: u8, b: u8) {} + fn bar() { + delegate_local!(foo); + delegate!(foo); + //~^ ERROR function takes 2 arguments but 1 + delegate_from!(Bar, foo); + } +} + fn main() { - foo(1, 2, 3); - //~^ ERROR function takes 4 arguments but 3 - bar(1, 2, 3); - //~^ ERROR function takes 6 arguments but 3 + foo(1, 2, 3); + //~^ ERROR function takes 4 arguments but 3 + bar(1, 2, 3); + //~^ ERROR function takes 6 arguments but 3 } diff --git a/tests/ui/not-enough-arguments.stderr b/tests/ui/not-enough-arguments.stderr index 099d82eb93552..908d0273bbecd 100644 --- a/tests/ui/not-enough-arguments.stderr +++ b/tests/ui/not-enough-arguments.stderr @@ -1,42 +1,88 @@ +error[E0061]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/not-enough-arguments.rs:24:9 + | +LL | ::$method(8) + | ^^^^^^^^^^^^^^^--- argument #2 of type `u8` is missing +... +LL | delegate_local!(foo); + | -------------------- in this macro invocation + | +note: associated function defined here + --> $DIR/not-enough-arguments.rs:39:8 + | +LL | fn foo(a: u8, b: u8) {} + | ^^^ ----- + = note: this error originates in the macro `delegate_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: provide the argument + | +LL | ::$method(8, /* u8 */) + | ++++++++++ + +error[E0061]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/not-enough-arguments.rs:42:9 + | +LL | delegate!(foo); + | ^^^^^^^^^^^^^^ argument #2 of type `u8` is missing + | +note: associated function defined here + --> $DIR/not-enough-arguments.rs:39:8 + | +LL | fn foo(a: u8, b: u8) {} + | ^^^ ----- + = note: this error originates in the macro `delegate` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0061]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/not-enough-arguments.rs:31:9 + | +LL | <$from>::$method(8) + | ^^^^^^^^^^^^^^^^--- argument #2 of type `u8` is missing +... +LL | delegate_from!(Bar, foo); + | ------------------------ in this macro invocation + | +note: associated function defined here + --> $DIR/not-enough-arguments.rs:39:8 + | +LL | fn foo(a: u8, b: u8) {} + | ^^^ ----- + = note: this error originates in the macro `delegate_from` (in Nightly builds, run with -Z macro-backtrace for more info) +help: provide the argument + | +LL | <$from>::$method(8, /* u8 */) + | ++++++++++ + error[E0061]: this function takes 4 arguments but 3 arguments were supplied - --> $DIR/not-enough-arguments.rs:27:3 + --> $DIR/not-enough-arguments.rs:49:5 | -LL | foo(1, 2, 3); - | ^^^--------- argument #4 of type `isize` is missing +LL | foo(1, 2, 3); + | ^^^--------- argument #4 of type `isize` is missing | note: function defined here - --> $DIR/not-enough-arguments.rs:5:4 + --> $DIR/not-enough-arguments.rs:8:4 | -LL | fn foo(a: isize, b: isize, c: isize, d:isize) { - | ^^^ ------- +LL | fn foo(a: isize, b: isize, c: isize, d: isize) { + | ^^^ -------- help: provide the argument | -LL | foo(1, 2, 3, /* isize */); - | +++++++++++++ +LL | foo(1, 2, 3, /* isize */); + | +++++++++++++ error[E0061]: this function takes 6 arguments but 3 arguments were supplied - --> $DIR/not-enough-arguments.rs:29:3 + --> $DIR/not-enough-arguments.rs:51:5 | -LL | bar(1, 2, 3); - | ^^^--------- three arguments of type `i32`, `i32`, and `i32` are missing +LL | bar(1, 2, 3); + | ^^^--------- three arguments of type `i32`, `i32`, and `i32` are missing | note: function defined here - --> $DIR/not-enough-arguments.rs:10:4 + --> $DIR/not-enough-arguments.rs:13:4 | -LL | fn bar( - | ^^^ -... -LL | d: i32, - | ------ -LL | e: i32, - | ------ -LL | f: i32, - | ------ +LL | fn bar(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) { + | ^^^ ------ ------ ------ help: provide the arguments | -LL | bar(1, 2, 3, /* i32 */, /* i32 */, /* i32 */); - | +++++++++++++++++++++++++++++++++ +LL | bar(1, 2, 3, /* i32 */, /* i32 */, /* i32 */); + | +++++++++++++++++++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0061`. From 72386693b16aef949c9bc2fb96fb78c9ce91093c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 24 May 2025 15:06:08 +0200 Subject: [PATCH 02/18] intrinsics: reduce references to LLVM and update notes on where the implementations live --- library/core/src/intrinsics/mod.rs | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 23bafa778bc6b..439c8c1f9a1e6 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1,7 +1,10 @@ //! Compiler intrinsics. //! -//! The corresponding definitions are in . -//! The corresponding const implementations are in . +//! These are the imports making intrinsics available to Rust code. The actual implementations live in the compiler. +//! Some of these intrinsics are lowered to MIR in . +//! The remaining intrinsics are implemented for the LLVM backend in +//! and , +//! and for const evaluation in . //! //! # Const intrinsics //! @@ -20,28 +23,14 @@ //! //! The volatile intrinsics provide operations intended to act on I/O //! memory, which are guaranteed to not be reordered by the compiler -//! across other volatile intrinsics. See the LLVM documentation on -//! [[volatile]]. -//! -//! [volatile]: https://llvm.org/docs/LangRef.html#volatile-memory-accesses +//! across other volatile intrinsics. See [`read_volatile`][ptr::read_volatile] +//! and [`write_volatile`][ptr::write_volatile]. //! //! # Atomics //! //! The atomic intrinsics provide common atomic operations on machine -//! words, with multiple possible memory orderings. They obey the same -//! semantics as C++11. See the LLVM documentation on [[atomics]]. -//! -//! [atomics]: https://llvm.org/docs/Atomics.html -//! -//! A quick refresher on memory ordering: -//! -//! * Acquire - a barrier for acquiring a lock. Subsequent reads and writes -//! take place after the barrier. -//! * Release - a barrier for releasing a lock. Preceding reads and writes -//! take place before the barrier. -//! * Sequentially consistent - sequentially consistent operations are -//! guaranteed to happen in order. This is the standard mode for working -//! with atomic types and is equivalent to Java's `volatile`. +//! words, with multiple possible memory orderings. See the +//! [atomic types][crate::sync::atomic] docs for details. //! //! # Unwinding //! From ff3341434def8b34e8027411c6b100a621b42085 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 24 May 2025 16:13:10 +0200 Subject: [PATCH 03/18] ScalarInt: support conversion with signed int types and cmp::Ordering --- .../rustc_const_eval/src/interpret/operand.rs | 2 +- .../rustc_middle/src/mir/interpret/value.rs | 10 ++-- compiler/rustc_middle/src/ty/consts/int.rs | 47 ++++++++++++++++++- 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 36da9037e43d9..39755169e6cae 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -310,7 +310,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { let ty = tcx.ty_ordering_enum(None); let layout = tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)).unwrap(); - Self::from_scalar(Scalar::from_i8(c as i8), layout) + Self::from_scalar(Scalar::Int(c.into()), layout) } pub fn from_pair(a: Self, b: Self, cx: &(impl HasTypingEnv<'tcx> + HasTyCtxt<'tcx>)) -> Self { diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 9d462093b9ea1..7ba0e5b5e07e5 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -180,27 +180,27 @@ impl Scalar { #[inline] pub fn from_i8(i: i8) -> Self { - Self::from_int(i, Size::from_bits(8)) + Self::Int(i.into()) } #[inline] pub fn from_i16(i: i16) -> Self { - Self::from_int(i, Size::from_bits(16)) + Self::Int(i.into()) } #[inline] pub fn from_i32(i: i32) -> Self { - Self::from_int(i, Size::from_bits(32)) + Self::Int(i.into()) } #[inline] pub fn from_i64(i: i64) -> Self { - Self::from_int(i, Size::from_bits(64)) + Self::Int(i.into()) } #[inline] pub fn from_i128(i: i128) -> Self { - Self::from_int(i, Size::from_bits(128)) + Self::Int(i.into()) } #[inline] diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 9f5e31d894cb3..9c9cd6953392a 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -422,9 +422,9 @@ macro_rules! from_scalar_int_for_x { impl From for $ty { #[inline] fn from(int: ScalarInt) -> Self { - // The `unwrap` cannot fail because to_bits (if it succeeds) + // The `unwrap` cannot fail because to_uint (if it succeeds) // is guaranteed to return a value that fits into the size. - int.to_bits(Size::from_bytes(size_of::<$ty>())) + int.to_uint(Size::from_bytes(size_of::<$ty>())) .try_into().unwrap() } } @@ -450,6 +450,49 @@ impl From for ScalarInt { } } +macro_rules! from_x_for_scalar_int_signed { + ($($ty:ty),*) => { + $( + impl From<$ty> for ScalarInt { + #[inline] + fn from(u: $ty) -> Self { + Self { + data: u128::from(u.cast_unsigned()), // go via the unsigned type of the same size + size: NonZero::new(size_of::<$ty>() as u8).unwrap(), + } + } + } + )* + } +} + +macro_rules! from_scalar_int_for_x_signed { + ($($ty:ty),*) => { + $( + impl From for $ty { + #[inline] + fn from(int: ScalarInt) -> Self { + // The `unwrap` cannot fail because to_int (if it succeeds) + // is guaranteed to return a value that fits into the size. + int.to_int(Size::from_bytes(size_of::<$ty>())) + .try_into().unwrap() + } + } + )* + } +} + +from_x_for_scalar_int_signed!(i8, i16, i32, i64, i128); +from_scalar_int_for_x_signed!(i8, i16, i32, i64, i128); + +impl From for ScalarInt { + #[inline] + fn from(c: std::cmp::Ordering) -> Self { + // Here we rely on `Ordering` having the same values in host and target! + ScalarInt::from(c as i8) + } +} + /// Error returned when a conversion from ScalarInt to char fails. #[derive(Debug)] pub struct CharTryFromScalarInt; From 77e295c39c6bd4a29d310388219fc31b6cfc7136 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 25 May 2025 11:33:45 +0200 Subject: [PATCH 04/18] Improve `ambiguous_wide_pointer_comparisons` lint compare diagnostics --- compiler/rustc_lint/messages.ftl | 2 + compiler/rustc_lint/src/lints.rs | 110 ++++++++----- compiler/rustc_lint/src/types.rs | 52 +++--- tests/ui/lint/wide_pointer_comparisons.stderr | 150 +++++++++++++++--- 4 files changed, 226 insertions(+), 88 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 08180bf8f8b2c..999ae6360edbf 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -13,6 +13,8 @@ lint_ambiguous_negative_literals = `-` has lower precedence than method calls, w lint_ambiguous_wide_pointer_comparisons = ambiguous wide pointer comparison, the comparison includes metadata which may not be expected .addr_metadata_suggestion = use explicit `std::ptr::eq` method to compare metadata and addresses .addr_suggestion = use `std::ptr::addr_eq` or untyped pointers to only compare their addresses + .cast_suggestion = use untyped pointers to only compare their addresses + .expect_suggestion = or expect the lint to compare the pointers metadata and addresses lint_associated_const_elided_lifetime = {$elided -> [true] `&` without an explicit lifetime name cannot be used here diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 7268a7f704fcb..686d4e84fcecb 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1782,13 +1782,20 @@ pub(crate) enum InvalidNanComparisonsSuggestion { #[derive(LintDiagnostic)] pub(crate) enum AmbiguousWidePointerComparisons<'a> { #[diag(lint_ambiguous_wide_pointer_comparisons)] - Spanful { + SpanfulEq { #[subdiagnostic] addr_suggestion: AmbiguousWidePointerComparisonsAddrSuggestion<'a>, #[subdiagnostic] addr_metadata_suggestion: Option>, }, #[diag(lint_ambiguous_wide_pointer_comparisons)] + SpanfulCmp { + #[subdiagnostic] + cast_suggestion: AmbiguousWidePointerComparisonsCastSuggestion<'a>, + #[subdiagnostic] + expect_suggestion: AmbiguousWidePointerComparisonsExpectSuggestion<'a>, + }, + #[diag(lint_ambiguous_wide_pointer_comparisons)] #[help(lint_addr_metadata_suggestion)] #[help(lint_addr_suggestion)] Spanless, @@ -1816,48 +1823,67 @@ pub(crate) struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> { } #[derive(Subdiagnostic)] -pub(crate) enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> { - #[multipart_suggestion( - lint_addr_suggestion, - style = "verbose", - // FIXME(#53934): make machine-applicable again - applicability = "maybe-incorrect" - )] - AddrEq { - ne: &'a str, - deref_left: &'a str, - deref_right: &'a str, - l_modifiers: &'a str, - r_modifiers: &'a str, - #[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")] - left: Span, - #[suggestion_part(code = "{l_modifiers}, {deref_right}")] - middle: Span, - #[suggestion_part(code = "{r_modifiers})")] - right: Span, - }, - #[multipart_suggestion( - lint_addr_suggestion, - style = "verbose", - // FIXME(#53934): make machine-applicable again - applicability = "maybe-incorrect" +#[multipart_suggestion( + lint_addr_suggestion, + style = "verbose", + // FIXME(#53934): make machine-applicable again + applicability = "maybe-incorrect" +)] +pub(crate) struct AmbiguousWidePointerComparisonsAddrSuggestion<'a> { + pub(crate) ne: &'a str, + pub(crate) deref_left: &'a str, + pub(crate) deref_right: &'a str, + pub(crate) l_modifiers: &'a str, + pub(crate) r_modifiers: &'a str, + #[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")] + pub(crate) left: Span, + #[suggestion_part(code = "{l_modifiers}, {deref_right}")] + pub(crate) middle: Span, + #[suggestion_part(code = "{r_modifiers})")] + pub(crate) right: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + lint_cast_suggestion, + style = "verbose", + // FIXME(#53934): make machine-applicable again + applicability = "maybe-incorrect" +)] +pub(crate) struct AmbiguousWidePointerComparisonsCastSuggestion<'a> { + pub(crate) deref_left: &'a str, + pub(crate) deref_right: &'a str, + pub(crate) paren_left: &'a str, + pub(crate) paren_right: &'a str, + pub(crate) l_modifiers: &'a str, + pub(crate) r_modifiers: &'a str, + #[suggestion_part(code = "({deref_left}")] + pub(crate) left_before: Option, + #[suggestion_part(code = "{l_modifiers}{paren_left}.cast::<()>()")] + pub(crate) left_after: Span, + #[suggestion_part(code = "({deref_right}")] + pub(crate) right_before: Option, + #[suggestion_part(code = "{r_modifiers}{paren_right}.cast::<()>()")] + pub(crate) right_after: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + lint_expect_suggestion, + style = "verbose", + // FIXME(#53934): make machine-applicable again + applicability = "maybe-incorrect" +)] +pub(crate) struct AmbiguousWidePointerComparisonsExpectSuggestion<'a> { + pub(crate) paren_left: &'a str, + pub(crate) paren_right: &'a str, + // FIXME(#127436): Adjust once resolved + #[suggestion_part( + code = r#"{{ #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] {paren_left}"# )] - Cast { - deref_left: &'a str, - deref_right: &'a str, - paren_left: &'a str, - paren_right: &'a str, - l_modifiers: &'a str, - r_modifiers: &'a str, - #[suggestion_part(code = "({deref_left}")] - left_before: Option, - #[suggestion_part(code = "{l_modifiers}{paren_left}.cast::<()>()")] - left_after: Span, - #[suggestion_part(code = "({deref_right}")] - right_before: Option, - #[suggestion_part(code = "{r_modifiers}{paren_right}.cast::<()>()")] - right_after: Span, - }, + pub(crate) before: Span, + #[suggestion_part(code = "{paren_right} }}")] + pub(crate) after: Span, } #[derive(LintDiagnostic)] diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index f1c06dfe6ce0e..af134622d38cb 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -24,7 +24,8 @@ mod improper_ctypes; use crate::lints::{ AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion, - AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad, + AmbiguousWidePointerComparisonsAddrSuggestion, AmbiguousWidePointerComparisonsCastSuggestion, + AmbiguousWidePointerComparisonsExpectSuggestion, AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons, InvalidNanComparisonsSuggestion, UnpredictableFunctionPointerComparisons, UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons, UsesPowerAlignment, @@ -362,6 +363,7 @@ fn lint_wide_pointer<'tcx>( let ne = if cmpop == ComparisonOp::BinOp(hir::BinOpKind::Ne) { "!" } else { "" }; let is_eq_ne = matches!(cmpop, ComparisonOp::BinOp(hir::BinOpKind::Eq | hir::BinOpKind::Ne)); let is_dyn_comparison = l_inner_ty_is_dyn && r_inner_ty_is_dyn; + let via_method_call = matches!(&e.kind, ExprKind::MethodCall(..) | ExprKind::Call(..)); let left = e.span.shrink_to_lo().until(l_span.shrink_to_lo()); let middle = l_span.shrink_to_hi().until(r_span.shrink_to_lo()); @@ -376,21 +378,21 @@ fn lint_wide_pointer<'tcx>( cx.emit_span_lint( AMBIGUOUS_WIDE_POINTER_COMPARISONS, e.span, - AmbiguousWidePointerComparisons::Spanful { - addr_metadata_suggestion: (is_eq_ne && !is_dyn_comparison).then(|| { - AmbiguousWidePointerComparisonsAddrMetadataSuggestion { - ne, - deref_left, - deref_right, - l_modifiers, - r_modifiers, - left, - middle, - right, - } - }), - addr_suggestion: if is_eq_ne { - AmbiguousWidePointerComparisonsAddrSuggestion::AddrEq { + if is_eq_ne { + AmbiguousWidePointerComparisons::SpanfulEq { + addr_metadata_suggestion: (!is_dyn_comparison).then(|| { + AmbiguousWidePointerComparisonsAddrMetadataSuggestion { + ne, + deref_left, + deref_right, + l_modifiers, + r_modifiers, + left, + middle, + right, + } + }), + addr_suggestion: AmbiguousWidePointerComparisonsAddrSuggestion { ne, deref_left, deref_right, @@ -399,9 +401,11 @@ fn lint_wide_pointer<'tcx>( left, middle, right, - } - } else { - AmbiguousWidePointerComparisonsAddrSuggestion::Cast { + }, + } + } else { + AmbiguousWidePointerComparisons::SpanfulCmp { + cast_suggestion: AmbiguousWidePointerComparisonsCastSuggestion { deref_left, deref_right, l_modifiers, @@ -412,8 +416,14 @@ fn lint_wide_pointer<'tcx>( left_after: l_span.shrink_to_hi(), right_before: (r_ty_refs != 0).then_some(r_span.shrink_to_lo()), right_after: r_span.shrink_to_hi(), - } - }, + }, + expect_suggestion: AmbiguousWidePointerComparisonsExpectSuggestion { + paren_left: if via_method_call { "" } else { "(" }, + paren_right: if via_method_call { "" } else { ")" }, + before: e.span.shrink_to_lo(), + after: e.span.shrink_to_hi(), + }, + } }, ); } diff --git a/tests/ui/lint/wide_pointer_comparisons.stderr b/tests/ui/lint/wide_pointer_comparisons.stderr index 5a0b914d8320e..4f5238e8252f5 100644 --- a/tests/ui/lint/wide_pointer_comparisons.stderr +++ b/tests/ui/lint/wide_pointer_comparisons.stderr @@ -29,10 +29,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a < b; | ^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.cast::<()>() < b.cast::<()>(); | +++++++++++++ +++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a < b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:26:13 @@ -40,10 +44,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a <= b; | ^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.cast::<()>() <= b.cast::<()>(); | +++++++++++++ +++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a <= b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:28:13 @@ -51,10 +59,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a > b; | ^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.cast::<()>() > b.cast::<()>(); | +++++++++++++ +++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a > b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:30:13 @@ -62,10 +74,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a >= b; | ^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.cast::<()>() >= b.cast::<()>(); | +++++++++++++ +++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a >= b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:33:13 @@ -121,10 +137,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a.cmp(&b); | ^^^^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.cast::<()>().cmp(&b.cast::<()>()); | +++++++++++++ +++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.cmp(&b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:43:13 @@ -132,10 +152,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a.partial_cmp(&b); | ^^^^^^^^^^^^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.cast::<()>().partial_cmp(&b.cast::<()>()); | +++++++++++++ +++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.partial_cmp(&b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:45:13 @@ -143,10 +167,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a.le(&b); | ^^^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.cast::<()>().le(&b.cast::<()>()); | +++++++++++++ +++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.le(&b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:47:13 @@ -154,10 +182,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a.lt(&b); | ^^^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.cast::<()>().lt(&b.cast::<()>()); | +++++++++++++ +++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.lt(&b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:49:13 @@ -165,10 +197,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a.ge(&b); | ^^^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.cast::<()>().ge(&b.cast::<()>()); | +++++++++++++ +++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.ge(&b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:51:13 @@ -176,10 +212,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a.gt(&b); | ^^^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.cast::<()>().gt(&b.cast::<()>()); | +++++++++++++ +++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.gt(&b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:57:17 @@ -199,10 +239,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a >= b; | ^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.as_ptr().cast::<()>() >= b.as_ptr().cast::<()>(); | ++++++++++++++++++++++ ++++++++++++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a >= b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:61:17 @@ -246,10 +290,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a < b; | ^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = (*a).cast::<()>() < (*b).cast::<()>(); | ++ ++++++++++++++ ++ ++++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a < b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:76:17 @@ -257,10 +305,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a <= b; | ^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = (*a).cast::<()>() <= (*b).cast::<()>(); | ++ ++++++++++++++ ++ ++++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a <= b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:78:17 @@ -268,10 +320,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a > b; | ^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = (*a).cast::<()>() > (*b).cast::<()>(); | ++ ++++++++++++++ ++ ++++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a > b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:80:17 @@ -279,10 +335,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a >= b; | ^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = (*a).cast::<()>() >= (*b).cast::<()>(); | ++ ++++++++++++++ ++ ++++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a >= b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:83:17 @@ -362,10 +422,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a.cmp(&b); | ^^^^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = (*a).cast::<()>().cmp(&(*b).cast::<()>()); | ++ ++++++++++++++ ++ ++++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.cmp(&b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:97:17 @@ -373,10 +437,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a.partial_cmp(&b); | ^^^^^^^^^^^^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = (*a).cast::<()>().partial_cmp(&(*b).cast::<()>()); | ++ ++++++++++++++ ++ ++++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.partial_cmp(&b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:99:17 @@ -384,10 +452,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a.le(&b); | ^^^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = (*a).cast::<()>().le(&(*b).cast::<()>()); | ++ ++++++++++++++ ++ ++++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.le(&b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:101:17 @@ -395,10 +467,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a.lt(&b); | ^^^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = (*a).cast::<()>().lt(&(*b).cast::<()>()); | ++ ++++++++++++++ ++ ++++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.lt(&b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:103:17 @@ -406,10 +482,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a.ge(&b); | ^^^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = (*a).cast::<()>().ge(&(*b).cast::<()>()); | ++ ++++++++++++++ ++ ++++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.ge(&b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:105:17 @@ -417,10 +497,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a.gt(&b); | ^^^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = (*a).cast::<()>().gt(&(*b).cast::<()>()); | ++ ++++++++++++++ ++ ++++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.gt(&b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:110:13 @@ -496,10 +580,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a < b; | ^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.cast::<()>() < b.cast::<()>(); | +++++++++++++ +++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a < b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:124:17 @@ -507,10 +595,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a <= b; | ^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.cast::<()>() <= b.cast::<()>(); | +++++++++++++ +++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a <= b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:126:17 @@ -518,10 +610,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a > b; | ^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.cast::<()>() > b.cast::<()>(); | +++++++++++++ +++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a > b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:128:17 @@ -529,10 +625,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi LL | let _ = a >= b; | ^^^^^^ | -help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +help: use untyped pointers to only compare their addresses | LL | let _ = a.cast::<()>() >= b.cast::<()>(); | +++++++++++++ +++++++++++++ +help: or expect the lint to compare the pointers metadata and addresses + | +LL | let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a >= b) }; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:131:17 From b71a1279a1a0238c8d4875c569721465823645a8 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 26 May 2025 08:08:50 +0300 Subject: [PATCH 05/18] dist: make sure llvm-project submodule is present Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/dist.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 253fa224152cc..7b5393a115a7b 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -2282,6 +2282,10 @@ impl Step for LlvmTools { } } + if !builder.config.dry_run() { + builder.require_submodule("src/llvm-project", None); + } + builder.ensure(crate::core::build_steps::llvm::Llvm { target }); let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple); @@ -2400,6 +2404,10 @@ impl Step for RustDev { } } + if !builder.config.dry_run() { + builder.require_submodule("src/llvm-project", None); + } + let mut tarball = Tarball::new(builder, "rust-dev", &target.triple); tarball.set_overlay(OverlayKind::Llvm); // LLVM requires a shared object symlink to exist on some platforms. From 0ea12c3c5fd218671ae42a99757a332fba8597cc Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Mon, 26 May 2025 00:04:20 +0800 Subject: [PATCH 06/18] cfg_version: pull out dedicated syntax test from feature gate test The feature gate test was dual-purposing causing feature gate errors to distract from syntax exercises. --- tests/ui/cfg/cfg-version/syntax.rs | 152 +++++++++++++ tests/ui/cfg/cfg-version/syntax.stderr | 188 ++++++++++++++++ .../feature-gates/feature-gate-cfg-version.rs | 49 +---- .../feature-gate-cfg-version.stderr | 204 +----------------- 4 files changed, 350 insertions(+), 243 deletions(-) create mode 100644 tests/ui/cfg/cfg-version/syntax.rs create mode 100644 tests/ui/cfg/cfg-version/syntax.stderr diff --git a/tests/ui/cfg/cfg-version/syntax.rs b/tests/ui/cfg/cfg-version/syntax.rs new file mode 100644 index 0000000000000..22aab47e1ecdf --- /dev/null +++ b/tests/ui/cfg/cfg-version/syntax.rs @@ -0,0 +1,152 @@ +//! Check `#[cfg(version(..))]` parsing. + +#![feature(cfg_version)] + +// Overall grammar +// =============== +// +// `#[cfg(version(..))]` accepts only the `version(VERSION_STRING_LITERAL)` predicate form, where +// only a single string literal is permitted. + +#[cfg(version(42))] +//~^ ERROR expected a version literal +fn not_a_string_literal_simple() {} + +#[cfg(version(1.20))] +//~^ ERROR expected a version literal +fn not_a_string_literal_semver_like() {} + +#[cfg(version(false))] +//~^ ERROR expected a version literal +fn not_a_string_literal_other() {} + +#[cfg(version("1.43", "1.44", "1.45"))] +//~^ ERROR expected single version literal +fn multiple_version_literals() {} + +// The key-value form `cfg(version = "..")` is not considered a valid `cfg(version(..))` usage, but +// it will only trigger the `unexpected_cfgs` lint and not a hard error. + +#[cfg(version = "1.43")] +//~^ WARN unexpected `cfg` condition name: `version` +fn key_value_form() {} + +// Additional version string literal constraints +// ============================================= +// +// The `VERSION_STRING_LITERAL` ("version literal") has additional constraints on its syntactical +// well-formedness. + +// 1. A valid version literal can only constitute of numbers and periods (a "simple" semver version +// string). Non-semver strings or "complex" semver strings (such as build metadata) are not +// considered valid version literals, and will emit a non-lint warning "unknown version literal +// format". + +#[cfg(version("1.43.0"))] +fn valid_major_minor_patch() {} + +#[cfg(version("0.0.0"))] +fn valid_zero_zero_zero_major_minor_patch() {} + +#[cfg(version("foo"))] +//~^ WARN unknown version literal format, assuming it refers to a future version +fn not_numbers_or_periods() {} + +#[cfg(version("1.20.0-stable"))] +//~^ WARN unknown version literal format, assuming it refers to a future version +fn complex_semver_with_metadata() {} + +// 2. "Shortened" version strings are permitted but *only* for the omission of the patch number. + +#[cfg(version("1.0"))] +fn valid_major_minor_1() {} + +#[cfg(version("1.43"))] +fn valid_major_minor_2() {} + +#[cfg(not(version("1.44")))] +fn valid_major_minor_negated_smoke_test() {} + +#[cfg(version("0.0"))] +fn valid_zero_zero_major_minor() {} + +#[cfg(version("0.7"))] +fn valid_zero_major_minor() {} + +// 3. Major-only, or other non-Semver-like strings are not permitted. + +#[cfg(version("1"))] +//~^ WARN unknown version literal format, assuming it refers to a future version +fn invalid_major_only() {} + +#[cfg(version("0"))] +//~^ WARN unknown version literal format, assuming it refers to a future version +fn invalid_major_only_zero() {} + +#[cfg(version(".7"))] +//~^ WARN unknown version literal format, assuming it refers to a future version +fn invalid_decimal_like() {} + +// Misc parsing overflow/underflow edge cases +// ========================================== +// +// Check that we report "unknown version literal format" user-facing warnings and not ICEs. + +#[cfg(version("-1"))] +//~^ WARN unknown version literal format, assuming it refers to a future version +fn invalid_major_only_negative() {} + +// Implementation detail: we store rustc version as `{ major: u16, minor: u16, patch: u16 }`. + +#[cfg(version("65536"))] +//~^ WARN unknown version literal format, assuming it refers to a future version +fn exceed_u16_major() {} + +#[cfg(version("1.65536.0"))] +//~^ WARN unknown version literal format, assuming it refers to a future version +fn exceed_u16_minor() {} + +#[cfg(version("1.0.65536"))] +//~^ WARN unknown version literal format, assuming it refers to a future version +fn exceed_u16_patch() {} + +#[cfg(version("65536.0.65536"))] +//~^ WARN unknown version literal format, assuming it refers to a future version +fn exceed_u16_mixed() {} + +// Usage as `cfg!()` +// ================= + +fn cfg_usage() { + assert!(cfg!(version("1.0"))); + assert!(cfg!(version("1.43"))); + assert!(cfg!(version("1.43.0"))); + + assert!(cfg!(version("foo"))); + //~^ WARN unknown version literal format, assuming it refers to a future version + assert!(cfg!(version("1.20.0-stable"))); + //~^ WARN unknown version literal format, assuming it refers to a future version + + assert!(cfg!(version = "1.43")); + //~^ WARN unexpected `cfg` condition name: `version` +} + +fn main() { + cfg_usage(); + + // `cfg(version = "..")` is not a valid `cfg_version` form, but it only triggers + // `unexpected_cfgs` lint, and `cfg(version = "..")` eval to `false`. + key_value_form(); //~ ERROR cannot find function + + // Invalid version literal formats within valid `cfg(version(..))` form should also cause + // `cfg(version(..))` eval to `false`. + not_numbers_or_periods(); //~ ERROR cannot find function + complex_semver_with_metadata(); //~ ERROR cannot find function + invalid_major_only(); //~ ERROR cannot find function + invalid_major_only_zero(); //~ ERROR cannot find function + invalid_major_only_negative(); //~ ERROR cannot find function + exceed_u16_major(); //~ ERROR cannot find function + exceed_u16_minor(); //~ ERROR cannot find function + exceed_u16_patch(); //~ ERROR cannot find function + exceed_u16_mixed(); //~ ERROR cannot find function +} diff --git a/tests/ui/cfg/cfg-version/syntax.stderr b/tests/ui/cfg/cfg-version/syntax.stderr new file mode 100644 index 0000000000000..2facd96076317 --- /dev/null +++ b/tests/ui/cfg/cfg-version/syntax.stderr @@ -0,0 +1,188 @@ +error: expected a version literal + --> $DIR/syntax.rs:11:15 + | +LL | #[cfg(version(42))] + | ^^ + +error: expected a version literal + --> $DIR/syntax.rs:15:15 + | +LL | #[cfg(version(1.20))] + | ^^^^ + +error: expected a version literal + --> $DIR/syntax.rs:19:15 + | +LL | #[cfg(version(false))] + | ^^^^^ + +error: expected single version literal + --> $DIR/syntax.rs:23:7 + | +LL | #[cfg(version("1.43", "1.44", "1.45"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/syntax.rs:51:15 + | +LL | #[cfg(version("foo"))] + | ^^^^^ + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/syntax.rs:55:15 + | +LL | #[cfg(version("1.20.0-stable"))] + | ^^^^^^^^^^^^^^^ + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/syntax.rs:78:15 + | +LL | #[cfg(version("1"))] + | ^^^ + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/syntax.rs:82:15 + | +LL | #[cfg(version("0"))] + | ^^^ + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/syntax.rs:86:15 + | +LL | #[cfg(version(".7"))] + | ^^^^ + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/syntax.rs:95:15 + | +LL | #[cfg(version("-1"))] + | ^^^^ + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/syntax.rs:101:15 + | +LL | #[cfg(version("65536"))] + | ^^^^^^^ + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/syntax.rs:105:15 + | +LL | #[cfg(version("1.65536.0"))] + | ^^^^^^^^^^^ + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/syntax.rs:109:15 + | +LL | #[cfg(version("1.0.65536"))] + | ^^^^^^^^^^^ + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/syntax.rs:113:15 + | +LL | #[cfg(version("65536.0.65536"))] + | ^^^^^^^^^^^^^^^ + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/syntax.rs:125:26 + | +LL | assert!(cfg!(version("foo"))); + | ^^^^^ + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/syntax.rs:127:26 + | +LL | assert!(cfg!(version("1.20.0-stable"))); + | ^^^^^^^^^^^^^^^ + +warning: unexpected `cfg` condition name: `version` + --> $DIR/syntax.rs:30:7 + | +LL | #[cfg(version = "1.43")] + | ^^^^^^^^^^^^^^^^ + | + = help: to expect this configuration use `--check-cfg=cfg(version, values("1.43"))` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default +help: there is a similar config predicate: `version("..")` + | +LL - #[cfg(version = "1.43")] +LL + #[cfg(version("1.43"))] + | + +warning: unexpected `cfg` condition name: `version` + --> $DIR/syntax.rs:130:18 + | +LL | assert!(cfg!(version = "1.43")); + | ^^^^^^^^^^^^^^^^ + | + = help: to expect this configuration use `--check-cfg=cfg(version, values("1.43"))` + = note: see for more information about checking conditional configuration +help: there is a similar config predicate: `version("..")` + | +LL - assert!(cfg!(version = "1.43")); +LL + assert!(cfg!(version("1.43"))); + | + +error[E0425]: cannot find function `key_value_form` in this scope + --> $DIR/syntax.rs:139:5 + | +LL | key_value_form(); + | ^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find function `not_numbers_or_periods` in this scope + --> $DIR/syntax.rs:143:5 + | +LL | not_numbers_or_periods(); + | ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find function `complex_semver_with_metadata` in this scope + --> $DIR/syntax.rs:144:5 + | +LL | complex_semver_with_metadata(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find function `invalid_major_only` in this scope + --> $DIR/syntax.rs:145:5 + | +LL | invalid_major_only(); + | ^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find function `invalid_major_only_zero` in this scope + --> $DIR/syntax.rs:146:5 + | +LL | invalid_major_only_zero(); + | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find function `invalid_major_only_negative` in this scope + --> $DIR/syntax.rs:147:5 + | +LL | invalid_major_only_negative(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find function `exceed_u16_major` in this scope + --> $DIR/syntax.rs:148:5 + | +LL | exceed_u16_major(); + | ^^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find function `exceed_u16_minor` in this scope + --> $DIR/syntax.rs:149:5 + | +LL | exceed_u16_minor(); + | ^^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find function `exceed_u16_patch` in this scope + --> $DIR/syntax.rs:150:5 + | +LL | exceed_u16_patch(); + | ^^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find function `exceed_u16_mixed` in this scope + --> $DIR/syntax.rs:151:5 + | +LL | exceed_u16_mixed(); + | ^^^^^^^^^^^^^^^^ not found in this scope + +error: aborting due to 14 previous errors; 14 warnings emitted + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/feature-gates/feature-gate-cfg-version.rs b/tests/ui/feature-gates/feature-gate-cfg-version.rs index e35784a68d101..ec2446cc14648 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-version.rs +++ b/tests/ui/feature-gates/feature-gate-cfg-version.rs @@ -1,49 +1,12 @@ -#[cfg(version(42))] //~ ERROR: expected a version literal -//~^ ERROR `cfg(version)` is experimental and subject to change -fn foo() {} -#[cfg(version(1.20))] //~ ERROR: expected a version literal -//~^ ERROR `cfg(version)` is experimental and subject to change -fn foo() -> bool { true } -#[cfg(version("1.44"))] -//~^ ERROR `cfg(version)` is experimental and subject to change -fn foo() -> bool { true } -#[cfg(not(version("1.44")))] -//~^ ERROR `cfg(version)` is experimental and subject to change -fn foo() -> bool { false } +//! Feature gate test for `cfg_version`. +//! +//! Tracking issue: #64796. -#[cfg(version("1.43", "1.44", "1.45"))] //~ ERROR: expected single version literal -//~^ ERROR `cfg(version)` is experimental and subject to change -fn bar() -> bool { false } -#[cfg(version(false))] //~ ERROR: expected a version literal -//~^ ERROR `cfg(version)` is experimental and subject to change -fn bar() -> bool { false } -#[cfg(version("foo"))] //~ WARNING: unknown version literal format -//~^ ERROR `cfg(version)` is experimental and subject to change -fn bar() -> bool { false } -#[cfg(version("999"))] //~ WARNING: unknown version literal format -//~^ ERROR `cfg(version)` is experimental and subject to change -fn bar() -> bool { false } -#[cfg(version("-1"))] //~ WARNING: unknown version literal format -//~^ ERROR `cfg(version)` is experimental and subject to change -fn bar() -> bool { false } -#[cfg(version("65536"))] //~ WARNING: unknown version literal format -//~^ ERROR `cfg(version)` is experimental and subject to change -fn bar() -> bool { false } -#[cfg(version("0"))] //~ WARNING: unknown version literal format -//~^ ERROR `cfg(version)` is experimental and subject to change -fn bar() -> bool { true } -#[cfg(version("1.0"))] -//~^ ERROR `cfg(version)` is experimental and subject to change -fn bar() -> bool { true } -#[cfg(version("1.65536.2"))] //~ WARNING: unknown version literal format -//~^ ERROR `cfg(version)` is experimental and subject to change -fn bar() -> bool { false } -#[cfg(version("1.20.0-stable"))] //~ WARNING: unknown version literal format +#[cfg(version("1.42"))] //~^ ERROR `cfg(version)` is experimental and subject to change fn bar() {} fn main() { - assert!(foo()); - assert!(bar()); - assert!(cfg!(version("1.42"))); //~ ERROR `cfg(version)` is experimental and subject to change + assert!(cfg!(version("1.42"))); + //~^ ERROR `cfg(version)` is experimental and subject to change } diff --git a/tests/ui/feature-gates/feature-gate-cfg-version.stderr b/tests/ui/feature-gates/feature-gate-cfg-version.stderr index c1c3e8e5897a6..7cb2f1e07afe6 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-version.stderr +++ b/tests/ui/feature-gates/feature-gate-cfg-version.stderr @@ -1,39 +1,7 @@ error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:1:7 + --> $DIR/feature-gate-cfg-version.rs:5:7 | -LL | #[cfg(version(42))] - | ^^^^^^^^^^^ - | - = note: see issue #64796 for more information - = help: add `#![feature(cfg_version)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: expected a version literal - --> $DIR/feature-gate-cfg-version.rs:1:15 - | -LL | #[cfg(version(42))] - | ^^ - -error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:4:7 - | -LL | #[cfg(version(1.20))] - | ^^^^^^^^^^^^^ - | - = note: see issue #64796 for more information - = help: add `#![feature(cfg_version)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: expected a version literal - --> $DIR/feature-gate-cfg-version.rs:4:15 - | -LL | #[cfg(version(1.20))] - | ^^^^ - -error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:7:7 - | -LL | #[cfg(version("1.44"))] +LL | #[cfg(version("1.42"))] | ^^^^^^^^^^^^^^^ | = note: see issue #64796 for more information @@ -41,171 +9,7 @@ LL | #[cfg(version("1.44"))] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:10:11 - | -LL | #[cfg(not(version("1.44")))] - | ^^^^^^^^^^^^^^^ - | - = note: see issue #64796 for more information - = help: add `#![feature(cfg_version)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:14:7 - | -LL | #[cfg(version("1.43", "1.44", "1.45"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #64796 for more information - = help: add `#![feature(cfg_version)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: expected single version literal - --> $DIR/feature-gate-cfg-version.rs:14:7 - | -LL | #[cfg(version("1.43", "1.44", "1.45"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:17:7 - | -LL | #[cfg(version(false))] - | ^^^^^^^^^^^^^^ - | - = note: see issue #64796 for more information - = help: add `#![feature(cfg_version)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: expected a version literal - --> $DIR/feature-gate-cfg-version.rs:17:15 - | -LL | #[cfg(version(false))] - | ^^^^^ - -error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:20:7 - | -LL | #[cfg(version("foo"))] - | ^^^^^^^^^^^^^^ - | - = note: see issue #64796 for more information - = help: add `#![feature(cfg_version)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -warning: unknown version literal format, assuming it refers to a future version - --> $DIR/feature-gate-cfg-version.rs:20:15 - | -LL | #[cfg(version("foo"))] - | ^^^^^ - -error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:23:7 - | -LL | #[cfg(version("999"))] - | ^^^^^^^^^^^^^^ - | - = note: see issue #64796 for more information - = help: add `#![feature(cfg_version)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -warning: unknown version literal format, assuming it refers to a future version - --> $DIR/feature-gate-cfg-version.rs:23:15 - | -LL | #[cfg(version("999"))] - | ^^^^^ - -error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:26:7 - | -LL | #[cfg(version("-1"))] - | ^^^^^^^^^^^^^ - | - = note: see issue #64796 for more information - = help: add `#![feature(cfg_version)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -warning: unknown version literal format, assuming it refers to a future version - --> $DIR/feature-gate-cfg-version.rs:26:15 - | -LL | #[cfg(version("-1"))] - | ^^^^ - -error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:29:7 - | -LL | #[cfg(version("65536"))] - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #64796 for more information - = help: add `#![feature(cfg_version)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -warning: unknown version literal format, assuming it refers to a future version - --> $DIR/feature-gate-cfg-version.rs:29:15 - | -LL | #[cfg(version("65536"))] - | ^^^^^^^ - -error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:32:7 - | -LL | #[cfg(version("0"))] - | ^^^^^^^^^^^^ - | - = note: see issue #64796 for more information - = help: add `#![feature(cfg_version)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -warning: unknown version literal format, assuming it refers to a future version - --> $DIR/feature-gate-cfg-version.rs:32:15 - | -LL | #[cfg(version("0"))] - | ^^^ - -error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:35:7 - | -LL | #[cfg(version("1.0"))] - | ^^^^^^^^^^^^^^ - | - = note: see issue #64796 for more information - = help: add `#![feature(cfg_version)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:38:7 - | -LL | #[cfg(version("1.65536.2"))] - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #64796 for more information - = help: add `#![feature(cfg_version)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -warning: unknown version literal format, assuming it refers to a future version - --> $DIR/feature-gate-cfg-version.rs:38:15 - | -LL | #[cfg(version("1.65536.2"))] - | ^^^^^^^^^^^ - -error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:41:7 - | -LL | #[cfg(version("1.20.0-stable"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #64796 for more information - = help: add `#![feature(cfg_version)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -warning: unknown version literal format, assuming it refers to a future version - --> $DIR/feature-gate-cfg-version.rs:41:15 - | -LL | #[cfg(version("1.20.0-stable"))] - | ^^^^^^^^^^^^^^^ - -error[E0658]: `cfg(version)` is experimental and subject to change - --> $DIR/feature-gate-cfg-version.rs:48:18 + --> $DIR/feature-gate-cfg-version.rs:10:18 | LL | assert!(cfg!(version("1.42"))); | ^^^^^^^^^^^^^^^ @@ -214,6 +18,6 @@ LL | assert!(cfg!(version("1.42"))); = help: add `#![feature(cfg_version)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 19 previous errors; 7 warnings emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. From 5e31cd30aae245aaa1374e12521667b8c728402d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 26 May 2025 12:19:34 +0000 Subject: [PATCH 07/18] Support opaque_types_defined_by for SyntheticCoroutineBody --- compiler/rustc_ty_utils/src/opaque_types.rs | 8 +++++--- .../async-await/async-closures/promote-in-body.rs | 13 +++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 tests/ui/async-await/async-closures/promote-in-body.rs diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 841f602d985cd..3b4482146d4f1 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -321,7 +321,10 @@ fn opaque_types_defined_by<'tcx>( collector.collect_taits_declared_in_body(); } // Closures and coroutines are type checked with their parent - DefKind::Closure | DefKind::InlineConst => { + // Note that we also support `SyntheticCoroutineBody` since we create + // a MIR body for the def kind, and some MIR passes (like promotion) + // may require doing analysis using its typing env. + DefKind::Closure | DefKind::InlineConst | DefKind::SyntheticCoroutineBody => { collector.opaques.extend(tcx.opaque_types_defined_by(tcx.local_parent(item))); } DefKind::AssocTy | DefKind::TyAlias | DefKind::GlobalAsm => {} @@ -343,8 +346,7 @@ fn opaque_types_defined_by<'tcx>( | DefKind::ForeignMod | DefKind::Field | DefKind::LifetimeParam - | DefKind::Impl { .. } - | DefKind::SyntheticCoroutineBody => { + | DefKind::Impl { .. } => { span_bug!( tcx.def_span(item), "`opaque_types_defined_by` not defined for {} `{item:?}`", diff --git a/tests/ui/async-await/async-closures/promote-in-body.rs b/tests/ui/async-await/async-closures/promote-in-body.rs new file mode 100644 index 0000000000000..ea95d680987e0 --- /dev/null +++ b/tests/ui/async-await/async-closures/promote-in-body.rs @@ -0,0 +1,13 @@ +//@ build-pass +//@ compile-flags: --crate-type=lib +//@ edition: 2024 + +union U { + f: i32, +} + +fn foo() { + async || { + &U { f: 1 } + }; +} From 1d35ac9ce0e5e5265fae1b2a4754013c1e479960 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 26 May 2025 14:47:19 +0200 Subject: [PATCH 08/18] Add missing edition directives for async-await tests --- .../async-fn/edition-2015-not-async-bound.rs | 1 + tests/ui/async-await/async-fn/edition-2015.rs | 1 + .../async-await/async-fn/edition-2015.stderr | 8 +++---- .../2015-edition-error-various-positions.rs | 1 + ...015-edition-error-various-positions.stderr | 22 +++++++++---------- .../await-keyword/2015-edition-warning.fixed | 1 + .../await-keyword/2015-edition-warning.rs | 1 + .../await-keyword/2015-edition-warning.stderr | 14 ++++++------ tests/ui/async-await/for-await-2015.rs | 1 + ...34-raw-ident-suggestion.edition2015.stderr | 6 ++--- ...34-raw-ident-suggestion.edition2018.stderr | 6 ++--- .../issue-65634-raw-ident-suggestion.rs | 1 + ...uggest-switching-edition-on-await-cargo.rs | 1 + ...st-switching-edition-on-await-cargo.stderr | 8 +++---- .../suggest-switching-edition-on-await.rs | 1 + .../suggest-switching-edition-on-await.stderr | 8 +++---- 16 files changed, 45 insertions(+), 36 deletions(-) diff --git a/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs b/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs index d222ddc081eff..60a7dff7d499a 100644 --- a/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs +++ b/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs @@ -1,3 +1,4 @@ +//@ edition:2015 //@ check-pass // Make sure that we don't eagerly recover `async ::Bound` in edition 2015. diff --git a/tests/ui/async-await/async-fn/edition-2015.rs b/tests/ui/async-await/async-fn/edition-2015.rs index 341b9b10e6711..5a81df3a4e4d9 100644 --- a/tests/ui/async-await/async-fn/edition-2015.rs +++ b/tests/ui/async-await/async-fn/edition-2015.rs @@ -1,3 +1,4 @@ +//@ edition:2015 fn foo(x: impl async Fn()) -> impl async Fn() { x } //~^ ERROR `async` trait bounds are only allowed in Rust 2018 or later //~| ERROR `async` trait bounds are only allowed in Rust 2018 or later diff --git a/tests/ui/async-await/async-fn/edition-2015.stderr b/tests/ui/async-await/async-fn/edition-2015.stderr index ca9e64cd1bb08..0bec00c162c9d 100644 --- a/tests/ui/async-await/async-fn/edition-2015.stderr +++ b/tests/ui/async-await/async-fn/edition-2015.stderr @@ -1,5 +1,5 @@ error: `async` trait bounds are only allowed in Rust 2018 or later - --> $DIR/edition-2015.rs:1:16 + --> $DIR/edition-2015.rs:2:16 | LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } | ^^^^^ @@ -8,7 +8,7 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } = note: for more on editions, read https://doc.rust-lang.org/edition-guide error: `async` trait bounds are only allowed in Rust 2018 or later - --> $DIR/edition-2015.rs:1:36 + --> $DIR/edition-2015.rs:2:36 | LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } | ^^^^^ @@ -17,7 +17,7 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0658]: `async` trait bounds are unstable - --> $DIR/edition-2015.rs:1:16 + --> $DIR/edition-2015.rs:2:16 | LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } | ^^^^^ @@ -28,7 +28,7 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } = help: use the desugared name of the async trait, such as `AsyncFn` error[E0658]: `async` trait bounds are unstable - --> $DIR/edition-2015.rs:1:36 + --> $DIR/edition-2015.rs:2:36 | LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } | ^^^^^ diff --git a/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs index 50c1639996ee5..714a3328ecf68 100644 --- a/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs +++ b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs @@ -1,3 +1,4 @@ +//@ edition:2015 #![allow(non_camel_case_types)] #![deny(keyword_idents)] diff --git a/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr index 8cea73f865148..70900e612f483 100644 --- a/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr +++ b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr @@ -1,5 +1,5 @@ error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:5:13 + --> $DIR/2015-edition-error-various-positions.rs:6:13 | LL | pub mod await { | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -7,14 +7,14 @@ LL | pub mod await { = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #49716 note: the lint level is defined here - --> $DIR/2015-edition-error-various-positions.rs:2:9 + --> $DIR/2015-edition-error-various-positions.rs:3:9 | LL | #![deny(keyword_idents)] | ^^^^^^^^^^^^^^ = note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]` error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:7:20 + --> $DIR/2015-edition-error-various-positions.rs:8:20 | LL | pub struct await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -23,7 +23,7 @@ LL | pub struct await; = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:11:16 + --> $DIR/2015-edition-error-various-positions.rs:12:16 | LL | use outer_mod::await::await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -32,7 +32,7 @@ LL | use outer_mod::await::await; = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:11:23 + --> $DIR/2015-edition-error-various-positions.rs:12:23 | LL | use outer_mod::await::await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -41,7 +41,7 @@ LL | use outer_mod::await::await; = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:16:14 + --> $DIR/2015-edition-error-various-positions.rs:17:14 | LL | struct Foo { await: () } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -50,7 +50,7 @@ LL | struct Foo { await: () } = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:20:15 + --> $DIR/2015-edition-error-various-positions.rs:21:15 | LL | impl Foo { fn await() {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -59,7 +59,7 @@ LL | impl Foo { fn await() {} } = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:24:14 + --> $DIR/2015-edition-error-various-positions.rs:25:14 | LL | macro_rules! await { | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -68,7 +68,7 @@ LL | macro_rules! await { = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:31:5 + --> $DIR/2015-edition-error-various-positions.rs:32:5 | LL | await!(); | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -77,7 +77,7 @@ LL | await!(); = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:34:11 + --> $DIR/2015-edition-error-various-positions.rs:35:11 | LL | match await { await => {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -86,7 +86,7 @@ LL | match await { await => {} } = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:34:19 + --> $DIR/2015-edition-error-various-positions.rs:35:19 | LL | match await { await => {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` diff --git a/tests/ui/async-await/await-keyword/2015-edition-warning.fixed b/tests/ui/async-await/await-keyword/2015-edition-warning.fixed index 4cb8017c7ee36..45758cb10391d 100644 --- a/tests/ui/async-await/await-keyword/2015-edition-warning.fixed +++ b/tests/ui/async-await/await-keyword/2015-edition-warning.fixed @@ -1,3 +1,4 @@ +//@ edition:2015 //@ run-rustfix #![allow(non_camel_case_types)] diff --git a/tests/ui/async-await/await-keyword/2015-edition-warning.rs b/tests/ui/async-await/await-keyword/2015-edition-warning.rs index d591a5af8218c..ea26abe072b37 100644 --- a/tests/ui/async-await/await-keyword/2015-edition-warning.rs +++ b/tests/ui/async-await/await-keyword/2015-edition-warning.rs @@ -1,3 +1,4 @@ +//@ edition:2015 //@ run-rustfix #![allow(non_camel_case_types)] diff --git a/tests/ui/async-await/await-keyword/2015-edition-warning.stderr b/tests/ui/async-await/await-keyword/2015-edition-warning.stderr index 70b7fa52a19c7..9d19a09092b94 100644 --- a/tests/ui/async-await/await-keyword/2015-edition-warning.stderr +++ b/tests/ui/async-await/await-keyword/2015-edition-warning.stderr @@ -1,5 +1,5 @@ error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-warning.rs:7:13 + --> $DIR/2015-edition-warning.rs:8:13 | LL | pub mod await { | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -7,14 +7,14 @@ LL | pub mod await { = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #49716 note: the lint level is defined here - --> $DIR/2015-edition-warning.rs:4:9 + --> $DIR/2015-edition-warning.rs:5:9 | LL | #![deny(keyword_idents)] | ^^^^^^^^^^^^^^ = note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]` error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-warning.rs:10:20 + --> $DIR/2015-edition-warning.rs:11:20 | LL | pub struct await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -23,7 +23,7 @@ LL | pub struct await; = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-warning.rs:15:16 + --> $DIR/2015-edition-warning.rs:16:16 | LL | use outer_mod::await::await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -32,7 +32,7 @@ LL | use outer_mod::await::await; = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-warning.rs:15:23 + --> $DIR/2015-edition-warning.rs:16:23 | LL | use outer_mod::await::await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -41,7 +41,7 @@ LL | use outer_mod::await::await; = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-warning.rs:22:11 + --> $DIR/2015-edition-warning.rs:23:11 | LL | match await { await => {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -50,7 +50,7 @@ LL | match await { await => {} } = note: for more information, see issue #49716 error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-warning.rs:22:19 + --> $DIR/2015-edition-warning.rs:23:19 | LL | match await { await => {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` diff --git a/tests/ui/async-await/for-await-2015.rs b/tests/ui/async-await/for-await-2015.rs index 89ff256da1ddf..c2bd39c844663 100644 --- a/tests/ui/async-await/for-await-2015.rs +++ b/tests/ui/async-await/for-await-2015.rs @@ -1,3 +1,4 @@ +//@ edition:2015 //@ check-pass #![feature(async_for_loop)] diff --git a/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2015.stderr b/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2015.stderr index 2bdc1347c815d..8ce4d4ea06ac8 100644 --- a/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2015.stderr +++ b/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2015.stderr @@ -1,16 +1,16 @@ error[E0034]: multiple applicable items in scope - --> $DIR/issue-65634-raw-ident-suggestion.rs:24:13 + --> $DIR/issue-65634-raw-ident-suggestion.rs:25:13 | LL | r#fn {}.r#struct(); | ^^^^^^^^ multiple `r#struct` found | note: candidate #1 is defined in an impl of the trait `async` for the type `r#fn` - --> $DIR/issue-65634-raw-ident-suggestion.rs:7:5 + --> $DIR/issue-65634-raw-ident-suggestion.rs:8:5 | LL | fn r#struct(&self) { | ^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl of the trait `await` for the type `r#fn` - --> $DIR/issue-65634-raw-ident-suggestion.rs:13:5 + --> $DIR/issue-65634-raw-ident-suggestion.rs:14:5 | LL | fn r#struct(&self) { | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2018.stderr b/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2018.stderr index ab10ab749fedf..d910ef9872cdb 100644 --- a/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2018.stderr +++ b/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2018.stderr @@ -1,16 +1,16 @@ error[E0034]: multiple applicable items in scope - --> $DIR/issue-65634-raw-ident-suggestion.rs:24:13 + --> $DIR/issue-65634-raw-ident-suggestion.rs:25:13 | LL | r#fn {}.r#struct(); | ^^^^^^^^ multiple `r#struct` found | note: candidate #1 is defined in an impl of the trait `r#async` for the type `r#fn` - --> $DIR/issue-65634-raw-ident-suggestion.rs:7:5 + --> $DIR/issue-65634-raw-ident-suggestion.rs:8:5 | LL | fn r#struct(&self) { | ^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl of the trait `r#await` for the type `r#fn` - --> $DIR/issue-65634-raw-ident-suggestion.rs:13:5 + --> $DIR/issue-65634-raw-ident-suggestion.rs:14:5 | LL | fn r#struct(&self) { | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/async-await/issue-65634-raw-ident-suggestion.rs b/tests/ui/async-await/issue-65634-raw-ident-suggestion.rs index ef5760f4846b7..98f5b6dd9f98e 100644 --- a/tests/ui/async-await/issue-65634-raw-ident-suggestion.rs +++ b/tests/ui/async-await/issue-65634-raw-ident-suggestion.rs @@ -1,4 +1,5 @@ //@ revisions: edition2015 edition2018 +//@[edition2015]edition:2015 //@[edition2018]edition:2018 #![allow(non_camel_case_types)] diff --git a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs index bcb5cb94b77c8..555b011052158 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs +++ b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs @@ -1,3 +1,4 @@ +//@ edition:2015 //@ rustc-env:CARGO_CRATE_NAME=foo use std::pin::Pin; diff --git a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr index 11f5825c232ea..c5f1793731ea4 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr +++ b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr @@ -1,5 +1,5 @@ error[E0609]: no field `await` on type `await_on_struct_missing::S` - --> $DIR/suggest-switching-edition-on-await-cargo.rs:11:7 + --> $DIR/suggest-switching-edition-on-await-cargo.rs:12:7 | LL | x.await; | ^^^^^ unknown field @@ -9,7 +9,7 @@ LL | x.await; = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0609]: no field `await` on type `await_on_struct_similar::S` - --> $DIR/suggest-switching-edition-on-await-cargo.rs:24:7 + --> $DIR/suggest-switching-edition-on-await-cargo.rs:25:7 | LL | x.await; | ^^^^^ unknown field @@ -24,7 +24,7 @@ LL + x.awai; | error[E0609]: no field `await` on type `Pin<&mut dyn Future>` - --> $DIR/suggest-switching-edition-on-await-cargo.rs:34:7 + --> $DIR/suggest-switching-edition-on-await-cargo.rs:35:7 | LL | x.await; | ^^^^^ unknown field @@ -34,7 +34,7 @@ LL | x.await; = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0609]: no field `await` on type `impl Future` - --> $DIR/suggest-switching-edition-on-await-cargo.rs:43:7 + --> $DIR/suggest-switching-edition-on-await-cargo.rs:44:7 | LL | x.await; | ^^^^^ unknown field diff --git a/tests/ui/async-await/suggest-switching-edition-on-await.rs b/tests/ui/async-await/suggest-switching-edition-on-await.rs index 0907a87e02cf3..6b639fa0b4ea5 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await.rs +++ b/tests/ui/async-await/suggest-switching-edition-on-await.rs @@ -1,3 +1,4 @@ +//@ edition:2015 use std::pin::Pin; use std::future::Future; diff --git a/tests/ui/async-await/suggest-switching-edition-on-await.stderr b/tests/ui/async-await/suggest-switching-edition-on-await.stderr index 2ede8d5b7f42e..bf03016222eaf 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await.stderr +++ b/tests/ui/async-await/suggest-switching-edition-on-await.stderr @@ -1,5 +1,5 @@ error[E0609]: no field `await` on type `await_on_struct_missing::S` - --> $DIR/suggest-switching-edition-on-await.rs:9:7 + --> $DIR/suggest-switching-edition-on-await.rs:10:7 | LL | x.await; | ^^^^^ unknown field @@ -9,7 +9,7 @@ LL | x.await; = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0609]: no field `await` on type `await_on_struct_similar::S` - --> $DIR/suggest-switching-edition-on-await.rs:22:7 + --> $DIR/suggest-switching-edition-on-await.rs:23:7 | LL | x.await; | ^^^^^ unknown field @@ -24,7 +24,7 @@ LL + x.awai; | error[E0609]: no field `await` on type `Pin<&mut dyn Future>` - --> $DIR/suggest-switching-edition-on-await.rs:32:7 + --> $DIR/suggest-switching-edition-on-await.rs:33:7 | LL | x.await; | ^^^^^ unknown field @@ -34,7 +34,7 @@ LL | x.await; = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0609]: no field `await` on type `impl Future` - --> $DIR/suggest-switching-edition-on-await.rs:41:7 + --> $DIR/suggest-switching-edition-on-await.rs:42:7 | LL | x.await; | ^^^^^ unknown field From c27aff35caad45093b52988994c2bc9b5631b544 Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 26 May 2025 16:35:36 +0100 Subject: [PATCH 09/18] Add test --- .../copy-check-when-count-inferred-later.rs | 11 +++++++++++ .../copy-check-when-count-inferred-later.stderr | 14 ++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/ui/repeat-expr/copy-check-when-count-inferred-later.rs create mode 100644 tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr diff --git a/tests/ui/repeat-expr/copy-check-when-count-inferred-later.rs b/tests/ui/repeat-expr/copy-check-when-count-inferred-later.rs new file mode 100644 index 0000000000000..b9d123cbefae6 --- /dev/null +++ b/tests/ui/repeat-expr/copy-check-when-count-inferred-later.rs @@ -0,0 +1,11 @@ +#![feature(generic_arg_infer)] + +// Test that we enforce repeat expr element types are `Copy` even +// when the repeat count is only inferred at a later point in type +// checking. + +fn main() { + let a = [String::new(); _]; + //~^ ERROR: the trait bound `String: Copy` is not satisfied + let b: [_; 2] = a; +} diff --git a/tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr b/tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr new file mode 100644 index 0000000000000..d974f5add5052 --- /dev/null +++ b/tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/copy-check-when-count-inferred-later.rs:8:14 + | +LL | let a = [String::new(); _]; + | ^^^^^^^^^^^^^ + | | + | the trait `Copy` is not implemented for `String` + | help: create an inline `const` block: `const { String::new() }` + | + = note: the `Copy` trait is required because this value will be copied for each element of the array + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 0497f31122e0c5908bf68d83f3e8ba5b559ae3d6 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 26 May 2025 17:55:03 +0200 Subject: [PATCH 10/18] rustc book: fix erratic sentence by making it more simple --- src/doc/rustc/src/check-cfg/cargo-specifics.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc/src/check-cfg/cargo-specifics.md b/src/doc/rustc/src/check-cfg/cargo-specifics.md index 371bbd26e943f..62a4dd1a3901d 100644 --- a/src/doc/rustc/src/check-cfg/cargo-specifics.md +++ b/src/doc/rustc/src/check-cfg/cargo-specifics.md @@ -9,8 +9,8 @@ rustc, not Cargo. --> This document is intended to summarize the principal ways Cargo interacts with -the `unexpected_cfgs` lint and `--check-cfg` flag. It is not intended to provide -individual details, for that refer to the [`--check-cfg` documentation](../check-cfg.md) and +the `unexpected_cfgs` lint and `--check-cfg` flag. +For individual details, refer to the [`--check-cfg` documentation](../check-cfg.md) and to the [Cargo book](../../cargo/index.html). > The full list of well known cfgs (aka builtins) can be found under [Checking conditional configurations / Well known names and values](../check-cfg.md#well-known-names-and-values). From 19802e8e9cf2732768c89dcfe1c5fa0eb88cd558 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 27 May 2025 02:06:40 +1000 Subject: [PATCH 11/18] Remove an unnecessary use of `Box::into_inner`. --- compiler/rustc_errors/src/diagnostic.rs | 2 +- compiler/rustc_errors/src/lib.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 539ecfbb42e2c..a11f81b55bb84 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1325,7 +1325,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { )); self.note("consider using `--verbose` to print the full type name to the console"); } - Box::into_inner(self.diag.take().unwrap()) + *self.diag.take().unwrap() } /// This method allows us to access the path of the file where "long types" are written to. diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index f8e19e5077893..bd421a441f95c 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -12,7 +12,6 @@ #![feature(array_windows)] #![feature(assert_matches)] #![feature(associated_type_defaults)] -#![feature(box_into_inner)] #![feature(box_patterns)] #![feature(default_field_values)] #![feature(error_reporter)] From 108c16eebd1d3de3641c9cdec48314596d01b1b8 Mon Sep 17 00:00:00 2001 From: Jeremy Drake Date: Mon, 26 May 2025 10:31:56 -0700 Subject: [PATCH 12/18] bootstrap: translate Windows paths in a way that works for both Cygwin and MSYS2 Cygwin defaults to rooting Windows paths in /cygdrive/X, while MSYS2 configures them to be /X. Regardless of configuration, drives are always accessible as /proc/cygdrive/X, so use that. --- src/bootstrap/src/core/build_steps/install.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index 585adf9be1604..5419540aa2e08 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -38,7 +38,9 @@ fn sanitize_sh(path: &Path, is_cygwin: bool) -> String { if ch.next() != Some('/') { return None; } - Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..])) + // The prefix for Windows drives in Cygwin/MSYS2 is configurable, but + // /proc/cygdrive is available regardless of configuration since 1.7.33 + Some(format!("/proc/cygdrive/{}/{}", drive, &s[drive.len_utf8() + 2..])) } } From 6a8663ae2602f3fdaf49a8f116b8a78ea3325f65 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 26 May 2025 12:01:43 -0700 Subject: [PATCH 13/18] Update mdbook to 0.4.51 This fixes a silly regression introduced in 0.4.50 that broke the search hotkey (https://github.com/rust-lang/rust/pull/141457). Changelog: https://github.com/rust-lang/mdBook/blob/master/CHANGELOG.md#mdbook-0451 --- src/tools/rustbook/Cargo.lock | 4 ++-- src/tools/rustbook/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index 5c862e9540075..07c5106331bf5 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -885,9 +885,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.50" +version = "0.4.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f72bc08f096e1fb15cfc382babe218317c2897d2040f967c4db40d156ca28e21" +checksum = "a87e65420ab45ca9c1b8cdf698f95b710cc826d373fa550f0f7fad82beac9328" dependencies = [ "ammonia", "anyhow", diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index ee2ada5aa2b38..69c0cfaf5c99d 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -15,6 +15,6 @@ mdbook-i18n-helpers = "0.3.3" mdbook-spec = { path = "../../doc/reference/mdbook-spec" } [dependencies.mdbook] -version = "0.4.50" +version = "0.4.51" default-features = false features = ["search"] From c8ed2a74236816072c8361994dd92d21a87cc36c Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 26 May 2025 18:13:54 -0300 Subject: [PATCH 14/18] Remove spastorino from vacations --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 9d7a0ef5aec0c..308e8db34384a 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1170,7 +1170,6 @@ contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ "fmease", "jyn514", - "spastorino", ] [[assign.warn_non_default_branch.exceptions]] From 7fe82632854ce64dd98044163b0e0e61be51fb04 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 27 May 2025 01:18:54 +0200 Subject: [PATCH 15/18] use custom types to clarify arguments to `emit_ptr_va_arg` --- compiler/rustc_codegen_llvm/src/va_arg.rs | 83 +++++++++++++++++------ 1 file changed, 61 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index c216f0f4a09d0..b91b6efed4522 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -63,14 +63,33 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>( } } +enum PassMode { + Direct, + Indirect, +} + +enum SlotSize { + Bytes8 = 8, + Bytes4 = 4, +} + +enum AllowHigherAlign { + No, + Yes, +} + fn emit_ptr_va_arg<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, target_ty: Ty<'tcx>, - indirect: bool, - slot_size: Align, - allow_higher_align: bool, + pass_mode: PassMode, + slot_size: SlotSize, + allow_higher_align: AllowHigherAlign, ) -> &'ll Value { + let indirect = matches!(pass_mode, PassMode::Indirect); + let allow_higher_align = matches!(allow_higher_align, AllowHigherAlign::Yes); + let slot_size = Align::from_bytes(slot_size as u64).unwrap(); + let layout = bx.cx.layout_of(target_ty); let (llty, size, align) = if indirect { ( @@ -179,8 +198,14 @@ fn emit_aapcs_va_arg<'ll, 'tcx>( // On Stack block bx.switch_to_block(on_stack); - let stack_value = - emit_ptr_va_arg(bx, list, target_ty, false, Align::from_bytes(8).unwrap(), true); + let stack_value = emit_ptr_va_arg( + bx, + list, + target_ty, + PassMode::Direct, + SlotSize::Bytes8, + AllowHigherAlign::Yes, + ); bx.br(end); bx.switch_to_block(end); @@ -386,29 +411,43 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( // Determine the va_arg implementation to use. The LLVM va_arg instruction // is lacking in some instances, so we should only use it as a fallback. let target = &bx.cx.tcx.sess.target; - let arch = &bx.cx.tcx.sess.target.arch; - match &**arch { - // Windows x86 - "x86" if target.is_like_windows => { - emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), false) - } - // Generic x86 - "x86" => emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), true), - // Windows AArch64 - "aarch64" | "arm64ec" if target.is_like_windows => { - emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false) - } - // macOS / iOS AArch64 - "aarch64" if target.is_like_darwin => { - emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), true) + + match &*target.arch { + "x86" => emit_ptr_va_arg( + bx, + addr, + target_ty, + PassMode::Direct, + SlotSize::Bytes4, + if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes }, + ), + "aarch64" | "arm64ec" if target.is_like_windows || target.is_like_darwin => { + emit_ptr_va_arg( + bx, + addr, + target_ty, + PassMode::Direct, + SlotSize::Bytes8, + if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes }, + ) } "aarch64" => emit_aapcs_va_arg(bx, addr, target_ty), "s390x" => emit_s390x_va_arg(bx, addr, target_ty), // Windows x86_64 "x86_64" if target.is_like_windows => { let target_ty_size = bx.cx.size_of(target_ty).bytes(); - let indirect: bool = target_ty_size > 8 || !target_ty_size.is_power_of_two(); - emit_ptr_va_arg(bx, addr, target_ty, indirect, Align::from_bytes(8).unwrap(), false) + emit_ptr_va_arg( + bx, + addr, + target_ty, + if target_ty_size > 8 || !target_ty_size.is_power_of_two() { + PassMode::Indirect + } else { + PassMode::Direct + }, + SlotSize::Bytes8, + AllowHigherAlign::No, + ) } "xtensa" => emit_xtensa_va_arg(bx, addr, target_ty), // For all other architecture/OS combinations fall back to using From e0d4cf38f49991c7c39ad563e32ddf840e8e4cd9 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Tue, 27 May 2025 14:54:02 +0800 Subject: [PATCH 16/18] further dedup `WalkItemKind` for `mut_visit` and `visit` also some drive-by fixes. --- compiler/rustc_ast/src/mut_visit.rs | 127 ------------ compiler/rustc_ast/src/visit.rs | 302 +++++++++++++--------------- 2 files changed, 145 insertions(+), 284 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 6770fd5a4aaeb..27a1eb17083e3 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1041,78 +1041,6 @@ pub fn walk_item_kind( kind.walk(span, id, visibility, ctxt, vis) } -impl WalkItemKind for AssocItemKind { - type Ctxt = AssocCtxt; - fn walk( - &mut self, - span: Span, - id: NodeId, - visibility: &mut Visibility, - ctxt: Self::Ctxt, - visitor: &mut V, - ) { - match self { - AssocItemKind::Const(item) => { - walk_const_item(visitor, item); - } - AssocItemKind::Fn(func) => { - visitor.visit_fn(FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &mut *func), span, id); - } - AssocItemKind::Type(box TyAlias { - defaultness, - ident, - generics, - where_clauses, - bounds, - ty, - }) => { - visit_defaultness(visitor, defaultness); - visitor.visit_ident(ident); - visitor.visit_generics(generics); - visit_bounds(visitor, bounds, BoundKind::Bound); - visit_opt(ty, |ty| visitor.visit_ty(ty)); - walk_ty_alias_where_clauses(visitor, where_clauses); - } - AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac), - AssocItemKind::Delegation(box Delegation { - id, - qself, - path, - ident, - rename, - body, - from_glob: _, - }) => { - visitor.visit_id(id); - visitor.visit_qself(qself); - visitor.visit_path(path); - visitor.visit_ident(ident); - if let Some(rename) = rename { - visitor.visit_ident(rename); - } - if let Some(body) = body { - visitor.visit_block(body); - } - } - AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { - visitor.visit_qself(qself); - visitor.visit_path(prefix); - if let Some(suffixes) = suffixes { - for (ident, rename) in suffixes { - visitor.visit_ident(ident); - if let Some(rename) = rename { - visitor.visit_ident(rename); - } - } - } - if let Some(body) = body { - visitor.visit_block(body); - } - } - } - } -} - pub fn walk_crate(vis: &mut T, krate: &mut Crate) { let Crate { attrs, items, spans, id, is_placeholder: _ } = krate; vis.visit_id(id); @@ -1123,14 +1051,6 @@ pub fn walk_crate(vis: &mut T, krate: &mut Crate) { vis.visit_span(inject_use_span); } -pub fn walk_item(visitor: &mut impl MutVisitor, item: &mut P>>) { - walk_item_ctxt(visitor, item, ()) -} - -pub fn walk_assoc_item(visitor: &mut impl MutVisitor, item: &mut P, ctxt: AssocCtxt) { - walk_item_ctxt(visitor, item, ctxt) -} - pub fn walk_flat_map_item(vis: &mut impl MutVisitor, mut item: P) -> SmallVec<[P; 1]> { vis.visit_item(&mut item); smallvec![item] @@ -1153,53 +1073,6 @@ pub fn walk_flat_map_assoc_item( smallvec![item] } -impl WalkItemKind for ForeignItemKind { - type Ctxt = (); - fn walk( - &mut self, - span: Span, - id: NodeId, - visibility: &mut Visibility, - _ctxt: Self::Ctxt, - visitor: &mut V, - ) { - match self { - ForeignItemKind::Static(box StaticItem { - ident, - ty, - mutability: _, - expr, - safety: _, - define_opaque, - }) => { - visitor.visit_ident(ident); - visitor.visit_ty(ty); - visit_opt(expr, |expr| visitor.visit_expr(expr)); - walk_define_opaques(visitor, define_opaque); - } - ForeignItemKind::Fn(func) => { - visitor.visit_fn(FnKind::Fn(FnCtxt::Foreign, visibility, &mut *func), span, id); - } - ForeignItemKind::TyAlias(box TyAlias { - defaultness, - ident, - generics, - where_clauses, - bounds, - ty, - }) => { - visit_defaultness(visitor, defaultness); - visitor.visit_ident(ident); - visitor.visit_generics(generics); - visit_bounds(visitor, bounds, BoundKind::Bound); - visit_opt(ty, |ty| visitor.visit_ty(ty)); - walk_ty_alias_where_clauses(visitor, where_clauses); - } - ForeignItemKind::MacCall(mac) => visitor.visit_mac_call(mac), - } - } -} - pub fn walk_pat(vis: &mut T, pat: &mut P) { let Pat { id, kind, span, tokens: _ } = pat.deref_mut(); vis.visit_id(id); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index c069425748098..bf5c402e52e5a 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -393,9 +393,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_fn_header<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, header: &$($lt)? $($mut)? FnHeader) $(-> >::Result)? { let FnHeader { safety, coroutine_kind, constness, ext: _ } = header; try_visit!(visit_constness(visitor, constness)); - if let Some(coroutine_kind) = coroutine_kind { - try_visit!(visitor.visit_coroutine_kind(coroutine_kind)); - } + visit_opt!(visitor, visit_coroutine_kind, coroutine_kind); visit_safety(visitor, safety) } @@ -417,6 +415,21 @@ macro_rules! common_visitor_and_walkers { visit_span(visitor, span) } + pub fn walk_item<$($lt,)? V: $Visitor$(<$lt>)?, K: WalkItemKind>( + visitor: &mut V, + item: &$($mut P>)? $($lt Item)?, + ) $(-> >::Result)? { + walk_item_ctxt(visitor, item, ()) + } + + pub fn walk_assoc_item<$($lt,)? V: $Visitor$(<$lt>)?>( + visitor: &mut V, + item: &$($mut P)? $($lt AssocItem)?, + ctxt: AssocCtxt, + ) $(-> >::Result)? { + walk_item_ctxt(visitor, item, ctxt) + } + impl WalkItemKind for ItemKind { type Ctxt = (); fn walk<$($lt,)? V: $Visitor$(<$lt>)?>( @@ -580,12 +593,8 @@ macro_rules! common_visitor_and_walkers { try_visit!(vis.visit_qself(qself)); try_visit!(vis.visit_path(path$(${ignore($lt)}, *id)?)); try_visit!(vis.visit_ident(ident)); - if let Some(rename) = rename { - try_visit!(vis.visit_ident(rename)); - } - if let Some(body) = body { - try_visit!(vis.visit_block(body)); - } + visit_opt!(vis, visit_ident, rename); + visit_opt!(vis, visit_block, body); $(>::Result::output())? } ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { @@ -594,14 +603,10 @@ macro_rules! common_visitor_and_walkers { if let Some(suffixes) = suffixes { for (ident, rename) in suffixes { try_visit!(vis.visit_ident(ident)); - if let Some(rename) = rename { - try_visit!(vis.visit_ident(rename)); - } + visit_opt!(vis, visit_ident, rename); } } - if let Some(body) = body { - try_visit!(vis.visit_block(body)); - } + visit_opt!(vis, visit_block, body); $(>::Result::output())? } } @@ -643,6 +648,131 @@ macro_rules! common_visitor_and_walkers { } $(>::Result::output())? } + + impl WalkItemKind for AssocItemKind { + type Ctxt = AssocCtxt; + fn walk<$($lt,)? V: $Visitor$(<$lt>)?>( + &$($lt)? $($mut)? self, + span: Span, + id: NodeId, + visibility: &$($lt)? $($mut)? Visibility, + ctxt: Self::Ctxt, + vis: &mut V, + ) $(-> >::Result)? { + match self { + AssocItemKind::Const(item) => { + walk_const_item(vis, item) + } + AssocItemKind::Fn(func) => { + vis.visit_fn(FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &$($mut)? *func), span, id) + } + AssocItemKind::Type(box TyAlias { + generics, + ident, + bounds, + ty, + defaultness, + $(${ignore($lt)} #[expect(unused)])? + where_clauses, + }) => { + try_visit!(visit_defaultness(vis, defaultness)); + try_visit!(vis.visit_ident(ident)); + try_visit!(vis.visit_generics(generics)); + try_visit!(visit_bounds(vis, bounds, BoundKind::Bound)); + visit_opt!(vis, visit_ty, ty); + $(${ignore($mut)} + walk_ty_alias_where_clauses(vis, where_clauses); + )? + $(>::Result::output())? + } + AssocItemKind::MacCall(mac) => { + vis.visit_mac_call(mac) + } + AssocItemKind::Delegation(box Delegation { + id, + qself, + path, + ident, + rename, + body, + from_glob: _, + }) => { + try_visit!(visit_id(vis, id)); + try_visit!(vis.visit_qself(qself)); + try_visit!(vis.visit_path(path $(${ignore($lt)}, *id)?)); + try_visit!(vis.visit_ident(ident)); + visit_opt!(vis, visit_ident, rename); + visit_opt!(vis, visit_block, body); + $(>::Result::output())? + } + AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { + try_visit!(vis.visit_qself(qself)); + try_visit!(vis.visit_path(prefix$(${ignore($lt)}, id)?)); + if let Some(suffixes) = suffixes { + for (ident, rename) in suffixes { + try_visit!(vis.visit_ident(ident)); + visit_opt!(vis, visit_ident, rename); + } + } + visit_opt!(vis, visit_block, body); + $(>::Result::output())? + } + } + } + } + + impl WalkItemKind for ForeignItemKind { + type Ctxt = (); + fn walk<$($lt,)? V: $Visitor$(<$lt>)?>( + &$($lt)? $($mut)? self, + span: Span, + id: NodeId, + visibility: &$($lt)? $($mut)? Visibility, + _ctxt: Self::Ctxt, + vis: &mut V, + ) $(-> >::Result)? { + match self { + ForeignItemKind::Static(box StaticItem { + ident, + ty, + mutability: _, + expr, + safety: _, + define_opaque, + }) => { + try_visit!(vis.visit_ident(ident)); + try_visit!(vis.visit_ty(ty)); + visit_opt!(vis, visit_expr, expr); + walk_define_opaques(vis, define_opaque) + } + ForeignItemKind::Fn(func) => { + vis.visit_fn(FnKind::Fn(FnCtxt::Foreign, visibility, &$($mut)?*func), span, id) + } + ForeignItemKind::TyAlias(box TyAlias { + defaultness, + ident, + generics, + bounds, + ty, + $(${ignore($lt)} #[expect(unused)])? + where_clauses, + }) => { + try_visit!(visit_defaultness(vis, defaultness)); + try_visit!(vis.visit_ident(ident)); + try_visit!(vis.visit_generics(generics)); + try_visit!(visit_bounds(vis, bounds, BoundKind::Bound)); + visit_opt!(vis, visit_ty, ty); + $(${ignore($mut)} + walk_ty_alias_where_clauses(vis, where_clauses); + )? + $(>::Result::output())? + } + ForeignItemKind::MacCall(mac) => { + vis.visit_mac_call(mac) + } + } + } + } }; } @@ -928,55 +1058,6 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res V::Result::output() } -impl WalkItemKind for ForeignItemKind { - type Ctxt = (); - fn walk<'a, V: Visitor<'a>>( - &'a self, - span: Span, - id: NodeId, - vis: &'a Visibility, - _ctxt: Self::Ctxt, - visitor: &mut V, - ) -> V::Result { - match self { - ForeignItemKind::Static(box StaticItem { - ident, - ty, - mutability: _, - expr, - safety: _, - define_opaque, - }) => { - try_visit!(visitor.visit_ident(ident)); - try_visit!(visitor.visit_ty(ty)); - visit_opt!(visitor, visit_expr, expr); - try_visit!(walk_define_opaques(visitor, define_opaque)); - } - ForeignItemKind::Fn(func) => { - let kind = FnKind::Fn(FnCtxt::Foreign, vis, &*func); - try_visit!(visitor.visit_fn(kind, span, id)); - } - ForeignItemKind::TyAlias(box TyAlias { - generics, - ident, - bounds, - ty, - defaultness: _, - where_clauses: _, - }) => { - try_visit!(visitor.visit_ident(ident)); - try_visit!(visitor.visit_generics(generics)); - walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); - visit_opt!(visitor, visit_ty, ty); - } - ForeignItemKind::MacCall(mac) => { - try_visit!(visitor.visit_mac_call(mac)); - } - } - V::Result::output() - } -} - pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) -> V::Result { match bound { GenericBound::Trait(trait_ref) => visitor.visit_poly_trait_ref(trait_ref), @@ -1135,99 +1216,6 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu V::Result::output() } -impl WalkItemKind for AssocItemKind { - type Ctxt = AssocCtxt; - fn walk<'a, V: Visitor<'a>>( - &'a self, - span: Span, - id: NodeId, - vis: &'a Visibility, - ctxt: Self::Ctxt, - visitor: &mut V, - ) -> V::Result { - match self { - AssocItemKind::Const(box ConstItem { - defaultness: _, - ident, - generics, - ty, - expr, - define_opaque, - }) => { - try_visit!(visitor.visit_ident(ident)); - try_visit!(visitor.visit_generics(generics)); - try_visit!(visitor.visit_ty(ty)); - visit_opt!(visitor, visit_expr, expr); - try_visit!(walk_define_opaques(visitor, define_opaque)); - } - AssocItemKind::Fn(func) => { - let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), vis, &*func); - try_visit!(visitor.visit_fn(kind, span, id)); - } - AssocItemKind::Type(box TyAlias { - generics, - ident, - bounds, - ty, - defaultness: _, - where_clauses: _, - }) => { - try_visit!(visitor.visit_generics(generics)); - try_visit!(visitor.visit_ident(ident)); - walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); - visit_opt!(visitor, visit_ty, ty); - } - AssocItemKind::MacCall(mac) => { - try_visit!(visitor.visit_mac_call(mac)); - } - AssocItemKind::Delegation(box Delegation { - id, - qself, - path, - ident, - rename, - body, - from_glob: _, - }) => { - try_visit!(visitor.visit_qself(qself)); - try_visit!(visitor.visit_path(path, *id)); - try_visit!(visitor.visit_ident(ident)); - visit_opt!(visitor, visit_ident, rename); - visit_opt!(visitor, visit_block, body); - } - AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { - try_visit!(visitor.visit_qself(qself)); - try_visit!(visitor.visit_path(prefix, id)); - if let Some(suffixes) = suffixes { - for (ident, rename) in suffixes { - visitor.visit_ident(ident); - if let Some(rename) = rename { - visitor.visit_ident(rename); - } - } - } - visit_opt!(visitor, visit_block, body); - } - } - V::Result::output() - } -} - -pub fn walk_item<'a, V: Visitor<'a>>( - visitor: &mut V, - item: &'a Item>, -) -> V::Result { - walk_item_ctxt(visitor, item, ()) -} - -pub fn walk_assoc_item<'a, V: Visitor<'a>>( - visitor: &mut V, - item: &'a AssocItem, - ctxt: AssocCtxt, -) -> V::Result { - walk_item_ctxt(visitor, item, ctxt) -} - pub fn walk_struct_def<'a, V: Visitor<'a>>( visitor: &mut V, struct_definition: &'a VariantData, From 3fff727e87099b6cc4daca13f5fd0adf439ad4e7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 26 May 2025 10:38:02 +0000 Subject: [PATCH 17/18] Use more detailed spans in dyn compat errors within bodies --- compiler/rustc_hir_analysis/src/collect.rs | 8 ++- .../src/hir_ty_lowering/dyn_compatibility.rs | 5 +- .../src/hir_ty_lowering/mod.rs | 6 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 6 +- .../dyn/mut-is-pointer-like.stderr | 4 +- tests/ui/async-await/dyn/works.stderr | 4 +- tests/ui/async-await/dyn/wrong-size.stderr | 4 +- .../in-trait/dyn-compatibility.stderr | 4 +- ...ect-reference-without-parens-suggestion.rs | 1 + ...reference-without-parens-suggestion.stderr | 16 ++++- .../almost-supertrait-associated-type.stderr | 4 +- tests/ui/dyn-compatibility/generics.stderr | 4 +- ...tion-correct-dyn-incompatible-trait.stderr | 4 +- tests/ui/dyn-compatibility/no-static.stderr | 4 +- ...gate-dispatch-from-dyn-missing-impl.stderr | 4 +- .../issue-76535.stderr | 4 +- .../issue-78671.stderr | 4 +- .../issue-79422.stderr | 4 +- .../trait-bounds/span-bug-issue-121597.rs | 1 - .../trait-bounds/span-bug-issue-121597.stderr | 25 ++----- ...ible-trait-in-return-position-dyn-trait.rs | 2 + ...-trait-in-return-position-dyn-trait.stderr | 72 ++++++++++++++++++- .../in-trait/dyn-compatibility.stderr | 4 +- .../in-trait/foreign-dyn-error.stderr | 4 +- tests/ui/issues/issue-18959.rs | 1 + tests/ui/issues/issue-18959.stderr | 22 +++++- tests/ui/issues/issue-50781.stderr | 4 +- tests/ui/issues/issue-58734.rs | 3 +- tests/ui/issues/issue-58734.stderr | 11 +-- .../kindck/kindck-inherited-copy-bound.stderr | 4 +- ...bitrary-self-types-dyn-incompatible.stderr | 4 +- tests/ui/traits/issue-20692.stderr | 4 +- tests/ui/traits/issue-38604.stderr | 4 +- tests/ui/traits/item-privacy.rs | 4 +- tests/ui/traits/item-privacy.stderr | 54 +++----------- .../supertrait-dyn-compatibility.rs | 1 - .../supertrait-dyn-compatibility.stderr | 22 +----- ...onicalize-fresh-infer-vars-issue-103626.rs | 1 - ...alize-fresh-infer-vars-issue-103626.stderr | 24 ++----- tests/ui/traits/object/macro-matcher.stderr | 16 ++--- tests/ui/traits/object/safety.stderr | 4 +- tests/ui/traits/test-2.stderr | 4 +- ...rameter-defaults-referencing-Self-ppaux.rs | 1 - ...ter-defaults-referencing-Self-ppaux.stderr | 21 ++---- tests/ui/wf/wf-dyn-incompatible.stderr | 4 +- 45 files changed, 205 insertions(+), 206 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index f5206d9a01529..8a2edd843f209 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -31,7 +31,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt, walk_generics}; use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::ObligationCause; +use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause}; use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; @@ -40,7 +40,7 @@ use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName; use rustc_trait_selection::infer::InferCtxtExt; -use rustc_trait_selection::traits::ObligationCtxt; +use rustc_trait_selection::traits::{ObligationCtxt, hir_ty_lowering_dyn_compatibility_violations}; use tracing::{debug, instrument}; use crate::errors; @@ -625,6 +625,10 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { (input_tys, output_ty) } + + fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec { + hir_ty_lowering_dyn_compatibility_violations(self.tcx, trait_def_id) + } } /// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 9e44b645aca7b..fb65c9a8929b0 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::{ }; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility; -use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations}; +use rustc_trait_selection::traits; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; @@ -97,8 +97,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // to avoid ICEs. for (clause, span) in user_written_bounds { if let Some(trait_pred) = clause.as_trait_clause() { - let violations = - hir_ty_lowering_dyn_compatibility_violations(tcx, trait_pred.def_id()); + let violations = self.dyn_compatibility_violations(trait_pred.def_id()); if !violations.is_empty() { let reported = report_dyn_incompatibility( tcx, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 6b21bbbfcd809..a5dd17b4d634a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -33,7 +33,7 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::ObligationCause; +use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause}; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::ty::print::PrintPolyTraitRefExt as _; @@ -200,6 +200,10 @@ pub trait HirTyLowerer<'tcx> { { self } + + /// Performs minimalistic dyn compat checks outside of bodies, but full within bodies. + /// Outside of bodies we could end up in cycles, so we delay most checks to later phases. + fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec; } /// The "qualified self" of an associated item path. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index ea0adf16b1a36..cfb25deac0e04 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -14,7 +14,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, HirId, ItemLocalMap}; use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason}; use rustc_infer::infer; -use rustc_infer::traits::Obligation; +use rustc_infer::traits::{DynCompatibilityViolation, Obligation}; use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::Session; use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span, sym}; @@ -388,6 +388,10 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { }; (input_tys, output_ty) } + + fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec { + self.tcx.dyn_compatibility_violations(trait_def_id).to_vec() + } } /// The `ty` representation of a user-provided type. Depending on the use-site diff --git a/tests/ui/async-await/dyn/mut-is-pointer-like.stderr b/tests/ui/async-await/dyn/mut-is-pointer-like.stderr index 9b818a15c29ce..6689539ff453a 100644 --- a/tests/ui/async-await/dyn/mut-is-pointer-like.stderr +++ b/tests/ui/async-await/dyn/mut-is-pointer-like.stderr @@ -8,10 +8,10 @@ LL | #![feature(async_fn_in_dyn_trait)] = note: `#[warn(incomplete_features)]` on by default error[E0038]: the trait `AsyncTrait` is not dyn compatible - --> $DIR/mut-is-pointer-like.rs:35:16 + --> $DIR/mut-is-pointer-like.rs:35:29 | LL | let x: Pin<&mut dyn AsyncTrait> = f; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible + | ^^^^^^^^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/async-await/dyn/works.stderr b/tests/ui/async-await/dyn/works.stderr index 5d2cc385cbd64..338479d8b70a9 100644 --- a/tests/ui/async-await/dyn/works.stderr +++ b/tests/ui/async-await/dyn/works.stderr @@ -8,10 +8,10 @@ LL | #![feature(async_fn_in_dyn_trait)] = note: `#[warn(incomplete_features)]` on by default error[E0038]: the trait `AsyncTrait` is not dyn compatible - --> $DIR/works.rs:27:16 + --> $DIR/works.rs:27:21 | LL | let x: &dyn AsyncTrait = &"hello, world!"; - | ^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible + | ^^^^^^^^^^ `AsyncTrait` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/async-await/dyn/wrong-size.stderr b/tests/ui/async-await/dyn/wrong-size.stderr index 930ca571417d7..a465f91f62af0 100644 --- a/tests/ui/async-await/dyn/wrong-size.stderr +++ b/tests/ui/async-await/dyn/wrong-size.stderr @@ -8,10 +8,10 @@ LL | #![feature(async_fn_in_dyn_trait)] = note: `#[warn(incomplete_features)]` on by default error[E0038]: the trait `AsyncTrait` is not dyn compatible - --> $DIR/wrong-size.rs:21:12 + --> $DIR/wrong-size.rs:21:17 | LL | let x: &dyn AsyncTrait = &"hello, world!"; - | ^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible + | ^^^^^^^^^^ `AsyncTrait` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/async-await/in-trait/dyn-compatibility.stderr b/tests/ui/async-await/in-trait/dyn-compatibility.stderr index 553bcbf89d590..f0c5dc5347882 100644 --- a/tests/ui/async-await/in-trait/dyn-compatibility.stderr +++ b/tests/ui/async-await/in-trait/dyn-compatibility.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/dyn-compatibility.rs:9:12 + --> $DIR/dyn-compatibility.rs:9:17 | LL | let x: &dyn Foo = todo!(); - | ^^^^^^^^ `Foo` is not dyn compatible + | ^^^ `Foo` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs index 9cd32ffeb6d0b..b7470864a30db 100644 --- a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs +++ b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs @@ -4,4 +4,5 @@ fn main() { let _: &Copy + 'static; //~ ERROR expected a path //~^ ERROR is not dyn compatible let _: &'static Copy + 'static; //~ ERROR expected a path + //~^ ERROR is not dyn compatible } diff --git a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr index 762b37b9e9d69..57dbc79a0fda2 100644 --- a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr +++ b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr @@ -21,16 +21,26 @@ LL | let _: &'static (Copy + 'static); | + + error[E0038]: the trait `Copy` is not dyn compatible - --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12 + --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:13 | LL | let _: &Copy + 'static; - | ^^^^^ `Copy` is not dyn compatible + | ^^^^ `Copy` is not dyn compatible + | + = note: the trait is not dyn compatible because it requires `Self: Sized` + = note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + +error[E0038]: the trait `Copy` is not dyn compatible + --> $DIR/trait-object-reference-without-parens-suggestion.rs:6:21 + | +LL | let _: &'static Copy + 'static; + | ^^^^ `Copy` is not dyn compatible | = note: the trait is not dyn compatible because it requires `Self: Sized` = note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0038, E0178. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr index d3022b5d8cd4a..acd6dbe7b2c22 100644 --- a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr +++ b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr @@ -16,10 +16,10 @@ LL | fn transmute(&self, t: T) -> >::Assoc; = help: consider moving `transmute` to another trait error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/almost-supertrait-associated-type.rs:7:27 + --> $DIR/almost-supertrait-associated-type.rs:7:32 | LL | (&PhantomData:: as &dyn Foo).transmute(t) - | ^^^^^^^^^^^^^^ `Foo` is not dyn compatible + | ^^^^^^^^^ `Foo` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/dyn-compatibility/generics.stderr b/tests/ui/dyn-compatibility/generics.stderr index aec51970ebb17..79dccc4224487 100644 --- a/tests/ui/dyn-compatibility/generics.stderr +++ b/tests/ui/dyn-compatibility/generics.stderr @@ -31,10 +31,10 @@ LL | fn bar(&self, t: T); = help: consider moving `bar` to another trait error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/generics.rs:22:10 + --> $DIR/generics.rs:22:15 | LL | t as &dyn Bar - | ^^^^^^^^ `Bar` is not dyn compatible + | ^^^ `Bar` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr index 5bc1847ebde5e..dd7b31a70c555 100644 --- a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr +++ b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:15 + --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:24 | LL | let test: &mut dyn Bar = &mut thing; - | ^^^^^^^^^^^^ `Bar` is not dyn compatible + | ^^^ `Bar` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/dyn-compatibility/no-static.stderr b/tests/ui/dyn-compatibility/no-static.stderr index 8e4f109c97db3..c1d5dd6f562f7 100644 --- a/tests/ui/dyn-compatibility/no-static.stderr +++ b/tests/ui/dyn-compatibility/no-static.stderr @@ -23,10 +23,10 @@ LL | fn foo() where Self: Sized {} | +++++++++++++++++ error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/no-static.rs:18:12 + --> $DIR/no-static.rs:18:20 | LL | let b: Box = Box::new(Bar); - | ^^^^^^^^^^^^ `Foo` is not dyn compatible + | ^^^ `Foo` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr index 18b99d24083b7..c70ab65aa9056 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Trait` is not dyn compatible - --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:25 + --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:33 | LL | fn ptr(self: Ptr); | --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self` ... LL | Ptr(Box::new(4)) as Ptr; - | ^^^^^^^^^^^^^^ `Trait` is not dyn compatible + | ^^^^^ `Trait` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/generic-associated-types/issue-76535.stderr b/tests/ui/generic-associated-types/issue-76535.stderr index 9bac3318948c0..2daf9d817bb35 100644 --- a/tests/ui/generic-associated-types/issue-76535.stderr +++ b/tests/ui/generic-associated-types/issue-76535.stderr @@ -15,10 +15,10 @@ LL | let sub: Box = SubStruct>> = Box::new(SuperS | ++++ error[E0038]: the trait `SuperTrait` is not dyn compatible - --> $DIR/issue-76535.rs:34:14 + --> $DIR/issue-76535.rs:34:22 | LL | let sub: Box> = Box::new(SuperStruct::new(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` is not dyn compatible + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/generic-associated-types/issue-78671.stderr b/tests/ui/generic-associated-types/issue-78671.stderr index c6da137672de9..fff061a8ada75 100644 --- a/tests/ui/generic-associated-types/issue-78671.stderr +++ b/tests/ui/generic-associated-types/issue-78671.stderr @@ -15,10 +15,10 @@ LL | Box::new(Family) as &dyn CollectionFamily=usize> | +++ error[E0038]: the trait `CollectionFamily` is not dyn compatible - --> $DIR/issue-78671.rs:5:25 + --> $DIR/issue-78671.rs:5:30 | LL | Box::new(Family) as &dyn CollectionFamily - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` is not dyn compatible + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/generic-associated-types/issue-79422.stderr b/tests/ui/generic-associated-types/issue-79422.stderr index 403cb67adb414..dcf3a9008de5f 100644 --- a/tests/ui/generic-associated-types/issue-79422.stderr +++ b/tests/ui/generic-associated-types/issue-79422.stderr @@ -15,10 +15,10 @@ LL | as Box = dyn RefCont<'_, u8>>>; | ++++ error[E0038]: the trait `MapLike` is not dyn compatible - --> $DIR/issue-79422.rs:45:12 + --> $DIR/issue-79422.rs:45:20 | LL | as Box>>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` is not dyn compatible + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs index 949c49a820b79..cc8134304685c 100644 --- a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs +++ b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs @@ -15,5 +15,4 @@ fn main() { //~^ ERROR the trait `Foo` is not dyn compatible needs_bar(x); - //~^ ERROR mismatched types } diff --git a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr index 10a9e2c8d24b3..d35394a4f669d 100644 --- a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr +++ b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/span-bug-issue-121597.rs:14:12 + --> $DIR/span-bug-issue-121597.rs:14:17 | LL | let x: &dyn Foo = &(); - | ^^^^^^^^ `Foo` is not dyn compatible + | ^^^ `Foo` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit @@ -13,23 +13,6 @@ LL | trait Foo: for Bar {} | | | this trait is not dyn compatible... -error[E0308]: mismatched types - --> $DIR/span-bug-issue-121597.rs:17:15 - | -LL | needs_bar(x); - | --------- ^ types differ in mutability - | | - | arguments to this function are incorrect - | - = note: expected raw pointer `*mut Type2` - found reference `&dyn Foo` -note: function defined here - --> $DIR/span-bug-issue-121597.rs:11:4 - | -LL | fn needs_bar(_: *mut Type2) {} - | ^^^^^^^^^ ------------- - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0038, E0308. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs index c3dc417b18730..accd173ce235a 100644 --- a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs @@ -21,6 +21,8 @@ impl DynIncompatible for B { fn car() -> dyn DynIncompatible { //~ ERROR the trait `DynIncompatible` is not dyn compatible //~^ ERROR return type cannot be a trait object without pointer indirection +//~| ERROR the trait `DynIncompatible` is not dyn compatible +//~| ERROR the trait `DynIncompatible` is not dyn compatible if true { return A; } diff --git a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr index a230090eb00e2..a8787a01a6f6a 100644 --- a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr @@ -41,6 +41,7 @@ help: alternatively, box the return type, and wrap all of the returned values in | LL ~ fn car() -> Box { LL | +... LL | if true { LL ~ return Box::new(A); LL | } @@ -48,7 +49,7 @@ LL ~ Box::new(B) | error[E0038]: the trait `DynIncompatible` is not dyn compatible - --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:30:17 + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:32:17 | LL | fn cat() -> Box { | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible @@ -75,7 +76,74 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ -error: aborting due to 3 previous errors +error[E0038]: the trait `DynIncompatible` is not dyn compatible + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:22:17 + | +LL | fn car() -> dyn DynIncompatible { + | ^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 + | +LL | trait DynIncompatible { + | --------------- this trait is not dyn compatible... +LL | fn foo() -> Self; + | ^^^ ...because associated function `foo` has no `self` parameter + = help: the following types implement `DynIncompatible`: + A + B + consider defining an enum where each variant holds one of these types, + implementing `DynIncompatible` for this new enum and using it instead +help: consider using an opaque type instead + | +LL - fn car() -> dyn DynIncompatible { +LL + fn car() -> impl DynIncompatible { + | +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self) -> Self; + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() -> Self where Self: Sized; + | +++++++++++++++++ + +error[E0038]: the trait `DynIncompatible` is not dyn compatible + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:22:17 + | +LL | fn car() -> dyn DynIncompatible { + | ^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 + | +LL | trait DynIncompatible { + | --------------- this trait is not dyn compatible... +LL | fn foo() -> Self; + | ^^^ ...because associated function `foo` has no `self` parameter + = help: the following types implement `DynIncompatible`: + A + B + consider defining an enum where each variant holds one of these types, + implementing `DynIncompatible` for this new enum and using it instead + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider using an opaque type instead + | +LL - fn car() -> dyn DynIncompatible { +LL + fn car() -> impl DynIncompatible { + | +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self) -> Self; + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() -> Self where Self: Sized; + | +++++++++++++++++ + +error: aborting due to 5 previous errors Some errors have detailed explanations: E0038, E0746. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr index d65ed6bbcdac5..8cdb380853313 100644 --- a/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr +++ b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/dyn-compatibility.rs:14:33 + --> $DIR/dyn-compatibility.rs:14:41 | LL | let i = Box::new(42_u32) as Box; - | ^^^^^^^^^^^^ `Foo` is not dyn compatible + | ^^^ `Foo` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr index 29235ca78a504..68ac765a3c1e5 100644 --- a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr +++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/foreign-dyn-error.rs:6:12 + --> $DIR/foreign-dyn-error.rs:6:17 | LL | let _: &dyn rpitit::Foo = todo!(); - | ^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible + | ^^^^^^^^^^^ `Foo` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/issues/issue-18959.rs b/tests/ui/issues/issue-18959.rs index 4fe669adcdaf8..415fe818f5308 100644 --- a/tests/ui/issues/issue-18959.rs +++ b/tests/ui/issues/issue-18959.rs @@ -18,4 +18,5 @@ fn main() { let test: &dyn Bar = &mut thing; //~^ ERROR E0038 foo(test); + //~^ ERROR E0038 } diff --git a/tests/ui/issues/issue-18959.stderr b/tests/ui/issues/issue-18959.stderr index 5345046ba6d3c..df47d50a01979 100644 --- a/tests/ui/issues/issue-18959.stderr +++ b/tests/ui/issues/issue-18959.stderr @@ -15,10 +15,10 @@ LL | pub trait Bar: Foo { } = help: consider moving `foo` to another trait error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/issue-18959.rs:18:15 + --> $DIR/issue-18959.rs:18:20 | LL | let test: &dyn Bar = &mut thing; - | ^^^^^^^^ `Bar` is not dyn compatible + | ^^^ `Bar` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit @@ -30,6 +30,22 @@ LL | pub trait Bar: Foo { } | --- this trait is not dyn compatible... = help: consider moving `foo` to another trait -error: aborting due to 2 previous errors +error[E0038]: the trait `Bar` is not dyn compatible + --> $DIR/issue-18959.rs:20:9 + | +LL | foo(test); + | ^^^^ `Bar` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/issue-18959.rs:1:20 + | +LL | pub trait Foo { fn foo(&self, ext_thing: &T); } + | ^^^ ...because method `foo` has generic type parameters +LL | pub trait Bar: Foo { } + | --- this trait is not dyn compatible... + = help: consider moving `foo` to another trait + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/issues/issue-50781.stderr b/tests/ui/issues/issue-50781.stderr index be6519429a515..4ba3166b6c581 100644 --- a/tests/ui/issues/issue-50781.stderr +++ b/tests/ui/issues/issue-50781.stderr @@ -16,10 +16,10 @@ LL | fn foo(&self) where Self: Trait; = help: only type `()` implements `X`; consider using it directly instead. error[E0038]: the trait `X` is not dyn compatible - --> $DIR/issue-50781.rs:16:6 + --> $DIR/issue-50781.rs:16:10 | LL | ::foo(&()); - | ^^^^^ `X` is not dyn compatible + | ^ `X` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/issues/issue-58734.rs b/tests/ui/issues/issue-58734.rs index ee23be87b6b79..e5b371f5530dc 100644 --- a/tests/ui/issues/issue-58734.rs +++ b/tests/ui/issues/issue-58734.rs @@ -18,8 +18,7 @@ fn main() { Trait::exists(()); // no dyn-compatibility error Trait::nonexistent(()); - //~^ ERROR no function or associated item named `nonexistent` found - //~| WARN trait objects without an explicit `dyn` are deprecated + //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition //~| ERROR the trait `Trait` is not dyn compatible } diff --git a/tests/ui/issues/issue-58734.stderr b/tests/ui/issues/issue-58734.stderr index c4624cecc621c..e5dad000b510a 100644 --- a/tests/ui/issues/issue-58734.stderr +++ b/tests/ui/issues/issue-58734.stderr @@ -37,13 +37,6 @@ help: alternatively, consider constraining `dyn_incompatible` so it does not app LL | fn dyn_incompatible() -> Self where Self: Sized; | +++++++++++++++++ -error[E0599]: no function or associated item named `nonexistent` found for trait object `dyn Trait` in the current scope - --> $DIR/issue-58734.rs:20:12 - | -LL | Trait::nonexistent(()); - | ^^^^^^^^^^^ function or associated item not found in `dyn Trait` - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted -Some errors have detailed explanations: E0038, E0599. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.stderr index 05d31f48f47a4..c15aabacddd17 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.stderr @@ -20,10 +20,10 @@ LL | fn take_param(foo: &T) { } | ^^^ required by this bound in `take_param` error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/kindck-inherited-copy-bound.rs:23:19 + --> $DIR/kindck-inherited-copy-bound.rs:23:24 | LL | let z = &x as &dyn Foo; - | ^^^^^^^^ `Foo` is not dyn compatible + | ^^^ `Foo` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr b/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr index 977ccecea0641..fe4802c9b3a47 100644 --- a/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr +++ b/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/arbitrary-self-types-dyn-incompatible.rs:29:32 + --> $DIR/arbitrary-self-types-dyn-incompatible.rs:29:39 | LL | fn foo(self: &Rc) -> usize; | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` ... LL | let x = Rc::new(5usize) as Rc; - | ^^^^^^^^^^^ `Foo` is not dyn compatible + | ^^^ `Foo` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/traits/issue-20692.stderr b/tests/ui/traits/issue-20692.stderr index e902a582cc70f..d4a18899dcbbd 100644 --- a/tests/ui/traits/issue-20692.stderr +++ b/tests/ui/traits/issue-20692.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Array` is not dyn compatible - --> $DIR/issue-20692.rs:6:5 + --> $DIR/issue-20692.rs:6:10 | LL | &dyn Array; - | ^^^^^^^^^^ `Array` is not dyn compatible + | ^^^^^ `Array` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/traits/issue-38604.stderr b/tests/ui/traits/issue-38604.stderr index 0455230b1aa3c..0f39dc536eb88 100644 --- a/tests/ui/traits/issue-38604.stderr +++ b/tests/ui/traits/issue-38604.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/issue-38604.rs:14:13 + --> $DIR/issue-38604.rs:14:21 | LL | let _f: Box = - | ^^^^^^^^^^^^ `Foo` is not dyn compatible + | ^^^ `Foo` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/traits/item-privacy.rs b/tests/ui/traits/item-privacy.rs index cdfd667a6f12e..9f75e6e4c1235 100644 --- a/tests/ui/traits/item-privacy.rs +++ b/tests/ui/traits/item-privacy.rs @@ -99,9 +99,7 @@ fn check_assoc_const() { S::C; // OK // A, B, C are resolved as inherent items, their traits don't need to be in scope ::A; - //~^ ERROR associated constant `A` is private - //~| ERROR the trait `assoc_const::C` is not dyn compatible - //~| ERROR the trait `assoc_const::C` is not dyn compatible + //~^ ERROR the trait `assoc_const::C` is not dyn compatible ::B; //~^ ERROR the trait `assoc_const::C` is not dyn compatible C::C; // OK diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr index 1d3d8cb98437c..bf59cd079a5a9 100644 --- a/tests/ui/traits/item-privacy.stderr +++ b/tests/ui/traits/item-privacy.stderr @@ -131,44 +131,10 @@ LL + use assoc_const::B; | error[E0038]: the trait `assoc_const::C` is not dyn compatible - --> $DIR/item-privacy.rs:101:6 + --> $DIR/item-privacy.rs:101:10 | LL | ::A; - | ^^^^^ `assoc_const::C` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/item-privacy.rs:25:15 - | -LL | const A: u8 = 0; - | ^ ...because it contains this associated `const` -... -LL | const B: u8 = 0; - | ^ ...because it contains this associated `const` -... -LL | pub trait C: A + B { - | - this trait is not dyn compatible... -LL | const C: u8 = 0; - | ^ ...because it contains this associated `const` - = help: consider moving `C` to another trait - = help: consider moving `A` to another trait - = help: consider moving `B` to another trait - = help: only type `S` implements `assoc_const::C`; consider using it directly instead. - -error[E0624]: associated constant `A` is private - --> $DIR/item-privacy.rs:101:14 - | -LL | const A: u8 = 0; - | ----------- private associated constant defined here -... -LL | ::A; - | ^ private associated constant - -error[E0038]: the trait `assoc_const::C` is not dyn compatible - --> $DIR/item-privacy.rs:101:5 - | -LL | ::A; - | ^^^^^^^^^^ `assoc_const::C` is not dyn compatible + | ^ `assoc_const::C` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit @@ -190,10 +156,10 @@ LL | const C: u8 = 0; = help: only type `S` implements `assoc_const::C`; consider using it directly instead. error[E0038]: the trait `assoc_const::C` is not dyn compatible - --> $DIR/item-privacy.rs:105:5 + --> $DIR/item-privacy.rs:103:10 | LL | ::B; - | ^^^^^^^^^^ `assoc_const::C` is not dyn compatible + | ^ `assoc_const::C` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit @@ -215,7 +181,7 @@ LL | const C: u8 = 0; = help: only type `S` implements `assoc_const::C`; consider using it directly instead. error[E0223]: ambiguous associated type - --> $DIR/item-privacy.rs:118:12 + --> $DIR/item-privacy.rs:116:12 | LL | let _: S::A; | ^^^^ @@ -227,7 +193,7 @@ LL + let _: ::A; | error[E0223]: ambiguous associated type - --> $DIR/item-privacy.rs:119:12 + --> $DIR/item-privacy.rs:117:12 | LL | let _: S::B; | ^^^^ @@ -239,7 +205,7 @@ LL + let _: ::B; | error[E0223]: ambiguous associated type - --> $DIR/item-privacy.rs:120:12 + --> $DIR/item-privacy.rs:118:12 | LL | let _: S::C; | ^^^^ @@ -251,7 +217,7 @@ LL + let _: ::C; | error[E0624]: associated type `A` is private - --> $DIR/item-privacy.rs:122:12 + --> $DIR/item-privacy.rs:120:12 | LL | type A = u8; | ------ the associated type is defined here @@ -260,7 +226,7 @@ LL | let _: T::A; | ^^^^ private associated type error[E0624]: associated type `A` is private - --> $DIR/item-privacy.rs:131:9 + --> $DIR/item-privacy.rs:129:9 | LL | type A = u8; | ------ the associated type is defined here @@ -268,7 +234,7 @@ LL | type A = u8; LL | A = u8, | ^^^^^^ private associated type -error: aborting due to 17 previous errors +error: aborting due to 15 previous errors Some errors have detailed explanations: E0038, E0223, E0599, E0624. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs index 2945b28eec36e..96345732f0f66 100644 --- a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs +++ b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs @@ -19,5 +19,4 @@ fn main() { let x: &dyn Foo = &(); //~^ ERROR the trait `Foo` is not dyn compatible needs_bar(x); - //~^ ERROR the trait `Foo` is not dyn compatible } diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr index 2cf6329d0a101..aead19c45272c 100644 --- a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr +++ b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr @@ -8,10 +8,10 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/supertrait-dyn-compatibility.rs:19:12 + --> $DIR/supertrait-dyn-compatibility.rs:19:17 | LL | let x: &dyn Foo = &(); - | ^^^^^^^^ `Foo` is not dyn compatible + | ^^^ `Foo` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit @@ -23,22 +23,6 @@ LL | trait Foo: for Bar {} | this trait is not dyn compatible... = help: only type `()` implements `Foo`; consider using it directly instead. -error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/supertrait-dyn-compatibility.rs:21:5 - | -LL | needs_bar(x); - | ^^^^^^^^^ `Foo` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/supertrait-dyn-compatibility.rs:4:12 - | -LL | trait Foo: for Bar {} - | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables - | | - | this trait is not dyn compatible... - = help: only type `()` implements `Foo`; consider using it directly instead. - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs index 415b050b9d69d..9ac3b84dc122d 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs @@ -9,7 +9,6 @@ trait Try { fn w<'a, T: 'a, F: Fn(&'a T)>() { let b: &dyn FromResidual = &(); //~^ ERROR: the trait `FromResidual` is not dyn compatible - //~| ERROR the type parameter `R` must be explicitly specified } fn main() {} diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr index 0f872dfba5d55..707aa9e9713db 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr @@ -1,23 +1,8 @@ -error[E0393]: the type parameter `R` must be explicitly specified - --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:17 - | -LL | trait FromResidual::Residual> { - | ----------------------------------------------- type parameter `R` must be specified for this -... -LL | let b: &dyn FromResidual = &(); - | ^^^^^^^^^^^^ - | - = note: because the parameter default references `Self`, the parameter must be specified on the object type -help: set the type parameter to the desired type - | -LL | let b: &dyn FromResidual = &(); - | +++ - error[E0038]: the trait `FromResidual` is not dyn compatible - --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:12 + --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:17 | LL | let b: &dyn FromResidual = &(); - | ^^^^^^^^^^^^^^^^^ `FromResidual` is not dyn compatible + | ^^^^^^^^^^^^ `FromResidual` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit @@ -36,7 +21,6 @@ help: alternatively, consider constraining `from_residual` so it does not apply LL | fn from_residual(residual: R) -> Self where Self: Sized; | +++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0038, E0393. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/object/macro-matcher.stderr b/tests/ui/traits/object/macro-matcher.stderr index 3c668ce99c7f5..94d5c189a4361 100644 --- a/tests/ui/traits/object/macro-matcher.stderr +++ b/tests/ui/traits/object/macro-matcher.stderr @@ -1,19 +1,19 @@ -error[E0224]: at least one trait is required for an object type - --> $DIR/macro-matcher.rs:11:8 - | -LL | m!(dyn 'static +); - | ^^^^^^^^^^^^^ - error[E0038]: the trait `Copy` is not dyn compatible - --> $DIR/macro-matcher.rs:8:8 + --> $DIR/macro-matcher.rs:8:12 | LL | m!(dyn Copy + Send + 'static); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` is not dyn compatible + | ^^^^ `Copy` is not dyn compatible | = note: the trait is not dyn compatible because it requires `Self: Sized` = note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit +error[E0224]: at least one trait is required for an object type + --> $DIR/macro-matcher.rs:11:8 + | +LL | m!(dyn 'static +); + | ^^^^^^^^^^^^^ + error: aborting due to 2 previous errors Some errors have detailed explanations: E0038, E0224. diff --git a/tests/ui/traits/object/safety.stderr b/tests/ui/traits/object/safety.stderr index a3671d90d2837..c5637b435262c 100644 --- a/tests/ui/traits/object/safety.stderr +++ b/tests/ui/traits/object/safety.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Tr` is not dyn compatible - --> $DIR/safety.rs:15:12 + --> $DIR/safety.rs:15:17 | LL | let _: &dyn Tr = &St; - | ^^^^^^^ `Tr` is not dyn compatible + | ^^ `Tr` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr index e4e39e9194ca2..6a8109281a855 100644 --- a/tests/ui/traits/test-2.stderr +++ b/tests/ui/traits/test-2.stderr @@ -27,10 +27,10 @@ LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } | ^^^^ - error[E0038]: the trait `bar` is not dyn compatible - --> $DIR/test-2.rs:13:22 + --> $DIR/test-2.rs:13:30 | LL | (Box::new(10) as Box).dup(); - | ^^^^^^^^^^^^ `bar` is not dyn compatible + | ^^^ `bar` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs index 444453dc69437..b877ef569f6dc 100644 --- a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs +++ b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs @@ -13,5 +13,4 @@ fn main() { let x: i32 = 5; let y = x as dyn MyAdd; //~^ ERROR E0038 - //~| ERROR cast to unsized type: `i32` as `dyn MyAdd` } diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr index eea2e75a2382a..33478740d65cd 100644 --- a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr +++ b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr @@ -1,20 +1,8 @@ -error[E0620]: cast to unsized type: `i32` as `dyn MyAdd` - --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:13 - | -LL | let y = x as dyn MyAdd; - | ^^^^^^^^^^^^^^^^^^^ - | -help: consider using a box or reference as appropriate - --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:13 - | -LL | let y = x as dyn MyAdd; - | ^ - error[E0038]: the trait `MyAdd` is not dyn compatible - --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18 + --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:22 | LL | let y = x as dyn MyAdd; - | ^^^^^^^^^^^^^^ `MyAdd` is not dyn compatible + | ^^^^^^^^^^ `MyAdd` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit @@ -25,7 +13,6 @@ LL | trait MyAdd { fn add(&self, other: &Rhs) -> Self; } = help: consider moving `add` to another trait = help: only type `i32` implements `MyAdd`; consider using it directly instead. -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0038, E0620. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/wf-dyn-incompatible.stderr b/tests/ui/wf/wf-dyn-incompatible.stderr index e61b37d92932f..2ba17b7aaefca 100644 --- a/tests/ui/wf/wf-dyn-incompatible.stderr +++ b/tests/ui/wf/wf-dyn-incompatible.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `A` is not dyn compatible - --> $DIR/wf-dyn-incompatible.rs:9:13 + --> $DIR/wf-dyn-incompatible.rs:9:18 | LL | let _x: &dyn A; - | ^^^^^^ `A` is not dyn compatible + | ^ `A` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit From 89c21f7c1af83cfbd862e08e716026f1c357a316 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 20 May 2025 08:47:29 +1000 Subject: [PATCH 18/18] Remove out-of-date `noop_*` names. `mut_visit.rs` has a single function with a `noop_` prefix: `noop_filter_map_expr`. This commit renames as `walk_filter_map_expr` which is consistent with other functions in this file. The commit also removes out-of-date comments that refer to `noop_*` methods. --- compiler/rustc_ast/src/mut_visit.rs | 26 ++++------------------- compiler/rustc_expand/src/placeholders.rs | 2 +- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 6770fd5a4aaeb..74dcdd86fcbfc 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -40,12 +40,6 @@ pub trait MutVisitor: Sized { // fn flat_map_t(&mut self, t: T) -> SmallVec<[T; 1]>; // rare // fn filter_map_t(&mut self, t: T) -> Option; // rarest // - // Any additions to this trait should happen in form of a call to a public - // `noop_*` function that only calls out to the visitor again, not other - // `noop_*` functions. This is a necessary API workaround to the problem of - // not being able to call out to the super default method in an overridden - // default method. - // // When writing these methods, it is better to use destructuring like this: // // fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) { @@ -179,7 +173,7 @@ pub trait MutVisitor: Sized { } fn filter_map_expr(&mut self, e: P) -> Option> { - noop_filter_map_expr(self, e) + walk_filter_map_expr(self, e) } fn visit_generic_arg(&mut self, arg: &mut GenericArg) { @@ -381,14 +375,11 @@ super::common_visitor_and_walkers!((mut) MutVisitor); /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful /// when using a `flat_map_*` or `filter_map_*` method within a `visit_` /// method. -// -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. pub fn visit_clobber(t: &mut T, f: impl FnOnce(T) -> T) { let old_t = std::mem::replace(t, T::dummy()); *t = f(old_t); } -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. #[inline] fn visit_vec(elems: &mut Vec, mut visit_elem: F) where @@ -399,7 +390,6 @@ where } } -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. #[inline] fn visit_thin_vec(elems: &mut ThinVec, mut visit_elem: F) where @@ -410,7 +400,6 @@ where } } -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. #[inline] fn visit_opt(opt: &mut Option, mut visit_elem: F) where @@ -421,25 +410,21 @@ where } } -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. fn visit_attrs(vis: &mut T, attrs: &mut AttrVec) { for attr in attrs.iter_mut() { vis.visit_attribute(attr); } } -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. #[allow(unused)] fn visit_exprs(vis: &mut T, exprs: &mut Vec>) { exprs.flat_map_in_place(|expr| vis.filter_map_expr(expr)) } -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. fn visit_thin_exprs(vis: &mut T, exprs: &mut ThinVec>) { exprs.flat_map_in_place(|expr| vis.filter_map_expr(expr)) } -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. fn visit_attr_args(vis: &mut T, args: &mut AttrArgs) { match args { AttrArgs::Empty => {} @@ -451,7 +436,6 @@ fn visit_attr_args(vis: &mut T, args: &mut AttrArgs) { } } -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. fn visit_delim_args(vis: &mut T, args: &mut DelimArgs) { let DelimArgs { dspan, delim: _, tokens: _ } = args; let DelimSpan { open, close } = dspan; @@ -1500,11 +1484,9 @@ pub fn walk_expr(vis: &mut T, Expr { kind, id, span, attrs, token vis.visit_span(span); } -pub fn noop_filter_map_expr(vis: &mut T, mut e: P) -> Option> { - Some({ - vis.visit_expr(&mut e); - e - }) +pub fn walk_filter_map_expr(vis: &mut T, mut e: P) -> Option> { + vis.visit_expr(&mut e); + Some(e) } pub fn walk_flat_map_stmt( diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 0136292decbcf..3dcb20c8c7682 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -349,7 +349,7 @@ impl MutVisitor for PlaceholderExpander { fn filter_map_expr(&mut self, expr: P) -> Option> { match expr.kind { ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(), - _ => noop_filter_map_expr(self, expr), + _ => walk_filter_map_expr(self, expr), } }