From 05c39438e295389e30a580a5376bbed83b1ddfa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 26 Dec 2024 01:30:29 +0000 Subject: [PATCH] Account for `for<'a>` types when checking for non-structural type in constant as pattern When we encounter a constant in a pattern, we check if it is non-structural. If so, we check if the type implements `PartialEq`, but for types with escaping bound vars the check would be incorrect as is, so we break early. This is ok because these types would be filtered anyways. Fix #134764. --- .../src/thir/pattern/const_to_pat.rs | 13 ++++++++++--- .../non_structural_with_escaping_bounds.rs | 15 +++++++++++++++ .../non_structural_with_escaping_bounds.stderr | 15 +++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 tests/ui/consts/const_in_pattern/non_structural_with_escaping_bounds.rs create mode 100644 tests/ui/consts/const_in_pattern/non_structural_with_escaping_bounds.stderr 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 2b3c98db966cd..a1d9b9024ab32 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 @@ -8,7 +8,9 @@ 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, TypeVisitor, ValTree}; +use rustc_middle::ty::{ + self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitableExt, TypeVisitor, ValTree, +}; use rustc_middle::{mir, span_bug}; use rustc_span::def_id::DefId; use rustc_span::{Span, sym}; @@ -387,7 +389,9 @@ fn extend_type_not_partial_eq<'tcx>( impl<'tcx> TypeVisitor> for UsedParamsNeedInstantiationVisitor<'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { - if let ty::Adt(def, _args) = ty.kind() { + if let ty::Adt(def, _args) = ty.kind() + && !ty.has_escaping_bound_vars() + { 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) = @@ -412,7 +416,6 @@ fn extend_type_not_partial_eq<'tcx>( _ => {} }; } - use rustc_middle::ty::TypeSuperVisitable; ty.super_visit_with(self) } } @@ -468,6 +471,10 @@ fn type_has_partial_eq_impl<'tcx>( 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); + if ty.has_escaping_bound_vars() { + return (false, false, false, None); + } + let partial_eq_obligation = Obligation::new( tcx, ObligationCause::dummy(), diff --git a/tests/ui/consts/const_in_pattern/non_structural_with_escaping_bounds.rs b/tests/ui/consts/const_in_pattern/non_structural_with_escaping_bounds.rs new file mode 100644 index 0000000000000..e5d095fd61780 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/non_structural_with_escaping_bounds.rs @@ -0,0 +1,15 @@ +#![feature(structural_match)] +impl std::marker::StructuralPartialEq for O { } + +enum O { + Some(*const T), + None, +} + +const C: O Fn(Box)> = O::None; + +fn main() { + match O::None { + C => (), //~ ERROR constant of non-structural type + } +} diff --git a/tests/ui/consts/const_in_pattern/non_structural_with_escaping_bounds.stderr b/tests/ui/consts/const_in_pattern/non_structural_with_escaping_bounds.stderr new file mode 100644 index 0000000000000..47378569084a4 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/non_structural_with_escaping_bounds.stderr @@ -0,0 +1,15 @@ +error: constant of non-structural type `O Fn(Box)>` in a pattern + --> $DIR/non_structural_with_escaping_bounds.rs:13:9 + | +LL | const C: O Fn(Box)> = O::None; + | ----------------------------------------------- constant defined here +... +LL | C => (), + | ^ constant of non-structural type + | + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + = note: `std::alloc::Global` must be annotated with `#[derive(PartialEq)]` to be usable in patterns + = note: `std::alloc::Global` must be annotated with `#[derive(PartialEq)]` to be usable in patterns + +error: aborting due to 1 previous error +