1
+ use std:: ops:: ControlFlow ;
2
+
1
3
use rustc_abi:: { FieldIdx , VariantIdx } ;
2
4
use rustc_apfloat:: Float ;
3
5
use rustc_data_structures:: fx:: FxHashSet ;
@@ -187,7 +189,7 @@ impl<'tcx> ConstToPat<'tcx> {
187
189
188
190
if !inlined_const_as_pat. references_error ( ) {
189
191
// Always check for `PartialEq` if we had no other errors yet.
190
- if !type_has_partial_eq_impl ( self . tcx , typing_env, ty) . 0 {
192
+ if !type_has_partial_eq_impl ( self . tcx , typing_env, ty) . has_impl {
191
193
let mut err = self . tcx . dcx ( ) . create_err ( TypeNotPartialEq { span : self . span , ty } ) ;
192
194
extend_type_not_partial_eq ( self . tcx , typing_env, ty, & mut err) ;
193
195
return self . mk_err ( err, ty) ;
@@ -221,12 +223,13 @@ impl<'tcx> ConstToPat<'tcx> {
221
223
// Extremely important check for all ADTs! Make sure they opted-in to be used in
222
224
// patterns.
223
225
debug ! ( "adt_def {:?} has !type_marked_structural for cv.ty: {:?}" , adt_def, ty) ;
224
- let ( _impls_partial_eq, derived, structural, impl_def_id) =
225
- type_has_partial_eq_impl ( self . tcx , self . typing_env , ty) ;
226
+ let PartialEqImplStatus {
227
+ is_derived, structural_partial_eq, non_blanket_impl, ..
228
+ } = type_has_partial_eq_impl ( self . tcx , self . typing_env , ty) ;
226
229
let ( manual_partialeq_impl_span, manual_partialeq_impl_note) =
227
- match ( structural , impl_def_id ) {
230
+ match ( structural_partial_eq , non_blanket_impl ) {
228
231
( true , _) => ( None , false ) ,
229
- ( _, Some ( def_id) ) if def_id. is_local ( ) && !derived => {
232
+ ( _, Some ( def_id) ) if def_id. is_local ( ) && !is_derived => {
230
233
( Some ( tcx. def_span ( def_id) ) , false )
231
234
}
232
235
_ => ( None , true ) ,
@@ -390,15 +393,24 @@ fn extend_type_not_partial_eq<'tcx>(
390
393
}
391
394
392
395
impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for UsedParamsNeedInstantiationVisitor < ' tcx > {
393
- fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> Self :: Result {
396
+ type Result = ControlFlow < ( ) > ;
397
+ fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> ControlFlow < ( ) > {
394
398
if ty. has_escaping_bound_vars ( ) {
395
399
self . has_escaping_bound_vars = true ;
400
+ return ControlFlow :: Break ( ( ) ) ;
401
+ } else if let ty:: Dynamic ( ..) = ty. kind ( ) {
402
+ self . has_escaping_bound_vars = true ;
403
+ return ControlFlow :: Break ( ( ) ) ;
396
404
} else if let ty:: Adt ( def, _args) = ty. kind ( ) {
397
405
let ty_def_id = def. did ( ) ;
398
406
let ty_def_span = self . tcx . def_span ( ty_def_id) ;
399
- let ( impls_partial_eq, derived, structural, impl_def_id) =
400
- type_has_partial_eq_impl ( self . tcx , self . typing_env , ty) ;
401
- match ( impls_partial_eq, derived, structural, impl_def_id) {
407
+ let PartialEqImplStatus {
408
+ has_impl,
409
+ is_derived,
410
+ structural_partial_eq,
411
+ non_blanket_impl,
412
+ } = type_has_partial_eq_impl ( self . tcx , self . typing_env , ty) ;
413
+ match ( has_impl, is_derived, structural_partial_eq, non_blanket_impl) {
402
414
( _, _, true , _) => { }
403
415
( true , false , _, Some ( def_id) ) if def_id. is_local ( ) => {
404
416
self . adts_with_manual_partialeq . insert ( self . tcx . def_span ( def_id) ) ;
@@ -459,17 +471,20 @@ fn extend_type_not_partial_eq<'tcx>(
459
471
}
460
472
}
461
473
474
+ #[ derive( Debug ) ]
475
+ struct PartialEqImplStatus {
476
+ has_impl : bool ,
477
+ is_derived : bool ,
478
+ structural_partial_eq : bool ,
479
+ non_blanket_impl : Option < DefId > ,
480
+ }
481
+
462
482
#[ instrument( level = "trace" , skip( tcx) , ret) ]
463
483
fn type_has_partial_eq_impl < ' tcx > (
464
484
tcx : TyCtxt < ' tcx > ,
465
485
typing_env : ty:: TypingEnv < ' tcx > ,
466
486
ty : Ty < ' tcx > ,
467
- ) -> (
468
- /* has impl */ bool ,
469
- /* is derived */ bool ,
470
- /* structural partial eq */ bool ,
471
- /* non-blanket impl */ Option < DefId > ,
472
- ) {
487
+ ) -> PartialEqImplStatus {
473
488
let ( infcx, param_env) = tcx. infer_ctxt ( ) . build_with_typing_env ( typing_env) ;
474
489
// double-check there even *is* a semantic `PartialEq` to dispatch to.
475
490
//
@@ -479,10 +494,6 @@ fn type_has_partial_eq_impl<'tcx>(
479
494
let partial_eq_trait_id = tcx. require_lang_item ( hir:: LangItem :: PartialEq , None ) ;
480
495
let structural_partial_eq_trait_id = tcx. require_lang_item ( hir:: LangItem :: StructuralPeq , None ) ;
481
496
482
- if ty. has_escaping_bound_vars ( ) {
483
- return ( false , false , false , None ) ;
484
- }
485
-
486
497
let partial_eq_obligation = Obligation :: new (
487
498
tcx,
488
499
ObligationCause :: dummy ( ) ,
@@ -510,10 +521,10 @@ fn type_has_partial_eq_impl<'tcx>(
510
521
// that patterns can only do things that the code could also do without patterns, but it is
511
522
// needed for backwards compatibility. The actual pattern matching compares primitive values,
512
523
// `PartialEq::eq` never gets invoked, so there's no risk of us running non-const code.
513
- (
514
- infcx. predicate_must_hold_modulo_regions ( & partial_eq_obligation) ,
515
- automatically_derived,
516
- structural_peq,
517
- impl_def_id,
518
- )
524
+ PartialEqImplStatus {
525
+ has_impl : infcx. predicate_must_hold_modulo_regions ( & partial_eq_obligation) ,
526
+ is_derived : automatically_derived,
527
+ structural_partial_eq : structural_peq,
528
+ non_blanket_impl : impl_def_id,
529
+ }
519
530
}
0 commit comments