@@ -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