Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 3795886

Browse files
committed
Split check for PartialEq impl into a method
1 parent b2532a8 commit 3795886

File tree

1 file changed

+35
-28
lines changed

1 file changed

+35
-28
lines changed

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -159,34 +159,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
159159
}
160160
});
161161

162-
// double-check there even *is* a semantic `PartialEq` to dispatch to.
163-
//
164-
// (If there isn't, then we can safely issue a hard
165-
// error, because that's never worked, due to compiler
166-
// using `PartialEq::eq` in this scenario in the past.)
167-
//
168-
// Note: To fix rust-lang/rust#65466, one could lift this check
169-
// *before* any structural-match checking, and unconditionally error
170-
// if `PartialEq` is not implemented. However, that breaks stable
171-
// code at the moment, because types like `for <'a> fn(&'a ())` do
172-
// not *yet* implement `PartialEq`. So for now we leave this here.
173-
let ty_is_partial_eq: bool = {
174-
let partial_eq_trait_id =
175-
self.tcx().require_lang_item(hir::LangItem::PartialEq, Some(self.span));
176-
let obligation: PredicateObligation<'_> = predicate_for_trait_def(
177-
self.tcx(),
178-
self.param_env,
179-
ObligationCause::misc(self.span, self.id),
180-
partial_eq_trait_id,
181-
0,
182-
cv.ty,
183-
&[],
184-
);
185-
// FIXME: should this call a `predicate_must_hold` variant instead?
186-
self.infcx.predicate_may_hold(&obligation)
187-
};
188-
189-
if !ty_is_partial_eq {
162+
if !self.type_has_partial_eq_impl(cv.ty) {
190163
// span_fatal avoids ICE from resolution of non-existent method (rare case).
191164
self.tcx().sess.span_fatal(self.span, &msg);
192165
} else if mir_structural_match_violation {
@@ -208,6 +181,40 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
208181
inlined_const_as_pat
209182
}
210183

184+
fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
185+
// double-check there even *is* a semantic `PartialEq` to dispatch to.
186+
//
187+
// (If there isn't, then we can safely issue a hard
188+
// error, because that's never worked, due to compiler
189+
// using `PartialEq::eq` in this scenario in the past.)
190+
let partial_eq_trait_id =
191+
self.tcx().require_lang_item(hir::LangItem::PartialEq, Some(self.span));
192+
let obligation: PredicateObligation<'_> = predicate_for_trait_def(
193+
self.tcx(),
194+
self.param_env,
195+
ObligationCause::misc(self.span, self.id),
196+
partial_eq_trait_id,
197+
0,
198+
ty,
199+
&[],
200+
);
201+
// FIXME: should this call a `predicate_must_hold` variant instead?
202+
203+
let has_impl = self.infcx.predicate_may_hold(&obligation);
204+
205+
// Note: To fix rust-lang/rust#65466, we could just remove this type
206+
// walk hack for function pointers, and unconditionally error
207+
// if `PartialEq` is not implemented. However, that breaks stable
208+
// code at the moment, because types like `for <'a> fn(&'a ())` do
209+
// not *yet* implement `PartialEq`. So for now we leave this here.
210+
has_impl
211+
|| ty.walk().any(|t| match t.unpack() {
212+
ty::subst::GenericArgKind::Lifetime(_) => false,
213+
ty::subst::GenericArgKind::Type(t) => t.is_fn_ptr(),
214+
ty::subst::GenericArgKind::Const(_) => false,
215+
})
216+
}
217+
211218
// Recursive helper for `to_pat`; invoke that (instead of calling this directly).
212219
fn recur(&self, cv: &'tcx ty::Const<'tcx>) -> Pat<'tcx> {
213220
let id = self.id;

0 commit comments

Comments
 (0)