From 9d1f790594cc58187aaca5cb64b4e324b331a565 Mon Sep 17 00:00:00 2001 From: Urgau Date: Thu, 9 Nov 2023 17:37:27 +0100 Subject: [PATCH 01/21] Add warn-by-default lint against unpredictable fn pointer comparisons --- compiler/rustc_lint/messages.ftl | 6 + compiler/rustc_lint/src/lints.rs | 36 ++++ compiler/rustc_lint/src/types.rs | 138 +++++++++++++- tests/ui/lint/fn-ptr-comparisons-weird.rs | 15 ++ tests/ui/lint/fn-ptr-comparisons-weird.stderr | 43 +++++ tests/ui/lint/fn-ptr-comparisons.fixed | 58 ++++++ tests/ui/lint/fn-ptr-comparisons.rs | 58 ++++++ tests/ui/lint/fn-ptr-comparisons.stderr | 171 ++++++++++++++++++ 8 files changed, 521 insertions(+), 4 deletions(-) create mode 100644 tests/ui/lint/fn-ptr-comparisons-weird.rs create mode 100644 tests/ui/lint/fn-ptr-comparisons-weird.stderr create mode 100644 tests/ui/lint/fn-ptr-comparisons.fixed create mode 100644 tests/ui/lint/fn-ptr-comparisons.rs create mode 100644 tests/ui/lint/fn-ptr-comparisons.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 4aeaf61681604..54039d56929cf 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -882,6 +882,12 @@ lint_unnameable_test_items = cannot test inner items lint_unnecessary_qualification = unnecessary qualification .suggestion = remove the unnecessary path segments +lint_unpredictable_fn_pointer_comparisons = function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + .note_duplicated_fn = the address of the same function can vary between different codegen units + .note_deduplicated_fn = furthermore, different functions could have the same address after being merged together + .note_visit_fn_addr_eq = for more information visit + .fn_addr_eq_suggestion = refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint + lint_unqualified_local_imports = `use` of a local item without leading `self::`, `super::`, or `crate::` lint_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 3a854796f6735..5721ef644da4c 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1810,6 +1810,42 @@ pub(crate) enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> { }, } +#[derive(LintDiagnostic)] +pub(crate) enum UnpredictableFunctionPointerComparisons<'a> { + #[diag(lint_unpredictable_fn_pointer_comparisons)] + #[note(lint_note_duplicated_fn)] + #[note(lint_note_deduplicated_fn)] + #[note(lint_note_visit_fn_addr_eq)] + Suggestion { + #[subdiagnostic] + sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a>, + }, + #[diag(lint_unpredictable_fn_pointer_comparisons)] + #[note(lint_note_duplicated_fn)] + #[note(lint_note_deduplicated_fn)] + #[note(lint_note_visit_fn_addr_eq)] + Warn, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + lint_fn_addr_eq_suggestion, + style = "verbose", + applicability = "maybe-incorrect" +)] +pub(crate) struct UnpredictableFunctionPointerComparisonsSuggestion<'a> { + pub ne: &'a str, + pub cast_right: String, + pub deref_left: &'a str, + pub deref_right: &'a str, + #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")] + pub left: Span, + #[suggestion_part(code = ", {deref_right}")] + pub middle: Span, + #[suggestion_part(code = "{cast_right})")] + pub right: Span, +} + pub(crate) struct ImproperCTypes<'a> { pub ty: Ty<'a>, pub desc: &'a str, diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index b1d7d4ab68951..33650be056dd1 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -23,7 +23,9 @@ use crate::lints::{ AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion, AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons, - InvalidNanComparisonsSuggestion, UnusedComparisons, VariantSizeDifferencesDiag, + InvalidNanComparisonsSuggestion, UnpredictableFunctionPointerComparisons, + UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons, + VariantSizeDifferencesDiag, }; use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent}; @@ -166,6 +168,35 @@ declare_lint! { "detects ambiguous wide pointer comparisons" } +declare_lint! { + /// The `unpredictable_function_pointer_comparisons` lint checks comparison + /// of function pointer as the operands. + /// + /// ### Example + /// + /// ```rust + /// fn a() {} + /// fn b() {} + /// + /// let f: fn() = a; + /// let g: fn() = b; + /// + /// let _ = f == g; + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Function pointers comparisons do not produce meaningful result since + /// they are never guaranteed to be unique and could vary between different + /// code generation units. Furthermore, different functions could have the + /// same address after being merged together. + UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS, + Warn, + "detects unpredictable function pointer comparisons" +} + #[derive(Copy, Clone, Default)] pub(crate) struct TypeLimits { /// Id of the last visited negated expression @@ -178,7 +209,8 @@ impl_lint_pass!(TypeLimits => [ UNUSED_COMPARISONS, OVERFLOWING_LITERALS, INVALID_NAN_COMPARISONS, - AMBIGUOUS_WIDE_POINTER_COMPARISONS + AMBIGUOUS_WIDE_POINTER_COMPARISONS, + UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS ]); impl TypeLimits { @@ -255,7 +287,7 @@ fn lint_nan<'tcx>( cx.emit_span_lint(INVALID_NAN_COMPARISONS, e.span, lint); } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Copy, Clone)] enum ComparisonOp { BinOp(hir::BinOpKind), Other, @@ -383,6 +415,100 @@ fn lint_wide_pointer<'tcx>( ); } +fn lint_fn_pointer<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx hir::Expr<'tcx>, + cmpop: ComparisonOp, + l: &'tcx hir::Expr<'tcx>, + r: &'tcx hir::Expr<'tcx>, +) { + let peel_refs = |mut ty: Ty<'tcx>| -> (Ty<'tcx>, usize) { + let mut refs = 0; + + while let ty::Ref(_, inner_ty, _) = ty.kind() { + ty = *inner_ty; + refs += 1; + } + + (ty, refs) + }; + + // Left and right operands can have borrows, remove them + let l = l.peel_borrows(); + let r = r.peel_borrows(); + + let Some(l_ty) = cx.typeck_results().expr_ty_opt(l) else { return }; + let Some(r_ty) = cx.typeck_results().expr_ty_opt(r) else { return }; + + // Remove any references as `==` will deref through them (and count the + // number of references removed, for latter). + let (l_ty, l_ty_refs) = peel_refs(l_ty); + let (r_ty, r_ty_refs) = peel_refs(r_ty); + + if !l_ty.is_fn() || !r_ty.is_fn() { + return; + } + + // Let's try to suggest `ptr::fn_addr_eq` if/when possible. + + let is_eq_ne = matches!(cmpop, ComparisonOp::BinOp(hir::BinOpKind::Eq | hir::BinOpKind::Ne)); + + if !is_eq_ne { + // Neither `==` nor `!=`, we can't suggest `ptr::fn_addr_eq`, just show the warning. + return cx.emit_span_lint( + UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS, + e.span, + UnpredictableFunctionPointerComparisons::Warn, + ); + } + + let (Some(l_span), Some(r_span)) = + (l.span.find_ancestor_inside(e.span), r.span.find_ancestor_inside(e.span)) + else { + // No appropriate spans for the left and right operands, just show the warning. + return cx.emit_span_lint( + UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS, + e.span, + UnpredictableFunctionPointerComparisons::Warn, + ); + }; + + let ne = if cmpop == ComparisonOp::BinOp(hir::BinOpKind::Ne) { "!" } else { "" }; + + // `ptr::fn_addr_eq` only works with raw pointer, deref any references. + let deref_left = &*"*".repeat(l_ty_refs); + let deref_right = &*"*".repeat(r_ty_refs); + + 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()); + let right = r_span.shrink_to_hi().until(e.span.shrink_to_hi()); + + // We only check for a right cast as `FnDef` == `FnPtr` is not possible, + // only `FnPtr == FnDef` is possible. + let cast_right = if !r_ty.is_fn_ptr() { + let fn_sig = r_ty.fn_sig(cx.tcx); + format!(" as {fn_sig}") + } else { + String::new() + }; + + cx.emit_span_lint( + UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS, + e.span, + UnpredictableFunctionPointerComparisons::Suggestion { + sugg: UnpredictableFunctionPointerComparisonsSuggestion { + ne, + deref_left, + deref_right, + left, + middle, + right, + cast_right, + }, + }, + ); +} + impl<'tcx> LateLintPass<'tcx> for TypeLimits { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) { match e.kind { @@ -399,7 +525,9 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { cx.emit_span_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons); } else { lint_nan(cx, e, binop, l, r); - lint_wide_pointer(cx, e, ComparisonOp::BinOp(binop.node), l, r); + let cmpop = ComparisonOp::BinOp(binop.node); + lint_wide_pointer(cx, e, cmpop, l, r); + lint_fn_pointer(cx, e, cmpop, l, r); } } } @@ -411,6 +539,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { && let Some(cmpop) = diag_item_cmpop(diag_item) => { lint_wide_pointer(cx, e, cmpop, l, r); + lint_fn_pointer(cx, e, cmpop, l, r); } hir::ExprKind::MethodCall(_, l, [r], _) if let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) @@ -418,6 +547,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { && let Some(cmpop) = diag_item_cmpop(diag_item) => { lint_wide_pointer(cx, e, cmpop, l, r); + lint_fn_pointer(cx, e, cmpop, l, r); } _ => {} }; diff --git a/tests/ui/lint/fn-ptr-comparisons-weird.rs b/tests/ui/lint/fn-ptr-comparisons-weird.rs new file mode 100644 index 0000000000000..171fbfb87279d --- /dev/null +++ b/tests/ui/lint/fn-ptr-comparisons-weird.rs @@ -0,0 +1,15 @@ +//@ check-pass + +fn main() { + let f: fn() = main; + let g: fn() = main; + + let _ = f > g; + //~^ WARN function pointer comparisons + let _ = f >= g; + //~^ WARN function pointer comparisons + let _ = f <= g; + //~^ WARN function pointer comparisons + let _ = f < g; + //~^ WARN function pointer comparisons +} diff --git a/tests/ui/lint/fn-ptr-comparisons-weird.stderr b/tests/ui/lint/fn-ptr-comparisons-weird.stderr new file mode 100644 index 0000000000000..f237166392238 --- /dev/null +++ b/tests/ui/lint/fn-ptr-comparisons-weird.stderr @@ -0,0 +1,43 @@ +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons-weird.rs:7:13 + | +LL | let _ = f > g; + | ^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit + = note: `#[warn(unpredictable_function_pointer_comparisons)]` on by default + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons-weird.rs:9:13 + | +LL | let _ = f >= g; + | ^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons-weird.rs:11:13 + | +LL | let _ = f <= g; + | ^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons-weird.rs:13:13 + | +LL | let _ = f < g; + | ^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit + +warning: 4 warnings emitted + diff --git a/tests/ui/lint/fn-ptr-comparisons.fixed b/tests/ui/lint/fn-ptr-comparisons.fixed new file mode 100644 index 0000000000000..22f16177a0446 --- /dev/null +++ b/tests/ui/lint/fn-ptr-comparisons.fixed @@ -0,0 +1,58 @@ +//@ check-pass +//@ run-rustfix + +extern "C" { + fn test(); +} + +fn a() {} + +extern "C" fn c() {} + +extern "C" fn args(_a: i32) -> i32 { 0 } + +#[derive(PartialEq, Eq)] +struct A { + f: fn(), +} + +fn main() { + let f: fn() = a; + let g: fn() = f; + + let a1 = A { f }; + let a2 = A { f }; + + let _ = std::ptr::fn_addr_eq(f, a as fn()); + //~^ WARN function pointer comparisons + let _ = !std::ptr::fn_addr_eq(f, a as fn()); + //~^ WARN function pointer comparisons + let _ = std::ptr::fn_addr_eq(f, g); + //~^ WARN function pointer comparisons + let _ = std::ptr::fn_addr_eq(f, f); + //~^ WARN function pointer comparisons + let _ = std::ptr::fn_addr_eq(g, g); + //~^ WARN function pointer comparisons + let _ = std::ptr::fn_addr_eq(g, g); + //~^ WARN function pointer comparisons + let _ = std::ptr::fn_addr_eq(g, g); + //~^ WARN function pointer comparisons + let _ = std::ptr::fn_addr_eq(a as fn(), g); + //~^ WARN function pointer comparisons + + let cfn: extern "C" fn() = c; + let _ = std::ptr::fn_addr_eq(cfn, c as extern "C" fn()); + //~^ WARN function pointer comparisons + + let argsfn: extern "C" fn(i32) -> i32 = args; + let _ = std::ptr::fn_addr_eq(argsfn, args as extern "C" fn(i32) -> i32); + //~^ WARN function pointer comparisons + + let t: unsafe extern "C" fn() = test; + let _ = std::ptr::fn_addr_eq(t, test as unsafe extern "C" fn()); + //~^ WARN function pointer comparisons + + let _ = a1 == a2; // should not warn + let _ = std::ptr::fn_addr_eq(a1.f, a2.f); + //~^ WARN function pointer comparisons +} diff --git a/tests/ui/lint/fn-ptr-comparisons.rs b/tests/ui/lint/fn-ptr-comparisons.rs new file mode 100644 index 0000000000000..90a8ab5c926b6 --- /dev/null +++ b/tests/ui/lint/fn-ptr-comparisons.rs @@ -0,0 +1,58 @@ +//@ check-pass +//@ run-rustfix + +extern "C" { + fn test(); +} + +fn a() {} + +extern "C" fn c() {} + +extern "C" fn args(_a: i32) -> i32 { 0 } + +#[derive(PartialEq, Eq)] +struct A { + f: fn(), +} + +fn main() { + let f: fn() = a; + let g: fn() = f; + + let a1 = A { f }; + let a2 = A { f }; + + let _ = f == a; + //~^ WARN function pointer comparisons + let _ = f != a; + //~^ WARN function pointer comparisons + let _ = f == g; + //~^ WARN function pointer comparisons + let _ = f == f; + //~^ WARN function pointer comparisons + let _ = g == g; + //~^ WARN function pointer comparisons + let _ = g == g; + //~^ WARN function pointer comparisons + let _ = &g == &g; + //~^ WARN function pointer comparisons + let _ = a as fn() == g; + //~^ WARN function pointer comparisons + + let cfn: extern "C" fn() = c; + let _ = cfn == c; + //~^ WARN function pointer comparisons + + let argsfn: extern "C" fn(i32) -> i32 = args; + let _ = argsfn == args; + //~^ WARN function pointer comparisons + + let t: unsafe extern "C" fn() = test; + let _ = t == test; + //~^ WARN function pointer comparisons + + let _ = a1 == a2; // should not warn + let _ = a1.f == a2.f; + //~^ WARN function pointer comparisons +} diff --git a/tests/ui/lint/fn-ptr-comparisons.stderr b/tests/ui/lint/fn-ptr-comparisons.stderr new file mode 100644 index 0000000000000..eaba23a461ab6 --- /dev/null +++ b/tests/ui/lint/fn-ptr-comparisons.stderr @@ -0,0 +1,171 @@ +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons.rs:26:13 + | +LL | let _ = f == a; + | ^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit + = note: `#[warn(unpredictable_function_pointer_comparisons)]` on by default +help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint + | +LL | let _ = std::ptr::fn_addr_eq(f, a as fn()); + | +++++++++++++++++++++ ~ ++++++++ + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons.rs:28:13 + | +LL | let _ = f != a; + | ^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit +help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint + | +LL | let _ = !std::ptr::fn_addr_eq(f, a as fn()); + | ++++++++++++++++++++++ ~ ++++++++ + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons.rs:30:13 + | +LL | let _ = f == g; + | ^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit +help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint + | +LL | let _ = std::ptr::fn_addr_eq(f, g); + | +++++++++++++++++++++ ~ + + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons.rs:32:13 + | +LL | let _ = f == f; + | ^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit +help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint + | +LL | let _ = std::ptr::fn_addr_eq(f, f); + | +++++++++++++++++++++ ~ + + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons.rs:34:13 + | +LL | let _ = g == g; + | ^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit +help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint + | +LL | let _ = std::ptr::fn_addr_eq(g, g); + | +++++++++++++++++++++ ~ + + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons.rs:36:13 + | +LL | let _ = g == g; + | ^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit +help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint + | +LL | let _ = std::ptr::fn_addr_eq(g, g); + | +++++++++++++++++++++ ~ + + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons.rs:38:13 + | +LL | let _ = &g == &g; + | ^^^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit +help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint + | +LL | let _ = std::ptr::fn_addr_eq(g, g); + | ~~~~~~~~~~~~~~~~~~~~~ ~ + + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons.rs:40:13 + | +LL | let _ = a as fn() == g; + | ^^^^^^^^^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit +help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint + | +LL | let _ = std::ptr::fn_addr_eq(a as fn(), g); + | +++++++++++++++++++++ ~ + + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons.rs:44:13 + | +LL | let _ = cfn == c; + | ^^^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit +help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint + | +LL | let _ = std::ptr::fn_addr_eq(cfn, c as extern "C" fn()); + | +++++++++++++++++++++ ~ +++++++++++++++++++ + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons.rs:48:13 + | +LL | let _ = argsfn == args; + | ^^^^^^^^^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit +help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint + | +LL | let _ = std::ptr::fn_addr_eq(argsfn, args as extern "C" fn(i32) -> i32); + | +++++++++++++++++++++ ~ +++++++++++++++++++++++++++++ + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons.rs:52:13 + | +LL | let _ = t == test; + | ^^^^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit +help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint + | +LL | let _ = std::ptr::fn_addr_eq(t, test as unsafe extern "C" fn()); + | +++++++++++++++++++++ ~ ++++++++++++++++++++++++++ + +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons.rs:56:13 + | +LL | let _ = a1.f == a2.f; + | ^^^^^^^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit +help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint + | +LL | let _ = std::ptr::fn_addr_eq(a1.f, a2.f); + | +++++++++++++++++++++ ~ + + +warning: 12 warnings emitted + From 5e34c2e43c9110ac91579cb1b6d44ebdba0b5712 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 10 Dec 2023 18:16:53 +0100 Subject: [PATCH 02/21] Drop uplifted `clippy::fn_address_comparisons` --- .../clippy/clippy_lints/src/declared_lints.rs | 1 - .../clippy_lints/src/deprecated_lints.rs | 2 + src/tools/clippy/clippy_lints/src/lib.rs | 2 - .../clippy_lints/src/unnamed_address.rs | 60 -------- .../clippy/tests/ui/fn_address_comparisons.rs | 23 --- .../tests/ui/fn_address_comparisons.stderr | 17 --- src/tools/clippy/tests/ui/rename.fixed | 2 + src/tools/clippy/tests/ui/rename.rs | 2 + src/tools/clippy/tests/ui/rename.stderr | 140 +++++++++--------- 9 files changed, 79 insertions(+), 170 deletions(-) delete mode 100644 src/tools/clippy/clippy_lints/src/unnamed_address.rs delete mode 100644 src/tools/clippy/tests/ui/fn_address_comparisons.rs delete mode 100644 src/tools/clippy/tests/ui/fn_address_comparisons.stderr diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index c4a0c8f186510..022ed180ed8ca 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -744,7 +744,6 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::unit_types::LET_UNIT_VALUE_INFO, crate::unit_types::UNIT_ARG_INFO, crate::unit_types::UNIT_CMP_INFO, - crate::unnamed_address::FN_ADDRESS_COMPARISONS_INFO, crate::unnecessary_box_returns::UNNECESSARY_BOX_RETURNS_INFO, crate::unnecessary_literal_bound::UNNECESSARY_LITERAL_BOUND_INFO, crate::unnecessary_map_on_constructor::UNNECESSARY_MAP_ON_CONSTRUCTOR_INFO, diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index 77dbe9b78a182..3ea792d8b835c 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -74,6 +74,8 @@ declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[ #[clippy::version = "1.53.0"] ("clippy::filter_map", "clippy::manual_filter_map"), #[clippy::version = ""] + ("clippy::fn_address_comparisons", "unpredictable_function_pointer_comparisons"), + #[clippy::version = ""] ("clippy::identity_conversion", "clippy::useless_conversion"), #[clippy::version = "pre 1.29.0"] ("clippy::if_let_redundant_pattern_matching", "clippy::redundant_pattern_matching"), diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index c9064df25ac89..e80cca6e7db4b 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -363,7 +363,6 @@ mod uninhabited_references; mod uninit_vec; mod unit_return_expecting_ord; mod unit_types; -mod unnamed_address; mod unnecessary_box_returns; mod unnecessary_literal_bound; mod unnecessary_map_on_constructor; @@ -786,7 +785,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap)); store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(conf))); store.register_late_pass(|_| Box::::default()); - store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress)); store.register_late_pass(|_| Box::>::default()); store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse)); store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend)); diff --git a/src/tools/clippy/clippy_lints/src/unnamed_address.rs b/src/tools/clippy/clippy_lints/src/unnamed_address.rs deleted file mode 100644 index cd2dacc9f099c..0000000000000 --- a/src/tools/clippy/clippy_lints/src/unnamed_address.rs +++ /dev/null @@ -1,60 +0,0 @@ -use clippy_utils::diagnostics::span_lint; -use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; -use rustc_session::declare_lint_pass; - -declare_clippy_lint! { - /// ### What it does - /// Checks for comparisons with an address of a function item. - /// - /// ### Why is this bad? - /// Function item address is not guaranteed to be unique and could vary - /// between different code generation units. Furthermore different function items could have - /// the same address after being merged together. - /// - /// ### Example - /// ```no_run - /// type F = fn(); - /// fn a() {} - /// let f: F = a; - /// if f == a { - /// // ... - /// } - /// ``` - #[clippy::version = "1.44.0"] - pub FN_ADDRESS_COMPARISONS, - correctness, - "comparison with an address of a function item" -} - -declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS]); - -impl LateLintPass<'_> for UnnamedAddress { - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - fn is_comparison(binop: BinOpKind) -> bool { - matches!( - binop, - BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ne | BinOpKind::Ge | BinOpKind::Gt - ) - } - - fn is_fn_def(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - matches!(cx.typeck_results().expr_ty(expr).kind(), ty::FnDef(..)) - } - - if let ExprKind::Binary(binop, left, right) = expr.kind - && is_comparison(binop.node) - && cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr() - && cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr() - && (is_fn_def(cx, left) || is_fn_def(cx, right)) - { - span_lint( - cx, - FN_ADDRESS_COMPARISONS, - expr.span, - "comparing with a non-unique address of a function item", - ); - } - } -} diff --git a/src/tools/clippy/tests/ui/fn_address_comparisons.rs b/src/tools/clippy/tests/ui/fn_address_comparisons.rs deleted file mode 100644 index 35535bd4fddd0..0000000000000 --- a/src/tools/clippy/tests/ui/fn_address_comparisons.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::fmt::Debug; -use std::ptr; -use std::rc::Rc; -use std::sync::Arc; - -fn a() {} - -#[warn(clippy::fn_address_comparisons)] -fn main() { - type F = fn(); - let f: F = a; - let g: F = f; - - // These should fail: - let _ = f == a; - //~^ ERROR: comparing with a non-unique address of a function item - //~| NOTE: `-D clippy::fn-address-comparisons` implied by `-D warnings` - let _ = f != a; - //~^ ERROR: comparing with a non-unique address of a function item - - // These should be fine: - let _ = f == g; -} diff --git a/src/tools/clippy/tests/ui/fn_address_comparisons.stderr b/src/tools/clippy/tests/ui/fn_address_comparisons.stderr deleted file mode 100644 index e6de7e358075d..0000000000000 --- a/src/tools/clippy/tests/ui/fn_address_comparisons.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: comparing with a non-unique address of a function item - --> tests/ui/fn_address_comparisons.rs:15:13 - | -LL | let _ = f == a; - | ^^^^^^ - | - = note: `-D clippy::fn-address-comparisons` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::fn_address_comparisons)]` - -error: comparing with a non-unique address of a function item - --> tests/ui/fn_address_comparisons.rs:18:13 - | -LL | let _ = f != a; - | ^^^^^^ - -error: aborting due to 2 previous errors - diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed index 0d6e07aa546cf..47149622ef7c6 100644 --- a/src/tools/clippy/tests/ui/rename.fixed +++ b/src/tools/clippy/tests/ui/rename.fixed @@ -59,6 +59,7 @@ #![allow(unknown_lints)] #![allow(unused_labels)] #![allow(ambiguous_wide_pointer_comparisons)] +#![allow(unpredictable_function_pointer_comparisons)] #![allow(clippy::reversed_empty_ranges)] #![warn(clippy::almost_complete_range)] //~ ERROR: lint `clippy::almost_complete_letter_range` #![warn(clippy::disallowed_names)] //~ ERROR: lint `clippy::blacklisted_name` @@ -74,6 +75,7 @@ #![warn(clippy::mixed_read_write_in_expression)] //~ ERROR: lint `clippy::eval_order_dependence` #![warn(clippy::manual_find_map)] //~ ERROR: lint `clippy::find_map` #![warn(clippy::manual_filter_map)] //~ ERROR: lint `clippy::filter_map` +#![warn(unpredictable_function_pointer_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons` #![warn(clippy::useless_conversion)] //~ ERROR: lint `clippy::identity_conversion` #![warn(clippy::redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching` #![warn(clippy::match_result_ok)] //~ ERROR: lint `clippy::if_let_some_result` diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs index 2ac59718786b6..7a78a5d280ddb 100644 --- a/src/tools/clippy/tests/ui/rename.rs +++ b/src/tools/clippy/tests/ui/rename.rs @@ -59,6 +59,7 @@ #![allow(unknown_lints)] #![allow(unused_labels)] #![allow(ambiguous_wide_pointer_comparisons)] +#![allow(unpredictable_function_pointer_comparisons)] #![allow(clippy::reversed_empty_ranges)] #![warn(clippy::almost_complete_letter_range)] //~ ERROR: lint `clippy::almost_complete_letter_range` #![warn(clippy::blacklisted_name)] //~ ERROR: lint `clippy::blacklisted_name` @@ -74,6 +75,7 @@ #![warn(clippy::eval_order_dependence)] //~ ERROR: lint `clippy::eval_order_dependence` #![warn(clippy::find_map)] //~ ERROR: lint `clippy::find_map` #![warn(clippy::filter_map)] //~ ERROR: lint `clippy::filter_map` +#![warn(clippy::fn_address_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons` #![warn(clippy::identity_conversion)] //~ ERROR: lint `clippy::identity_conversion` #![warn(clippy::if_let_redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching` #![warn(clippy::if_let_some_result)] //~ ERROR: lint `clippy::if_let_some_result` diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr index a5ae727b7ee82..dc24bc16d0ea4 100644 --- a/src/tools/clippy/tests/ui/rename.stderr +++ b/src/tools/clippy/tests/ui/rename.stderr @@ -1,5 +1,5 @@ error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range` - --> tests/ui/rename.rs:63:9 + --> tests/ui/rename.rs:64:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` @@ -8,394 +8,400 @@ LL | #![warn(clippy::almost_complete_letter_range)] = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]` error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` - --> tests/ui/rename.rs:64:9 + --> tests/ui/rename.rs:65:9 | LL | #![warn(clippy::blacklisted_name)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names` error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_conditions` - --> tests/ui/rename.rs:65:9 + --> tests/ui/rename.rs:66:9 | LL | #![warn(clippy::block_in_if_condition_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions` error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_conditions` - --> tests/ui/rename.rs:66:9 + --> tests/ui/rename.rs:67:9 | LL | #![warn(clippy::block_in_if_condition_stmt)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions` error: lint `clippy::blocks_in_if_conditions` has been renamed to `clippy::blocks_in_conditions` - --> tests/ui/rename.rs:67:9 + --> tests/ui/rename.rs:68:9 | LL | #![warn(clippy::blocks_in_if_conditions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions` error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` - --> tests/ui/rename.rs:68:9 + --> tests/ui/rename.rs:69:9 | LL | #![warn(clippy::box_vec)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` - --> tests/ui/rename.rs:69:9 + --> tests/ui/rename.rs:70:9 | LL | #![warn(clippy::const_static_lifetime)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` - --> tests/ui/rename.rs:70:9 + --> tests/ui/rename.rs:71:9 | LL | #![warn(clippy::cyclomatic_complexity)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq` - --> tests/ui/rename.rs:71:9 + --> tests/ui/rename.rs:72:9 | LL | #![warn(clippy::derive_hash_xor_eq)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq` error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods` - --> tests/ui/rename.rs:72:9 + --> tests/ui/rename.rs:73:9 | LL | #![warn(clippy::disallowed_method)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods` error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types` - --> tests/ui/rename.rs:73:9 + --> tests/ui/rename.rs:74:9 | LL | #![warn(clippy::disallowed_type)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types` error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression` - --> tests/ui/rename.rs:74:9 + --> tests/ui/rename.rs:75:9 | LL | #![warn(clippy::eval_order_dependence)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression` error: lint `clippy::find_map` has been renamed to `clippy::manual_find_map` - --> tests/ui/rename.rs:75:9 + --> tests/ui/rename.rs:76:9 | LL | #![warn(clippy::find_map)] | ^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_find_map` error: lint `clippy::filter_map` has been renamed to `clippy::manual_filter_map` - --> tests/ui/rename.rs:76:9 + --> tests/ui/rename.rs:77:9 | LL | #![warn(clippy::filter_map)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_filter_map` +error: lint `clippy::fn_address_comparisons` has been renamed to `unpredictable_function_pointer_comparisons` + --> tests/ui/rename.rs:78:9 + | +LL | #![warn(clippy::fn_address_comparisons)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unpredictable_function_pointer_comparisons` + error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion` - --> tests/ui/rename.rs:77:9 + --> tests/ui/rename.rs:79:9 | LL | #![warn(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion` error: lint `clippy::if_let_redundant_pattern_matching` has been renamed to `clippy::redundant_pattern_matching` - --> tests/ui/rename.rs:78:9 + --> tests/ui/rename.rs:80:9 | LL | #![warn(clippy::if_let_redundant_pattern_matching)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_pattern_matching` error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok` - --> tests/ui/rename.rs:79:9 + --> tests/ui/rename.rs:81:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl` - --> tests/ui/rename.rs:80:9 + --> tests/ui/rename.rs:82:9 | LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl` error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl` - --> tests/ui/rename.rs:81:9 + --> tests/ui/rename.rs:83:9 | LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` - --> tests/ui/rename.rs:82:9 + --> tests/ui/rename.rs:84:9 | LL | #![warn(clippy::integer_arithmetic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` - --> tests/ui/rename.rs:83:9 + --> tests/ui/rename.rs:85:9 | LL | #![warn(clippy::logic_bug)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr` error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` - --> tests/ui/rename.rs:84:9 + --> tests/ui/rename.rs:86:9 | LL | #![warn(clippy::new_without_default_derive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map` - --> tests/ui/rename.rs:85:9 + --> tests/ui/rename.rs:87:9 | LL | #![warn(clippy::option_and_then_some)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map` error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used` - --> tests/ui/rename.rs:86:9 + --> tests/ui/rename.rs:88:9 | LL | #![warn(clippy::option_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or` - --> tests/ui/rename.rs:87:9 + --> tests/ui/rename.rs:89:9 | LL | #![warn(clippy::option_map_unwrap_or)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> tests/ui/rename.rs:88:9 + --> tests/ui/rename.rs:90:9 | LL | #![warn(clippy::option_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used` - --> tests/ui/rename.rs:89:9 + --> tests/ui/rename.rs:91:9 | LL | #![warn(clippy::option_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::overflow_check_conditional` has been renamed to `clippy::panicking_overflow_checks` - --> tests/ui/rename.rs:90:9 + --> tests/ui/rename.rs:92:9 | LL | #![warn(clippy::overflow_check_conditional)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::panicking_overflow_checks` error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow` - --> tests/ui/rename.rs:91:9 + --> tests/ui/rename.rs:93:9 | LL | #![warn(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow` error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used` - --> tests/ui/rename.rs:92:9 + --> tests/ui/rename.rs:94:9 | LL | #![warn(clippy::result_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> tests/ui/rename.rs:93:9 + --> tests/ui/rename.rs:95:9 | LL | #![warn(clippy::result_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used` - --> tests/ui/rename.rs:94:9 + --> tests/ui/rename.rs:96:9 | LL | #![warn(clippy::result_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str` - --> tests/ui/rename.rs:95:9 + --> tests/ui/rename.rs:97:9 | LL | #![warn(clippy::single_char_push_str)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` - --> tests/ui/rename.rs:96:9 + --> tests/ui/rename.rs:98:9 | LL | #![warn(clippy::stutter)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` error: lint `clippy::thread_local_initializer_can_be_made_const` has been renamed to `clippy::missing_const_for_thread_local` - --> tests/ui/rename.rs:97:9 + --> tests/ui/rename.rs:99:9 | LL | #![warn(clippy::thread_local_initializer_can_be_made_const)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::missing_const_for_thread_local` error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl` - --> tests/ui/rename.rs:98:9 + --> tests/ui/rename.rs:100:9 | LL | #![warn(clippy::to_string_in_display)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl` error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default` - --> tests/ui/rename.rs:99:9 + --> tests/ui/rename.rs:101:9 | LL | #![warn(clippy::unwrap_or_else_default)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default` error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` - --> tests/ui/rename.rs:100:9 + --> tests/ui/rename.rs:102:9 | LL | #![warn(clippy::zero_width_space)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting` - --> tests/ui/rename.rs:101:9 + --> tests/ui/rename.rs:103:9 | LL | #![warn(clippy::cast_ref_to_mut)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting` error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` - --> tests/ui/rename.rs:102:9 + --> tests/ui/rename.rs:104:9 | LL | #![warn(clippy::clone_double_ref)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op` error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons` - --> tests/ui/rename.rs:103:9 + --> tests/ui/rename.rs:105:9 | LL | #![warn(clippy::cmp_nan)] | ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons` error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` - --> tests/ui/rename.rs:104:9 + --> tests/ui/rename.rs:106:9 | LL | #![warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types` - --> tests/ui/rename.rs:105:9 + --> tests/ui/rename.rs:107:9 | LL | #![warn(clippy::drop_copy)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types` error: lint `clippy::drop_ref` has been renamed to `dropping_references` - --> tests/ui/rename.rs:106:9 + --> tests/ui/rename.rs:108:9 | LL | #![warn(clippy::drop_ref)] | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks` - --> tests/ui/rename.rs:107:9 + --> tests/ui/rename.rs:109:9 | LL | #![warn(clippy::fn_null_check)] | ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> tests/ui/rename.rs:108:9 + --> tests/ui/rename.rs:110:9 | LL | #![warn(clippy::for_loop_over_option)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles` - --> tests/ui/rename.rs:109:9 + --> tests/ui/rename.rs:111:9 | LL | #![warn(clippy::for_loop_over_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles` - --> tests/ui/rename.rs:110:9 + --> tests/ui/rename.rs:112:9 | LL | #![warn(clippy::for_loops_over_fallibles)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types` - --> tests/ui/rename.rs:111:9 + --> tests/ui/rename.rs:113:9 | LL | #![warn(clippy::forget_copy)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types` error: lint `clippy::forget_ref` has been renamed to `forgetting_references` - --> tests/ui/rename.rs:112:9 + --> tests/ui/rename.rs:114:9 | LL | #![warn(clippy::forget_ref)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references` error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> tests/ui/rename.rs:113:9 + --> tests/ui/rename.rs:115:9 | LL | #![warn(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` - --> tests/ui/rename.rs:114:9 + --> tests/ui/rename.rs:116:9 | LL | #![warn(clippy::invalid_atomic_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` error: lint `clippy::invalid_ref` has been renamed to `invalid_value` - --> tests/ui/rename.rs:115:9 + --> tests/ui/rename.rs:117:9 | LL | #![warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked` - --> tests/ui/rename.rs:116:9 + --> tests/ui/rename.rs:118:9 | LL | #![warn(clippy::invalid_utf8_in_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` - --> tests/ui/rename.rs:117:9 + --> tests/ui/rename.rs:119:9 | LL | #![warn(clippy::let_underscore_drop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop` error: lint `clippy::maybe_misused_cfg` has been renamed to `unexpected_cfgs` - --> tests/ui/rename.rs:118:9 + --> tests/ui/rename.rs:120:9 | LL | #![warn(clippy::maybe_misused_cfg)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` - --> tests/ui/rename.rs:119:9 + --> tests/ui/rename.rs:121:9 | LL | #![warn(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` error: lint `clippy::mismatched_target_os` has been renamed to `unexpected_cfgs` - --> tests/ui/rename.rs:120:9 + --> tests/ui/rename.rs:122:9 | LL | #![warn(clippy::mismatched_target_os)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` - --> tests/ui/rename.rs:121:9 + --> tests/ui/rename.rs:123:9 | LL | #![warn(clippy::panic_params)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally` - --> tests/ui/rename.rs:122:9 + --> tests/ui/rename.rs:124:9 | LL | #![warn(clippy::positional_named_format_parameters)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally` error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries` - --> tests/ui/rename.rs:123:9 + --> tests/ui/rename.rs:125:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries` error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops` - --> tests/ui/rename.rs:124:9 + --> tests/ui/rename.rs:126:9 | LL | #![warn(clippy::undropped_manually_drops)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> tests/ui/rename.rs:125:9 + --> tests/ui/rename.rs:127:9 | LL | #![warn(clippy::unknown_clippy_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` error: lint `clippy::unused_label` has been renamed to `unused_labels` - --> tests/ui/rename.rs:126:9 + --> tests/ui/rename.rs:128:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons` - --> tests/ui/rename.rs:127:9 + --> tests/ui/rename.rs:129:9 | LL | #![warn(clippy::vtable_address_comparisons)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons` error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_empty_ranges` - --> tests/ui/rename.rs:128:9 + --> tests/ui/rename.rs:130:9 | LL | #![warn(clippy::reverse_range_loop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges` -error: aborting due to 66 previous errors +error: aborting due to 67 previous errors From 8ce63576bddc95e99b54ebf8ec9da6f52a647ad2 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 10 Dec 2023 15:51:06 +0100 Subject: [PATCH 03/21] Allow fn pointers comparisons lint in UI tests --- src/tools/miri/tests/pass/function_pointers.rs | 2 ++ src/tools/miri/tests/pass/issues/issue-91636.rs | 2 ++ tests/ui/binop/binary-op-on-fn-ptr-eq.rs | 3 +++ tests/ui/box/unit/unique-ffi-symbols.rs | 3 +++ tests/ui/consts/const-extern-function.rs | 2 ++ tests/ui/cross-crate/const-cross-crate-extern.rs | 2 ++ tests/ui/extern/extern-compare-with-return-type.rs | 1 + tests/ui/extern/extern-take-value.rs | 2 ++ .../function-pointer-comparison-issue-54685.rs | 2 ++ tests/ui/issues/issue-54696.rs | 2 ++ .../mir/validate/issue-95978-validator-lifetime-comparison.rs | 2 ++ 11 files changed, 23 insertions(+) diff --git a/src/tools/miri/tests/pass/function_pointers.rs b/src/tools/miri/tests/pass/function_pointers.rs index a5c4bc5e0d95b..7145be334a13e 100644 --- a/src/tools/miri/tests/pass/function_pointers.rs +++ b/src/tools/miri/tests/pass/function_pointers.rs @@ -1,3 +1,5 @@ +#![allow(unpredictable_function_pointer_comparisons)] + use std::mem; trait Answer { diff --git a/src/tools/miri/tests/pass/issues/issue-91636.rs b/src/tools/miri/tests/pass/issues/issue-91636.rs index 00370165812f5..d0cadcd2c70a9 100644 --- a/src/tools/miri/tests/pass/issues/issue-91636.rs +++ b/src/tools/miri/tests/pass/issues/issue-91636.rs @@ -1,3 +1,5 @@ +#![allow(unpredictable_function_pointer_comparisons)] + type BuiltIn = for<'a> fn(&str); struct Function { diff --git a/tests/ui/binop/binary-op-on-fn-ptr-eq.rs b/tests/ui/binop/binary-op-on-fn-ptr-eq.rs index a5ec63587f96e..47b79f3855f60 100644 --- a/tests/ui/binop/binary-op-on-fn-ptr-eq.rs +++ b/tests/ui/binop/binary-op-on-fn-ptr-eq.rs @@ -1,6 +1,9 @@ //@ run-pass // Tests equality between supertype and subtype of a function // See the issue #91636 + +#![allow(unpredictable_function_pointer_comparisons)] + fn foo(_a: &str) {} fn main() { diff --git a/tests/ui/box/unit/unique-ffi-symbols.rs b/tests/ui/box/unit/unique-ffi-symbols.rs index 65a9a32b2bb0c..75877f8397efe 100644 --- a/tests/ui/box/unit/unique-ffi-symbols.rs +++ b/tests/ui/box/unit/unique-ffi-symbols.rs @@ -1,6 +1,9 @@ //@ run-pass // We used to have a __rust_abi shim that resulted in duplicated symbols // whenever the item path wasn't enough to disambiguate between them. + +#![allow(unpredictable_function_pointer_comparisons)] + fn main() { let a = { extern "C" fn good() -> i32 { return 0; } diff --git a/tests/ui/consts/const-extern-function.rs b/tests/ui/consts/const-extern-function.rs index acc438189cb86..7629d63266acd 100644 --- a/tests/ui/consts/const-extern-function.rs +++ b/tests/ui/consts/const-extern-function.rs @@ -1,5 +1,7 @@ //@ run-pass + #![allow(non_upper_case_globals)] +#![allow(unpredictable_function_pointer_comparisons)] extern "C" fn foopy() {} diff --git a/tests/ui/cross-crate/const-cross-crate-extern.rs b/tests/ui/cross-crate/const-cross-crate-extern.rs index 8d48a6a520606..0ec8753c30f2f 100644 --- a/tests/ui/cross-crate/const-cross-crate-extern.rs +++ b/tests/ui/cross-crate/const-cross-crate-extern.rs @@ -1,6 +1,8 @@ //@ run-pass //@ aux-build:cci_const.rs + #![allow(non_upper_case_globals)] +#![allow(unpredictable_function_pointer_comparisons)] extern crate cci_const; use cci_const::bar; diff --git a/tests/ui/extern/extern-compare-with-return-type.rs b/tests/ui/extern/extern-compare-with-return-type.rs index 316e8b2fc7360..7d1027d5e776f 100644 --- a/tests/ui/extern/extern-compare-with-return-type.rs +++ b/tests/ui/extern/extern-compare-with-return-type.rs @@ -2,6 +2,7 @@ // Tests that we can compare various kinds of extern fn signatures. #![allow(non_camel_case_types)] +#![allow(unpredictable_function_pointer_comparisons)] // `dbg!()` differentiates these functions to ensure they won't be merged. extern "C" fn voidret1() { dbg!() } diff --git a/tests/ui/extern/extern-take-value.rs b/tests/ui/extern/extern-take-value.rs index 56ed3328614ce..f3df82b26109f 100644 --- a/tests/ui/extern/extern-take-value.rs +++ b/tests/ui/extern/extern-take-value.rs @@ -1,6 +1,8 @@ //@ run-pass //@ aux-build:extern-take-value.rs +#![allow(unpredictable_function_pointer_comparisons)] + extern crate extern_take_value; pub fn main() { diff --git a/tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs b/tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs index 2e1c863e0f4ca..3ec958f2ebff2 100644 --- a/tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs +++ b/tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs @@ -1,6 +1,8 @@ //@ compile-flags: -C opt-level=3 //@ run-pass +#![allow(unpredictable_function_pointer_comparisons)] + fn foo(_i: i32) -> i32 { 1 } diff --git a/tests/ui/issues/issue-54696.rs b/tests/ui/issues/issue-54696.rs index 75b1824f0b383..63ffbe42bcc9f 100644 --- a/tests/ui/issues/issue-54696.rs +++ b/tests/ui/issues/issue-54696.rs @@ -1,5 +1,7 @@ //@ run-pass +#![allow(unpredictable_function_pointer_comparisons)] + fn main() { // We shouldn't promote this let _ = &(main as fn() == main as fn()); diff --git a/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs b/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs index 44b7fae351cd2..45d519739eba8 100644 --- a/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs +++ b/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs @@ -1,6 +1,8 @@ //@ check-pass //@ compile-flags: -Zvalidate-mir +#![allow(unpredictable_function_pointer_comparisons)] + fn foo(_a: &str) {} fn main() { From 7b06fcf55900cbc31c58d62793a40e808cefe68e Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 12 Dec 2023 13:10:13 +0100 Subject: [PATCH 04/21] Allow fn pointers comparisons lint in library --- library/core/tests/ptr.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 7e9773f2fb952..454b13a7ee389 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -304,6 +304,7 @@ fn test_const_nonnull_new() { #[test] #[cfg(unix)] // printf may not be available on other platforms #[allow(deprecated)] // For SipHasher +#[cfg_attr(not(bootstrap), allow(unpredictable_function_pointer_comparisons))] pub fn test_variadic_fnptr() { use core::ffi; use core::hash::{Hash, SipHasher}; From f613636ae87e7e973138c7cb3e850ec26f93c723 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 4 Dec 2024 16:01:31 +0000 Subject: [PATCH 05/21] Rename `core_pattern_type` and `core_pattern_types` lib feature gates to `pattern_type_macro` That's what the gates are actually gating, and the single char difference in naming was not helpful either --- library/core/src/lib.rs | 2 +- library/core/src/pat.rs | 2 +- library/std/src/lib.rs | 2 +- .../crates/ide-db/src/generated/lints.rs | 13 ++---------- tests/codegen/pattern_type_symbols.rs | 3 +-- .../bad_const_generics_args_on_const_param.rs | 2 +- tests/ui/type/pattern_types/bad_pat.rs | 3 +-- tests/ui/type/pattern_types/bad_pat.stderr | 6 +++--- tests/ui/type/pattern_types/const_generics.rs | 3 +-- tests/ui/type/pattern_types/derives.rs | 3 +-- tests/ui/type/pattern_types/derives.stderr | 2 +- .../feature-gate-pattern_types.rs | 10 +++++----- .../feature-gate-pattern_types.stderr | 20 +++++++++---------- .../feature-gate-pattern_types2.rs | 2 +- tests/ui/type/pattern_types/missing-is.rs | 2 +- tests/ui/type/pattern_types/range_patterns.rs | 3 +-- .../type/pattern_types/range_patterns.stderr | 10 +++++----- .../range_patterns_inherent_impls.rs | 3 +-- .../range_patterns_inherent_impls.stderr | 4 ++-- .../range_patterns_trait_impls.rs | 3 +-- .../range_patterns_trait_impls2.rs | 3 +-- .../range_patterns_trait_impls2.stderr | 2 +- .../pattern_types/range_patterns_unusable.rs | 3 +-- .../range_patterns_unusable.stderr | 2 +- .../range_patterns_unusable_math.rs | 3 +-- .../range_patterns_unusable_math.stderr | 2 +- .../pattern_types/range_patterns_usage.rs | 3 +-- .../type/pattern_types/unimplemented_pat.rs | 3 +-- .../pattern_types/unimplemented_pat.stderr | 4 ++-- tests/ui/unpretty/expanded-exhaustive.rs | 2 +- tests/ui/unpretty/expanded-exhaustive.stdout | 2 +- 31 files changed, 53 insertions(+), 74 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index ab9c33ee75477..fde6887c5abae 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -345,7 +345,7 @@ pub mod net; pub mod option; pub mod panic; pub mod panicking; -#[unstable(feature = "core_pattern_types", issue = "123646")] +#[unstable(feature = "pattern_type_macro", issue = "123646")] pub mod pat; pub mod pin; #[unstable(feature = "random", issue = "130703")] diff --git a/library/core/src/pat.rs b/library/core/src/pat.rs index 1f89d960be67b..752e79c2dacee 100644 --- a/library/core/src/pat.rs +++ b/library/core/src/pat.rs @@ -6,7 +6,7 @@ /// ``` #[macro_export] #[rustc_builtin_macro(pattern_type)] -#[unstable(feature = "core_pattern_type", issue = "123646")] +#[unstable(feature = "pattern_type_macro", issue = "123646")] macro_rules! pattern_type { ($($arg:tt)*) => { /* compiler built-in */ diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 585946c1d50e0..6be27b283b291 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -589,7 +589,7 @@ pub mod net; pub mod num; pub mod os; pub mod panic; -#[unstable(feature = "core_pattern_types", issue = "123646")] +#[unstable(feature = "pattern_type_macro", issue = "123646")] pub mod pat; pub mod path; #[unstable(feature = "anonymous_pipe", issue = "127154")] diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index 266109765ab8c..b97dfb3b8ef8b 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -3936,17 +3936,8 @@ The tracking issue for this feature is: [#117693] "##, }, Lint { - label: "core_pattern_type", - description: r##"# `core_pattern_type` - -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. - ------------------------- -"##, - }, - Lint { - label: "core_pattern_types", - description: r##"# `core_pattern_types` + label: "pattern_type_macro", + description: r##"# `pattern_type_macro` This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. diff --git a/tests/codegen/pattern_type_symbols.rs b/tests/codegen/pattern_type_symbols.rs index a99b3efca415b..b504a3508f94c 100644 --- a/tests/codegen/pattern_type_symbols.rs +++ b/tests/codegen/pattern_type_symbols.rs @@ -4,8 +4,7 @@ //@ compile-flags: -Csymbol-mangling-version=v0 -Copt-level=0 --crate-type=lib #![feature(pattern_types)] -#![feature(core_pattern_types)] -#![feature(core_pattern_type)] +#![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs index 3defe0cb44d3b..55f45ade38804 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs @@ -1,4 +1,4 @@ -#![feature(pattern_types, core_pattern_type)] +#![feature(pattern_types, pattern_type_macro)] #![allow(internal_features)] type Pat = diff --git a/tests/ui/type/pattern_types/bad_pat.rs b/tests/ui/type/pattern_types/bad_pat.rs index 8ad042eeba65e..6cb2a0f1f8e74 100644 --- a/tests/ui/type/pattern_types/bad_pat.rs +++ b/tests/ui/type/pattern_types/bad_pat.rs @@ -1,6 +1,5 @@ #![feature(pattern_types)] -#![feature(core_pattern_types)] -#![feature(core_pattern_type)] +#![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/bad_pat.stderr b/tests/ui/type/pattern_types/bad_pat.stderr index f5cf7930c8328..c857cc3c3add9 100644 --- a/tests/ui/type/pattern_types/bad_pat.stderr +++ b/tests/ui/type/pattern_types/bad_pat.stderr @@ -1,5 +1,5 @@ error[E0586]: inclusive range with no end - --> $DIR/bad_pat.rs:7:43 + --> $DIR/bad_pat.rs:6:43 | LL | type NonNullU32_2 = pattern_type!(u32 is 1..=); | ^^^ @@ -12,7 +12,7 @@ LL + type NonNullU32_2 = pattern_type!(u32 is 1..); | error[E0586]: inclusive range with no end - --> $DIR/bad_pat.rs:9:40 + --> $DIR/bad_pat.rs:8:40 | LL | type Positive2 = pattern_type!(i32 is 0..=); | ^^^ @@ -25,7 +25,7 @@ LL + type Positive2 = pattern_type!(i32 is 0..); | error: wildcard patterns are not permitted for pattern types - --> $DIR/bad_pat.rs:11:33 + --> $DIR/bad_pat.rs:10:33 | LL | type Wild = pattern_type!(() is _); | ^ diff --git a/tests/ui/type/pattern_types/const_generics.rs b/tests/ui/type/pattern_types/const_generics.rs index 5bc6fd54e0fce..5cef0dc030552 100644 --- a/tests/ui/type/pattern_types/const_generics.rs +++ b/tests/ui/type/pattern_types/const_generics.rs @@ -1,8 +1,7 @@ //@ check-pass #![feature(pattern_types)] -#![feature(core_pattern_types)] -#![feature(core_pattern_type)] +#![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/derives.rs b/tests/ui/type/pattern_types/derives.rs index b8b53e61102bc..3878c47554d98 100644 --- a/tests/ui/type/pattern_types/derives.rs +++ b/tests/ui/type/pattern_types/derives.rs @@ -1,8 +1,7 @@ //! Check that pattern types don't implement traits of their base automatically #![feature(pattern_types)] -#![feature(core_pattern_types)] -#![feature(core_pattern_type)] +#![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/derives.stderr b/tests/ui/type/pattern_types/derives.stderr index 1d4d3fc55c3fa..9d4baef621be3 100644 --- a/tests/ui/type/pattern_types/derives.stderr +++ b/tests/ui/type/pattern_types/derives.stderr @@ -1,5 +1,5 @@ error[E0369]: binary operation `==` cannot be applied to type `(i32) is 0..=999999999` - --> $DIR/derives.rs:11:20 + --> $DIR/derives.rs:10:20 | LL | #[derive(Clone, Copy, PartialEq)] | --------- in this derive macro expansion diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs index e638f3c6c40d7..b90ba4784023a 100644 --- a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs @@ -3,12 +3,12 @@ use std::pat::pattern_type; type NonNullU32 = pattern_type!(u32 is 1..); -//~^ use of unstable library feature `core_pattern_type` +//~^ use of unstable library feature `pattern_type_macro` type Percent = pattern_type!(u32 is 0..=100); -//~^ use of unstable library feature `core_pattern_type` +//~^ use of unstable library feature `pattern_type_macro` type Negative = pattern_type!(i32 is ..=0); -//~^ use of unstable library feature `core_pattern_type` +//~^ use of unstable library feature `pattern_type_macro` type Positive = pattern_type!(i32 is 0..); -//~^ use of unstable library feature `core_pattern_type` +//~^ use of unstable library feature `pattern_type_macro` type Always = pattern_type!(Option is Some(_)); -//~^ use of unstable library feature `core_pattern_type` +//~^ use of unstable library feature `pattern_type_macro` diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr index 6cbadf370a7dc..69239d68bdc75 100644 --- a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr @@ -1,51 +1,51 @@ -error[E0658]: use of unstable library feature `core_pattern_type` +error[E0658]: use of unstable library feature `pattern_type_macro` --> $DIR/feature-gate-pattern_types.rs:5:19 | LL | type NonNullU32 = pattern_type!(u32 is 1..); | ^^^^^^^^^^^^ | = note: see issue #123646 for more information - = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable + = help: add `#![feature(pattern_type_macro)]` 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]: use of unstable library feature `core_pattern_type` +error[E0658]: use of unstable library feature `pattern_type_macro` --> $DIR/feature-gate-pattern_types.rs:7:16 | LL | type Percent = pattern_type!(u32 is 0..=100); | ^^^^^^^^^^^^ | = note: see issue #123646 for more information - = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable + = help: add `#![feature(pattern_type_macro)]` 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]: use of unstable library feature `core_pattern_type` +error[E0658]: use of unstable library feature `pattern_type_macro` --> $DIR/feature-gate-pattern_types.rs:9:17 | LL | type Negative = pattern_type!(i32 is ..=0); | ^^^^^^^^^^^^ | = note: see issue #123646 for more information - = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable + = help: add `#![feature(pattern_type_macro)]` 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]: use of unstable library feature `core_pattern_type` +error[E0658]: use of unstable library feature `pattern_type_macro` --> $DIR/feature-gate-pattern_types.rs:11:17 | LL | type Positive = pattern_type!(i32 is 0..); | ^^^^^^^^^^^^ | = note: see issue #123646 for more information - = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable + = help: add `#![feature(pattern_type_macro)]` 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]: use of unstable library feature `core_pattern_type` +error[E0658]: use of unstable library feature `pattern_type_macro` --> $DIR/feature-gate-pattern_types.rs:13:15 | LL | type Always = pattern_type!(Option is Some(_)); | ^^^^^^^^^^^^ | = note: see issue #123646 for more information - = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable + = help: add `#![feature(pattern_type_macro)]` 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 5 previous errors diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs b/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs index d7b3ea58e0265..50c355c8de61a 100644 --- a/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Zno-analysis //@ check-pass -#![feature(core_pattern_type)] +#![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/missing-is.rs b/tests/ui/type/pattern_types/missing-is.rs index 2fbcc1908efcb..564b41649d899 100644 --- a/tests/ui/type/pattern_types/missing-is.rs +++ b/tests/ui/type/pattern_types/missing-is.rs @@ -1,4 +1,4 @@ -#![feature(core_pattern_type, core_pattern_types)] +#![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/range_patterns.rs b/tests/ui/type/pattern_types/range_patterns.rs index 9eddc8cab7fe1..7c25edb1c3fd5 100644 --- a/tests/ui/type/pattern_types/range_patterns.rs +++ b/tests/ui/type/pattern_types/range_patterns.rs @@ -1,6 +1,5 @@ #![feature(pattern_types, rustc_attrs)] -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] #![allow(incomplete_features)] //@ normalize-stderr-test: "pref: Align\([1-8] bytes\)" -> "pref: $$SOME_ALIGN" diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr index 7bd0d826cab71..0eed7c2ce1ce8 100644 --- a/tests/ui/type/pattern_types/range_patterns.stderr +++ b/tests/ui/type/pattern_types/range_patterns.stderr @@ -37,7 +37,7 @@ error: layout_of(NonZero) = Layout { max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } - --> $DIR/range_patterns.rs:11:1 + --> $DIR/range_patterns.rs:10:1 | LL | type X = std::num::NonZeroU32; | ^^^^^^ @@ -74,7 +74,7 @@ error: layout_of((u32) is 1..=) = Layout { max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } - --> $DIR/range_patterns.rs:13:1 + --> $DIR/range_patterns.rs:12:1 | LL | type Y = pattern_type!(u32 is 1..); | ^^^^^^ @@ -182,7 +182,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout { max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } - --> $DIR/range_patterns.rs:15:1 + --> $DIR/range_patterns.rs:14:1 | LL | type Z = Option; | ^^^^^^ @@ -290,7 +290,7 @@ error: layout_of(Option>) = Layout { max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } - --> $DIR/range_patterns.rs:17:1 + --> $DIR/range_patterns.rs:16:1 | LL | type A = Option; | ^^^^^^ @@ -334,7 +334,7 @@ error: layout_of(NonZeroU32New) = Layout { max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } - --> $DIR/range_patterns.rs:19:1 + --> $DIR/range_patterns.rs:18:1 | LL | struct NonZeroU32New(pattern_type!(u32 is 1..)); | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/type/pattern_types/range_patterns_inherent_impls.rs b/tests/ui/type/pattern_types/range_patterns_inherent_impls.rs index 9653a744c4162..fe8feda0934e2 100644 --- a/tests/ui/type/pattern_types/range_patterns_inherent_impls.rs +++ b/tests/ui/type/pattern_types/range_patterns_inherent_impls.rs @@ -1,6 +1,5 @@ #![feature(pattern_types, rustc_attrs)] -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] #![allow(incomplete_features)] //! check that pattern types can have traits implemented for them if diff --git a/tests/ui/type/pattern_types/range_patterns_inherent_impls.stderr b/tests/ui/type/pattern_types/range_patterns_inherent_impls.stderr index 784ebb0c9f012..ed2e4c0bd5f8c 100644 --- a/tests/ui/type/pattern_types/range_patterns_inherent_impls.stderr +++ b/tests/ui/type/pattern_types/range_patterns_inherent_impls.stderr @@ -1,12 +1,12 @@ error[E0390]: cannot define inherent `impl` for primitive types outside of `core` - --> $DIR/range_patterns_inherent_impls.rs:13:1 + --> $DIR/range_patterns_inherent_impls.rs:12:1 | LL | impl Y { | ^^^^^^ | = help: consider moving this inherent impl into `core` if possible help: alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items - --> $DIR/range_patterns_inherent_impls.rs:15:5 + --> $DIR/range_patterns_inherent_impls.rs:14:5 | LL | fn foo() {} | ^^^^^^^^ diff --git a/tests/ui/type/pattern_types/range_patterns_trait_impls.rs b/tests/ui/type/pattern_types/range_patterns_trait_impls.rs index f8c9af8628182..1731cd470fe2c 100644 --- a/tests/ui/type/pattern_types/range_patterns_trait_impls.rs +++ b/tests/ui/type/pattern_types/range_patterns_trait_impls.rs @@ -1,6 +1,5 @@ #![feature(pattern_types, rustc_attrs)] -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] #![allow(incomplete_features)] //! check that pattern types can have local traits diff --git a/tests/ui/type/pattern_types/range_patterns_trait_impls2.rs b/tests/ui/type/pattern_types/range_patterns_trait_impls2.rs index acde4580c1b20..90f80a2f34645 100644 --- a/tests/ui/type/pattern_types/range_patterns_trait_impls2.rs +++ b/tests/ui/type/pattern_types/range_patterns_trait_impls2.rs @@ -1,6 +1,5 @@ #![feature(pattern_types, rustc_attrs)] -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] #![allow(incomplete_features)] //! check that pattern types can have local traits diff --git a/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr b/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr index df56db031ed18..d5c539b6c52e6 100644 --- a/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr +++ b/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr @@ -1,5 +1,5 @@ error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/range_patterns_trait_impls2.rs:13:1 + --> $DIR/range_patterns_trait_impls2.rs:12:1 | LL | impl Eq for Y {} | ^^^^^^^^^^^^- diff --git a/tests/ui/type/pattern_types/range_patterns_unusable.rs b/tests/ui/type/pattern_types/range_patterns_unusable.rs index 7cde44f41335b..98f13ca0bc0bb 100644 --- a/tests/ui/type/pattern_types/range_patterns_unusable.rs +++ b/tests/ui/type/pattern_types/range_patterns_unusable.rs @@ -1,6 +1,5 @@ #![feature(pattern_types, rustc_attrs)] -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] #![allow(incomplete_features)] //! Some practical niche checks. diff --git a/tests/ui/type/pattern_types/range_patterns_unusable.stderr b/tests/ui/type/pattern_types/range_patterns_unusable.stderr index aa0e592684b6b..8377d417452bb 100644 --- a/tests/ui/type/pattern_types/range_patterns_unusable.stderr +++ b/tests/ui/type/pattern_types/range_patterns_unusable.stderr @@ -1,5 +1,5 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/range_patterns_unusable.rs:14:35 + --> $DIR/range_patterns_unusable.rs:13:35 | LL | let _: Option = unsafe { std::mem::transmute(z) }; | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/type/pattern_types/range_patterns_unusable_math.rs b/tests/ui/type/pattern_types/range_patterns_unusable_math.rs index bc1ab75429d66..ece4009e1e7d8 100644 --- a/tests/ui/type/pattern_types/range_patterns_unusable_math.rs +++ b/tests/ui/type/pattern_types/range_patterns_unusable_math.rs @@ -1,6 +1,5 @@ #![feature(pattern_types, rustc_attrs)] -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] #![allow(incomplete_features)] //! check that pattern types don't have an `Add` impl. diff --git a/tests/ui/type/pattern_types/range_patterns_unusable_math.stderr b/tests/ui/type/pattern_types/range_patterns_unusable_math.stderr index e52d899a703f2..373615e3714e5 100644 --- a/tests/ui/type/pattern_types/range_patterns_unusable_math.stderr +++ b/tests/ui/type/pattern_types/range_patterns_unusable_math.stderr @@ -1,5 +1,5 @@ error[E0369]: cannot add `u32` to `(u32) is 1..=` - --> $DIR/range_patterns_unusable_math.rs:15:15 + --> $DIR/range_patterns_unusable_math.rs:14:15 | LL | let x = x + 1_u32; | - ^ ----- u32 diff --git a/tests/ui/type/pattern_types/range_patterns_usage.rs b/tests/ui/type/pattern_types/range_patterns_usage.rs index 2a9f736ae61d5..0ecbdcaa0f7a3 100644 --- a/tests/ui/type/pattern_types/range_patterns_usage.rs +++ b/tests/ui/type/pattern_types/range_patterns_usage.rs @@ -1,6 +1,5 @@ #![feature(pattern_types, rustc_attrs)] -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] #![allow(incomplete_features)] //@ check-pass diff --git a/tests/ui/type/pattern_types/unimplemented_pat.rs b/tests/ui/type/pattern_types/unimplemented_pat.rs index c02160ff58a6c..b2398cec7c9b5 100644 --- a/tests/ui/type/pattern_types/unimplemented_pat.rs +++ b/tests/ui/type/pattern_types/unimplemented_pat.rs @@ -1,8 +1,7 @@ //! This test ensures we do not ICE for unimplemented //! patterns unless the feature gate is enabled. -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/unimplemented_pat.stderr b/tests/ui/type/pattern_types/unimplemented_pat.stderr index 481c6017dccc2..7b0f9cbaa6a96 100644 --- a/tests/ui/type/pattern_types/unimplemented_pat.stderr +++ b/tests/ui/type/pattern_types/unimplemented_pat.stderr @@ -1,5 +1,5 @@ error[E0658]: pattern types are unstable - --> $DIR/unimplemented_pat.rs:9:15 + --> $DIR/unimplemented_pat.rs:8:15 | LL | type Always = pattern_type!(Option is Some(_)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | type Always = pattern_type!(Option is Some(_)); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pattern types are unstable - --> $DIR/unimplemented_pat.rs:12:16 + --> $DIR/unimplemented_pat.rs:11:16 | LL | type Binding = pattern_type!(Option is x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs index 891021e876609..9af57fe4c3cd0 100644 --- a/tests/ui/unpretty/expanded-exhaustive.rs +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -8,7 +8,6 @@ #![feature(builtin_syntax)] #![feature(concat_idents)] #![feature(const_trait_impl)] -#![feature(core_pattern_type)] #![feature(decl_macro)] #![feature(deref_patterns)] #![feature(explicit_tail_calls)] @@ -18,6 +17,7 @@ #![feature(never_patterns)] #![feature(never_type)] #![feature(pattern_types)] +#![feature(pattern_type_macro)] #![feature(prelude_import)] #![feature(specialization)] #![feature(trace_macros)] diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index 007626e2c4406..14a274415ca72 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -9,7 +9,6 @@ #![feature(builtin_syntax)] #![feature(concat_idents)] #![feature(const_trait_impl)] -#![feature(core_pattern_type)] #![feature(decl_macro)] #![feature(deref_patterns)] #![feature(explicit_tail_calls)] @@ -19,6 +18,7 @@ #![feature(never_patterns)] #![feature(never_type)] #![feature(pattern_types)] +#![feature(pattern_type_macro)] #![feature(prelude_import)] #![feature(specialization)] #![feature(trace_macros)] From 1b449e123d8d935b3ac7d475e3fc075860af444e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 4 Dec 2024 05:57:55 +0000 Subject: [PATCH 06/21] Do not emit empty suggestion The `println!();` statement's span doesn't include the `;`, and the modified suggestions where trying to get the `;` by getting the differenece between the statement's and the expression's spans, which was an empty suggestion. Fix #133833, fix #133834. --- .../src/fn_ctxt/suggestions.rs | 8 ++- .../src/error_reporting/traits/suggestions.rs | 6 +++ ...uggestion-when-stmt-and-expr-span-equal.rs | 26 ++++++++++ ...stion-when-stmt-and-expr-span-equal.stderr | 50 +++++++++++++++++++ 4 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.rs create mode 100644 tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 61260dbd16c51..ddcd90a2a9da6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -3394,7 +3394,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else { return; }; - if self.can_eq(self.param_env, expected_ty, ty) { + if self.can_eq(self.param_env, expected_ty, ty) + // FIXME: this happens with macro calls. Need to figure out why the stmt + // `println!();` doesn't include the `;` in its `Span`. (#133845) + // We filter these out to avoid ICEs with debug assertions on caused by + // empty suggestions. + && stmt.span.hi() != tail_expr.span.hi() + { err.span_suggestion_short( stmt.span.with_lo(tail_expr.span.hi()), "remove this semicolon", diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 2bb503f17b4ed..94682f501a8c4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3838,6 +3838,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && self.predicate_must_hold_modulo_regions(&Obligation::misc( tcx, expr.span, body_id, param_env, pred, )) + && expr.span.hi() != rcvr.span.hi() { err.span_suggestion_verbose( expr.span.with_lo(rcvr.span.hi()), @@ -4115,6 +4116,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // the expected is a projection that we need to resolve. // && let Some(tail_ty) = typeck_results.expr_ty_opt(expr) && expected_found.found.is_unit() + // FIXME: this happens with macro calls. Need to figure out why the stmt + // `println!();` doesn't include the `;` in its `Span`. (#133845) + // We filter these out to avoid ICEs with debug assertions on caused by + // empty suggestions. + && expr.span.hi() != stmt.span.hi() { err.span_suggestion_verbose( expr.span.shrink_to_hi().with_hi(stmt.span.hi()), diff --git a/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.rs b/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.rs new file mode 100644 index 0000000000000..35612093aff04 --- /dev/null +++ b/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.rs @@ -0,0 +1,26 @@ +//! Regression test for suggestions that were fired on empty spans +//! involving macro-call statements. For some reason the semicolon +//! is not included in the overall span of the macro-call statement. +//! +//! Issue 1: . +//! Issue 2: . +//! See also: . + +fn foo() -> String { + let mut list = { + println!(); + }; + list //~ ERROR mismatched types +} + +fn bar() { + String::new() + .chars() + .filter(|x| !x.is_whitespace()) + .map(|x| { + println!("Child spawned with the size: {}", x); + }) + .collect::(); //~ ERROR E0277 +} + +fn main() {} diff --git a/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr b/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr new file mode 100644 index 0000000000000..4b83bfff86333 --- /dev/null +++ b/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr @@ -0,0 +1,50 @@ +error[E0308]: mismatched types + --> $DIR/semi-suggestion-when-stmt-and-expr-span-equal.rs:13:5 + | +LL | fn foo() -> String { + | ------ expected `String` because of return type +LL | let mut list = { + | ____________________- +LL | | println!(); +LL | | }; + | |_____- this block is missing a tail expression +LL | list + | ^^^^ expected `String`, found `()` + +error[E0277]: a value of type `String` cannot be built from an iterator over elements of type `()` + --> $DIR/semi-suggestion-when-stmt-and-expr-span-equal.rs:23:20 + | +LL | .collect::(); + | ------- ^^^^^^ value of type `String` cannot be built from `std::iter::Iterator` + | | + | required by a bound introduced by this call + | + = help: the trait `FromIterator<()>` is not implemented for `String` + = help: the following other types implement trait `FromIterator`: + `String` implements `FromIterator<&char>` + `String` implements `FromIterator<&str>` + `String` implements `FromIterator>` + `String` implements `FromIterator>` + `String` implements `FromIterator` + `String` implements `FromIterator` +note: the method call chain might not have had the expected associated types + --> $DIR/semi-suggestion-when-stmt-and-expr-span-equal.rs:20:10 + | +LL | String::new() + | ------------- this expression has type `String` +LL | .chars() + | ------- `Iterator::Item` is `char` here +LL | .filter(|x| !x.is_whitespace()) + | ------------------------------ `Iterator::Item` remains `char` here +LL | .map(|x| { + | __________^ +LL | | println!("Child spawned with the size: {}", x); +LL | | }) + | |__________^ `Iterator::Item` changed to `()` here +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. From 05c34cc5ed35dbf32f83e2eaa0ebbda4c4953294 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 8 Mar 2024 00:02:11 +0000 Subject: [PATCH 07/21] Fix suggestion when shorthand self has erroneous type --- compiler/rustc_ast/src/ast.rs | 12 ++++++ compiler/rustc_parse/messages.ftl | 3 ++ compiler/rustc_parse/src/errors.rs | 19 ++++++++++ compiler/rustc_parse/src/parser/item.rs | 30 ++++++++++++++- tests/ui/parser/typed-self-param.rs | 14 +++++++ tests/ui/parser/typed-self-param.stderr | 50 +++++++++++++++++++++++++ 6 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 tests/ui/parser/typed-self-param.rs create mode 100644 tests/ui/parser/typed-self-param.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index ed2a3a507c8ab..2f55a9eaedab3 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2566,6 +2566,18 @@ pub enum SelfKind { Explicit(P, Mutability), } +impl SelfKind { + pub fn to_ref_suggestion(&self) -> String { + match self { + SelfKind::Region(None, mutbl) => mutbl.ref_prefix_str().to_string(), + SelfKind::Region(Some(lt), mutbl) => format!("&{lt} {}", mutbl.prefix_str()), + SelfKind::Value(_) | SelfKind::Explicit(_, _) => { + unreachable!("if we had an explicit self, we wouldn't be here") + } + } + } +} + pub type ExplicitSelf = Spanned; impl Param { diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index b9a325eddd800..e5cd4622dae90 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -343,6 +343,9 @@ parse_incorrect_semicolon = .suggestion = remove this semicolon .help = {$name} declarations are not followed by a semicolon +parse_incorrect_type_on_self = type not allowed for shorthand `self` parameter + .suggestion = move the modifiers on `self` to the type + parse_incorrect_use_of_await = incorrect use of `await` .parentheses_suggestion = `await` is not a method call, remove the parentheses diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 2579e4c1f2596..14f2dd32e9232 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3409,3 +3409,22 @@ pub(crate) struct PolarityAndModifiers { pub polarity: &'static str, pub modifiers_concatenated: String, } + +#[derive(Diagnostic)] +#[diag(parse_incorrect_type_on_self)] +pub(crate) struct IncorrectTypeOnSelf { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub move_self_modifier: MoveSelfModifier, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +pub(crate) struct MoveSelfModifier { + #[suggestion_part(code = "")] + pub removal_span: Span, + #[suggestion_part(code = "{modifier}")] + pub insertion_span: Span, + pub modifier: String, +} diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 26e81b7676bb1..475cd09147f5c 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2941,6 +2941,32 @@ impl<'a> Parser<'a> { }; Ok((eself, eself_ident, eself_hi)) }; + let expect_self_ident_not_typed = + |this: &mut Self, modifier: &SelfKind, modifier_span: Span| { + let eself_ident = expect_self_ident(this); + + // Recover `: Type` after a qualified self + if this.may_recover() && this.eat_noexpect(&token::Colon) { + let snap = this.create_snapshot_for_diagnostic(); + match this.parse_ty() { + Ok(ty) => { + this.dcx().emit_err(errors::IncorrectTypeOnSelf { + span: ty.span, + move_self_modifier: errors::MoveSelfModifier { + removal_span: modifier_span, + insertion_span: ty.span.shrink_to_lo(), + modifier: modifier.to_ref_suggestion(), + }, + }); + } + Err(diag) => { + diag.cancel(); + this.restore_snapshot(snap); + } + } + } + eself_ident + }; // Recover for the grammar `*self`, `*const self`, and `*mut self`. let recover_self_ptr = |this: &mut Self| { this.dcx().emit_err(errors::SelfArgumentPointer { span: this.token.span }); @@ -2978,7 +3004,9 @@ impl<'a> Parser<'a> { // `¬_self` return Ok(None); }; - (eself, expect_self_ident(self), self.prev_token.span) + let hi = self.token.span; + let self_ident = expect_self_ident_not_typed(self, &eself, eself_lo.until(hi)); + (eself, self_ident, hi) } // `*self` token::BinOp(token::Star) if is_isolated_self(self, 1) => { diff --git a/tests/ui/parser/typed-self-param.rs b/tests/ui/parser/typed-self-param.rs new file mode 100644 index 0000000000000..e3d85ab891b5b --- /dev/null +++ b/tests/ui/parser/typed-self-param.rs @@ -0,0 +1,14 @@ +struct S; + +impl S { + fn a(&self: Self) {} + //~^ ERROR type not allowed for shorthand `self` parameter + fn b(&mut self: Self) {} + //~^ ERROR type not allowed for shorthand `self` parameter + fn c<'c>(&'c mut self: Self) {} + //~^ ERROR type not allowed for shorthand `self` parameter + fn d<'d>(&'d self: Self) {} + //~^ ERROR type not allowed for shorthand `self` parameter +} + +fn main() {} diff --git a/tests/ui/parser/typed-self-param.stderr b/tests/ui/parser/typed-self-param.stderr new file mode 100644 index 0000000000000..c1ecd3b7fef43 --- /dev/null +++ b/tests/ui/parser/typed-self-param.stderr @@ -0,0 +1,50 @@ +error: type not allowed for shorthand `self` parameter + --> $DIR/typed-self-param.rs:4:17 + | +LL | fn a(&self: Self) {} + | ^^^^ + | +help: move the modifiers on `self` to the type + | +LL - fn a(&self: Self) {} +LL + fn a(self: &Self) {} + | + +error: type not allowed for shorthand `self` parameter + --> $DIR/typed-self-param.rs:6:21 + | +LL | fn b(&mut self: Self) {} + | ^^^^ + | +help: move the modifiers on `self` to the type + | +LL - fn b(&mut self: Self) {} +LL + fn b(self: &mut Self) {} + | + +error: type not allowed for shorthand `self` parameter + --> $DIR/typed-self-param.rs:8:28 + | +LL | fn c<'c>(&'c mut self: Self) {} + | ^^^^ + | +help: move the modifiers on `self` to the type + | +LL - fn c<'c>(&'c mut self: Self) {} +LL + fn c<'c>(self: &'c mut Self) {} + | + +error: type not allowed for shorthand `self` parameter + --> $DIR/typed-self-param.rs:10:24 + | +LL | fn d<'d>(&'d self: Self) {} + | ^^^^ + | +help: move the modifiers on `self` to the type + | +LL - fn d<'d>(&'d self: Self) {} +LL + fn d<'d>(self: &'d Self) {} + | + +error: aborting due to 4 previous errors + From c6205055e085a1210c1503978225d34147a0d8bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Nov 2024 02:15:21 +0000 Subject: [PATCH 08/21] On `const` pattern errors, point at the `const` item definition Centralize emitting an error in `const_to_pat` so that all errors from that evaluating a `const` in a pattern can add addditional information. With this, now point at the `const` item's definition: ``` error[E0158]: constant pattern depends on a generic parameter --> $DIR/associated-const-type-parameter-pattern.rs:20:9 | LL | pub trait Foo { | ------------- LL | const X: EFoo; | ------------- constant defined here ... LL | A::X => println!("A::X"), | ^^^^ ``` --- compiler/rustc_mir_build/messages.ftl | 2 + .../src/thir/pattern/const_to_pat.rs | 103 ++++++++++++------ ...ciated-const-type-parameter-pattern.stderr | 20 ++++ ...e-type-mismatch-when-copying-112824.stderr | 5 + .../const-eval/const-eval-overflow-2.stderr | 3 + .../const-eval/ref_to_int_match.64bit.stderr | 3 + .../const_in_pattern/cross-crate-fail.stderr | 10 ++ ...ssue-34784-match-on-non-int-raw-ptr.stderr | 12 ++ .../const_in_pattern/issue-44333.stderr | 6 + .../const_in_pattern/issue-65466.stderr | 3 + .../const_in_pattern/no-eq-branch-fail.stderr | 3 + .../reject_non_partial_eq.stderr | 3 + .../const_in_pattern/reject_non_structural.rs | 20 ++-- .../reject_non_structural.stderr | 21 ++++ .../const_refs_to_static_fail_invalid.stderr | 9 ++ tests/ui/consts/issue-43105.stderr | 3 + .../ui/consts/issue-73976-polymorphic.stderr | 10 ++ tests/ui/consts/issue-78655.stderr | 3 + tests/ui/consts/issue-79137-toogeneric.stderr | 5 + tests/ui/consts/issue-87046.stderr | 3 + tests/ui/consts/issue-89088.stderr | 3 + tests/ui/consts/match_ice.stderr | 3 + .../const_refers_to_static_cross_crate.stderr | 12 ++ .../ui/consts/missing_assoc_const_type.stderr | 5 + ...ansmute-size-mismatch-before-typeck.stderr | 3 + tests/ui/match/issue-70972-dyn-trait.stderr | 3 + .../issue-72896-non-partial-eq-const.stderr | 3 + tests/ui/pattern/issue-115599.stderr | 3 + tests/ui/pattern/issue-72565.stderr | 3 + .../const-partial_eq-fallback-ice.stderr | 3 + .../pattern/usefulness/consts-opaque.stderr | 24 ++++ ...-hide-behind-direct-struct-embedded.stderr | 3 + ...ant-hide-behind-direct-struct-param.stderr | 3 + ...ide-behind-doubly-indirect-embedded.stderr | 3 + ...t-hide-behind-doubly-indirect-param.stderr | 3 + ...ide-behind-indirect-struct-embedded.stderr | 3 + ...t-hide-behind-indirect-struct-param.stderr | 3 + ...n-ptr-is-not-structurally-matchable.stderr | 30 +++++ ...88-match-slice-forbidden-without-eq.stderr | 3 + ...-match-ref-ref-forbidden-without-eq.stderr | 6 + .../issue-63479-match-fnptr.stderr | 6 + .../issue-6804-nan-match.stderr | 21 ++++ ...atch-requires-both-partialeq-and-eq.stderr | 3 + .../structural-match-no-leak.stderr | 3 + .../structural-match.stderr | 3 + tests/ui/union/union-const-pat.stderr | 3 + 46 files changed, 365 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index f28cf84fa693e..fdefc0bfd190c 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -84,6 +84,8 @@ mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable +mir_build_const_defined_here = constant defined here + mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns mir_build_const_pattern_depends_on_generic_parameter = diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 5db08f01fdbdc..aa98874654edd 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -1,5 +1,6 @@ use rustc_abi::{FieldIdx, VariantIdx}; use rustc_apfloat::Float; +use rustc_errors::{Diag, PResult}; use rustc_hir as hir; use rustc_index::Idx; use rustc_infer::infer::TyCtxtInferExt; @@ -35,11 +36,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { id: hir::HirId, span: Span, ) -> Box> { - let mut convert = ConstToPat::new(self, id, span); + let mut convert = ConstToPat::new(self, id, span, c); match c.kind() { ty::ConstKind::Unevaluated(uv) => convert.unevaluated_to_pat(uv, ty), - ty::ConstKind::Value(_, val) => convert.valtree_to_pat(val, ty), + ty::ConstKind::Value(_, val) => match convert.valtree_to_pat(val, ty) { + Ok(pat) => pat, + Err(err) => convert.mk_err(err, ty), + }, _ => span_bug!(span, "Invalid `ConstKind` for `const_to_pat`: {:?}", c), } } @@ -51,10 +55,12 @@ struct ConstToPat<'tcx> { span: Span, treat_byte_string_as_slice: bool, + + c: ty::Const<'tcx>, } impl<'tcx> ConstToPat<'tcx> { - fn new(pat_ctxt: &PatCtxt<'_, 'tcx>, id: hir::HirId, span: Span) -> Self { + fn new(pat_ctxt: &PatCtxt<'_, 'tcx>, id: hir::HirId, span: Span, c: ty::Const<'tcx>) -> Self { trace!(?pat_ctxt.typeck_results.hir_owner); ConstToPat { tcx: pat_ctxt.tcx, @@ -64,6 +70,7 @@ impl<'tcx> ConstToPat<'tcx> { .typeck_results .treat_byte_string_as_slice .contains(&id.local_id), + c, } } @@ -71,13 +78,32 @@ impl<'tcx> ConstToPat<'tcx> { ty.is_structural_eq_shallow(self.tcx) } + /// We errored. Signal that in the pattern, so that follow up errors can be silenced. + fn mk_err(&self, mut err: Diag<'_>, ty: Ty<'tcx>) -> Box> { + if let ty::ConstKind::Unevaluated(uv) = self.c.kind() { + let def_kind = self.tcx.def_kind(uv.def); + if let hir::def::DefKind::AssocConst = def_kind + && let Some(def_id) = uv.def.as_local() + { + // Include the container item in the output. + err.span_label(self.tcx.def_span(self.tcx.local_parent(def_id)), ""); + } + if let hir::def::DefKind::Const | hir::def::DefKind::AssocConst = def_kind { + err.span_label( + self.tcx.def_span(uv.def), + crate::fluent_generated::mir_build_const_defined_here, + ); + } + } + Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit()) }) + } + fn unevaluated_to_pat( &mut self, uv: ty::UnevaluatedConst<'tcx>, ty: Ty<'tcx>, ) -> Box> { trace!(self.treat_byte_string_as_slice); - let pat_from_kind = |kind| Box::new(Pat { span: self.span, ty, kind }); // It's not *technically* correct to be revealing opaque types here as borrowcheck has // not run yet. However, CTFE itself uses `TypingMode::PostAnalysis` unconditionally even @@ -96,44 +122,46 @@ impl<'tcx> ConstToPat<'tcx> { Ok(Ok(c)) => c, Err(ErrorHandled::Reported(_, _)) => { // Let's tell the use where this failing const occurs. - let e = self.tcx.dcx().emit_err(CouldNotEvalConstPattern { span: self.span }); - return pat_from_kind(PatKind::Error(e)); + let err = self.tcx.dcx().create_err(CouldNotEvalConstPattern { span: self.span }); + return self.mk_err(err, ty); } Err(ErrorHandled::TooGeneric(_)) => { let e = self .tcx .dcx() - .emit_err(ConstPatternDependsOnGenericParameter { span: self.span }); - return pat_from_kind(PatKind::Error(e)); + .create_err(ConstPatternDependsOnGenericParameter { span: self.span }); + return self.mk_err(e, ty); } Ok(Err(bad_ty)) => { // The pattern cannot be turned into a valtree. let e = match bad_ty.kind() { ty::Adt(def, ..) => { assert!(def.is_union()); - self.tcx.dcx().emit_err(UnionPattern { span: self.span }) + self.tcx.dcx().create_err(UnionPattern { span: self.span }) } ty::FnPtr(..) | ty::RawPtr(..) => { - self.tcx.dcx().emit_err(PointerPattern { span: self.span }) + self.tcx.dcx().create_err(PointerPattern { span: self.span }) } _ => self .tcx .dcx() - .emit_err(InvalidPattern { span: self.span, non_sm_ty: bad_ty }), + .create_err(InvalidPattern { span: self.span, non_sm_ty: bad_ty }), }; - return pat_from_kind(PatKind::Error(e)); + return self.mk_err(e, ty); } }; // Convert the valtree to a const. - let inlined_const_as_pat = self.valtree_to_pat(valtree, ty); + let inlined_const_as_pat = match self.valtree_to_pat(valtree, ty) { + Ok(pat) => pat, + Err(err) => self.mk_err(err, ty), + }; if !inlined_const_as_pat.references_error() { // Always check for `PartialEq` if we had no other errors yet. if !self.type_has_partial_eq_impl(ty) { let err = TypeNotPartialEq { span: self.span, non_peq_ty: ty }; - let e = self.tcx.dcx().emit_err(err); - return pat_from_kind(PatKind::Error(e)); + return self.mk_err(self.tcx.dcx().create_err(err), ty); } } @@ -175,14 +203,20 @@ impl<'tcx> ConstToPat<'tcx> { let field = FieldIdx::new(idx); // Patterns can only use monomorphic types. let ty = self.tcx.normalize_erasing_regions(self.typing_env, ty); - FieldPat { field, pattern: self.valtree_to_pat(val, ty) } + FieldPat { + field, + pattern: match self.valtree_to_pat(val, ty) { + Ok(pat) => pat, + Err(err) => self.mk_err(err, ty), + }, + } }) .collect() } // Recursive helper for `to_pat`; invoke that (instead of calling this directly). #[instrument(skip(self), level = "debug")] - fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box> { + fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> PResult<'_, Box>> { let span = self.span; let tcx = self.tcx; let kind = match ty.kind() { @@ -191,9 +225,7 @@ impl<'tcx> ConstToPat<'tcx> { // patterns. debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty); let err = TypeNotStructural { span, non_sm_ty: ty }; - let e = tcx.dcx().emit_err(err); - // We errored. Signal that in the pattern, so that follow up errors can be silenced. - PatKind::Error(e) + return Err(tcx.dcx().create_err(err)); } ty::Adt(adt_def, args) if adt_def.is_enum() => { let (&variant_index, fields) = cv.unwrap_branch().split_first().unwrap(); @@ -227,7 +259,10 @@ impl<'tcx> ConstToPat<'tcx> { prefix: cv .unwrap_branch() .iter() - .map(|val| self.valtree_to_pat(*val, *elem_ty)) + .map(|val| match self.valtree_to_pat(*val, *elem_ty) { + Ok(pat) => pat, + Err(err) => self.mk_err(err, ty), + }) .collect(), slice: None, suffix: Box::new([]), @@ -236,7 +271,10 @@ impl<'tcx> ConstToPat<'tcx> { prefix: cv .unwrap_branch() .iter() - .map(|val| self.valtree_to_pat(*val, *elem_ty)) + .map(|val| match self.valtree_to_pat(*val, *elem_ty) { + Ok(pat) => pat, + Err(err) => self.mk_err(err, ty), + }) .collect(), slice: None, suffix: Box::new([]), @@ -252,10 +290,9 @@ impl<'tcx> ConstToPat<'tcx> { // deref pattern. _ => { if !pointee_ty.is_sized(tcx, self.typing_env) && !pointee_ty.is_slice() { - let err = UnsizedPattern { span, non_sm_ty: *pointee_ty }; - let e = tcx.dcx().emit_err(err); - // We errored. Signal that in the pattern, so that follow up errors can be silenced. - PatKind::Error(e) + return Err(tcx + .dcx() + .create_err(UnsizedPattern { span, non_sm_ty: *pointee_ty })); } else { // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when // matching against references, you can only use byte string literals. @@ -270,7 +307,10 @@ impl<'tcx> ConstToPat<'tcx> { _ => *pointee_ty, }; // References have the same valtree representation as their pointee. - let subpattern = self.valtree_to_pat(cv, pointee_ty); + let subpattern = match self.valtree_to_pat(cv, pointee_ty) { + Ok(pat) => pat, + Err(err) => self.mk_err(err, ty), + }; PatKind::Deref { subpattern } } } @@ -286,8 +326,7 @@ impl<'tcx> ConstToPat<'tcx> { if is_nan { // NaNs are not ever equal to anything so they make no sense as patterns. // Also see . - let e = tcx.dcx().emit_err(NaNPattern { span }); - PatKind::Error(e) + return Err(tcx.dcx().create_err(NaNPattern { span })); } else { PatKind::Constant { value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)), @@ -306,12 +345,10 @@ impl<'tcx> ConstToPat<'tcx> { } _ => { let err = InvalidPattern { span, non_sm_ty: ty }; - let e = tcx.dcx().emit_err(err); - // We errored. Signal that in the pattern, so that follow up errors can be silenced. - PatKind::Error(e) + return Err(tcx.dcx().create_err(err)); } }; - Box::new(Pat { span, ty, kind }) + Ok(Box::new(Pat { span, ty, kind })) } } diff --git a/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr b/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr index adc8f3992072d..5aef0fa414bd4 100644 --- a/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr +++ b/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr @@ -1,24 +1,44 @@ error[E0158]: constant pattern depends on a generic parameter --> $DIR/associated-const-type-parameter-pattern.rs:20:9 | +LL | pub trait Foo { + | ------------- +LL | const X: EFoo; + | ------------- constant defined here +... LL | A::X => println!("A::X"), | ^^^^ error[E0158]: constant pattern depends on a generic parameter --> $DIR/associated-const-type-parameter-pattern.rs:22:9 | +LL | pub trait Foo { + | ------------- +LL | const X: EFoo; + | ------------- constant defined here +... LL | B::X => println!("B::X"), | ^^^^ error[E0158]: constant pattern depends on a generic parameter --> $DIR/associated-const-type-parameter-pattern.rs:30:9 | +LL | pub trait Foo { + | ------------- +LL | const X: EFoo; + | ------------- constant defined here +... LL | let A::X = arg; | ^^^^ error[E0158]: constant pattern depends on a generic parameter --> $DIR/associated-const-type-parameter-pattern.rs:28:48 | +LL | pub trait Foo { + | ------------- +LL | const X: EFoo; + | ------------- constant defined here +... LL | pub fn test_let_pat(arg: EFoo, A::X: EFoo) { | ^^^^ diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr index 9442eac0cf54a..9cce6fee55ac6 100644 --- a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr +++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr @@ -20,6 +20,11 @@ LL | pub struct Opcode2(&'a S); error: could not evaluate constant pattern --> $DIR/ice-type-mismatch-when-copying-112824.rs:15:9 | +LL | impl Opcode2 { + | ------------ +LL | pub const OP2: Opcode2 = Opcode2(Opcode(0x1)); + | ---------------------- constant defined here +... LL | Opcode2::OP2 => unimplemented!(), | ^^^^^^^^^^^^ diff --git a/tests/ui/consts/const-eval/const-eval-overflow-2.stderr b/tests/ui/consts/const-eval/const-eval-overflow-2.stderr index fc0baf11051b7..66c54af4f83f6 100644 --- a/tests/ui/consts/const-eval/const-eval-overflow-2.stderr +++ b/tests/ui/consts/const-eval/const-eval-overflow-2.stderr @@ -7,6 +7,9 @@ LL | const NEG_NEG_128: i8 = -NEG_128; error: could not evaluate constant pattern --> $DIR/const-eval-overflow-2.rs:15:9 | +LL | const NEG_NEG_128: i8 = -NEG_128; + | --------------------- constant defined here +... LL | NEG_NEG_128 => println!("A"), | ^^^^^^^^^^^ diff --git a/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr b/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr index 8175fe6016ab8..b1c6cfd3246e2 100644 --- a/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr +++ b/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr @@ -12,6 +12,9 @@ error: could not evaluate constant pattern | LL | 10..=BAR => {}, | ^^^ +... +LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; + | -------------- constant defined here error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr b/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr index e0f97a9abd210..81fc67e6aebb5 100644 --- a/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr +++ b/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr @@ -4,6 +4,11 @@ error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be ann LL | consts::SOME => panic!(), | ^^^^^^^^^^^^ | + ::: $DIR/auxiliary/consts.rs:11:1 + | +LL | pub const SOME: Option = Some(CustomEq); + | -------------------------------- constant defined here + | = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details @@ -13,6 +18,11 @@ error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be ann LL | ::SOME => panic!(), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + ::: $DIR/auxiliary/consts.rs:15:5 + | +LL | const SOME: Option = Some(CustomEq); + | ---------------------------- constant defined here + | = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details diff --git a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr index aa208341c131d..cc7ec771e6cd6 100644 --- a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr @@ -1,24 +1,36 @@ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:9:9 | +LL | const C: *const u8 = &0; + | ------------------ constant defined here +... LL | C => {} | ^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:16:9 | +LL | const C_INNER: (*const u8, u8) = (C, 0); + | ------------------------------ constant defined here +... LL | C_INNER => {} | ^^^^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:27:9 | +LL | const D: *const [u8; 4] = b"abcd"; + | ----------------------- constant defined here +... LL | D => {} | ^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:32:9 | +LL | const STR: *const str = "abcd"; + | --------------------- constant defined here +... LL | STR => {} | ^^^ diff --git a/tests/ui/consts/const_in_pattern/issue-44333.stderr b/tests/ui/consts/const_in_pattern/issue-44333.stderr index d377bfd95f9cd..81393952f0fcf 100644 --- a/tests/ui/consts/const_in_pattern/issue-44333.stderr +++ b/tests/ui/consts/const_in_pattern/issue-44333.stderr @@ -1,12 +1,18 @@ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-44333.rs:15:9 | +LL | const FOO: Func = foo; + | --------------- constant defined here +... LL | FOO => println!("foo"), | ^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-44333.rs:16:9 | +LL | const BAR: Func = bar; + | --------------- constant defined here +... LL | BAR => println!("bar"), | ^^^ diff --git a/tests/ui/consts/const_in_pattern/issue-65466.stderr b/tests/ui/consts/const_in_pattern/issue-65466.stderr index 7d5e5b5b0c64a..070ce384f6aad 100644 --- a/tests/ui/consts/const_in_pattern/issue-65466.stderr +++ b/tests/ui/consts/const_in_pattern/issue-65466.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `&[O]` in a pattern, the type must implement `PartialEq` --> $DIR/issue-65466.rs:14:9 | +LL | const C: &[O] = &[O::None]; + | ---------------- constant defined here +... LL | C => (), | ^ diff --git a/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr index 7766c6ce683d2..5e2fc6eca3c5d 100644 --- a/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr +++ b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq)]` --> $DIR/no-eq-branch-fail.rs:19:9 | +LL | const BAR_BAZ: Foo = if 42 == 42 { + | ------------------ constant defined here +... LL | BAR_BAZ => panic!(), | ^^^^^^^ | diff --git a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr index ed531a1fead8d..463b37e7caa73 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `Option` in a pattern, the type must implement `PartialEq` --> $DIR/reject_non_partial_eq.rs:28:9 | +LL | const NO_PARTIAL_EQ_NONE: Option = None; + | --------------------------------------------- constant defined here +... LL | NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"), | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.rs b/tests/ui/consts/const_in_pattern/reject_non_structural.rs index e3dcecec960a7..52cb974c1df1b 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.rs +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.rs @@ -36,63 +36,63 @@ fn main() { #[derive(PartialEq, Eq, Debug)] enum Derive { Some(X), None, } - const ENUM: Derive = Derive::Some(NoDerive); + const ENUM: Derive = Derive::Some(NoDerive); //~ NOTE constant defined here match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), }; //~^ ERROR must be annotated with `#[derive(PartialEq)]` //~| NOTE the traits must be derived //~| NOTE StructuralPartialEq.html for details - const FIELD: OND = TrivialEq(Some(NoDerive)).0; + const FIELD: OND = TrivialEq(Some(NoDerive)).0; //~ NOTE constant defined here match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), }; //~^ ERROR must be annotated with `#[derive(PartialEq)]` //~| NOTE the traits must be derived //~| NOTE StructuralPartialEq.html for details const NO_DERIVE_SOME: OND = Some(NoDerive); - const INDIRECT: OND = NO_DERIVE_SOME; + const INDIRECT: OND = NO_DERIVE_SOME; //~ NOTE constant defined here match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), }; //~^ ERROR must be annotated with `#[derive(PartialEq)]` //~| NOTE the traits must be derived //~| NOTE StructuralPartialEq.html for details - const TUPLE: (OND, OND) = (None, Some(NoDerive)); + const TUPLE: (OND, OND) = (None, Some(NoDerive)); //~ NOTE constant defined here match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), }; //~^ ERROR must be annotated with `#[derive(PartialEq)]` //~| NOTE the traits must be derived //~| NOTE StructuralPartialEq.html for details - const TYPE_ASCRIPTION: OND = type_ascribe!(Some(NoDerive), OND); + const TYPE_ASCRIPTION: OND = type_ascribe!(Some(NoDerive), OND); //~ NOTE constant defined here match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), }; //~^ ERROR must be annotated with `#[derive(PartialEq)]` //~| NOTE the traits must be derived //~| NOTE StructuralPartialEq.html for details - const ARRAY: [OND; 2] = [None, Some(NoDerive)]; + const ARRAY: [OND; 2] = [None, Some(NoDerive)]; //~ NOTE constant defined here match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), }; //~^ ERROR must be annotated with `#[derive(PartialEq)]` //~| NOTE the traits must be derived //~| NOTE StructuralPartialEq.html for details - const REPEAT: [OND; 2] = [Some(NoDerive); 2]; + const REPEAT: [OND; 2] = [Some(NoDerive); 2]; //~ NOTE constant defined here match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), }; //~^ ERROR must be annotated with `#[derive(PartialEq)]` //~| NOTE the traits must be derived //~| NOTE StructuralPartialEq.html for details - trait Trait: Sized { const ASSOC: Option; } + trait Trait: Sized { const ASSOC: Option; } //~ NOTE constant defined here impl Trait for NoDerive { const ASSOC: Option = Some(NoDerive); } match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), }; //~^ ERROR must be annotated with `#[derive(PartialEq)]` //~| NOTE the traits must be derived //~| NOTE StructuralPartialEq.html for details - const BLOCK: OND = { NoDerive; Some(NoDerive) }; + const BLOCK: OND = { NoDerive; Some(NoDerive) }; //~ NOTE constant defined here match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), }; //~^ ERROR must be annotated with `#[derive(PartialEq)]` //~| NOTE the traits must be derived //~| NOTE StructuralPartialEq.html for details - const ADDR_OF: &OND = &Some(NoDerive); + const ADDR_OF: &OND = &Some(NoDerive); //~ NOTE constant defined here match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; //~^ ERROR must be annotated with `#[derive(PartialEq)]` //~| NOTE the traits must be derived diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr index c068db42e4d90..e8a69512e7eda 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr @@ -1,6 +1,8 @@ error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/reject_non_structural.rs:40:36 | +LL | const ENUM: Derive = Derive::Some(NoDerive); + | ---------------------------- constant defined here LL | match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), }; | ^^^^ | @@ -10,6 +12,8 @@ LL | match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops" error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/reject_non_structural.rs:46:28 | +LL | const FIELD: OND = TrivialEq(Some(NoDerive)).0; + | ---------------- constant defined here LL | match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), }; | ^^^^^ | @@ -19,6 +23,8 @@ LL | match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), }; error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/reject_non_structural.rs:53:27 | +LL | const INDIRECT: OND = NO_DERIVE_SOME; + | ------------------- constant defined here LL | match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), }; | ^^^^^^^^ | @@ -28,6 +34,8 @@ LL | match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops") error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/reject_non_structural.rs:59:36 | +LL | const TUPLE: (OND, OND) = (None, Some(NoDerive)); + | ----------------------- constant defined here LL | match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), }; | ^^^^^ | @@ -37,6 +45,8 @@ LL | match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoop error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/reject_non_structural.rs:65:28 | +LL | const TYPE_ASCRIPTION: OND = type_ascribe!(Some(NoDerive), OND); + | -------------------------- constant defined here LL | match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), }; | ^^^^^^^^^^^^^^^ | @@ -46,6 +56,8 @@ LL | match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => p error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/reject_non_structural.rs:71:36 | +LL | const ARRAY: [OND; 2] = [None, Some(NoDerive)]; + | --------------------- constant defined here LL | match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), }; | ^^^^^ | @@ -55,6 +67,8 @@ LL | match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoop error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/reject_non_structural.rs:77:33 | +LL | const REPEAT: [OND; 2] = [Some(NoDerive); 2]; + | ---------------------- constant defined here LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), }; | ^^^^^^ | @@ -64,6 +78,9 @@ LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/reject_non_structural.rs:84:28 | +LL | trait Trait: Sized { const ASSOC: Option; } + | ------------------ ------------------------- constant defined here +LL | impl Trait for NoDerive { const ASSOC: Option = Some(NoDerive); } LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), }; | ^^^^^^^^^^^^^^^ | @@ -73,6 +90,8 @@ LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => p error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/reject_non_structural.rs:90:28 | +LL | const BLOCK: OND = { NoDerive; Some(NoDerive) }; + | ---------------- constant defined here LL | match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), }; | ^^^^^ | @@ -82,6 +101,8 @@ LL | match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), }; error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/reject_non_structural.rs:96:29 | +LL | const ADDR_OF: &OND = &Some(NoDerive); + | ------------------- constant defined here LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; | ^^^^^^^ | diff --git a/tests/ui/consts/const_refs_to_static_fail_invalid.stderr b/tests/ui/consts/const_refs_to_static_fail_invalid.stderr index 0153f501174b2..9f2633a64d594 100644 --- a/tests/ui/consts/const_refs_to_static_fail_invalid.stderr +++ b/tests/ui/consts/const_refs_to_static_fail_invalid.stderr @@ -34,18 +34,27 @@ LL | const C: &i32 = unsafe { &S_MUT }; error: could not evaluate constant pattern --> $DIR/const_refs_to_static_fail_invalid.rs:14:9 | +LL | const C: &bool = unsafe { std::mem::transmute(&S) }; + | -------------- constant defined here +... LL | C => {} | ^ error: could not evaluate constant pattern --> $DIR/const_refs_to_static_fail_invalid.rs:30:9 | +LL | const C: &i8 = unsafe { &S }; + | ------------ constant defined here +... LL | C => {} | ^ error: could not evaluate constant pattern --> $DIR/const_refs_to_static_fail_invalid.rs:45:9 | +LL | const C: &i32 = unsafe { &S_MUT }; + | ------------- constant defined here +... LL | C => {} | ^ diff --git a/tests/ui/consts/issue-43105.stderr b/tests/ui/consts/issue-43105.stderr index 856a8f0dab6c0..4c59bdd4520eb 100644 --- a/tests/ui/consts/issue-43105.stderr +++ b/tests/ui/consts/issue-43105.stderr @@ -9,6 +9,9 @@ LL | const NUM: u8 = xyz(); error: could not evaluate constant pattern --> $DIR/issue-43105.rs:8:9 | +LL | const NUM: u8 = xyz(); + | ------------- constant defined here +... LL | NUM => unimplemented!(), | ^^^ diff --git a/tests/ui/consts/issue-73976-polymorphic.stderr b/tests/ui/consts/issue-73976-polymorphic.stderr index 8a44eb9854fef..79a03d4ec32c9 100644 --- a/tests/ui/consts/issue-73976-polymorphic.stderr +++ b/tests/ui/consts/issue-73976-polymorphic.stderr @@ -1,12 +1,22 @@ error[E0158]: constant pattern depends on a generic parameter --> $DIR/issue-73976-polymorphic.rs:20:37 | +LL | impl GetTypeId { + | ----------------------------- +LL | pub const VALUE: TypeId = TypeId::of::(); + | ----------------------- constant defined here +... LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) | ^^^^^^^^^^^^^^^^^^^^^ error[E0158]: constant pattern depends on a generic parameter --> $DIR/issue-73976-polymorphic.rs:31:42 | +LL | impl GetTypeNameLen { + | ---------------------------------- +LL | pub const VALUE: usize = any::type_name::().len(); + | ---------------------- constant defined here +... LL | matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/issue-78655.stderr b/tests/ui/consts/issue-78655.stderr index ccaed03b4c1df..5d684227be8bf 100644 --- a/tests/ui/consts/issue-78655.stderr +++ b/tests/ui/consts/issue-78655.stderr @@ -14,6 +14,9 @@ LL | let x = 42; error: could not evaluate constant pattern --> $DIR/issue-78655.rs:7:9 | +LL | const FOO: *const u32 = { + | --------------------- constant defined here +... LL | let FOO = FOO; | ^^^ diff --git a/tests/ui/consts/issue-79137-toogeneric.stderr b/tests/ui/consts/issue-79137-toogeneric.stderr index de81512ec6d2c..9b53a2595479d 100644 --- a/tests/ui/consts/issue-79137-toogeneric.stderr +++ b/tests/ui/consts/issue-79137-toogeneric.stderr @@ -1,6 +1,11 @@ error[E0158]: constant pattern depends on a generic parameter --> $DIR/issue-79137-toogeneric.rs:12:43 | +LL | impl GetVariantCount { + | -------------------------- +LL | pub const VALUE: usize = std::mem::variant_count::(); + | ---------------------- constant defined here +... LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/issue-87046.stderr b/tests/ui/consts/issue-87046.stderr index 0f965e1ac3f1b..36e2564fae6b0 100644 --- a/tests/ui/consts/issue-87046.stderr +++ b/tests/ui/consts/issue-87046.stderr @@ -1,6 +1,9 @@ error: cannot use unsized non-slice type `Username` in constant patterns --> $DIR/issue-87046.rs:28:13 | +LL | pub const ROOT_USER: &Username = Username::from_str("root"); + | ------------------------------ constant defined here +... LL | ROOT_USER => true, | ^^^^^^^^^ diff --git a/tests/ui/consts/issue-89088.stderr b/tests/ui/consts/issue-89088.stderr index 362c63a2a4569..740cc25647e52 100644 --- a/tests/ui/consts/issue-89088.stderr +++ b/tests/ui/consts/issue-89088.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `Cow<'_, str>` in a pattern, `Cow<'_, str>` must be annotated with `#[derive(PartialEq)]` --> $DIR/issue-89088.rs:16:9 | +LL | const FOO: &A = &A::Field(Cow::Borrowed("foo")); + | ------------- constant defined here +... LL | FOO => todo!(), | ^^^ | diff --git a/tests/ui/consts/match_ice.stderr b/tests/ui/consts/match_ice.stderr index 472c24a5cbe31..0841ed050251a 100644 --- a/tests/ui/consts/match_ice.stderr +++ b/tests/ui/consts/match_ice.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `S` in a pattern, `S` must be annotated with `#[derive(PartialEq)]` --> $DIR/match_ice.rs:11:9 | +LL | const C: &S = &S; + | ----------- constant defined here +LL | match C { LL | C => {} | ^ | diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr index 147d3f238f777..513f456bdf4e6 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr @@ -40,24 +40,36 @@ LL | match static_cross_crate::OPT_ZERO { error: could not evaluate constant pattern --> $DIR/const_refers_to_static_cross_crate.rs:40:9 | +LL | const SLICE_MUT: &[u8; 1] = { + | ------------------------- constant defined here +... LL | SLICE_MUT => true, | ^^^^^^^^^ error: could not evaluate constant pattern --> $DIR/const_refers_to_static_cross_crate.rs:48:9 | +LL | const U8_MUT: &u8 = { + | ----------------- constant defined here +... LL | U8_MUT => true, | ^^^^^^ error: could not evaluate constant pattern --> $DIR/const_refers_to_static_cross_crate.rs:58:9 | +LL | const U8_MUT2: &u8 = { + | ------------------ constant defined here +... LL | U8_MUT2 => true, | ^^^^^^^ error: could not evaluate constant pattern --> $DIR/const_refers_to_static_cross_crate.rs:65:9 | +LL | const U8_MUT3: &u8 = { + | ------------------ constant defined here +... LL | U8_MUT3 => true, | ^^^^^^^ diff --git a/tests/ui/consts/missing_assoc_const_type.stderr b/tests/ui/consts/missing_assoc_const_type.stderr index ef7ff962d2d12..8123a43ef74fe 100644 --- a/tests/ui/consts/missing_assoc_const_type.stderr +++ b/tests/ui/consts/missing_assoc_const_type.stderr @@ -7,6 +7,11 @@ LL | const FIRST: = 10; error: could not evaluate constant pattern --> $DIR/missing_assoc_const_type.rs:19:9 | +LL | trait Range { + | ----------- +LL | const FIRST: u8; + | --------------- constant defined here +... LL | TwoDigits::FIRST..=TwoDigits::LAST => 0, | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr index e0d658db99760..79f59ba865d8d 100644 --- a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr +++ b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr @@ -12,6 +12,9 @@ error: could not evaluate constant pattern | LL | ZST => {} | ^^^ +... +LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; + | ---------------- constant defined here error: aborting due to 2 previous errors diff --git a/tests/ui/match/issue-70972-dyn-trait.stderr b/tests/ui/match/issue-70972-dyn-trait.stderr index b0af50f8599c5..91f49c8a2ff10 100644 --- a/tests/ui/match/issue-70972-dyn-trait.stderr +++ b/tests/ui/match/issue-70972-dyn-trait.stderr @@ -1,6 +1,9 @@ error: `dyn Send` cannot be used in patterns --> $DIR/issue-70972-dyn-trait.rs:6:9 | +LL | const F: &'static dyn Send = &7u32; + | -------------------------- constant defined here +... LL | F => panic!(), | ^ diff --git a/tests/ui/match/issue-72896-non-partial-eq-const.stderr b/tests/ui/match/issue-72896-non-partial-eq-const.stderr index 4155586c16060..eeca541fc3cd8 100644 --- a/tests/ui/match/issue-72896-non-partial-eq-const.stderr +++ b/tests/ui/match/issue-72896-non-partial-eq-const.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `EnumSet` in a pattern, the type must implement `PartialEq` --> $DIR/issue-72896-non-partial-eq-const.rs:19:9 | +LL | const CONST_SET: EnumSet = EnumSet { __enumset_underlying: 3 }; + | ------------------------------- constant defined here +... LL | CONST_SET => { /* ok */ } | ^^^^^^^^^ diff --git a/tests/ui/pattern/issue-115599.stderr b/tests/ui/pattern/issue-115599.stderr index adab4e4d241b7..65e3b08ac4853 100644 --- a/tests/ui/pattern/issue-115599.stderr +++ b/tests/ui/pattern/issue-115599.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `Vec` in a pattern, `Vec` must be annotated with `#[derive(PartialEq)]` --> $DIR/issue-115599.rs:5:12 | +LL | const CONST_STRING: String = String::new(); + | -------------------------- constant defined here +... LL | if let CONST_STRING = empty_str {} | ^^^^^^^^^^^^ | diff --git a/tests/ui/pattern/issue-72565.stderr b/tests/ui/pattern/issue-72565.stderr index b503a17fe849f..abfd4512e9b8e 100644 --- a/tests/ui/pattern/issue-72565.stderr +++ b/tests/ui/pattern/issue-72565.stderr @@ -1,6 +1,9 @@ error: `dyn PartialEq` cannot be used in patterns --> $DIR/issue-72565.rs:6:9 | +LL | const F: &'static dyn PartialEq = &7u32; + | ------------------------------------ constant defined here +... LL | F => panic!(), | ^ diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr index 0b4d99727581b..bcbcd0bc280d8 100644 --- a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr +++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `MyType` in a pattern, `MyType` must be annotated with `#[derive(PartialEq)]` --> $DIR/const-partial_eq-fallback-ice.rs:14:12 | +LL | const CONSTANT: &&MyType = &&MyType; + | ------------------------ constant defined here +... LL | if let CONSTANT = &&MyType { | ^^^^^^^^ | diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index 32d385eecb476..15aa1769662cd 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -1,48 +1,72 @@ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:96:9 | +LL | const QUUX: Quux = quux; + | ---------------- constant defined here +... LL | QUUX => {} | ^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:97:9 | +LL | const QUUX: Quux = quux; + | ---------------- constant defined here +... LL | QUUX => {} | ^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:106:9 | +LL | const WRAPQUUX: Wrap = Wrap(quux); + | -------------------------- constant defined here +... LL | WRAPQUUX => {} | ^^^^^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:107:9 | +LL | const WRAPQUUX: Wrap = Wrap(quux); + | -------------------------- constant defined here +... LL | WRAPQUUX => {} | ^^^^^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:113:9 | +LL | const WRAPQUUX: Wrap = Wrap(quux); + | -------------------------- constant defined here +... LL | WRAPQUUX => {} | ^^^^^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:121:9 | +LL | const WRAPQUUX: Wrap = Wrap(quux); + | -------------------------- constant defined here +... LL | WRAPQUUX => {} | ^^^^^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:132:9 | +LL | const WHOKNOWSQUUX: WhoKnows = WhoKnows::Yay(quux); + | ---------------------------------- constant defined here +... LL | WHOKNOWSQUUX => {} | ^^^^^^^^^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:134:9 | +LL | const WHOKNOWSQUUX: WhoKnows = WhoKnows::Yay(quux); + | ---------------------------------- constant defined here +... LL | WHOKNOWSQUUX => {} | ^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr index cc5d4106331d2..dffaafd88a088 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/cant-hide-behind-direct-struct-embedded.rs:22:9 | +LL | const WRAP_DIRECT_INLINE: WrapInline = WrapInline(NoDerive(0)); + | ------------------------------------ constant defined here +... LL | WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); } | ^^^^^^^^^^^^^^^^^^ | diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr index 3d00ef2dfbf6d..8da9fa71c536a 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/cant-hide-behind-direct-struct-param.rs:21:9 | +LL | const WRAP_DIRECT_PARAM: WrapParam = WrapParam(NoDerive(0)); + | -------------------------------------------- constant defined here +... LL | WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); } | ^^^^^^^^^^^^^^^^^ | diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr index 3636307e16c61..3cd6a184bbe20 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:22:9 | +LL | const WRAP_DOUBLY_INDIRECT_INLINE: & &WrapInline = & &WrapInline(& & NoDerive(0)); + | ------------------------------------------------ constant defined here +... LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr index 40fd31762b2fe..35693da99abf3 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/cant-hide-behind-doubly-indirect-param.rs:22:9 | +LL | const WRAP_DOUBLY_INDIRECT_PARAM: & &WrapParam = & &WrapParam(& & NoDerive(0)); + | -------------------------------------------------------- constant defined here +... LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr index dbf1848326aa4..5312d61c44695 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:22:9 | +LL | const WRAP_INDIRECT_INLINE: & &WrapInline = & &WrapInline(NoDerive(0)); + | ----------------------------------------- constant defined here +... LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); } | ^^^^^^^^^^^^^^^^^^^^ | diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr index 58acc11a74498..2066c53e73a6b 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` --> $DIR/cant-hide-behind-indirect-struct-param.rs:22:9 | +LL | const WRAP_INDIRECT_PARAM: & &WrapParam = & &WrapParam(NoDerive(0)); + | ------------------------------------------------- constant defined here +... LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); } | ^^^^^^^^^^^^^^^^^^^ | diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr index 0bc1e7fc89b5f..ee6f44a364da4 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr @@ -1,60 +1,90 @@ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-not-structurally-matchable.rs:41:14 | +LL | const CFN1: Wrap = Wrap(trivial); + | ---------------------- constant defined here +... LL | Wrap(CFN1) => count += 1, | ^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-not-structurally-matchable.rs:49:14 | +LL | const CFN2: Wrap = Wrap(sm_to); + | ------------------------ constant defined here +... LL | Wrap(CFN2) => count += 1, | ^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-not-structurally-matchable.rs:57:14 | +LL | const CFN3: Wrap SM> = Wrap(to_sm); + | ---------------------------- constant defined here +... LL | Wrap(CFN3) => count += 1, | ^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-not-structurally-matchable.rs:65:14 | +LL | const CFN4: Wrap = Wrap(not_sm_to); + | --------------------------- constant defined here +... LL | Wrap(CFN4) => count += 1, | ^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-not-structurally-matchable.rs:73:14 | +LL | const CFN5: Wrap NotSM> = Wrap(to_not_sm); + | ------------------------------- constant defined here +... LL | Wrap(CFN5) => count += 1, | ^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-not-structurally-matchable.rs:81:14 | +LL | const CFN6: Wrap = Wrap(r_sm_to); + | ------------------------- constant defined here +... LL | Wrap(CFN6) => count += 1, | ^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-not-structurally-matchable.rs:89:14 | +LL | const CFN7: Wrap &SM> = Wrap(r_to_r_sm); + | -------------------------------- constant defined here +... LL | Wrap(CFN7) => count += 1, | ^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-not-structurally-matchable.rs:97:14 | +LL | const CFN8: Wrap = Wrap(r_not_sm_to); + | ---------------------------- constant defined here +... LL | Wrap(CFN8) => count += 1, | ^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-not-structurally-matchable.rs:105:14 | +LL | const CFN9: Wrap &NotSM> = Wrap(r_to_r_not_sm); + | ----------------------------------- constant defined here +... LL | Wrap(CFN9) => count += 1, | ^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-not-structurally-matchable.rs:127:9 | +LL | const CFOO: Foo = Foo { + | --------------- constant defined here +... LL | CFOO => count += 1, | ^^^^ diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr index 736e4c30c8ae3..e105c6a1f98a9 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `&[B]` in a pattern, the type must implement `PartialEq` --> $DIR/issue-61188-match-slice-forbidden-without-eq.rs:15:9 | +LL | const A: &[B] = &[]; + | ------------- constant defined here +... LL | A => (), | ^ diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr index e79b05fdf9dc6..5cfe6dabc8956 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]` --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:29:9 | +LL | const RR_B1: & & B = & & B(1); + | ------------------ constant defined here +... LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); } | ^^^^^ | @@ -10,6 +13,9 @@ LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]` --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:35:9 | +LL | const RR_B1: & & B = & & B(1); + | ------------------ constant defined here +... LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); } | ^^^^^ | diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr index 7b1832ed0fa58..be735ccab0a5a 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr @@ -1,12 +1,18 @@ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-63479-match-fnptr.rs:32:7 | +LL | const TEST: Fn = my_fn; + | -------------- constant defined here +... LL | B(TEST) => println!("matched"), | ^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-63479-match-fnptr.rs:37:5 | +LL | const TEST2: (Fn, u8) = (TEST, 0); + | --------------------- constant defined here +... LL | TEST2 => println!("matched"), | ^^^^^ diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr index 44b05ea31e962..4e2dcb52da807 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr @@ -1,6 +1,9 @@ error: cannot use NaN in patterns --> $DIR/issue-6804-nan-match.rs:14:9 | +LL | const NAN: f64 = f64::NAN; + | -------------- constant defined here +... LL | NAN => {}, | ^^^ | @@ -10,6 +13,9 @@ LL | NAN => {}, error: cannot use NaN in patterns --> $DIR/issue-6804-nan-match.rs:19:10 | +LL | const NAN: f64 = f64::NAN; + | -------------- constant defined here +... LL | [NAN, _] => {}, | ^^^ | @@ -19,6 +25,9 @@ LL | [NAN, _] => {}, error: cannot use NaN in patterns --> $DIR/issue-6804-nan-match.rs:24:9 | +LL | const C: MyType = MyType(f32::NAN); + | -------------------- constant defined here +... LL | C => {}, | ^ | @@ -28,6 +37,9 @@ LL | C => {}, error: cannot use NaN in patterns --> $DIR/issue-6804-nan-match.rs:30:9 | +LL | const NAN: f64 = f64::NAN; + | -------------- constant defined here +... LL | NAN..=1.0 => {}, | ^^^ | @@ -37,6 +49,9 @@ LL | NAN..=1.0 => {}, error: cannot use NaN in patterns --> $DIR/issue-6804-nan-match.rs:31:16 | +LL | const NAN: f64 = f64::NAN; + | -------------- constant defined here +... LL | -1.0..=NAN => {}, | ^^^ | @@ -46,6 +61,9 @@ LL | -1.0..=NAN => {}, error: cannot use NaN in patterns --> $DIR/issue-6804-nan-match.rs:32:9 | +LL | const NAN: f64 = f64::NAN; + | -------------- constant defined here +... LL | NAN.. => {}, | ^^^ | @@ -55,6 +73,9 @@ LL | NAN.. => {}, error: cannot use NaN in patterns --> $DIR/issue-6804-nan-match.rs:33:11 | +LL | const NAN: f64 = f64::NAN; + | -------------- constant defined here +... LL | ..NAN => {}, | ^^^ | diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr index efd9c8c45afa9..c471fe572548c 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr @@ -1,6 +1,9 @@ error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq)]` --> $DIR/match-requires-both-partialeq-and-eq.rs:17:9 | +LL | const FOO: Foo = Foo { x: 0 }; + | -------------- constant defined here +... LL | FOO => { } | ^^^ | diff --git a/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr b/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr index 98d71aa9a17dc..743ad75628e25 100644 --- a/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr +++ b/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr @@ -1,6 +1,9 @@ error: `Bar` cannot be used in patterns --> $DIR/structural-match-no-leak.rs:16:9 | +LL | const LEAK_FREE: bar::Bar = bar::leak_free(); + | ------------------------- constant defined here +... LL | LEAK_FREE => (), | ^^^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/structural-match.stderr b/tests/ui/type-alias-impl-trait/structural-match.stderr index c7478b0a135e5..9c26aa9a9a645 100644 --- a/tests/ui/type-alias-impl-trait/structural-match.stderr +++ b/tests/ui/type-alias-impl-trait/structural-match.stderr @@ -1,6 +1,9 @@ error: `foo::Foo` cannot be used in patterns --> $DIR/structural-match.rs:18:9 | +LL | const VALUE: Foo = value(); + | ---------------- constant defined here +... LL | VALUE => (), | ^^^^^ diff --git a/tests/ui/union/union-const-pat.stderr b/tests/ui/union/union-const-pat.stderr index e9dbb275944ae..baf32bf484950 100644 --- a/tests/ui/union/union-const-pat.stderr +++ b/tests/ui/union/union-const-pat.stderr @@ -1,6 +1,9 @@ error: cannot use unions in constant patterns --> $DIR/union-const-pat.rs:10:9 | +LL | const C: U = U { a: 10 }; + | ---------- constant defined here +... LL | C => {} | ^ From cc492edc9d65125a25a42446bbffefb8087dedf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Nov 2024 02:37:56 +0000 Subject: [PATCH 09/21] Tweak unevaluated constant in pattern error Silence errors that are implied by the errors in the `const` item definition. Add a primary span label. --- compiler/rustc_mir_build/messages.ftl | 1 + compiler/rustc_mir_build/src/errors.rs | 1 + .../src/thir/pattern/const_to_pat.rs | 11 +++++- .../ice-type-mismatch-when-copying-112824.rs | 3 +- ...e-type-mismatch-when-copying-112824.stderr | 13 +------ .../const-eval/const-eval-overflow-2.rs | 3 +- .../const-eval/const-eval-overflow-2.stderr | 11 +----- .../const-eval/ref_to_int_match.64bit.stderr | 11 +----- .../ui/consts/const-eval/ref_to_int_match.rs | 2 +- .../const_refs_to_static_fail_invalid.rs | 6 +-- .../const_refs_to_static_fail_invalid.stderr | 29 +------------- .../invalid-inline-const-in-match-arm.stderr | 2 +- tests/ui/consts/issue-43105.rs | 3 +- tests/ui/consts/issue-43105.stderr | 11 +----- tests/ui/consts/issue-78655.rs | 3 +- tests/ui/consts/issue-78655.stderr | 11 +----- .../const_refers_to_static_cross_crate.rs | 12 ++---- .../const_refers_to_static_cross_crate.stderr | 38 +------------------ tests/ui/consts/missing_assoc_const_type.rs | 5 +-- .../ui/consts/missing_assoc_const_type.stderr | 13 +------ .../transmute-size-mismatch-before-typeck.rs | 2 +- ...ansmute-size-mismatch-before-typeck.stderr | 11 +----- 22 files changed, 37 insertions(+), 165 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index fdefc0bfd190c..ad2f13f6d21ab 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -92,6 +92,7 @@ mir_build_const_pattern_depends_on_generic_parameter = constant pattern depends on a generic parameter mir_build_could_not_eval_const_pattern = could not evaluate constant pattern + .label = could not evaluate constant mir_build_deref_raw_pointer_requires_unsafe = dereference of raw pointer is unsafe and requires unsafe block diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 58487a48184ad..226c469b7d784 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -702,6 +702,7 @@ pub(crate) struct ConstPatternDependsOnGenericParameter { #[diag(mir_build_could_not_eval_const_pattern)] pub(crate) struct CouldNotEvalConstPattern { #[primary_span] + #[label] pub(crate) span: Span, } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index aa98874654edd..3690459bf5151 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -122,7 +122,16 @@ impl<'tcx> ConstToPat<'tcx> { Ok(Ok(c)) => c, Err(ErrorHandled::Reported(_, _)) => { // Let's tell the use where this failing const occurs. - let err = self.tcx.dcx().create_err(CouldNotEvalConstPattern { span: self.span }); + let mut err = + self.tcx.dcx().create_err(CouldNotEvalConstPattern { span: self.span }); + // We've emitted an error on the original const, it would be redundant to complain + // on its use as well. + if let ty::ConstKind::Unevaluated(uv) = self.c.kind() + && let hir::def::DefKind::Const | hir::def::DefKind::AssocConst = + self.tcx.def_kind(uv.def) + { + err.downgrade_to_delayed_bug(); + } return self.mk_err(err, ty); } Err(ErrorHandled::TooGeneric(_)) => { diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs index 09f7e2ba5b1dd..270496d45a6b0 100644 --- a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs +++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs @@ -12,8 +12,7 @@ impl Opcode2 { pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) { move |i| match msg_type { - Opcode2::OP2 => unimplemented!(), - //~^ ERROR: could not evaluate constant pattern + Opcode2::OP2 => unimplemented!(), // ok, `const` already emitted an error } } diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr index 9cce6fee55ac6..d95a8861230e0 100644 --- a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr +++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr @@ -17,18 +17,7 @@ help: you might be missing a type parameter LL | pub struct Opcode2(&'a S); | +++ -error: could not evaluate constant pattern - --> $DIR/ice-type-mismatch-when-copying-112824.rs:15:9 - | -LL | impl Opcode2 { - | ------------ -LL | pub const OP2: Opcode2 = Opcode2(Opcode(0x1)); - | ---------------------- constant defined here -... -LL | Opcode2::OP2 => unimplemented!(), - | ^^^^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0261, E0412. For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/consts/const-eval/const-eval-overflow-2.rs b/tests/ui/consts/const-eval/const-eval-overflow-2.rs index c19a0c443ec58..bae8a7ce243e9 100644 --- a/tests/ui/consts/const-eval/const-eval-overflow-2.rs +++ b/tests/ui/consts/const-eval/const-eval-overflow-2.rs @@ -12,8 +12,7 @@ const NEG_NEG_128: i8 = -NEG_128; //~ ERROR constant fn main() { match -128i8 { - NEG_NEG_128 => println!("A"), - //~^ ERROR could not evaluate constant pattern + NEG_NEG_128 => println!("A"), // ok, `const` error already emitted _ => println!("B"), } } diff --git a/tests/ui/consts/const-eval/const-eval-overflow-2.stderr b/tests/ui/consts/const-eval/const-eval-overflow-2.stderr index 66c54af4f83f6..5599ff931e8e5 100644 --- a/tests/ui/consts/const-eval/const-eval-overflow-2.stderr +++ b/tests/ui/consts/const-eval/const-eval-overflow-2.stderr @@ -4,15 +4,6 @@ error[E0080]: evaluation of constant value failed LL | const NEG_NEG_128: i8 = -NEG_128; | ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow -error: could not evaluate constant pattern - --> $DIR/const-eval-overflow-2.rs:15:9 - | -LL | const NEG_NEG_128: i8 = -NEG_128; - | --------------------- constant defined here -... -LL | NEG_NEG_128 => println!("A"), - | ^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr b/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr index b1c6cfd3246e2..18935626af1ca 100644 --- a/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr +++ b/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr @@ -7,15 +7,6 @@ LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error: could not evaluate constant pattern - --> $DIR/ref_to_int_match.rs:7:14 - | -LL | 10..=BAR => {}, - | ^^^ -... -LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; - | -------------- constant defined here - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ref_to_int_match.rs b/tests/ui/consts/const-eval/ref_to_int_match.rs index c627ad97bb05b..be9420e0215d1 100644 --- a/tests/ui/consts/const-eval/ref_to_int_match.rs +++ b/tests/ui/consts/const-eval/ref_to_int_match.rs @@ -4,7 +4,7 @@ fn main() { let n: Int = 40; match n { 0..=10 => {}, - 10..=BAR => {}, //~ ERROR could not evaluate constant pattern + 10..=BAR => {}, // ok, `const` error already emitted _ => {}, } } diff --git a/tests/ui/consts/const_refs_to_static_fail_invalid.rs b/tests/ui/consts/const_refs_to_static_fail_invalid.rs index a160862a0fa69..aa101cf9d8a62 100644 --- a/tests/ui/consts/const_refs_to_static_fail_invalid.rs +++ b/tests/ui/consts/const_refs_to_static_fail_invalid.rs @@ -11,7 +11,7 @@ fn invalid() { // This must be rejected here (or earlier), since it's not a valid `&bool`. match &true { - C => {} //~ERROR: could not evaluate constant pattern + C => {} // ok, `const` already emitted an error _ => {} } } @@ -27,7 +27,7 @@ fn extern_() { // This must be rejected here (or earlier), since the pattern cannot be read. match &0 { - C => {} //~ERROR: could not evaluate constant pattern + C => {} // ok, `const` already emitted an error _ => {} } } @@ -42,7 +42,7 @@ fn mutable() { // This *must not build*, the constant we are matching against // could change its value! match &42 { - C => {} //~ERROR: could not evaluate constant pattern + C => {} // ok, `const` already emitted an error _ => {} } } diff --git a/tests/ui/consts/const_refs_to_static_fail_invalid.stderr b/tests/ui/consts/const_refs_to_static_fail_invalid.stderr index 9f2633a64d594..c9d5cb60bf779 100644 --- a/tests/ui/consts/const_refs_to_static_fail_invalid.stderr +++ b/tests/ui/consts/const_refs_to_static_fail_invalid.stderr @@ -31,33 +31,6 @@ LL | const C: &i32 = unsafe { &S_MUT }; HEX_DUMP } -error: could not evaluate constant pattern - --> $DIR/const_refs_to_static_fail_invalid.rs:14:9 - | -LL | const C: &bool = unsafe { std::mem::transmute(&S) }; - | -------------- constant defined here -... -LL | C => {} - | ^ - -error: could not evaluate constant pattern - --> $DIR/const_refs_to_static_fail_invalid.rs:30:9 - | -LL | const C: &i8 = unsafe { &S }; - | ------------ constant defined here -... -LL | C => {} - | ^ - -error: could not evaluate constant pattern - --> $DIR/const_refs_to_static_fail_invalid.rs:45:9 - | -LL | const C: &i32 = unsafe { &S_MUT }; - | ------------- constant defined here -... -LL | C => {} - | ^ - -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr index 2e48837bdcdcb..b22f99f40d351 100644 --- a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr +++ b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr @@ -11,7 +11,7 @@ error: could not evaluate constant pattern --> $DIR/invalid-inline-const-in-match-arm.rs:5:9 | LL | const { (|| {})() } => {} - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ could not evaluate constant error: aborting due to 2 previous errors diff --git a/tests/ui/consts/issue-43105.rs b/tests/ui/consts/issue-43105.rs index 20b78d64209e1..a4ee34c0532f3 100644 --- a/tests/ui/consts/issue-43105.rs +++ b/tests/ui/consts/issue-43105.rs @@ -5,8 +5,7 @@ const NUM: u8 = xyz(); fn main() { match 1 { - NUM => unimplemented!(), - //~^ ERROR could not evaluate constant pattern + NUM => unimplemented!(), // ok, the `const` already emitted an error _ => unimplemented!(), } } diff --git a/tests/ui/consts/issue-43105.stderr b/tests/ui/consts/issue-43105.stderr index 4c59bdd4520eb..0e08feb58de9b 100644 --- a/tests/ui/consts/issue-43105.stderr +++ b/tests/ui/consts/issue-43105.stderr @@ -6,15 +6,6 @@ LL | const NUM: u8 = xyz(); | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: could not evaluate constant pattern - --> $DIR/issue-43105.rs:8:9 - | -LL | const NUM: u8 = xyz(); - | ------------- constant defined here -... -LL | NUM => unimplemented!(), - | ^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/issue-78655.rs b/tests/ui/consts/issue-78655.rs index cd95ee32c60d2..b0f862e84181a 100644 --- a/tests/ui/consts/issue-78655.rs +++ b/tests/ui/consts/issue-78655.rs @@ -4,6 +4,5 @@ const FOO: *const u32 = { }; fn main() { - let FOO = FOO; - //~^ ERROR could not evaluate constant pattern + let FOO = FOO; // ok, the `const` already emitted an error } diff --git a/tests/ui/consts/issue-78655.stderr b/tests/ui/consts/issue-78655.stderr index 5d684227be8bf..6a93c1a8cec91 100644 --- a/tests/ui/consts/issue-78655.stderr +++ b/tests/ui/consts/issue-78655.stderr @@ -11,15 +11,6 @@ help: consider assigning a value LL | let x = 42; | ++++ -error: could not evaluate constant pattern - --> $DIR/issue-78655.rs:7:9 - | -LL | const FOO: *const u32 = { - | --------------------- constant defined here -... -LL | let FOO = FOO; - | ^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs index a6d75658c7580..facb21a04ef0b 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs @@ -37,16 +37,14 @@ const U8_MUT3: &u8 = { pub fn test(x: &[u8; 1]) -> bool { match x { - SLICE_MUT => true, - //~^ ERROR could not evaluate constant pattern + SLICE_MUT => true, // ok, `const` error already emitted &[1..] => false, } } pub fn test2(x: &u8) -> bool { match x { - U8_MUT => true, - //~^ ERROR could not evaluate constant pattern + U8_MUT => true, // ok, `const` error already emitted &(1..) => false, } } @@ -55,15 +53,13 @@ pub fn test2(x: &u8) -> bool { // the errors above otherwise stop compilation too early? pub fn test3(x: &u8) -> bool { match x { - U8_MUT2 => true, - //~^ ERROR could not evaluate constant pattern + U8_MUT2 => true, // ok, `const` error already emitted &(1..) => false, } } pub fn test4(x: &u8) -> bool { match x { - U8_MUT3 => true, - //~^ ERROR could not evaluate constant pattern + U8_MUT3 => true, // ok, `const` error already emitted &(1..) => false, } } diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr index 513f456bdf4e6..8f8271cce38e9 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr @@ -37,42 +37,6 @@ error[E0080]: evaluation of constant value failed LL | match static_cross_crate::OPT_ZERO { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses mutable global memory -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:40:9 - | -LL | const SLICE_MUT: &[u8; 1] = { - | ------------------------- constant defined here -... -LL | SLICE_MUT => true, - | ^^^^^^^^^ - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:48:9 - | -LL | const U8_MUT: &u8 = { - | ----------------- constant defined here -... -LL | U8_MUT => true, - | ^^^^^^ - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:58:9 - | -LL | const U8_MUT2: &u8 = { - | ------------------ constant defined here -... -LL | U8_MUT2 => true, - | ^^^^^^^ - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:65:9 - | -LL | const U8_MUT3: &u8 = { - | ------------------ constant defined here -... -LL | U8_MUT3 => true, - | ^^^^^^^ - -error: aborting due to 8 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/missing_assoc_const_type.rs b/tests/ui/consts/missing_assoc_const_type.rs index 633998e9bc157..61042bfa96d08 100644 --- a/tests/ui/consts/missing_assoc_const_type.rs +++ b/tests/ui/consts/missing_assoc_const_type.rs @@ -9,14 +9,13 @@ trait Range { struct TwoDigits; impl Range for TwoDigits { - const FIRST: = 10; - //~^ ERROR: missing type for `const` item + const FIRST: = 10; //~ ERROR missing type for `const` item const LAST: u8 = 99; } const fn digits(x: u8) -> usize { match x { - TwoDigits::FIRST..=TwoDigits::LAST => 0, //~ ERROR: could not evaluate constant pattern + TwoDigits::FIRST..=TwoDigits::LAST => 0, // ok, `const` error already emitted 0..=9 | 100..=255 => panic!(), } } diff --git a/tests/ui/consts/missing_assoc_const_type.stderr b/tests/ui/consts/missing_assoc_const_type.stderr index 8123a43ef74fe..28af1f0f321e6 100644 --- a/tests/ui/consts/missing_assoc_const_type.stderr +++ b/tests/ui/consts/missing_assoc_const_type.stderr @@ -4,16 +4,5 @@ error: missing type for `const` item LL | const FIRST: = 10; | ^ help: provide a type for the associated constant: `u8` -error: could not evaluate constant pattern - --> $DIR/missing_assoc_const_type.rs:19:9 - | -LL | trait Range { - | ----------- -LL | const FIRST: u8; - | --------------- constant defined here -... -LL | TwoDigits::FIRST..=TwoDigits::LAST => 0, - | ^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/consts/transmute-size-mismatch-before-typeck.rs b/tests/ui/consts/transmute-size-mismatch-before-typeck.rs index 44eac5b16cc0b..ffb143da2d48b 100644 --- a/tests/ui/consts/transmute-size-mismatch-before-typeck.rs +++ b/tests/ui/consts/transmute-size-mismatch-before-typeck.rs @@ -5,7 +5,7 @@ fn main() { match &b""[..] { - ZST => {} //~ ERROR: could not evaluate constant pattern + ZST => {} // ok, `const` error already emitted } } diff --git a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr index 79f59ba865d8d..6bc7e7203aa74 100644 --- a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr +++ b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr @@ -7,15 +7,6 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; = note: source type: `usize` (word size) = note: target type: `&[u8]` (2 * word size) -error: could not evaluate constant pattern - --> $DIR/transmute-size-mismatch-before-typeck.rs:8:9 - | -LL | ZST => {} - | ^^^ -... -LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; - | ---------------- constant defined here - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0512`. From c0f00086f85ae1fff34dd2daf6a11850e5bfc2f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Nov 2024 03:00:58 +0000 Subject: [PATCH 10/21] Tweak ptr in pattern error Conform to error style guide. --- compiler/rustc_mir_build/messages.ftl | 4 +- compiler/rustc_mir_build/src/errors.rs | 2 + src/tools/tidy/src/fluent_period.rs | 1 - ...ssue-34784-match-on-non-int-raw-ptr.stderr | 24 +++++--- .../const_in_pattern/issue-44333.stderr | 12 ++-- .../pattern/usefulness/consts-opaque.stderr | 48 ++++++++++----- ...n-ptr-is-not-structurally-matchable.stderr | 60 ++++++++++++------- .../issue-63479-match-fnptr.stderr | 12 ++-- 8 files changed, 109 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index ad2f13f6d21ab..2bf49137e8f8c 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -274,7 +274,9 @@ mir_build_non_partial_eq_match = mir_build_pattern_not_covered = refutable pattern in {$origin} .pattern_ty = the matched value is of type `{$pattern_ty}` -mir_build_pointer_pattern = function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +mir_build_pointer_pattern = function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon + .label = can't be used in patterns + .note = see https://github.com/rust-lang/rust/issues/70861 for details mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 226c469b7d784..7f4bb139fad2c 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -916,8 +916,10 @@ pub(crate) struct NaNPattern { #[derive(Diagnostic)] #[diag(mir_build_pointer_pattern)] +#[note] pub(crate) struct PointerPattern { #[primary_span] + #[label] pub(crate) span: Span, } diff --git a/src/tools/tidy/src/fluent_period.rs b/src/tools/tidy/src/fluent_period.rs index 8bc404dc8581a..6a136e5aec698 100644 --- a/src/tools/tidy/src/fluent_period.rs +++ b/src/tools/tidy/src/fluent_period.rs @@ -18,7 +18,6 @@ const ALLOWLIST: &[&str] = &[ "const_eval_validation_failure_note", "driver_impl_ice", "incremental_corrupt_file", - "mir_build_pointer_pattern", ]; fn check_period(filename: &str, contents: &str, bad: &mut bool) { diff --git a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr index cc7ec771e6cd6..0453a88e43db9 100644 --- a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr @@ -1,38 +1,46 @@ -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:9:9 | LL | const C: *const u8 = &0; | ------------------ constant defined here ... LL | C => {} - | ^ + | ^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:16:9 | LL | const C_INNER: (*const u8, u8) = (C, 0); | ------------------------------ constant defined here ... LL | C_INNER => {} - | ^^^^^^^ + | ^^^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:27:9 | LL | const D: *const [u8; 4] = b"abcd"; | ----------------------- constant defined here ... LL | D => {} - | ^ + | ^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:32:9 | LL | const STR: *const str = "abcd"; | --------------------- constant defined here ... LL | STR => {} - | ^^^ + | ^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details error: aborting due to 4 previous errors diff --git a/tests/ui/consts/const_in_pattern/issue-44333.stderr b/tests/ui/consts/const_in_pattern/issue-44333.stderr index 81393952f0fcf..61b45377c7610 100644 --- a/tests/ui/consts/const_in_pattern/issue-44333.stderr +++ b/tests/ui/consts/const_in_pattern/issue-44333.stderr @@ -1,20 +1,24 @@ -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-44333.rs:15:9 | LL | const FOO: Func = foo; | --------------- constant defined here ... LL | FOO => println!("foo"), - | ^^^ + | ^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-44333.rs:16:9 | LL | const BAR: Func = bar; | --------------- constant defined here ... LL | BAR => println!("bar"), - | ^^^ + | ^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index 15aa1769662cd..d52451d9438a1 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -1,74 +1,90 @@ -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:96:9 | LL | const QUUX: Quux = quux; | ---------------- constant defined here ... LL | QUUX => {} - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:97:9 | LL | const QUUX: Quux = quux; | ---------------- constant defined here ... LL | QUUX => {} - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:106:9 | LL | const WRAPQUUX: Wrap = Wrap(quux); | -------------------------- constant defined here ... LL | WRAPQUUX => {} - | ^^^^^^^^ + | ^^^^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:107:9 | LL | const WRAPQUUX: Wrap = Wrap(quux); | -------------------------- constant defined here ... LL | WRAPQUUX => {} - | ^^^^^^^^ + | ^^^^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:113:9 | LL | const WRAPQUUX: Wrap = Wrap(quux); | -------------------------- constant defined here ... LL | WRAPQUUX => {} - | ^^^^^^^^ + | ^^^^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:121:9 | LL | const WRAPQUUX: Wrap = Wrap(quux); | -------------------------- constant defined here ... LL | WRAPQUUX => {} - | ^^^^^^^^ + | ^^^^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:132:9 | LL | const WHOKNOWSQUUX: WhoKnows = WhoKnows::Yay(quux); | ---------------------------------- constant defined here ... LL | WHOKNOWSQUUX => {} - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:134:9 | LL | const WHOKNOWSQUUX: WhoKnows = WhoKnows::Yay(quux); | ---------------------------------- constant defined here ... LL | WHOKNOWSQUUX => {} - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details error: unreachable pattern --> $DIR/consts-opaque.rs:48:9 diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr index ee6f44a364da4..cdbe72ca48f8f 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr @@ -1,92 +1,112 @@ -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:41:14 | LL | const CFN1: Wrap = Wrap(trivial); | ---------------------- constant defined here ... LL | Wrap(CFN1) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:49:14 | LL | const CFN2: Wrap = Wrap(sm_to); | ------------------------ constant defined here ... LL | Wrap(CFN2) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:57:14 | LL | const CFN3: Wrap SM> = Wrap(to_sm); | ---------------------------- constant defined here ... LL | Wrap(CFN3) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:65:14 | LL | const CFN4: Wrap = Wrap(not_sm_to); | --------------------------- constant defined here ... LL | Wrap(CFN4) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:73:14 | LL | const CFN5: Wrap NotSM> = Wrap(to_not_sm); | ------------------------------- constant defined here ... LL | Wrap(CFN5) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:81:14 | LL | const CFN6: Wrap = Wrap(r_sm_to); | ------------------------- constant defined here ... LL | Wrap(CFN6) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:89:14 | LL | const CFN7: Wrap &SM> = Wrap(r_to_r_sm); | -------------------------------- constant defined here ... LL | Wrap(CFN7) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:97:14 | LL | const CFN8: Wrap = Wrap(r_not_sm_to); | ---------------------------- constant defined here ... LL | Wrap(CFN8) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:105:14 | LL | const CFN9: Wrap &NotSM> = Wrap(r_to_r_not_sm); | ----------------------------------- constant defined here ... LL | Wrap(CFN9) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:127:9 | LL | const CFOO: Foo = Foo { | --------------- constant defined here ... LL | CFOO => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details error: aborting due to 10 previous errors diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr index be735ccab0a5a..ea6121839be5e 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr @@ -1,20 +1,24 @@ -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-63479-match-fnptr.rs:32:7 | LL | const TEST: Fn = my_fn; | -------------- constant defined here ... LL | B(TEST) => println!("matched"), - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-63479-match-fnptr.rs:37:5 | LL | const TEST2: (Fn, u8) = (TEST, 0); | --------------------- constant defined here ... LL | TEST2 => println!("matched"), - | ^^^^^ + | ^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details error: aborting due to 2 previous errors From 87ddc1ea33edbe1be119d73e57c2783940e797fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Nov 2024 03:08:52 +0000 Subject: [PATCH 11/21] Point at generic param through which a const is used in a pattern ``` error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/associated-const-type-parameter-pattern.rs:20:9 | LL | pub trait Foo { | ------------- LL | const X: EFoo; | ------------- constant defined here ... LL | pub fn test(arg: EFoo) { | - constant depends on this generic param LL | match arg { LL | A::X => println!("A::X"), | ^^^^ `const` depends on a generic parameter ``` --- compiler/rustc_mir_build/messages.ftl | 4 +-- compiler/rustc_mir_build/src/errors.rs | 1 + .../src/thir/pattern/const_to_pat.rs | 22 ++++++++++++++- ...ciated-const-type-parameter-pattern.stderr | 27 +++++++++++++------ .../ui/consts/issue-73976-polymorphic.stderr | 12 ++++++--- tests/ui/consts/issue-79137-toogeneric.stderr | 6 +++-- .../const-match-pat-generic.stderr | 8 +++--- 7 files changed, 59 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 2bf49137e8f8c..4bc7dcf956467 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -88,8 +88,8 @@ mir_build_const_defined_here = constant defined here mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns -mir_build_const_pattern_depends_on_generic_parameter = - constant pattern depends on a generic parameter +mir_build_const_pattern_depends_on_generic_parameter = constant pattern depends on a generic parameter, which is not allowed + .label = `const` depends on a generic parameter mir_build_could_not_eval_const_pattern = could not evaluate constant pattern .label = could not evaluate constant diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 7f4bb139fad2c..1068c56eeca61 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -695,6 +695,7 @@ pub(crate) struct WantedConstant { #[diag(mir_build_const_pattern_depends_on_generic_parameter, code = E0158)] pub(crate) struct ConstPatternDependsOnGenericParameter { #[primary_span] + #[label] pub(crate) span: Span, } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 3690459bf5151..b625c655fac42 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -53,6 +53,7 @@ struct ConstToPat<'tcx> { tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, span: Span, + id: hir::HirId, treat_byte_string_as_slice: bool, @@ -66,6 +67,7 @@ impl<'tcx> ConstToPat<'tcx> { tcx: pat_ctxt.tcx, typing_env: pat_ctxt.typing_env, span, + id, treat_byte_string_as_slice: pat_ctxt .typeck_results .treat_byte_string_as_slice @@ -135,10 +137,28 @@ impl<'tcx> ConstToPat<'tcx> { return self.mk_err(err, ty); } Err(ErrorHandled::TooGeneric(_)) => { - let e = self + let mut e = self .tcx .dcx() .create_err(ConstPatternDependsOnGenericParameter { span: self.span }); + for arg in uv.args { + if let ty::GenericArgKind::Type(ty) = arg.unpack() + && let ty::Param(param_ty) = ty.kind() + { + let def_id = self.tcx.hir().enclosing_body_owner(self.id); + let generics = self.tcx.generics_of(def_id); + let param = generics.type_param(*param_ty, self.tcx); + let span = self.tcx.def_span(param.def_id); + e.span_label(span, "constant depends on this generic param"); + if let Some(ident) = self.tcx.def_ident_span(def_id) + && self.tcx.sess.source_map().is_multiline(ident.between(span)) + { + // Display the `fn` name as well in the diagnostic, as the generic isn't + // in the same line and it could be confusing otherwise. + e.span_label(ident, ""); + } + } + } return self.mk_err(e, ty); } Ok(Err(bad_ty)) => { diff --git a/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr b/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr index 5aef0fa414bd4..455831e8401cb 100644 --- a/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr +++ b/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr @@ -1,4 +1,4 @@ -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/associated-const-type-parameter-pattern.rs:20:9 | LL | pub trait Foo { @@ -6,10 +6,13 @@ LL | pub trait Foo { LL | const X: EFoo; | ------------- constant defined here ... +LL | pub fn test(arg: EFoo) { + | - constant depends on this generic param +LL | match arg { LL | A::X => println!("A::X"), - | ^^^^ + | ^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/associated-const-type-parameter-pattern.rs:22:9 | LL | pub trait Foo { @@ -17,10 +20,13 @@ LL | pub trait Foo { LL | const X: EFoo; | ------------- constant defined here ... +LL | pub fn test(arg: EFoo) { + | - constant depends on this generic param +... LL | B::X => println!("B::X"), - | ^^^^ + | ^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/associated-const-type-parameter-pattern.rs:30:9 | LL | pub trait Foo { @@ -28,10 +34,13 @@ LL | pub trait Foo { LL | const X: EFoo; | ------------- constant defined here ... +LL | pub fn test_let_pat(arg: EFoo, A::X: EFoo) { + | - constant depends on this generic param +LL | LL | let A::X = arg; - | ^^^^ + | ^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/associated-const-type-parameter-pattern.rs:28:48 | LL | pub trait Foo { @@ -40,7 +49,9 @@ LL | const X: EFoo; | ------------- constant defined here ... LL | pub fn test_let_pat(arg: EFoo, A::X: EFoo) { - | ^^^^ + | - ^^^^ `const` depends on a generic parameter + | | + | constant depends on this generic param error: aborting due to 4 previous errors diff --git a/tests/ui/consts/issue-73976-polymorphic.stderr b/tests/ui/consts/issue-73976-polymorphic.stderr index 79a03d4ec32c9..2f50e6ac2fd42 100644 --- a/tests/ui/consts/issue-73976-polymorphic.stderr +++ b/tests/ui/consts/issue-73976-polymorphic.stderr @@ -1,4 +1,4 @@ -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/issue-73976-polymorphic.rs:20:37 | LL | impl GetTypeId { @@ -6,10 +6,12 @@ LL | impl GetTypeId { LL | pub const VALUE: TypeId = TypeId::of::(); | ----------------------- constant defined here ... +LL | const fn check_type_id() -> bool { + | - constant depends on this generic param LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/issue-73976-polymorphic.rs:31:42 | LL | impl GetTypeNameLen { @@ -17,8 +19,10 @@ LL | impl GetTypeNameLen { LL | pub const VALUE: usize = any::type_name::().len(); | ---------------------- constant defined here ... +LL | const fn check_type_name_len() -> bool { + | - constant depends on this generic param LL | matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `const` depends on a generic parameter error: aborting due to 2 previous errors diff --git a/tests/ui/consts/issue-79137-toogeneric.stderr b/tests/ui/consts/issue-79137-toogeneric.stderr index 9b53a2595479d..d36f3ecbb7690 100644 --- a/tests/ui/consts/issue-79137-toogeneric.stderr +++ b/tests/ui/consts/issue-79137-toogeneric.stderr @@ -1,4 +1,4 @@ -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/issue-79137-toogeneric.rs:12:43 | LL | impl GetVariantCount { @@ -6,8 +6,10 @@ LL | impl GetVariantCount { LL | pub const VALUE: usize = std::mem::variant_count::(); | ---------------------- constant defined here ... +LL | const fn check_variant_count() -> bool { + | - constant depends on this generic param LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `const` depends on a generic parameter error: aborting due to 1 previous error diff --git a/tests/ui/inline-const/const-match-pat-generic.stderr b/tests/ui/inline-const/const-match-pat-generic.stderr index 26f72b34eca29..cf48161b5e3d6 100644 --- a/tests/ui/inline-const/const-match-pat-generic.stderr +++ b/tests/ui/inline-const/const-match-pat-generic.stderr @@ -1,14 +1,14 @@ -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/const-match-pat-generic.rs:7:9 | LL | const { V } => {}, - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter +error[E0158]: constant pattern depends on a generic parameter, which is not allowed --> $DIR/const-match-pat-generic.rs:19:9 | LL | const { f(V) } => {}, - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ `const` depends on a generic parameter error: aborting due to 2 previous errors From 253eb95d4582e1abffc4a74dd8eaccd5b94b5d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Nov 2024 03:57:30 +0000 Subject: [PATCH 12/21] Tweak output of some const pattern errors - Add primary span labels. - Point at const generic parameter used as pattern. - Point at statics used as pattern. - Point at let bindings used in const pattern. --- compiler/rustc_mir_build/messages.ftl | 10 +++++++++- compiler/rustc_mir_build/src/errors.rs | 10 ++++++++++ compiler/rustc_mir_build/src/thir/pattern/mod.rs | 14 ++++++++++---- tests/ui/binding/const-param.rs | 2 +- tests/ui/binding/const-param.stderr | 7 +++++-- .../ui/consts/const_in_pattern/issue-65466.stderr | 2 +- .../const_in_pattern/reject_non_partial_eq.stderr | 2 +- .../match/issue-72896-non-partial-eq-const.stderr | 2 +- tests/ui/pattern/non-constant-in-const-path.stderr | 14 ++++++++++---- ...e-61188-match-slice-forbidden-without-eq.stderr | 2 +- .../issue-6804-nan-match.stderr | 14 +++++++------- tests/ui/union/union-const-pat.stderr | 2 +- 12 files changed, 57 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 4bc7dcf956467..28011833e5869 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -86,7 +86,9 @@ mir_build_confused = missing patterns are not covered because `{$variable}` is i mir_build_const_defined_here = constant defined here -mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns +mir_build_const_param_in_pattern = constant parameters cannot be referenced in patterns + .label = can't be used in patterns +mir_build_const_param_in_pattern_def = constant defined here mir_build_const_pattern_depends_on_generic_parameter = constant pattern depends on a generic parameter, which is not allowed .label = `const` depends on a generic parameter @@ -247,10 +249,12 @@ mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsa .label = mutation of layout constrained field mir_build_nan_pattern = cannot use NaN in patterns + .label = evaluates to `NaN`, which is not allowed in patterns .note = NaNs compare inequal to everything, even themselves, so this pattern would never match .help = try using the `is_nan` method instead mir_build_non_const_path = runtime values cannot be referenced in patterns + .label = references a runtime value mir_build_non_empty_never_pattern = mismatched types @@ -270,6 +274,7 @@ mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type mir_build_non_partial_eq_match = to use a constant of type `{$non_peq_ty}` in a pattern, the type must implement `PartialEq` + .label = constant of non-structural type mir_build_pattern_not_covered = refutable pattern in {$origin} .pattern_ty = the matched value is of type `{$pattern_ty}` @@ -288,6 +293,8 @@ mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly .missing_box = `#[rustc_box]` requires the `owned_box` lang item mir_build_static_in_pattern = statics cannot be referenced in patterns + .label = can't be used in patterns +mir_build_static_in_pattern_def = `static` defined here mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits @@ -339,6 +346,7 @@ mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = .label = access to union field mir_build_union_pattern = cannot use unions in constant patterns + .label = can't use a `union` here mir_build_unreachable_making_this_unreachable = collectively making this unreachable diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 1068c56eeca61..1c4de5c07a13e 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -631,20 +631,27 @@ pub(crate) struct NonExhaustiveMatchAllArmsGuarded; #[diag(mir_build_static_in_pattern, code = E0158)] pub(crate) struct StaticInPattern { #[primary_span] + #[label] pub(crate) span: Span, + #[label(mir_build_static_in_pattern_def)] + pub(crate) static_span: Span, } #[derive(Diagnostic)] #[diag(mir_build_const_param_in_pattern, code = E0158)] pub(crate) struct ConstParamInPattern { #[primary_span] + #[label] pub(crate) span: Span, + #[label(mir_build_const_param_in_pattern_def)] + pub(crate) const_span: Span, } #[derive(Diagnostic)] #[diag(mir_build_non_const_path, code = E0080)] pub(crate) struct NonConstPath { #[primary_span] + #[label] pub(crate) span: Span, } @@ -869,6 +876,7 @@ pub(crate) enum Conflict { #[diag(mir_build_union_pattern)] pub(crate) struct UnionPattern { #[primary_span] + #[label] pub(crate) span: Span, } @@ -886,6 +894,7 @@ pub(crate) struct TypeNotStructural<'tcx> { #[diag(mir_build_non_partial_eq_match)] pub(crate) struct TypeNotPartialEq<'tcx> { #[primary_span] + #[label] pub(crate) span: Span, pub(crate) non_peq_ty: Ty<'tcx>, } @@ -912,6 +921,7 @@ pub(crate) struct UnsizedPattern<'tcx> { #[help] pub(crate) struct NaNPattern { #[primary_span] + #[label] pub(crate) span: Span, } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 08c6b4abd3b91..3ac53fa6272be 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -528,11 +528,17 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { | Res::SelfCtor(..) => PatKind::Leaf { subpatterns }, _ => { let e = match res { - Res::Def(DefKind::ConstParam, _) => { - self.tcx.dcx().emit_err(ConstParamInPattern { span }) + Res::Def(DefKind::ConstParam, def_id) => { + self.tcx.dcx().emit_err(ConstParamInPattern { + span, + const_span: self.tcx().def_span(def_id), + }) } - Res::Def(DefKind::Static { .. }, _) => { - self.tcx.dcx().emit_err(StaticInPattern { span }) + Res::Def(DefKind::Static { .. }, def_id) => { + self.tcx.dcx().emit_err(StaticInPattern { + span, + static_span: self.tcx().def_span(def_id), + }) } _ => self.tcx.dcx().emit_err(NonConstPath { span }), }; diff --git a/tests/ui/binding/const-param.rs b/tests/ui/binding/const-param.rs index 2d051808fe0be..98bc90f508ab2 100644 --- a/tests/ui/binding/const-param.rs +++ b/tests/ui/binding/const-param.rs @@ -2,7 +2,7 @@ fn check() { match 1 { - N => {} //~ ERROR const parameters cannot be referenced in patterns + N => {} //~ ERROR constant parameters cannot be referenced in patterns _ => {} } } diff --git a/tests/ui/binding/const-param.stderr b/tests/ui/binding/const-param.stderr index e68893a59e499..b0b8108945c98 100644 --- a/tests/ui/binding/const-param.stderr +++ b/tests/ui/binding/const-param.stderr @@ -1,8 +1,11 @@ -error[E0158]: const parameters cannot be referenced in patterns +error[E0158]: constant parameters cannot be referenced in patterns --> $DIR/const-param.rs:5:9 | +LL | fn check() { + | -------------- constant defined here +LL | match 1 { LL | N => {} - | ^ + | ^ can't be used in patterns error: aborting due to 1 previous error diff --git a/tests/ui/consts/const_in_pattern/issue-65466.stderr b/tests/ui/consts/const_in_pattern/issue-65466.stderr index 070ce384f6aad..90bac6262cc9d 100644 --- a/tests/ui/consts/const_in_pattern/issue-65466.stderr +++ b/tests/ui/consts/const_in_pattern/issue-65466.stderr @@ -5,7 +5,7 @@ LL | const C: &[O] = &[O::None]; | ---------------- constant defined here ... LL | C => (), - | ^ + | ^ constant of non-structural type error: aborting due to 1 previous error diff --git a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr index 463b37e7caa73..d4952a8bfb8c6 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr @@ -5,7 +5,7 @@ LL | const NO_PARTIAL_EQ_NONE: Option = None; | --------------------------------------------- constant defined here ... LL | NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"), - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ constant of non-structural type error: aborting due to 1 previous error diff --git a/tests/ui/match/issue-72896-non-partial-eq-const.stderr b/tests/ui/match/issue-72896-non-partial-eq-const.stderr index eeca541fc3cd8..d6ae9e56377d5 100644 --- a/tests/ui/match/issue-72896-non-partial-eq-const.stderr +++ b/tests/ui/match/issue-72896-non-partial-eq-const.stderr @@ -5,7 +5,7 @@ LL | const CONST_SET: EnumSet = EnumSet { __enumset_underlying: 3 }; | ------------------------------- constant defined here ... LL | CONST_SET => { /* ok */ } - | ^^^^^^^^^ + | ^^^^^^^^^ constant of non-structural type error: aborting due to 1 previous error diff --git a/tests/ui/pattern/non-constant-in-const-path.stderr b/tests/ui/pattern/non-constant-in-const-path.stderr index 53c3974f780e4..2ba4963e6dc2d 100644 --- a/tests/ui/pattern/non-constant-in-const-path.stderr +++ b/tests/ui/pattern/non-constant-in-const-path.stderr @@ -2,25 +2,31 @@ error[E0080]: runtime values cannot be referenced in patterns --> $DIR/non-constant-in-const-path.rs:8:15 | LL | let 0u8..=x = 0; - | ^ + | ^ references a runtime value error[E0158]: statics cannot be referenced in patterns --> $DIR/non-constant-in-const-path.rs:10:15 | +LL | static FOO: u8 = 10; + | -------------- `static` defined here +... LL | let 0u8..=FOO = 0; - | ^^^ + | ^^^ can't be used in patterns error[E0080]: runtime values cannot be referenced in patterns --> $DIR/non-constant-in-const-path.rs:13:15 | LL | 0 ..= x => {} - | ^ + | ^ references a runtime value error[E0158]: statics cannot be referenced in patterns --> $DIR/non-constant-in-const-path.rs:15:15 | +LL | static FOO: u8 = 10; + | -------------- `static` defined here +... LL | 0 ..= FOO => {} - | ^^^ + | ^^^ can't be used in patterns error: aborting due to 4 previous errors diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr index e105c6a1f98a9..51bcfc07c9e01 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr @@ -5,7 +5,7 @@ LL | const A: &[B] = &[]; | ------------- constant defined here ... LL | A => (), - | ^ + | ^ constant of non-structural type error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr index 4e2dcb52da807..7c49870e5d03d 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr @@ -5,7 +5,7 @@ LL | const NAN: f64 = f64::NAN; | -------------- constant defined here ... LL | NAN => {}, - | ^^^ + | ^^^ evaluates to `NaN`, which is not allowed in patterns | = note: NaNs compare inequal to everything, even themselves, so this pattern would never match = help: try using the `is_nan` method instead @@ -17,7 +17,7 @@ LL | const NAN: f64 = f64::NAN; | -------------- constant defined here ... LL | [NAN, _] => {}, - | ^^^ + | ^^^ evaluates to `NaN`, which is not allowed in patterns | = note: NaNs compare inequal to everything, even themselves, so this pattern would never match = help: try using the `is_nan` method instead @@ -29,7 +29,7 @@ LL | const C: MyType = MyType(f32::NAN); | -------------------- constant defined here ... LL | C => {}, - | ^ + | ^ evaluates to `NaN`, which is not allowed in patterns | = note: NaNs compare inequal to everything, even themselves, so this pattern would never match = help: try using the `is_nan` method instead @@ -41,7 +41,7 @@ LL | const NAN: f64 = f64::NAN; | -------------- constant defined here ... LL | NAN..=1.0 => {}, - | ^^^ + | ^^^ evaluates to `NaN`, which is not allowed in patterns | = note: NaNs compare inequal to everything, even themselves, so this pattern would never match = help: try using the `is_nan` method instead @@ -53,7 +53,7 @@ LL | const NAN: f64 = f64::NAN; | -------------- constant defined here ... LL | -1.0..=NAN => {}, - | ^^^ + | ^^^ evaluates to `NaN`, which is not allowed in patterns | = note: NaNs compare inequal to everything, even themselves, so this pattern would never match = help: try using the `is_nan` method instead @@ -65,7 +65,7 @@ LL | const NAN: f64 = f64::NAN; | -------------- constant defined here ... LL | NAN.. => {}, - | ^^^ + | ^^^ evaluates to `NaN`, which is not allowed in patterns | = note: NaNs compare inequal to everything, even themselves, so this pattern would never match = help: try using the `is_nan` method instead @@ -77,7 +77,7 @@ LL | const NAN: f64 = f64::NAN; | -------------- constant defined here ... LL | ..NAN => {}, - | ^^^ + | ^^^ evaluates to `NaN`, which is not allowed in patterns | = note: NaNs compare inequal to everything, even themselves, so this pattern would never match = help: try using the `is_nan` method instead diff --git a/tests/ui/union/union-const-pat.stderr b/tests/ui/union/union-const-pat.stderr index baf32bf484950..59dc89c77a47c 100644 --- a/tests/ui/union/union-const-pat.stderr +++ b/tests/ui/union/union-const-pat.stderr @@ -5,7 +5,7 @@ LL | const C: U = U { a: 10 }; | ---------- constant defined here ... LL | C => {} - | ^ + | ^ can't use a `union` here error: aborting due to 1 previous error From a6040bc230bc7b26f413d7fbf60402e6e7940192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Nov 2024 04:06:39 +0000 Subject: [PATCH 13/21] Specify type kind of constant that can't be used in patterns ``` error: trait object `dyn Send` cannot be used in patterns --> $DIR/issue-70972-dyn-trait.rs:6:9 | LL | const F: &'static dyn Send = &7u32; | -------------------------- constant defined here ... LL | F => panic!(), | ^ trait object can't be used in patterns ``` --- compiler/rustc_mir_build/messages.ftl | 3 ++- compiler/rustc_mir_build/src/errors.rs | 2 ++ .../src/thir/pattern/const_to_pat.rs | 15 ++++++++++----- tests/ui/inline-const/pat-match-fndef.stderr | 4 ++-- tests/ui/match/issue-70972-dyn-trait.stderr | 4 ++-- tests/ui/pattern/issue-72565.stderr | 4 ++-- .../ui/pattern/non-structural-match-types.stderr | 8 ++++---- .../structural-match-no-leak.stderr | 4 ++-- .../type-alias-impl-trait/structural-match.stderr | 4 ++-- 9 files changed, 28 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 28011833e5869..1e6b32bf60557 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -152,7 +152,8 @@ mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = mir_build_interpreted_as_const = introduce a variable instead -mir_build_invalid_pattern = `{$non_sm_ty}` cannot be used in patterns +mir_build_invalid_pattern = {$prefix} `{$non_sm_ty}` cannot be used in patterns + .label = {$prefix} can't be used in patterns mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count -> [one] pattern diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 1c4de5c07a13e..2741830c62d0f 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -903,8 +903,10 @@ pub(crate) struct TypeNotPartialEq<'tcx> { #[diag(mir_build_invalid_pattern)] pub(crate) struct InvalidPattern<'tcx> { #[primary_span] + #[label] pub(crate) span: Span, pub(crate) non_sm_ty: Ty<'tcx>, + pub(crate) prefix: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index b625c655fac42..71cef18e3161b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -171,10 +171,11 @@ impl<'tcx> ConstToPat<'tcx> { ty::FnPtr(..) | ty::RawPtr(..) => { self.tcx.dcx().create_err(PointerPattern { span: self.span }) } - _ => self - .tcx - .dcx() - .create_err(InvalidPattern { span: self.span, non_sm_ty: bad_ty }), + _ => self.tcx.dcx().create_err(InvalidPattern { + span: self.span, + non_sm_ty: bad_ty, + prefix: bad_ty.prefix_string(self.tcx).to_string(), + }), }; return self.mk_err(e, ty); } @@ -373,7 +374,11 @@ impl<'tcx> ConstToPat<'tcx> { ) } _ => { - let err = InvalidPattern { span, non_sm_ty: ty }; + let err = InvalidPattern { + span, + non_sm_ty: ty, + prefix: ty.prefix_string(self.tcx).to_string(), + }; return Err(tcx.dcx().create_err(err)); } }; diff --git a/tests/ui/inline-const/pat-match-fndef.stderr b/tests/ui/inline-const/pat-match-fndef.stderr index b189ec51ade38..220437a0491af 100644 --- a/tests/ui/inline-const/pat-match-fndef.stderr +++ b/tests/ui/inline-const/pat-match-fndef.stderr @@ -1,8 +1,8 @@ -error: `fn() {uwu}` cannot be used in patterns +error: fn item `fn() {uwu}` cannot be used in patterns --> $DIR/pat-match-fndef.rs:8:9 | LL | const { uwu } => {} - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ fn item can't be used in patterns error: aborting due to 1 previous error diff --git a/tests/ui/match/issue-70972-dyn-trait.stderr b/tests/ui/match/issue-70972-dyn-trait.stderr index 91f49c8a2ff10..cec9c8539f416 100644 --- a/tests/ui/match/issue-70972-dyn-trait.stderr +++ b/tests/ui/match/issue-70972-dyn-trait.stderr @@ -1,11 +1,11 @@ -error: `dyn Send` cannot be used in patterns +error: trait object `dyn Send` cannot be used in patterns --> $DIR/issue-70972-dyn-trait.rs:6:9 | LL | const F: &'static dyn Send = &7u32; | -------------------------- constant defined here ... LL | F => panic!(), - | ^ + | ^ trait object can't be used in patterns error: aborting due to 1 previous error diff --git a/tests/ui/pattern/issue-72565.stderr b/tests/ui/pattern/issue-72565.stderr index abfd4512e9b8e..e2927ada0f70b 100644 --- a/tests/ui/pattern/issue-72565.stderr +++ b/tests/ui/pattern/issue-72565.stderr @@ -1,11 +1,11 @@ -error: `dyn PartialEq` cannot be used in patterns +error: trait object `dyn PartialEq` cannot be used in patterns --> $DIR/issue-72565.rs:6:9 | LL | const F: &'static dyn PartialEq = &7u32; | ------------------------------------ constant defined here ... LL | F => panic!(), - | ^ + | ^ trait object can't be used in patterns error: aborting due to 1 previous error diff --git a/tests/ui/pattern/non-structural-match-types.stderr b/tests/ui/pattern/non-structural-match-types.stderr index 9075cf40ddae9..3588751bf6687 100644 --- a/tests/ui/pattern/non-structural-match-types.stderr +++ b/tests/ui/pattern/non-structural-match-types.stderr @@ -1,14 +1,14 @@ -error: `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used in patterns +error: closure `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used in patterns --> $DIR/non-structural-match-types.rs:9:9 | LL | const { || {} } => {} - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ closure can't be used in patterns -error: `{async block@$DIR/non-structural-match-types.rs:12:17: 12:22}` cannot be used in patterns +error: `async` block `{async block@$DIR/non-structural-match-types.rs:12:17: 12:22}` cannot be used in patterns --> $DIR/non-structural-match-types.rs:12:9 | LL | const { async {} } => {} - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ `async` block can't be used in patterns error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr b/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr index 743ad75628e25..28f5d6728a9de 100644 --- a/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr +++ b/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr @@ -1,11 +1,11 @@ -error: `Bar` cannot be used in patterns +error: opaque type `Bar` cannot be used in patterns --> $DIR/structural-match-no-leak.rs:16:9 | LL | const LEAK_FREE: bar::Bar = bar::leak_free(); | ------------------------- constant defined here ... LL | LEAK_FREE => (), - | ^^^^^^^^^ + | ^^^^^^^^^ opaque type can't be used in patterns error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/structural-match.stderr b/tests/ui/type-alias-impl-trait/structural-match.stderr index 9c26aa9a9a645..b06b31a060fb9 100644 --- a/tests/ui/type-alias-impl-trait/structural-match.stderr +++ b/tests/ui/type-alias-impl-trait/structural-match.stderr @@ -1,11 +1,11 @@ -error: `foo::Foo` cannot be used in patterns +error: opaque type `foo::Foo` cannot be used in patterns --> $DIR/structural-match.rs:18:9 | LL | const VALUE: Foo = value(); | ---------------- constant defined here ... LL | VALUE => (), - | ^^^^^ + | ^^^^^ opaque type can't be used in patterns error: aborting due to 1 previous error From fb2f6a44c05c017139ef0266683fdfe3c66c4220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Nov 2024 04:15:37 +0000 Subject: [PATCH 14/21] Reword message for non-structural type constant in pattern --- compiler/rustc_mir_build/messages.ftl | 3 +-- tests/ui/consts/const_in_pattern/issue-65466.rs | 2 +- tests/ui/consts/const_in_pattern/issue-65466.stderr | 2 +- tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs | 2 +- tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr | 2 +- tests/ui/match/issue-72896-non-partial-eq-const.rs | 2 +- tests/ui/match/issue-72896-non-partial-eq-const.stderr | 2 +- .../issue-61188-match-slice-forbidden-without-eq.rs | 3 +-- .../issue-61188-match-slice-forbidden-without-eq.stderr | 2 +- 9 files changed, 9 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 1e6b32bf60557..df51388c7728b 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -273,8 +273,7 @@ mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern -mir_build_non_partial_eq_match = - to use a constant of type `{$non_peq_ty}` in a pattern, the type must implement `PartialEq` +mir_build_non_partial_eq_match = constant of non-structural type `{$non_peq_ty}` in a pattern .label = constant of non-structural type mir_build_pattern_not_covered = refutable pattern in {$origin} diff --git a/tests/ui/consts/const_in_pattern/issue-65466.rs b/tests/ui/consts/const_in_pattern/issue-65466.rs index 62efce648761a..82838657b02f5 100644 --- a/tests/ui/consts/const_in_pattern/issue-65466.rs +++ b/tests/ui/consts/const_in_pattern/issue-65466.rs @@ -11,7 +11,7 @@ const C: &[O] = &[O::None]; fn main() { let x = O::None; match &[x][..] { - C => (), //~ERROR: the type must implement `PartialEq` + C => (), //~ ERROR constant of non-structural type `&[O]` in a pattern _ => (), } } diff --git a/tests/ui/consts/const_in_pattern/issue-65466.stderr b/tests/ui/consts/const_in_pattern/issue-65466.stderr index 90bac6262cc9d..c51d14d39f889 100644 --- a/tests/ui/consts/const_in_pattern/issue-65466.stderr +++ b/tests/ui/consts/const_in_pattern/issue-65466.stderr @@ -1,4 +1,4 @@ -error: to use a constant of type `&[O]` in a pattern, the type must implement `PartialEq` +error: constant of non-structural type `&[O]` in a pattern --> $DIR/issue-65466.rs:14:9 | LL | const C: &[O] = &[O::None]; diff --git a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs index 645e141891243..e555ecfeb8f1f 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs +++ b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs @@ -26,7 +26,7 @@ fn main() { match None { NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"), - //~^ ERROR must implement `PartialEq` + //~^ ERROR constant of non-structural type `Option` in a pattern _ => panic!("whoops"), } } diff --git a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr index d4952a8bfb8c6..2c9cda7d18533 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr @@ -1,4 +1,4 @@ -error: to use a constant of type `Option` in a pattern, the type must implement `PartialEq` +error: constant of non-structural type `Option` in a pattern --> $DIR/reject_non_partial_eq.rs:28:9 | LL | const NO_PARTIAL_EQ_NONE: Option = None; diff --git a/tests/ui/match/issue-72896-non-partial-eq-const.rs b/tests/ui/match/issue-72896-non-partial-eq-const.rs index f15eae83896d1..e4fc1ac057d32 100644 --- a/tests/ui/match/issue-72896-non-partial-eq-const.rs +++ b/tests/ui/match/issue-72896-non-partial-eq-const.rs @@ -16,7 +16,7 @@ const CONST_SET: EnumSet = EnumSet { __enumset_underlying: 3 }; fn main() { match CONST_SET { - CONST_SET => { /* ok */ } //~ERROR: must implement `PartialEq` + CONST_SET => { /* ok */ } //~ ERROR constant of non-structural type `EnumSet` in a pattern _ => panic!("match fell through?"), } } diff --git a/tests/ui/match/issue-72896-non-partial-eq-const.stderr b/tests/ui/match/issue-72896-non-partial-eq-const.stderr index d6ae9e56377d5..47323b3cd22c5 100644 --- a/tests/ui/match/issue-72896-non-partial-eq-const.stderr +++ b/tests/ui/match/issue-72896-non-partial-eq-const.stderr @@ -1,4 +1,4 @@ -error: to use a constant of type `EnumSet` in a pattern, the type must implement `PartialEq` +error: constant of non-structural type `EnumSet` in a pattern --> $DIR/issue-72896-non-partial-eq-const.rs:19:9 | LL | const CONST_SET: EnumSet = EnumSet { __enumset_underlying: 3 }; diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs index c01f8934c750e..95a3be517a9a5 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs @@ -12,8 +12,7 @@ const A: &[B] = &[]; pub fn main() { match &[][..] { - A => (), - //~^ ERROR must implement `PartialEq` + A => (), //~ ERROR constant of non-structural type `&[B]` in a pattern _ => (), } } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr index 51bcfc07c9e01..33244b2841fb7 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr @@ -1,4 +1,4 @@ -error: to use a constant of type `&[B]` in a pattern, the type must implement `PartialEq` +error: constant of non-structural type `&[B]` in a pattern --> $DIR/issue-61188-match-slice-forbidden-without-eq.rs:15:9 | LL | const A: &[B] = &[]; From 335d05aee555c19d375a46c34134312ac720aba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Nov 2024 04:30:35 +0000 Subject: [PATCH 15/21] Add additional context for non-sructural type constant used in pattern - Point at type that should derive `PartialEq` to be structural. - Point at manual `impl PartialEq`, explaining that it is not sufficient to be structural. ``` error: constant of non-structural type `MyType` in a pattern --> $DIR/const-partial_eq-fallback-ice.rs:14:12 | LL | struct MyType; | ------------- `MyType` must be annotated with `#[derive(PartialEq)]` to be usable in patterns ... LL | const CONSTANT: &&MyType = &&MyType; | ------------------------ constant defined here ... LL | if let CONSTANT = &&MyType { | ^^^^^^^^ constant of non-structural type | note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details --> $DIR/const-partial_eq-fallback-ice.rs:5:1 | LL | impl PartialEq for MyType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ``` --- compiler/rustc_mir_build/messages.ftl | 10 +- compiler/rustc_mir_build/src/errors.rs | 9 +- .../src/thir/pattern/const_to_pat.rs | 23 ++- .../const_in_pattern/cross-crate-fail.rs | 6 +- .../const_in_pattern/cross-crate-fail.stderr | 22 ++- .../const_in_pattern/no-eq-branch-fail.rs | 3 +- .../const_in_pattern/no-eq-branch-fail.stderr | 8 +- .../const_in_pattern/reject_non_structural.rs | 70 ++++---- .../reject_non_structural.stderr | 160 ++++++++++++------ tests/ui/consts/issue-89088.rs | 2 +- tests/ui/consts/issue-89088.stderr | 8 +- tests/ui/consts/match_ice.rs | 3 +- tests/ui/consts/match_ice.stderr | 8 +- tests/ui/pattern/issue-115599.rs | 2 +- tests/ui/pattern/issue-115599.stderr | 8 +- .../const-partial_eq-fallback-ice.rs | 2 +- .../const-partial_eq-fallback-ice.stderr | 14 +- ...cant-hide-behind-direct-struct-embedded.rs | 2 +- ...-hide-behind-direct-struct-embedded.stderr | 14 +- .../cant-hide-behind-direct-struct-param.rs | 2 +- ...ant-hide-behind-direct-struct-param.stderr | 14 +- ...nt-hide-behind-doubly-indirect-embedded.rs | 2 +- ...ide-behind-doubly-indirect-embedded.stderr | 14 +- .../cant-hide-behind-doubly-indirect-param.rs | 2 +- ...t-hide-behind-doubly-indirect-param.stderr | 14 +- ...nt-hide-behind-indirect-struct-embedded.rs | 2 +- ...ide-behind-indirect-struct-embedded.stderr | 14 +- .../cant-hide-behind-indirect-struct-param.rs | 2 +- ...t-hide-behind-indirect-struct-param.stderr | 14 +- ...2307-match-ref-ref-forbidden-without-eq.rs | 12 +- ...-match-ref-ref-forbidden-without-eq.stderr | 32 ++-- .../match-requires-both-partialeq-and-eq.rs | 4 +- ...atch-requires-both-partialeq-and-eq.stderr | 16 +- 33 files changed, 343 insertions(+), 175 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index df51388c7728b..6122307e5bb95 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -322,12 +322,12 @@ mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count -> *[other] them } into the body -mir_build_type_not_structural = - to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]` - +mir_build_type_not_structural = constant of non-structural type `{$non_sm_ty}` in a pattern + .label = constant of non-structural type +mir_build_type_not_structural_def = `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - -mir_build_type_not_structural_tip = the traits must be derived, manual `impl`s are not sufficient +mir_build_type_not_structural_tip = + the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details mir_build_unconditional_recursion = function cannot return without recursing .label = cannot return without recursing diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 2741830c62d0f..da4c78ddc4ecf 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -882,12 +882,17 @@ pub(crate) struct UnionPattern { #[derive(Diagnostic)] #[diag(mir_build_type_not_structural)] -#[note(mir_build_type_not_structural_tip)] -#[note(mir_build_type_not_structural_more_info)] pub(crate) struct TypeNotStructural<'tcx> { #[primary_span] + #[label] pub(crate) span: Span, + #[label(mir_build_type_not_structural_def)] + pub(crate) ty_def_span: Span, pub(crate) non_sm_ty: Ty<'tcx>, + #[note(mir_build_type_not_structural_tip)] + pub(crate) manual_partialeq_impl_span: Option, + #[note(mir_build_type_not_structural_more_info)] + pub(crate) manual_partialeq_impl_note: bool, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 71cef18e3161b..36c84f68f7356 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -254,7 +254,22 @@ impl<'tcx> ConstToPat<'tcx> { // Extremely important check for all ADTs! Make sure they opted-in to be used in // patterns. debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty); - let err = TypeNotStructural { span, non_sm_ty: ty }; + let ty_def_span = tcx.def_span(adt_def.did()); + let mut manual_partialeq_impl_span = None; + let partial_eq_trait_id = + tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span)); + tcx.for_each_relevant_impl(partial_eq_trait_id, ty, |def_id| { + if def_id.is_local() { + manual_partialeq_impl_span = Some(tcx.def_span(def_id)); + } + }); + let err = TypeNotStructural { + span, + non_sm_ty: ty, + ty_def_span, + manual_partialeq_impl_span, + manual_partialeq_impl_note: manual_partialeq_impl_span.is_none(), + }; return Err(tcx.dcx().create_err(err)); } ty::Adt(adt_def, args) if adt_def.is_enum() => { @@ -269,7 +284,7 @@ impl<'tcx> ConstToPat<'tcx> { adt_def.variants()[variant_index] .fields .iter() - .map(|field| field.ty(self.tcx, args)), + .map(|field| field.ty(tcx, args)), ), ), } @@ -278,7 +293,7 @@ impl<'tcx> ConstToPat<'tcx> { assert!(!def.is_union()); // Valtree construction would never succeed for unions. PatKind::Leaf { subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip( - def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx, args)), + def.non_enum_variant().fields.iter().map(|field| field.ty(tcx, args)), )), } } @@ -377,7 +392,7 @@ impl<'tcx> ConstToPat<'tcx> { let err = InvalidPattern { span, non_sm_ty: ty, - prefix: ty.prefix_string(self.tcx).to_string(), + prefix: ty.prefix_string(tcx).to_string(), }; return Err(tcx.dcx().create_err(err)); } diff --git a/tests/ui/consts/const_in_pattern/cross-crate-fail.rs b/tests/ui/consts/const_in_pattern/cross-crate-fail.rs index 163a47f433369..f02e780f30e38 100644 --- a/tests/ui/consts/const_in_pattern/cross-crate-fail.rs +++ b/tests/ui/consts/const_in_pattern/cross-crate-fail.rs @@ -9,15 +9,13 @@ fn main() { let _ = Defaulted; match None { consts::SOME => panic!(), - //~^ must be annotated with `#[derive(PartialEq)]` - + //~^ ERROR constant of non-structural type `CustomEq` in a pattern _ => {} } match None { ::SOME => panic!(), - //~^ must be annotated with `#[derive(PartialEq)]` - + //~^ ERROR constant of non-structural type `CustomEq` in a pattern _ => {} } } diff --git a/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr b/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr index 81fc67e6aebb5..7cada8836450e 100644 --- a/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr +++ b/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr @@ -1,29 +1,33 @@ -error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be annotated with `#[derive(PartialEq)]` +error: constant of non-structural type `CustomEq` in a pattern --> $DIR/cross-crate-fail.rs:11:9 | LL | consts::SOME => panic!(), - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ constant of non-structural type | - ::: $DIR/auxiliary/consts.rs:11:1 + ::: $DIR/auxiliary/consts.rs:1:1 | +LL | pub struct CustomEq; + | ------------------- `CustomEq` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | pub const SOME: Option = Some(CustomEq); | -------------------------------- constant defined here | - = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details -error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be annotated with `#[derive(PartialEq)]` - --> $DIR/cross-crate-fail.rs:18:9 +error: constant of non-structural type `CustomEq` in a pattern + --> $DIR/cross-crate-fail.rs:17:9 | LL | ::SOME => panic!(), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant of non-structural type | - ::: $DIR/auxiliary/consts.rs:15:5 + ::: $DIR/auxiliary/consts.rs:1:1 | +LL | pub struct CustomEq; + | ------------------- `CustomEq` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const SOME: Option = Some(CustomEq); | ---------------------------- constant defined here | - = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const_in_pattern/no-eq-branch-fail.rs b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.rs index cf013c1a79061..91ef5ac53295b 100644 --- a/tests/ui/consts/const_in_pattern/no-eq-branch-fail.rs +++ b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.rs @@ -16,8 +16,7 @@ const BAR_BAZ: Foo = if 42 == 42 { fn main() { match Foo::Qux(NoEq) { - BAR_BAZ => panic!(), - //~^ ERROR must be annotated with `#[derive(PartialEq)]` + BAR_BAZ => panic!(), //~ ERROR constant of non-structural type `Foo` in a pattern _ => {} } } diff --git a/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr index 5e2fc6eca3c5d..154c94c6d3854 100644 --- a/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr +++ b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr @@ -1,13 +1,15 @@ -error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq)]` +error: constant of non-structural type `Foo` in a pattern --> $DIR/no-eq-branch-fail.rs:19:9 | +LL | enum Foo { + | -------- `Foo` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const BAR_BAZ: Foo = if 42 == 42 { | ------------------ constant defined here ... LL | BAR_BAZ => panic!(), - | ^^^^^^^ + | ^^^^^^^ constant of non-structural type | - = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details error: aborting due to 1 previous error diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.rs b/tests/ui/consts/const_in_pattern/reject_non_structural.rs index 52cb974c1df1b..39e5f732a8985 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.rs +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.rs @@ -17,9 +17,29 @@ struct NoPartialEq; #[derive(Copy, Clone, Debug)] struct NoDerive; +//~^ NOTE must be annotated with `#[derive(PartialEq)]` +//~| NOTE must be annotated with `#[derive(PartialEq)]` +//~| NOTE must be annotated with `#[derive(PartialEq)]` +//~| NOTE must be annotated with `#[derive(PartialEq)]` +//~| NOTE must be annotated with `#[derive(PartialEq)]` +//~| NOTE must be annotated with `#[derive(PartialEq)]` +//~| NOTE must be annotated with `#[derive(PartialEq)]` +//~| NOTE must be annotated with `#[derive(PartialEq)]` +//~| NOTE must be annotated with `#[derive(PartialEq)]` +//~| NOTE must be annotated with `#[derive(PartialEq)]` // This impl makes `NoDerive` irreflexive. impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } +//~^ NOTE StructuralPartialEq.html for details +//~| NOTE StructuralPartialEq.html for details +//~| NOTE StructuralPartialEq.html for details +//~| NOTE StructuralPartialEq.html for details +//~| NOTE StructuralPartialEq.html for details +//~| NOTE StructuralPartialEq.html for details +//~| NOTE StructuralPartialEq.html for details +//~| NOTE StructuralPartialEq.html for details +//~| NOTE StructuralPartialEq.html for details +//~| NOTE StructuralPartialEq.html for details impl Eq for NoDerive { } @@ -38,63 +58,53 @@ fn main() { const ENUM: Derive = Derive::Some(NoDerive); //~ NOTE constant defined here match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), }; - //~^ ERROR must be annotated with `#[derive(PartialEq)]` - //~| NOTE the traits must be derived - //~| NOTE StructuralPartialEq.html for details + //~^ ERROR constant of non-structural type `NoDerive` in a pattern + //~| NOTE constant of non-structural type const FIELD: OND = TrivialEq(Some(NoDerive)).0; //~ NOTE constant defined here match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), }; - //~^ ERROR must be annotated with `#[derive(PartialEq)]` - //~| NOTE the traits must be derived - //~| NOTE StructuralPartialEq.html for details + //~^ ERROR constant of non-structural type `NoDerive` in a pattern + //~| NOTE constant of non-structural type const NO_DERIVE_SOME: OND = Some(NoDerive); const INDIRECT: OND = NO_DERIVE_SOME; //~ NOTE constant defined here match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), }; - //~^ ERROR must be annotated with `#[derive(PartialEq)]` - //~| NOTE the traits must be derived - //~| NOTE StructuralPartialEq.html for details + //~^ ERROR constant of non-structural type `NoDerive` in a pattern + //~| NOTE constant of non-structural type const TUPLE: (OND, OND) = (None, Some(NoDerive)); //~ NOTE constant defined here match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), }; - //~^ ERROR must be annotated with `#[derive(PartialEq)]` - //~| NOTE the traits must be derived - //~| NOTE StructuralPartialEq.html for details + //~^ ERROR constant of non-structural type `NoDerive` in a pattern + //~| NOTE constant of non-structural type const TYPE_ASCRIPTION: OND = type_ascribe!(Some(NoDerive), OND); //~ NOTE constant defined here match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), }; - //~^ ERROR must be annotated with `#[derive(PartialEq)]` - //~| NOTE the traits must be derived - //~| NOTE StructuralPartialEq.html for details + //~^ ERROR constant of non-structural type `NoDerive` in a pattern + //~| NOTE constant of non-structural type const ARRAY: [OND; 2] = [None, Some(NoDerive)]; //~ NOTE constant defined here match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), }; - //~^ ERROR must be annotated with `#[derive(PartialEq)]` - //~| NOTE the traits must be derived - //~| NOTE StructuralPartialEq.html for details + //~^ ERROR constant of non-structural type `NoDerive` in a pattern + //~| NOTE constant of non-structural type const REPEAT: [OND; 2] = [Some(NoDerive); 2]; //~ NOTE constant defined here match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), }; - //~^ ERROR must be annotated with `#[derive(PartialEq)]` - //~| NOTE the traits must be derived - //~| NOTE StructuralPartialEq.html for details + //~^ ERROR constant of non-structural type `NoDerive` in a pattern + //~| NOTE constant of non-structural type trait Trait: Sized { const ASSOC: Option; } //~ NOTE constant defined here impl Trait for NoDerive { const ASSOC: Option = Some(NoDerive); } match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), }; - //~^ ERROR must be annotated with `#[derive(PartialEq)]` - //~| NOTE the traits must be derived - //~| NOTE StructuralPartialEq.html for details + //~^ ERROR constant of non-structural type `NoDerive` in a pattern + //~| NOTE constant of non-structural type const BLOCK: OND = { NoDerive; Some(NoDerive) }; //~ NOTE constant defined here match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), }; - //~^ ERROR must be annotated with `#[derive(PartialEq)]` - //~| NOTE the traits must be derived - //~| NOTE StructuralPartialEq.html for details + //~^ ERROR constant of non-structural type `NoDerive` in a pattern + //~| NOTE constant of non-structural type const ADDR_OF: &OND = &Some(NoDerive); //~ NOTE constant defined here match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; - //~^ ERROR must be annotated with `#[derive(PartialEq)]` - //~| NOTE the traits must be derived - //~| NOTE StructuralPartialEq.html for details + //~^ ERROR constant of non-structural type `NoDerive` in a pattern + //~| NOTE constant of non-structural type } diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr index e8a69512e7eda..fa16d0b06a7fe 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr @@ -1,113 +1,173 @@ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/reject_non_structural.rs:40:36 +error: constant of non-structural type `NoDerive` in a pattern + --> $DIR/reject_non_structural.rs:60:36 | +LL | struct NoDerive; + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const ENUM: Derive = Derive::Some(NoDerive); | ---------------------------- constant defined here LL | match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), }; - | ^^^^ + | ^^^^ constant of non-structural type | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/reject_non_structural.rs:32:1 + | +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/reject_non_structural.rs:46:28 +error: constant of non-structural type `NoDerive` in a pattern + --> $DIR/reject_non_structural.rs:65:28 | +LL | struct NoDerive; + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const FIELD: OND = TrivialEq(Some(NoDerive)).0; | ---------------- constant defined here LL | match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), }; - | ^^^^^ + | ^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/reject_non_structural.rs:32:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/reject_non_structural.rs:53:27 +error: constant of non-structural type `NoDerive` in a pattern + --> $DIR/reject_non_structural.rs:71:27 | +LL | struct NoDerive; + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const INDIRECT: OND = NO_DERIVE_SOME; | ------------------- constant defined here LL | match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), }; - | ^^^^^^^^ + | ^^^^^^^^ constant of non-structural type | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/reject_non_structural.rs:32:1 + | +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/reject_non_structural.rs:59:36 +error: constant of non-structural type `NoDerive` in a pattern + --> $DIR/reject_non_structural.rs:76:36 | +LL | struct NoDerive; + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const TUPLE: (OND, OND) = (None, Some(NoDerive)); | ----------------------- constant defined here LL | match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), }; - | ^^^^^ + | ^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/reject_non_structural.rs:32:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/reject_non_structural.rs:65:28 +error: constant of non-structural type `NoDerive` in a pattern + --> $DIR/reject_non_structural.rs:81:28 | +LL | struct NoDerive; + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const TYPE_ASCRIPTION: OND = type_ascribe!(Some(NoDerive), OND); | -------------------------- constant defined here LL | match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), }; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ constant of non-structural type | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/reject_non_structural.rs:32:1 + | +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/reject_non_structural.rs:71:36 +error: constant of non-structural type `NoDerive` in a pattern + --> $DIR/reject_non_structural.rs:86:36 | +LL | struct NoDerive; + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const ARRAY: [OND; 2] = [None, Some(NoDerive)]; | --------------------- constant defined here LL | match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), }; - | ^^^^^ + | ^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/reject_non_structural.rs:32:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/reject_non_structural.rs:77:33 +error: constant of non-structural type `NoDerive` in a pattern + --> $DIR/reject_non_structural.rs:91:33 | +LL | struct NoDerive; + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const REPEAT: [OND; 2] = [Some(NoDerive); 2]; | ---------------------- constant defined here LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), }; - | ^^^^^^ + | ^^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/reject_non_structural.rs:32:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/reject_non_structural.rs:84:28 +error: constant of non-structural type `NoDerive` in a pattern + --> $DIR/reject_non_structural.rs:97:28 | +LL | struct NoDerive; + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | trait Trait: Sized { const ASSOC: Option; } | ------------------ ------------------------- constant defined here LL | impl Trait for NoDerive { const ASSOC: Option = Some(NoDerive); } LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), }; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ constant of non-structural type | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/reject_non_structural.rs:32:1 + | +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/reject_non_structural.rs:90:28 +error: constant of non-structural type `NoDerive` in a pattern + --> $DIR/reject_non_structural.rs:102:28 | +LL | struct NoDerive; + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const BLOCK: OND = { NoDerive; Some(NoDerive) }; | ---------------- constant defined here LL | match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), }; - | ^^^^^ + | ^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/reject_non_structural.rs:32:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/reject_non_structural.rs:96:29 +error: constant of non-structural type `NoDerive` in a pattern + --> $DIR/reject_non_structural.rs:107:29 | +LL | struct NoDerive; + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const ADDR_OF: &OND = &Some(NoDerive); | ------------------- constant defined here LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; - | ^^^^^^^ + | ^^^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/reject_non_structural.rs:32:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 10 previous errors diff --git a/tests/ui/consts/issue-89088.rs b/tests/ui/consts/issue-89088.rs index 02a786e746513..f6dbf8f012502 100644 --- a/tests/ui/consts/issue-89088.rs +++ b/tests/ui/consts/issue-89088.rs @@ -13,7 +13,7 @@ fn main() { let var = A::Field(Cow::Borrowed("bar")); match &var { - FOO => todo!(), //~ERROR derive(PartialEq) + FOO => todo!(), //~ ERROR constant of non-structural type `Cow<'_, str>` in a pattern _ => todo!() } } diff --git a/tests/ui/consts/issue-89088.stderr b/tests/ui/consts/issue-89088.stderr index 740cc25647e52..56025e0d9b288 100644 --- a/tests/ui/consts/issue-89088.stderr +++ b/tests/ui/consts/issue-89088.stderr @@ -1,13 +1,15 @@ -error: to use a constant of type `Cow<'_, str>` in a pattern, `Cow<'_, str>` must be annotated with `#[derive(PartialEq)]` +error: constant of non-structural type `Cow<'_, str>` in a pattern --> $DIR/issue-89088.rs:16:9 | LL | const FOO: &A = &A::Field(Cow::Borrowed("foo")); | ------------- constant defined here ... LL | FOO => todo!(), - | ^^^ + | ^^^ constant of non-structural type + --> $SRC_DIR/alloc/src/borrow.rs:LL:COL + | + = note: `Cow<'_, str>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns | - = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details error: aborting due to 1 previous error diff --git a/tests/ui/consts/match_ice.rs b/tests/ui/consts/match_ice.rs index ed1fd78809b12..477a2de09a46f 100644 --- a/tests/ui/consts/match_ice.rs +++ b/tests/ui/consts/match_ice.rs @@ -8,8 +8,7 @@ struct T; fn main() { const C: &S = &S; match C { - C => {} - //~^ ERROR must be annotated with `#[derive(PartialEq)]` + C => {} //~ ERROR constant of non-structural type `S` in a pattern } const K: &T = &T; match K { diff --git a/tests/ui/consts/match_ice.stderr b/tests/ui/consts/match_ice.stderr index 0841ed050251a..95e96bbbd677d 100644 --- a/tests/ui/consts/match_ice.stderr +++ b/tests/ui/consts/match_ice.stderr @@ -1,13 +1,15 @@ -error: to use a constant of type `S` in a pattern, `S` must be annotated with `#[derive(PartialEq)]` +error: constant of non-structural type `S` in a pattern --> $DIR/match_ice.rs:11:9 | +LL | struct S; + | -------- `S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const C: &S = &S; | ----------- constant defined here LL | match C { LL | C => {} - | ^ + | ^ constant of non-structural type | - = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details error: aborting due to 1 previous error diff --git a/tests/ui/pattern/issue-115599.rs b/tests/ui/pattern/issue-115599.rs index 1521d728d9561..47fe6b87da942 100644 --- a/tests/ui/pattern/issue-115599.rs +++ b/tests/ui/pattern/issue-115599.rs @@ -3,5 +3,5 @@ const CONST_STRING: String = String::new(); fn main() { let empty_str = String::from(""); if let CONST_STRING = empty_str {} - //~^ ERROR to use a constant of type `Vec` in a pattern, `Vec` must be annotated with `#[derive(PartialEq)]` + //~^ ERROR constant of non-structural type `Vec` in a pattern } diff --git a/tests/ui/pattern/issue-115599.stderr b/tests/ui/pattern/issue-115599.stderr index 65e3b08ac4853..69d10728ccdd7 100644 --- a/tests/ui/pattern/issue-115599.stderr +++ b/tests/ui/pattern/issue-115599.stderr @@ -1,13 +1,15 @@ -error: to use a constant of type `Vec` in a pattern, `Vec` must be annotated with `#[derive(PartialEq)]` +error: constant of non-structural type `Vec` in a pattern --> $DIR/issue-115599.rs:5:12 | LL | const CONST_STRING: String = String::new(); | -------------------------- constant defined here ... LL | if let CONST_STRING = empty_str {} - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ constant of non-structural type + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + | + = note: `Vec` must be annotated with `#[derive(PartialEq)]` to be usable in patterns | - = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details error: aborting due to 1 previous error diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs index f34093ef1498b..f09dcf8498f38 100644 --- a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs +++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs @@ -12,7 +12,7 @@ const CONSTANT: &&MyType = &&MyType; fn main() { if let CONSTANT = &&MyType { - //~^ ERROR must be annotated with `#[derive(PartialEq)]` + //~^ ERROR constant of non-structural type `MyType` in a pattern println!("did match!"); } } diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr index bcbcd0bc280d8..f9da0430f2ef9 100644 --- a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr +++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr @@ -1,14 +1,20 @@ -error: to use a constant of type `MyType` in a pattern, `MyType` must be annotated with `#[derive(PartialEq)]` +error: constant of non-structural type `MyType` in a pattern --> $DIR/const-partial_eq-fallback-ice.rs:14:12 | +LL | struct MyType; + | ------------- `MyType` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const CONSTANT: &&MyType = &&MyType; | ------------------------ constant defined here ... LL | if let CONSTANT = &&MyType { - | ^^^^^^^^ + | ^^^^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/const-partial_eq-fallback-ice.rs:5:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for MyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs index 65a85a5ed68f6..e27c804804971 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs @@ -20,7 +20,7 @@ const WRAP_DIRECT_INLINE: WrapInline = WrapInline(NoDerive(0)); fn main() { match WRAP_DIRECT_INLINE { WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); } - //~^ ERROR must be annotated with `#[derive(PartialEq)]` + //~^ ERROR constant of non-structural type `NoDerive` in a pattern _ => { println!("WRAP_DIRECT_INLINE did not match itself"); } } } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr index dffaafd88a088..8787d140e17ff 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr @@ -1,14 +1,20 @@ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` +error: constant of non-structural type `NoDerive` in a pattern --> $DIR/cant-hide-behind-direct-struct-embedded.rs:22:9 | +LL | struct NoDerive(#[allow(dead_code)] i32); + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const WRAP_DIRECT_INLINE: WrapInline = WrapInline(NoDerive(0)); | ------------------------------------ constant defined here ... LL | WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); } - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/cant-hide-behind-direct-struct-embedded.rs:11:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs index f840b4040b653..713ff23573d43 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs @@ -19,7 +19,7 @@ const WRAP_DIRECT_PARAM: WrapParam = WrapParam(NoDerive(0)); fn main() { match WRAP_DIRECT_PARAM { WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); } - //~^ ERROR must be annotated with `#[derive(PartialEq)]` + //~^ ERROR constant of non-structural type `NoDerive` in a pattern _ => { println!("WRAP_DIRECT_PARAM did not match itself"); } } } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr index 8da9fa71c536a..ec836db02ad8a 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr @@ -1,14 +1,20 @@ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` +error: constant of non-structural type `NoDerive` in a pattern --> $DIR/cant-hide-behind-direct-struct-param.rs:21:9 | +LL | struct NoDerive(i32); + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const WRAP_DIRECT_PARAM: WrapParam = WrapParam(NoDerive(0)); | -------------------------------------------- constant defined here ... LL | WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); } - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/cant-hide-behind-direct-struct-param.rs:10:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs index 898acefc83cc0..7766a4691923d 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs @@ -20,7 +20,7 @@ const WRAP_DOUBLY_INDIRECT_INLINE: & &WrapInline = & &WrapInline(& & NoDerive(0) fn main() { match WRAP_DOUBLY_INDIRECT_INLINE { WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); } - //~^ ERROR must be annotated with `#[derive(PartialEq)]` + //~^ ERROR constant of non-structural type `NoDerive` in a pattern _ => { println!("WRAP_DOUBLY_INDIRECT_INLINE correctly did not match itself"); } } } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr index 3cd6a184bbe20..fdc16fe300c20 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr @@ -1,14 +1,20 @@ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` +error: constant of non-structural type `NoDerive` in a pattern --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:22:9 | +LL | struct NoDerive(#[allow(dead_code)] i32); + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const WRAP_DOUBLY_INDIRECT_INLINE: & &WrapInline = & &WrapInline(& & NoDerive(0)); | ------------------------------------------------ constant defined here ... LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:11:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs index 7cbaada88a30a..ed84900b6e914 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs @@ -20,7 +20,7 @@ const WRAP_DOUBLY_INDIRECT_PARAM: & &WrapParam = & &WrapParam(& & NoDe fn main() { match WRAP_DOUBLY_INDIRECT_PARAM { WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); } - //~^ ERROR must be annotated with `#[derive(PartialEq)]` + //~^ ERROR constant of non-structural type `NoDerive` in a pattern _ => { println!("WRAP_DOUBLY_INDIRECT_PARAM correctly did not match itself"); } } } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr index 35693da99abf3..b46fc041f14b1 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr @@ -1,14 +1,20 @@ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` +error: constant of non-structural type `NoDerive` in a pattern --> $DIR/cant-hide-behind-doubly-indirect-param.rs:22:9 | +LL | struct NoDerive(#[allow(dead_code)] i32); + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const WRAP_DOUBLY_INDIRECT_PARAM: & &WrapParam = & &WrapParam(& & NoDerive(0)); | -------------------------------------------------------- constant defined here ... LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/cant-hide-behind-doubly-indirect-param.rs:11:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs index ac868efed6fd1..5743d7a24d3a3 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs @@ -20,7 +20,7 @@ const WRAP_INDIRECT_INLINE: & &WrapInline = & &WrapInline(NoDerive(0)); fn main() { match WRAP_INDIRECT_INLINE { WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); } - //~^ ERROR must be annotated with `#[derive(PartialEq)]` + //~^ ERROR constant of non-structural type `NoDerive` in a pattern _ => { println!("WRAP_INDIRECT_INLINE did not match itself"); } } } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr index 5312d61c44695..70f39aa01d822 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr @@ -1,14 +1,20 @@ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` +error: constant of non-structural type `NoDerive` in a pattern --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:22:9 | +LL | struct NoDerive(#[allow(dead_code)] i32); + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const WRAP_INDIRECT_INLINE: & &WrapInline = & &WrapInline(NoDerive(0)); | ----------------------------------------- constant defined here ... LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); } - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:11:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs index cbfabec6819e9..9226f9c3ecdea 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs @@ -20,7 +20,7 @@ const WRAP_INDIRECT_PARAM: & &WrapParam = & &WrapParam(NoDerive(0)); fn main() { match WRAP_INDIRECT_PARAM { WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); } - //~^ ERROR must be annotated with `#[derive(PartialEq)]` + //~^ ERROR constant of non-structural type `NoDerive` in a pattern _ => { println!("WRAP_INDIRECT_PARAM correctly did not match itself"); } } } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr index 2066c53e73a6b..fceb3acb025eb 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr @@ -1,14 +1,20 @@ -error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` +error: constant of non-structural type `NoDerive` in a pattern --> $DIR/cant-hide-behind-indirect-struct-param.rs:22:9 | +LL | struct NoDerive(#[allow(dead_code)] i32); + | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const WRAP_INDIRECT_PARAM: & &WrapParam = & &WrapParam(NoDerive(0)); | ------------------------------------------------- constant defined here ... LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); } - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/cant-hide-behind-indirect-struct-param.rs:11:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs index 0fa2370c95bf4..843c5a3864907 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs @@ -13,27 +13,35 @@ #[derive(Debug)] struct B(i32); +//~^ NOTE `B` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +//~| NOTE `B` must be annotated with `#[derive(PartialEq)]` to be usable in patterns // Overriding `PartialEq` to use this strange notion of "equality" exposes // whether `match` is using structural-equality or method-dispatch // under the hood, which is the antithesis of rust-lang/rfcs#1445 impl PartialEq for B { +//~^ NOTE the `PartialEq` trait must be derived, manual `impl`s are not sufficient +//~| NOTE the `PartialEq` trait must be derived, manual `impl`s are not sufficient fn eq(&self, other: &B) -> bool { std::cmp::min(self.0, other.0) == 0 } } fn main() { const RR_B0: & & B = & & B(0); const RR_B1: & & B = & & B(1); + //~^ NOTE constant defined here + //~| NOTE constant defined here match RR_B0 { RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); } - //~^ ERROR must be annotated with `#[derive(PartialEq)]` + //~^ ERROR constant of non-structural type `B` in a pattern + //~| NOTE constant of non-structural type _ => { } } match RR_B1 { RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); } - //~^ ERROR must be annotated with `#[derive(PartialEq)]` + //~^ ERROR constant of non-structural type `B` in a pattern + //~| NOTE constant of non-structural type _ => { } } } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr index 5cfe6dabc8956..34fffd99c2c9f 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr @@ -1,26 +1,38 @@ -error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]` - --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:29:9 +error: constant of non-structural type `B` in a pattern + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:35:9 | +LL | struct B(i32); + | -------- `B` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const RR_B1: & & B = & & B(1); | ------------------ constant defined here ... LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); } - | ^^^^^ + | ^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:22:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for B { + | ^^^^^^^^^^^^^^^^^^^^ -error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]` - --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:35:9 +error: constant of non-structural type `B` in a pattern + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:42:9 | +LL | struct B(i32); + | -------- `B` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const RR_B1: & & B = & & B(1); | ------------------ constant defined here ... LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); } - | ^^^^^ + | ^^^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:22:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for B { + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs index 9020eb291f5c5..74394698fbcd9 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs @@ -1,3 +1,5 @@ +// Note: It is no longer true that both `Eq` and `PartialEq` must the derived, only the later. + #[derive(Eq)] struct Foo { x: u32 @@ -15,7 +17,7 @@ fn main() { let y = Foo { x: 1 }; match y { FOO => { } - //~^ ERROR must be annotated with `#[derive(PartialEq)]` + //~^ ERROR constant of non-structural type `Foo` in a pattern _ => { } } } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr index c471fe572548c..bbcab3b62d0e3 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr @@ -1,14 +1,20 @@ -error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq)]` - --> $DIR/match-requires-both-partialeq-and-eq.rs:17:9 +error: constant of non-structural type `Foo` in a pattern + --> $DIR/match-requires-both-partialeq-and-eq.rs:19:9 | +LL | struct Foo { + | ---------- `Foo` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const FOO: Foo = Foo { x: 0 }; | -------------- constant defined here ... LL | FOO => { } - | ^^^ + | ^^^ constant of non-structural type + | +note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + --> $DIR/match-requires-both-partialeq-and-eq.rs:8:1 | - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +LL | impl PartialEq for Foo { + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error From 27a1880593a057da01373c4cdafbbed3d34d650f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Nov 2024 06:49:13 +0000 Subject: [PATCH 16/21] Add context to fall-through "const pattern of non-structural type" error Unify wording with the regular non-structural type error. --- compiler/rustc_mir_build/messages.ftl | 6 +++--- compiler/rustc_mir_build/src/errors.rs | 6 ++++-- compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs | 5 +++-- tests/ui/consts/const_in_pattern/issue-65466.stderr | 3 +++ .../ui/consts/const_in_pattern/reject_non_partial_eq.stderr | 3 +++ tests/ui/match/issue-72896-non-partial-eq-const.stderr | 3 +++ .../issue-61188-match-slice-forbidden-without-eq.stderr | 3 +++ 7 files changed, 22 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 6122307e5bb95..f35252dbcc55e 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -273,7 +273,7 @@ mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern -mir_build_non_partial_eq_match = constant of non-structural type `{$non_peq_ty}` in a pattern +mir_build_non_partial_eq_match = constant of non-structural type `{$ty}` in a pattern .label = constant of non-structural type mir_build_pattern_not_covered = refutable pattern in {$origin} @@ -322,9 +322,9 @@ mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count -> *[other] them } into the body -mir_build_type_not_structural = constant of non-structural type `{$non_sm_ty}` in a pattern +mir_build_type_not_structural = constant of non-structural type `{$ty}` in a pattern .label = constant of non-structural type -mir_build_type_not_structural_def = `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +mir_build_type_not_structural_def = `{$ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details mir_build_type_not_structural_tip = the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index da4c78ddc4ecf..49e18891fcabc 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -888,7 +888,7 @@ pub(crate) struct TypeNotStructural<'tcx> { pub(crate) span: Span, #[label(mir_build_type_not_structural_def)] pub(crate) ty_def_span: Span, - pub(crate) non_sm_ty: Ty<'tcx>, + pub(crate) ty: Ty<'tcx>, #[note(mir_build_type_not_structural_tip)] pub(crate) manual_partialeq_impl_span: Option, #[note(mir_build_type_not_structural_more_info)] @@ -897,11 +897,13 @@ pub(crate) struct TypeNotStructural<'tcx> { #[derive(Diagnostic)] #[diag(mir_build_non_partial_eq_match)] +#[note(mir_build_type_not_structural_def)] +#[note(mir_build_type_not_structural_more_info)] pub(crate) struct TypeNotPartialEq<'tcx> { #[primary_span] #[label] pub(crate) span: Span, - pub(crate) non_peq_ty: Ty<'tcx>, + pub(crate) ty: Ty<'tcx>, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 36c84f68f7356..123a439c645a5 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -190,7 +190,8 @@ impl<'tcx> ConstToPat<'tcx> { if !inlined_const_as_pat.references_error() { // Always check for `PartialEq` if we had no other errors yet. if !self.type_has_partial_eq_impl(ty) { - let err = TypeNotPartialEq { span: self.span, non_peq_ty: ty }; + let err = TypeNotPartialEq { span: self.span, ty }; + // FIXME: visit every type in `ty` and if it doesn't derive `PartialEq`, mention it. return self.mk_err(self.tcx.dcx().create_err(err), ty); } } @@ -265,7 +266,7 @@ impl<'tcx> ConstToPat<'tcx> { }); let err = TypeNotStructural { span, - non_sm_ty: ty, + ty, ty_def_span, manual_partialeq_impl_span, manual_partialeq_impl_note: manual_partialeq_impl_span.is_none(), diff --git a/tests/ui/consts/const_in_pattern/issue-65466.stderr b/tests/ui/consts/const_in_pattern/issue-65466.stderr index c51d14d39f889..bd9748b5dda99 100644 --- a/tests/ui/consts/const_in_pattern/issue-65466.stderr +++ b/tests/ui/consts/const_in_pattern/issue-65466.stderr @@ -6,6 +6,9 @@ LL | const C: &[O] = &[O::None]; ... LL | C => (), | ^ constant of non-structural type + | + = note: `&[O]` must be annotated with `#[derive(PartialEq)]` to be usable in patterns + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details error: aborting due to 1 previous error diff --git a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr index 2c9cda7d18533..0ef5286e68937 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr @@ -6,6 +6,9 @@ LL | const NO_PARTIAL_EQ_NONE: Option = None; ... LL | NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"), | ^^^^^^^^^^^^^^^^^^ constant of non-structural type + | + = note: `Option` must be annotated with `#[derive(PartialEq)]` to be usable in patterns + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details error: aborting due to 1 previous error diff --git a/tests/ui/match/issue-72896-non-partial-eq-const.stderr b/tests/ui/match/issue-72896-non-partial-eq-const.stderr index 47323b3cd22c5..4287fbc188d59 100644 --- a/tests/ui/match/issue-72896-non-partial-eq-const.stderr +++ b/tests/ui/match/issue-72896-non-partial-eq-const.stderr @@ -6,6 +6,9 @@ LL | const CONST_SET: EnumSet = EnumSet { __enumset_underlying: 3 }; ... LL | CONST_SET => { /* ok */ } | ^^^^^^^^^ constant of non-structural type + | + = note: `EnumSet` must be annotated with `#[derive(PartialEq)]` to be usable in patterns + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr index 33244b2841fb7..4f83ca02c2879 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr @@ -6,6 +6,9 @@ LL | const A: &[B] = &[]; ... LL | A => (), | ^ constant of non-structural type + | + = note: `&[B]` must be annotated with `#[derive(PartialEq)]` to be usable in patterns + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details error: aborting due to 1 previous error From d136b3108def7af6d43229ba704ab21778f55125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Nov 2024 23:10:39 +0000 Subject: [PATCH 17/21] Add more context to fall-through "const pattern of non-structural type" error Point at types that need to be marked with `#[derive(PartialEq)]`. We use a visitor to look at a type that isn't structural, looking for all ADTs that don't derive `PartialEq`. These can either be manual `impl PartialEq`s or no `impl` at all, so we differentiate between those two cases to provide more context to the user. We also only point at types and impls from the local crate, otherwise show only a note. ``` error: constant of non-structural type `&[B]` in a pattern --> $DIR/issue-61188-match-slice-forbidden-without-eq.rs:15:9 | LL | struct B(i32); | -------- must be annotated with `#[derive(PartialEq)]` to be usable in patterns LL | LL | const A: &[B] = &[]; | ------------- constant defined here ... LL | A => (), | ^ constant of non-structural type | = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details ``` --- compiler/rustc_mir_build/src/errors.rs | 1 - .../src/thir/pattern/const_to_pat.rs | 198 ++++++++++++++---- .../const_in_pattern/issue-65466.stderr | 4 +- .../reject_non_partial_eq.stderr | 4 +- .../issue-72896-non-partial-eq-const.stderr | 4 +- ...88-match-slice-forbidden-without-eq.stderr | 4 +- 6 files changed, 169 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 49e18891fcabc..3632da943e18b 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -897,7 +897,6 @@ pub(crate) struct TypeNotStructural<'tcx> { #[derive(Diagnostic)] #[diag(mir_build_non_partial_eq_match)] -#[note(mir_build_type_not_structural_def)] #[note(mir_build_type_not_structural_more_info)] pub(crate) struct TypeNotPartialEq<'tcx> { #[primary_span] diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 123a439c645a5..feb6d2fcfe9c2 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -1,5 +1,6 @@ use rustc_abi::{FieldIdx, VariantIdx}; use rustc_apfloat::Float; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Diag, PResult}; use rustc_hir as hir; use rustc_index::Idx; @@ -7,9 +8,10 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::Obligation; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::thir::{FieldPat, Pat, PatKind}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, ValTree}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeVisitor, ValTree}; use rustc_middle::{mir, span_bug}; -use rustc_span::Span; +use rustc_span::def_id::DefId; +use rustc_span::{Span, sym}; use rustc_trait_selection::traits::ObligationCause; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use tracing::{debug, instrument, trace}; @@ -189,42 +191,16 @@ impl<'tcx> ConstToPat<'tcx> { if !inlined_const_as_pat.references_error() { // Always check for `PartialEq` if we had no other errors yet. - if !self.type_has_partial_eq_impl(ty) { - let err = TypeNotPartialEq { span: self.span, ty }; - // FIXME: visit every type in `ty` and if it doesn't derive `PartialEq`, mention it. - return self.mk_err(self.tcx.dcx().create_err(err), ty); + if !type_has_partial_eq_impl(self.tcx, typing_env, ty).0 { + let mut err = self.tcx.dcx().create_err(TypeNotPartialEq { span: self.span, ty }); + extend_type_not_partial_eq(self.tcx, typing_env, ty, &mut err); + return self.mk_err(err, ty); } } inlined_const_as_pat } - #[instrument(level = "trace", skip(self), ret)] - fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool { - let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env); - // double-check there even *is* a semantic `PartialEq` to dispatch to. - // - // (If there isn't, then we can safely issue a hard - // error, because that's never worked, due to compiler - // using `PartialEq::eq` in this scenario in the past.) - let partial_eq_trait_id = - self.tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span)); - let partial_eq_obligation = Obligation::new( - self.tcx, - ObligationCause::dummy(), - param_env, - ty::TraitRef::new(self.tcx, partial_eq_trait_id, [ty, ty]), - ); - - // This *could* accept a type that isn't actually `PartialEq`, because region bounds get - // ignored. However that should be pretty much impossible since consts that do not depend on - // generics can only mention the `'static` lifetime, and how would one have a type that's - // `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem - // we'll need to leave some sort of trace of this requirement in the MIR so that borrowck - // can ensure that the type really implements `PartialEq`. - infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation) - } - fn field_pats( &self, vals: impl Iterator, Ty<'tcx>)>, @@ -255,21 +231,23 @@ impl<'tcx> ConstToPat<'tcx> { // Extremely important check for all ADTs! Make sure they opted-in to be used in // patterns. debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty); + let (impls_partial_eq, derived, structural, impl_def_id) = + type_has_partial_eq_impl(self.tcx, self.typing_env, ty); + let (manual_partialeq_impl_span, manual_partialeq_impl_note) = + match (impls_partial_eq, derived, structural, impl_def_id) { + (_, _, true, _) => (None, false), + (_, false, _, Some(def_id)) if def_id.is_local() => { + (Some(tcx.def_span(def_id)), false) + } + _ => (None, true), + }; let ty_def_span = tcx.def_span(adt_def.did()); - let mut manual_partialeq_impl_span = None; - let partial_eq_trait_id = - tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span)); - tcx.for_each_relevant_impl(partial_eq_trait_id, ty, |def_id| { - if def_id.is_local() { - manual_partialeq_impl_span = Some(tcx.def_span(def_id)); - } - }); let err = TypeNotStructural { span, ty, ty_def_span, manual_partialeq_impl_span, - manual_partialeq_impl_note: manual_partialeq_impl_span.is_none(), + manual_partialeq_impl_note, }; return Err(tcx.dcx().create_err(err)); } @@ -402,3 +380,141 @@ impl<'tcx> ConstToPat<'tcx> { Ok(Box::new(Pat { span, ty, kind })) } } + +/// Given a type with type parameters, visit every ADT looking for types that need to +/// `#[derive(PartialEq)]` to be a structural type. +fn extend_type_not_partial_eq<'tcx>( + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, + err: &mut Diag<'_>, +) { + /// Collect all types that need to be `StructuralPartialEq`. + struct UsedParamsNeedInstantiationVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + /// The user has written `impl PartialEq for Ty` which means it's non-structual. + adts_with_manual_partialeq: FxHashSet, + /// The type has no `PartialEq` implementation, neither manual or derived. + adts_without_partialeq: FxHashSet, + /// The user has written `impl PartialEq for Ty` which means it's non-structual, + /// but we don't have a span to point at, so we'll just add them as a `note`. + manual: Vec>, + /// The type has no `PartialEq` implementation, neither manual or derived, but + /// we don't have a span to point at, so we'll just add them as a `note`. + without: Vec>, + } + + impl<'tcx> TypeVisitor> for UsedParamsNeedInstantiationVisitor<'tcx> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { + if let ty::Adt(def, _args) = ty.kind() { + let ty_def_id = def.did(); + let ty_def_span = self.tcx.def_span(ty_def_id); + let (impls_partial_eq, derived, structural, impl_def_id) = + type_has_partial_eq_impl(self.tcx, self.typing_env, ty); + match (impls_partial_eq, derived, structural, impl_def_id) { + (_, _, true, _) => {} + (true, false, _, Some(def_id)) if def_id.is_local() => { + self.adts_with_manual_partialeq.insert(self.tcx.def_span(def_id)); + } + (true, false, _, _) if ty_def_id.is_local() => { + self.adts_with_manual_partialeq.insert(ty_def_span); + } + (false, _, _, _) if ty_def_id.is_local() => { + self.adts_without_partialeq.insert(ty_def_span); + } + (true, false, _, _) => { + self.manual.push(ty); + } + (false, _, _, _) => { + self.without.push(ty); + } + _ => {} + }; + } + use rustc_middle::ty::TypeSuperVisitable; + ty.super_visit_with(self) + } + } + let mut v = UsedParamsNeedInstantiationVisitor { + tcx, + typing_env, + adts_with_manual_partialeq: FxHashSet::default(), + adts_without_partialeq: FxHashSet::default(), + manual: vec![], + without: vec![], + }; + v.visit_ty(ty); + #[allow(rustc::potential_query_instability)] // Span labels will be sorted by the rendering + for span in v.adts_with_manual_partialeq { + err.span_note(span, "the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details"); + } + #[allow(rustc::potential_query_instability)] // Span labels will be sorted by the rendering + for span in v.adts_without_partialeq { + err.span_label( + span, + "must be annotated with `#[derive(PartialEq)]` to be usable in patterns", + ); + } + for ty in v.manual { + err.note(format!( + "`{ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details" + )); + } + for ty in v.without { + err.note(format!( + "`{ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns" + )); + } +} + +#[instrument(level = "trace", skip(tcx), ret)] +fn type_has_partial_eq_impl<'tcx>( + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, +) -> ( + /* has impl */ bool, + /* is derived */ bool, + /* structural partial eq */ bool, + /* non-blanket impl */ Option, +) { + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); + // double-check there even *is* a semantic `PartialEq` to dispatch to. + // + // (If there isn't, then we can safely issue a hard + // error, because that's never worked, due to compiler + // using `PartialEq::eq` in this scenario in the past.) + let partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::PartialEq, None); + let structural_partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::StructuralPeq, None); + + let partial_eq_obligation = Obligation::new( + tcx, + ObligationCause::dummy(), + param_env, + ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]), + ); + + let mut automatically_derived = false; + let mut structural_peq = false; + let mut impl_def_id = None; + for def_id in tcx.non_blanket_impls_for_ty(partial_eq_trait_id, ty) { + automatically_derived = tcx.has_attr(def_id, sym::automatically_derived); + impl_def_id = Some(def_id); + } + for _ in tcx.non_blanket_impls_for_ty(structural_partial_eq_trait_id, ty) { + structural_peq = true; + } + // This *could* accept a type that isn't actually `PartialEq`, because region bounds get + // ignored. However that should be pretty much impossible since consts that do not depend on + // generics can only mention the `'static` lifetime, and how would one have a type that's + // `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem + // we'll need to leave some sort of trace of this requirement in the MIR so that borrowck + // can ensure that the type really implements `PartialEq`. + ( + infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation), + automatically_derived, + structural_peq, + impl_def_id, + ) +} diff --git a/tests/ui/consts/const_in_pattern/issue-65466.stderr b/tests/ui/consts/const_in_pattern/issue-65466.stderr index bd9748b5dda99..511a38bbc00d8 100644 --- a/tests/ui/consts/const_in_pattern/issue-65466.stderr +++ b/tests/ui/consts/const_in_pattern/issue-65466.stderr @@ -1,13 +1,15 @@ error: constant of non-structural type `&[O]` in a pattern --> $DIR/issue-65466.rs:14:9 | +LL | struct B; + | -------- must be annotated with `#[derive(PartialEq)]` to be usable in patterns +LL | LL | const C: &[O] = &[O::None]; | ---------------- constant defined here ... LL | C => (), | ^ constant of non-structural type | - = note: `&[O]` must be annotated with `#[derive(PartialEq)]` to be usable in patterns = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details error: aborting due to 1 previous error diff --git a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr index 0ef5286e68937..43894f0088621 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr @@ -1,13 +1,15 @@ error: constant of non-structural type `Option` in a pattern --> $DIR/reject_non_partial_eq.rs:28:9 | +LL | struct NoPartialEq(u32); + | ------------------ must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const NO_PARTIAL_EQ_NONE: Option = None; | --------------------------------------------- constant defined here ... LL | NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"), | ^^^^^^^^^^^^^^^^^^ constant of non-structural type | - = note: `Option` must be annotated with `#[derive(PartialEq)]` to be usable in patterns = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details error: aborting due to 1 previous error diff --git a/tests/ui/match/issue-72896-non-partial-eq-const.stderr b/tests/ui/match/issue-72896-non-partial-eq-const.stderr index 4287fbc188d59..1f82d3e822adb 100644 --- a/tests/ui/match/issue-72896-non-partial-eq-const.stderr +++ b/tests/ui/match/issue-72896-non-partial-eq-const.stderr @@ -1,13 +1,15 @@ error: constant of non-structural type `EnumSet` in a pattern --> $DIR/issue-72896-non-partial-eq-const.rs:19:9 | +LL | enum Enum8 { } + | ---------- must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... LL | const CONST_SET: EnumSet = EnumSet { __enumset_underlying: 3 }; | ------------------------------- constant defined here ... LL | CONST_SET => { /* ok */ } | ^^^^^^^^^ constant of non-structural type | - = note: `EnumSet` must be annotated with `#[derive(PartialEq)]` to be usable in patterns = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr index 4f83ca02c2879..7d3b37686b865 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr @@ -1,13 +1,15 @@ error: constant of non-structural type `&[B]` in a pattern --> $DIR/issue-61188-match-slice-forbidden-without-eq.rs:15:9 | +LL | struct B(i32); + | -------- must be annotated with `#[derive(PartialEq)]` to be usable in patterns +LL | LL | const A: &[B] = &[]; | ------------- constant defined here ... LL | A => (), | ^ constant of non-structural type | - = note: `&[B]` must be annotated with `#[derive(PartialEq)]` to be usable in patterns = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details error: aborting due to 1 previous error From da58406c73524054e9915aee4aa44d415868be6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 20 Nov 2024 23:10:52 +0000 Subject: [PATCH 18/21] fix test --- tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr b/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr index 8175fe6016ab8..18935626af1ca 100644 --- a/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr +++ b/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr @@ -7,12 +7,6 @@ LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error: could not evaluate constant pattern - --> $DIR/ref_to_int_match.rs:7:14 - | -LL | 10..=BAR => {}, - | ^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. From 81291ec7eaf824d748ef8d3201d13df444ada4ef Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 4 Dec 2024 20:29:02 +0000 Subject: [PATCH 19/21] No need to create placeholders for GAT args in confirm_object_candidate --- .../src/traits/select/confirmation.rs | 54 +------------------ 1 file changed, 2 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 19b4125e75cdf..2fbe2e1e323be 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -16,9 +16,7 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::{DefineOpaqueTypes, HigherRankedType, InferOk}; use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData}; -use rustc_middle::ty::{ - self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, Ty, TyCtxt, Upcast, -}; +use rustc_middle::ty::{self, GenericArgsRef, ToPolyTraitRef, Ty, TyCtxt, Upcast}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; use tracing::{debug, instrument}; @@ -638,60 +636,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // higher-ranked things. // Prevent, e.g., `dyn Iterator`. for bound in self.tcx().item_bounds(assoc_type).transpose_iter() { - let arg_bound = if defs.is_empty() { - bound.instantiate(tcx, trait_predicate.trait_ref.args) - } else { - let mut args = smallvec::SmallVec::with_capacity(defs.count()); - args.extend(trait_predicate.trait_ref.args.iter()); - let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> = - smallvec::SmallVec::with_capacity( - bound.skip_binder().kind().bound_vars().len() + defs.count(), - ); - bound_vars.extend(bound.skip_binder().kind().bound_vars().into_iter()); - GenericArgs::fill_single(&mut args, defs, &mut |param, _| match param.kind { - GenericParamDefKind::Type { .. } => { - let kind = ty::BoundTyKind::Param(param.def_id, param.name); - let bound_var = ty::BoundVariableKind::Ty(kind); - bound_vars.push(bound_var); - Ty::new_bound(tcx, ty::INNERMOST, ty::BoundTy { - var: ty::BoundVar::from_usize(bound_vars.len() - 1), - kind, - }) - .into() - } - GenericParamDefKind::Lifetime => { - let kind = ty::BoundRegionKind::Named(param.def_id, param.name); - let bound_var = ty::BoundVariableKind::Region(kind); - bound_vars.push(bound_var); - ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { - var: ty::BoundVar::from_usize(bound_vars.len() - 1), - kind, - }) - .into() - } - GenericParamDefKind::Const { .. } => { - let bound_var = ty::BoundVariableKind::Const; - bound_vars.push(bound_var); - ty::Const::new_bound( - tcx, - ty::INNERMOST, - ty::BoundVar::from_usize(bound_vars.len() - 1), - ) - .into() - } - }); - let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars); - let assoc_ty_args = tcx.mk_args(&args); - let bound = - bound.map_bound(|b| b.kind().skip_binder()).instantiate(tcx, assoc_ty_args); - ty::Binder::bind_with_vars(bound, bound_vars).upcast(tcx) - }; let normalized_bound = normalize_with_depth_to( self, obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - arg_bound, + bound.instantiate(tcx, trait_predicate.trait_ref.args), &mut nested, ); nested.push(obligation.with(tcx, normalized_bound)); From 4e6a401b224342287469a1a294bba7ad10e8641c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 4 Dec 2024 20:49:05 +0000 Subject: [PATCH 20/21] review comments: reword messages and simplify logic --- compiler/rustc_mir_build/messages.ftl | 2 +- .../src/thir/pattern/const_to_pat.rs | 64 +++++++------------ ...associated-const-type-parameter-pattern.rs | 8 +-- ...ciated-const-type-parameter-pattern.stderr | 16 ++--- tests/ui/consts/issue-73976-polymorphic.rs | 4 +- .../ui/consts/issue-73976-polymorphic.stderr | 8 +-- tests/ui/consts/issue-79137-toogeneric.rs | 2 +- tests/ui/consts/issue-79137-toogeneric.stderr | 4 +- .../inline-const/const-match-pat-generic.rs | 4 +- .../const-match-pat-generic.stderr | 4 +- 10 files changed, 48 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index f35252dbcc55e..f647486f62ade 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -90,7 +90,7 @@ mir_build_const_param_in_pattern = constant parameters cannot be referenced in p .label = can't be used in patterns mir_build_const_param_in_pattern_def = constant defined here -mir_build_const_pattern_depends_on_generic_parameter = constant pattern depends on a generic parameter, which is not allowed +mir_build_const_pattern_depends_on_generic_parameter = constant pattern cannot depend on generic parameters .label = `const` depends on a generic parameter mir_build_could_not_eval_const_pattern = could not evaluate constant pattern diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index feb6d2fcfe9c2..aed00aecefc99 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -1,7 +1,7 @@ use rustc_abi::{FieldIdx, VariantIdx}; use rustc_apfloat::Float; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{Diag, PResult}; +use rustc_errors::Diag; use rustc_hir as hir; use rustc_index::Idx; use rustc_infer::infer::TyCtxtInferExt; @@ -42,10 +42,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { match c.kind() { ty::ConstKind::Unevaluated(uv) => convert.unevaluated_to_pat(uv, ty), - ty::ConstKind::Value(_, val) => match convert.valtree_to_pat(val, ty) { - Ok(pat) => pat, - Err(err) => convert.mk_err(err, ty), - }, + ty::ConstKind::Value(_, val) => convert.valtree_to_pat(val, ty), _ => span_bug!(span, "Invalid `ConstKind` for `const_to_pat`: {:?}", c), } } @@ -151,7 +148,7 @@ impl<'tcx> ConstToPat<'tcx> { let generics = self.tcx.generics_of(def_id); let param = generics.type_param(*param_ty, self.tcx); let span = self.tcx.def_span(param.def_id); - e.span_label(span, "constant depends on this generic param"); + e.span_label(span, "constant depends on this generic parameter"); if let Some(ident) = self.tcx.def_ident_span(def_id) && self.tcx.sess.source_map().is_multiline(ident.between(span)) { @@ -184,10 +181,7 @@ impl<'tcx> ConstToPat<'tcx> { }; // Convert the valtree to a const. - let inlined_const_as_pat = match self.valtree_to_pat(valtree, ty) { - Ok(pat) => pat, - Err(err) => self.mk_err(err, ty), - }; + let inlined_const_as_pat = self.valtree_to_pat(valtree, ty); if !inlined_const_as_pat.references_error() { // Always check for `PartialEq` if we had no other errors yet. @@ -210,20 +204,14 @@ impl<'tcx> ConstToPat<'tcx> { let field = FieldIdx::new(idx); // Patterns can only use monomorphic types. let ty = self.tcx.normalize_erasing_regions(self.typing_env, ty); - FieldPat { - field, - pattern: match self.valtree_to_pat(val, ty) { - Ok(pat) => pat, - Err(err) => self.mk_err(err, ty), - }, - } + FieldPat { field, pattern: self.valtree_to_pat(val, ty) } }) .collect() } // Recursive helper for `to_pat`; invoke that (instead of calling this directly). #[instrument(skip(self), level = "debug")] - fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> PResult<'_, Box>> { + fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box> { let span = self.span; let tcx = self.tcx; let kind = match ty.kind() { @@ -231,12 +219,12 @@ impl<'tcx> ConstToPat<'tcx> { // Extremely important check for all ADTs! Make sure they opted-in to be used in // patterns. debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty); - let (impls_partial_eq, derived, structural, impl_def_id) = + let (_impls_partial_eq, derived, structural, impl_def_id) = type_has_partial_eq_impl(self.tcx, self.typing_env, ty); let (manual_partialeq_impl_span, manual_partialeq_impl_note) = - match (impls_partial_eq, derived, structural, impl_def_id) { - (_, _, true, _) => (None, false), - (_, false, _, Some(def_id)) if def_id.is_local() => { + match (structural, impl_def_id) { + (true, _) => (None, false), + (_, Some(def_id)) if def_id.is_local() && !derived => { (Some(tcx.def_span(def_id)), false) } _ => (None, true), @@ -249,7 +237,7 @@ impl<'tcx> ConstToPat<'tcx> { manual_partialeq_impl_span, manual_partialeq_impl_note, }; - return Err(tcx.dcx().create_err(err)); + return self.mk_err(tcx.dcx().create_err(err), ty); } ty::Adt(adt_def, args) if adt_def.is_enum() => { let (&variant_index, fields) = cv.unwrap_branch().split_first().unwrap(); @@ -283,10 +271,7 @@ impl<'tcx> ConstToPat<'tcx> { prefix: cv .unwrap_branch() .iter() - .map(|val| match self.valtree_to_pat(*val, *elem_ty) { - Ok(pat) => pat, - Err(err) => self.mk_err(err, ty), - }) + .map(|val| self.valtree_to_pat(*val, *elem_ty)) .collect(), slice: None, suffix: Box::new([]), @@ -295,10 +280,7 @@ impl<'tcx> ConstToPat<'tcx> { prefix: cv .unwrap_branch() .iter() - .map(|val| match self.valtree_to_pat(*val, *elem_ty) { - Ok(pat) => pat, - Err(err) => self.mk_err(err, ty), - }) + .map(|val| self.valtree_to_pat(*val, *elem_ty)) .collect(), slice: None, suffix: Box::new([]), @@ -314,9 +296,10 @@ impl<'tcx> ConstToPat<'tcx> { // deref pattern. _ => { if !pointee_ty.is_sized(tcx, self.typing_env) && !pointee_ty.is_slice() { - return Err(tcx - .dcx() - .create_err(UnsizedPattern { span, non_sm_ty: *pointee_ty })); + return self.mk_err( + tcx.dcx().create_err(UnsizedPattern { span, non_sm_ty: *pointee_ty }), + ty, + ); } else { // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when // matching against references, you can only use byte string literals. @@ -331,10 +314,7 @@ impl<'tcx> ConstToPat<'tcx> { _ => *pointee_ty, }; // References have the same valtree representation as their pointee. - let subpattern = match self.valtree_to_pat(cv, pointee_ty) { - Ok(pat) => pat, - Err(err) => self.mk_err(err, ty), - }; + let subpattern = self.valtree_to_pat(cv, pointee_ty); PatKind::Deref { subpattern } } } @@ -350,7 +330,7 @@ impl<'tcx> ConstToPat<'tcx> { if is_nan { // NaNs are not ever equal to anything so they make no sense as patterns. // Also see . - return Err(tcx.dcx().create_err(NaNPattern { span })); + return self.mk_err(tcx.dcx().create_err(NaNPattern { span }), ty); } else { PatKind::Constant { value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)), @@ -373,16 +353,16 @@ impl<'tcx> ConstToPat<'tcx> { non_sm_ty: ty, prefix: ty.prefix_string(tcx).to_string(), }; - return Err(tcx.dcx().create_err(err)); + return self.mk_err(tcx.dcx().create_err(err), ty); } }; - Ok(Box::new(Pat { span, ty, kind })) + Box::new(Pat { span, ty, kind }) } } /// Given a type with type parameters, visit every ADT looking for types that need to -/// `#[derive(PartialEq)]` to be a structural type. +/// `#[derive(PartialEq)]` for it to be a structural type. fn extend_type_not_partial_eq<'tcx>( tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, diff --git a/tests/ui/associated-consts/associated-const-type-parameter-pattern.rs b/tests/ui/associated-consts/associated-const-type-parameter-pattern.rs index b5798adc71c86..e6c80a7e54e85 100644 --- a/tests/ui/associated-consts/associated-const-type-parameter-pattern.rs +++ b/tests/ui/associated-consts/associated-const-type-parameter-pattern.rs @@ -18,17 +18,17 @@ impl Foo for Def { pub fn test(arg: EFoo) { match arg { A::X => println!("A::X"), - //~^ error: constant pattern depends on a generic parameter + //~^ ERROR constant pattern cannot depend on generic parameters B::X => println!("B::X"), - //~^ error: constant pattern depends on a generic parameter + //~^ ERROR constant pattern cannot depend on generic parameters _ => (), } } pub fn test_let_pat(arg: EFoo, A::X: EFoo) { - //~^ ERROR constant pattern depends on a generic parameter + //~^ ERROR constant pattern cannot depend on generic parameters let A::X = arg; - //~^ ERROR constant pattern depends on a generic parameter + //~^ ERROR constant pattern cannot depend on generic parameters } fn main() { diff --git a/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr b/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr index 455831e8401cb..a8256f775a68c 100644 --- a/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr +++ b/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr @@ -1,4 +1,4 @@ -error[E0158]: constant pattern depends on a generic parameter, which is not allowed +error[E0158]: constant pattern cannot depend on generic parameters --> $DIR/associated-const-type-parameter-pattern.rs:20:9 | LL | pub trait Foo { @@ -7,12 +7,12 @@ LL | const X: EFoo; | ------------- constant defined here ... LL | pub fn test(arg: EFoo) { - | - constant depends on this generic param + | - constant depends on this generic parameter LL | match arg { LL | A::X => println!("A::X"), | ^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter, which is not allowed +error[E0158]: constant pattern cannot depend on generic parameters --> $DIR/associated-const-type-parameter-pattern.rs:22:9 | LL | pub trait Foo { @@ -21,12 +21,12 @@ LL | const X: EFoo; | ------------- constant defined here ... LL | pub fn test(arg: EFoo) { - | - constant depends on this generic param + | - constant depends on this generic parameter ... LL | B::X => println!("B::X"), | ^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter, which is not allowed +error[E0158]: constant pattern cannot depend on generic parameters --> $DIR/associated-const-type-parameter-pattern.rs:30:9 | LL | pub trait Foo { @@ -35,12 +35,12 @@ LL | const X: EFoo; | ------------- constant defined here ... LL | pub fn test_let_pat(arg: EFoo, A::X: EFoo) { - | - constant depends on this generic param + | - constant depends on this generic parameter LL | LL | let A::X = arg; | ^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter, which is not allowed +error[E0158]: constant pattern cannot depend on generic parameters --> $DIR/associated-const-type-parameter-pattern.rs:28:48 | LL | pub trait Foo { @@ -51,7 +51,7 @@ LL | const X: EFoo; LL | pub fn test_let_pat(arg: EFoo, A::X: EFoo) { | - ^^^^ `const` depends on a generic parameter | | - | constant depends on this generic param + | constant depends on this generic parameter error: aborting due to 4 previous errors diff --git a/tests/ui/consts/issue-73976-polymorphic.rs b/tests/ui/consts/issue-73976-polymorphic.rs index 2c576d1f9ef08..98b4005792dbc 100644 --- a/tests/ui/consts/issue-73976-polymorphic.rs +++ b/tests/ui/consts/issue-73976-polymorphic.rs @@ -18,7 +18,7 @@ impl GetTypeId { const fn check_type_id() -> bool { matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) - //~^ ERROR constant pattern depends on a generic parameter + //~^ ERROR constant pattern cannot depend on generic parameters } pub struct GetTypeNameLen(T); @@ -29,7 +29,7 @@ impl GetTypeNameLen { const fn check_type_name_len() -> bool { matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) - //~^ ERROR constant pattern depends on a generic parameter + //~^ ERROR constant pattern cannot depend on generic parameters } fn main() { diff --git a/tests/ui/consts/issue-73976-polymorphic.stderr b/tests/ui/consts/issue-73976-polymorphic.stderr index 2f50e6ac2fd42..ec9512a261632 100644 --- a/tests/ui/consts/issue-73976-polymorphic.stderr +++ b/tests/ui/consts/issue-73976-polymorphic.stderr @@ -1,4 +1,4 @@ -error[E0158]: constant pattern depends on a generic parameter, which is not allowed +error[E0158]: constant pattern cannot depend on generic parameters --> $DIR/issue-73976-polymorphic.rs:20:37 | LL | impl GetTypeId { @@ -7,11 +7,11 @@ LL | pub const VALUE: TypeId = TypeId::of::(); | ----------------------- constant defined here ... LL | const fn check_type_id() -> bool { - | - constant depends on this generic param + | - constant depends on this generic parameter LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) | ^^^^^^^^^^^^^^^^^^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter, which is not allowed +error[E0158]: constant pattern cannot depend on generic parameters --> $DIR/issue-73976-polymorphic.rs:31:42 | LL | impl GetTypeNameLen { @@ -20,7 +20,7 @@ LL | pub const VALUE: usize = any::type_name::().len(); | ---------------------- constant defined here ... LL | const fn check_type_name_len() -> bool { - | - constant depends on this generic param + | - constant depends on this generic parameter LL | matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `const` depends on a generic parameter diff --git a/tests/ui/consts/issue-79137-toogeneric.rs b/tests/ui/consts/issue-79137-toogeneric.rs index a80c9f48d7bc9..43e06f3d6766b 100644 --- a/tests/ui/consts/issue-79137-toogeneric.rs +++ b/tests/ui/consts/issue-79137-toogeneric.rs @@ -10,7 +10,7 @@ impl GetVariantCount { const fn check_variant_count() -> bool { matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) - //~^ ERROR constant pattern depends on a generic parameter + //~^ ERROR constant pattern cannot depend on generic parameters } fn main() { diff --git a/tests/ui/consts/issue-79137-toogeneric.stderr b/tests/ui/consts/issue-79137-toogeneric.stderr index d36f3ecbb7690..33e32a7d15dca 100644 --- a/tests/ui/consts/issue-79137-toogeneric.stderr +++ b/tests/ui/consts/issue-79137-toogeneric.stderr @@ -1,4 +1,4 @@ -error[E0158]: constant pattern depends on a generic parameter, which is not allowed +error[E0158]: constant pattern cannot depend on generic parameters --> $DIR/issue-79137-toogeneric.rs:12:43 | LL | impl GetVariantCount { @@ -7,7 +7,7 @@ LL | pub const VALUE: usize = std::mem::variant_count::(); | ---------------------- constant defined here ... LL | const fn check_variant_count() -> bool { - | - constant depends on this generic param + | - constant depends on this generic parameter LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `const` depends on a generic parameter diff --git a/tests/ui/inline-const/const-match-pat-generic.rs b/tests/ui/inline-const/const-match-pat-generic.rs index 9d76fc2ad65bc..889c015e9acb3 100644 --- a/tests/ui/inline-const/const-match-pat-generic.rs +++ b/tests/ui/inline-const/const-match-pat-generic.rs @@ -5,7 +5,7 @@ fn foo() { match 0 { const { V } => {}, - //~^ ERROR constant pattern depends on a generic parameter + //~^ ERROR constant pattern cannot depend on generic parameters _ => {}, } } @@ -17,7 +17,7 @@ const fn f(x: usize) -> usize { fn bar() { match 0 { const { f(V) } => {}, - //~^ ERROR constant pattern depends on a generic parameter + //~^ ERROR constant pattern cannot depend on generic parameters _ => {}, } } diff --git a/tests/ui/inline-const/const-match-pat-generic.stderr b/tests/ui/inline-const/const-match-pat-generic.stderr index cf48161b5e3d6..7d9e1d9e407e1 100644 --- a/tests/ui/inline-const/const-match-pat-generic.stderr +++ b/tests/ui/inline-const/const-match-pat-generic.stderr @@ -1,10 +1,10 @@ -error[E0158]: constant pattern depends on a generic parameter, which is not allowed +error[E0158]: constant pattern cannot depend on generic parameters --> $DIR/const-match-pat-generic.rs:7:9 | LL | const { V } => {}, | ^^^^^^^^^^^ `const` depends on a generic parameter -error[E0158]: constant pattern depends on a generic parameter, which is not allowed +error[E0158]: constant pattern cannot depend on generic parameters --> $DIR/const-match-pat-generic.rs:19:9 | LL | const { f(V) } => {}, From 03aec5dbef301219a288c46401d2bf0079724929 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 16 Nov 2024 19:00:28 +0000 Subject: [PATCH 21/21] fn_sig_for_fn_abi should return a ty::FnSig, no need for a binder --- compiler/rustc_mir_transform/src/shim.rs | 4 +- compiler/rustc_ty_utils/src/abi.rs | 130 +++++++++-------------- 2 files changed, 52 insertions(+), 82 deletions(-) diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 809357ec11009..b8383e734e2ba 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -747,8 +747,8 @@ fn build_call_shim<'tcx>( sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output); } - // FIXME(eddyb) avoid having this snippet both here and in - // `Instance::fn_sig` (introduce `InstanceKind::fn_sig`?). + // FIXME: Avoid having to adjust the signature both here and in + // `fn_sig_for_fn_abi`. if let ty::InstanceKind::VTableShim(..) = instance { // Modify fn(self, ...) to fn(self: *mut Self, ...) let mut inputs_and_output = sig.inputs_and_output.to_vec(); diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index a5a9125c8b509..b746d6299efda 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -31,20 +31,20 @@ fn fn_sig_for_fn_abi<'tcx>( tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>, typing_env: ty::TypingEnv<'tcx>, -) -> ty::PolyFnSig<'tcx> { +) -> ty::FnSig<'tcx> { if let InstanceKind::ThreadLocalShim(..) = instance.def { - return ty::Binder::dummy(tcx.mk_fn_sig( + return tcx.mk_fn_sig( [], tcx.thread_local_ptr_ty(instance.def_id()), false, hir::Safety::Safe, rustc_abi::ExternAbi::Unadjusted, - )); + ); } let ty = instance.ty(tcx, typing_env); match *ty.kind() { - ty::FnDef(..) => { + ty::FnDef(def_id, args) => { // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering // parameters unused if they show up in the signature, but not in the `mir::Body` // (i.e. due to being inside a projection that got normalized, see @@ -52,9 +52,8 @@ fn fn_sig_for_fn_abi<'tcx>( // track of a polymorphization `ParamEnv` to allow normalizing later. // // We normalize the `fn_sig` again after instantiating at a later point. - let mut sig = match *ty.kind() { - ty::FnDef(def_id, args) => tcx - .fn_sig(def_id) + let mut sig = tcx.instantiate_bound_regions_with_erased( + tcx.fn_sig(def_id) .map_bound(|fn_sig| { tcx.normalize_erasing_regions( ty::TypingEnv::non_body_analysis(tcx, def_id), @@ -62,62 +61,36 @@ fn fn_sig_for_fn_abi<'tcx>( ) }) .instantiate(tcx, args), - _ => unreachable!(), - }; + ); if let ty::InstanceKind::VTableShim(..) = instance.def { - // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. - sig = sig.map_bound(|mut sig| { - let mut inputs_and_output = sig.inputs_and_output.to_vec(); - inputs_and_output[0] = Ty::new_mut_ptr(tcx, inputs_and_output[0]); - sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output); - sig - }); + let mut inputs_and_output = sig.inputs_and_output.to_vec(); + inputs_and_output[0] = Ty::new_mut_ptr(tcx, inputs_and_output[0]); + sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output); } + sig } ty::Closure(def_id, args) => { - let sig = args.as_closure().sig(); - - let bound_vars = - tcx.mk_bound_variable_kinds_from_iter(sig.bound_vars().iter().chain(iter::once( - ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv), - ))); - let br = ty::BoundRegion { - var: ty::BoundVar::from_usize(bound_vars.len() - 1), - kind: ty::BoundRegionKind::ClosureEnv, - }; - let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); + let sig = tcx.instantiate_bound_regions_with_erased(args.as_closure().sig()); let env_ty = tcx.closure_env_ty( Ty::new_closure(tcx, def_id, args), args.as_closure().kind(), - env_region, + tcx.lifetimes.re_erased, ); - let sig = sig.skip_binder(); - ty::Binder::bind_with_vars( - tcx.mk_fn_sig( - iter::once(env_ty).chain(sig.inputs().iter().cloned()), - sig.output(), - sig.c_variadic, - sig.safety, - sig.abi, - ), - bound_vars, + tcx.mk_fn_sig( + iter::once(env_ty).chain(sig.inputs().iter().cloned()), + sig.output(), + sig.c_variadic, + sig.safety, + sig.abi, ) } ty::CoroutineClosure(def_id, args) => { let coroutine_ty = Ty::new_coroutine_closure(tcx, def_id, args); let sig = args.as_coroutine_closure().coroutine_closure_sig(); - let bound_vars = - tcx.mk_bound_variable_kinds_from_iter(sig.bound_vars().iter().chain(iter::once( - ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv), - ))); - let br = ty::BoundRegion { - var: ty::BoundVar::from_usize(bound_vars.len() - 1), - kind: ty::BoundRegionKind::ClosureEnv, - }; - let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); + // When this `CoroutineClosure` comes from a `ConstructCoroutineInClosureShim`, // make sure we respect the `target_kind` in that shim. // FIXME(async_closures): This shouldn't be needed, and we should be populating @@ -138,42 +111,32 @@ fn fn_sig_for_fn_abi<'tcx>( coroutine_ty } } else { - tcx.closure_env_ty(coroutine_ty, coroutine_kind, env_region) + tcx.closure_env_ty(coroutine_ty, coroutine_kind, tcx.lifetimes.re_erased) }; - let sig = sig.skip_binder(); - ty::Binder::bind_with_vars( - tcx.mk_fn_sig( - iter::once(env_ty).chain([sig.tupled_inputs_ty]), - sig.to_coroutine_given_kind_and_upvars( - tcx, - args.as_coroutine_closure().parent_args(), - tcx.coroutine_for_closure(def_id), - coroutine_kind, - env_region, - args.as_coroutine_closure().tupled_upvars_ty(), - args.as_coroutine_closure().coroutine_captures_by_ref_ty(), - ), - sig.c_variadic, - sig.safety, - sig.abi, + let sig = tcx.instantiate_bound_regions_with_erased(sig); + + tcx.mk_fn_sig( + iter::once(env_ty).chain([sig.tupled_inputs_ty]), + sig.to_coroutine_given_kind_and_upvars( + tcx, + args.as_coroutine_closure().parent_args(), + tcx.coroutine_for_closure(def_id), + coroutine_kind, + tcx.lifetimes.re_erased, + args.as_coroutine_closure().tupled_upvars_ty(), + args.as_coroutine_closure().coroutine_captures_by_ref_ty(), ), - bound_vars, + sig.c_variadic, + sig.safety, + sig.abi, ) } ty::Coroutine(did, args) => { let coroutine_kind = tcx.coroutine_kind(did).unwrap(); let sig = args.as_coroutine().sig(); - let bound_vars = tcx.mk_bound_variable_kinds_from_iter(iter::once( - ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv), - )); - let br = ty::BoundRegion { - var: ty::BoundVar::from_usize(bound_vars.len() - 1), - kind: ty::BoundRegionKind::ClosureEnv, - }; - - let env_ty = Ty::new_mut_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), ty); + let env_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty); let pin_did = tcx.require_lang_item(LangItem::Pin, None); let pin_adt_ref = tcx.adt_def(pin_did); @@ -268,7 +231,7 @@ fn fn_sig_for_fn_abi<'tcx>( } }; - let fn_sig = if let Some(resume_ty) = resume_ty { + if let Some(resume_ty) = resume_ty { tcx.mk_fn_sig( [env_ty, resume_ty], ret_ty, @@ -285,8 +248,7 @@ fn fn_sig_for_fn_abi<'tcx>( hir::Safety::Safe, rustc_abi::ExternAbi::Rust, ) - }; - ty::Binder::bind_with_vars(fn_sig, bound_vars) + } } _ => bug!("unexpected type {:?} in Instance::fn_sig", ty), } @@ -335,8 +297,16 @@ fn fn_abi_of_fn_ptr<'tcx>( query: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)>, ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> { let ty::PseudoCanonicalInput { typing_env, value: (sig, extra_args) } = query; + let cx = LayoutCx::new(tcx, typing_env); - fn_abi_new_uncached(&cx, sig, extra_args, None, None, false) + fn_abi_new_uncached( + &cx, + tcx.instantiate_bound_regions_with_erased(sig), + extra_args, + None, + None, + false, + ) } fn fn_abi_of_instance<'tcx>( @@ -567,7 +537,7 @@ fn fn_abi_sanity_check<'tcx>( #[tracing::instrument(level = "debug", skip(cx, caller_location, fn_def_id, force_thin_self_ptr))] fn fn_abi_new_uncached<'tcx>( cx: &LayoutCx<'tcx>, - sig: ty::PolyFnSig<'tcx>, + sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>], caller_location: Option>, fn_def_id: Option, @@ -575,7 +545,7 @@ fn fn_abi_new_uncached<'tcx>( force_thin_self_ptr: bool, ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> { let tcx = cx.tcx(); - let sig = tcx.normalize_erasing_late_bound_regions(cx.typing_env, sig); + let sig = tcx.normalize_erasing_regions(cx.typing_env, sig); let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic);