@@ -25,6 +25,7 @@ use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
25
25
use rustc_session:: lint:: builtin:: WHERE_CLAUSES_OBJECT_SAFETY ;
26
26
use rustc_span:: symbol:: Symbol ;
27
27
use rustc_span:: Span ;
28
+ use rustc_target:: abi:: Abi ;
28
29
use smallvec:: SmallVec ;
29
30
30
31
use std:: iter;
@@ -144,6 +145,14 @@ fn object_safety_violations_for_trait(
144
145
violations. push ( ObjectSafetyViolation :: SupertraitNonLifetimeBinder ( spans) ) ;
145
146
}
146
147
148
+ if violations. is_empty ( ) {
149
+ for item in tcx. associated_items ( trait_def_id) . in_definition_order ( ) {
150
+ if let ty:: AssocKind :: Fn = item. kind {
151
+ check_receiver_correct ( tcx, trait_def_id, * item) ;
152
+ }
153
+ }
154
+ }
155
+
147
156
debug ! (
148
157
"object_safety_violations_for_trait(trait_def_id={:?}) = {:?}" ,
149
158
trait_def_id, violations
@@ -497,59 +506,8 @@ fn virtual_call_violations_for_method<'tcx>(
497
506
} ;
498
507
errors. push ( MethodViolationCode :: UndispatchableReceiver ( span) ) ;
499
508
} else {
500
- // Do sanity check to make sure the receiver actually has the layout of a pointer.
501
-
502
- use rustc_target:: abi:: Abi ;
503
-
504
- let param_env = tcx. param_env ( method. def_id ) ;
505
-
506
- let abi_of_ty = |ty : Ty < ' tcx > | -> Option < Abi > {
507
- match tcx. layout_of ( param_env. and ( ty) ) {
508
- Ok ( layout) => Some ( layout. abi ) ,
509
- Err ( err) => {
510
- // #78372
511
- tcx. dcx ( ) . span_delayed_bug (
512
- tcx. def_span ( method. def_id ) ,
513
- format ! ( "error: {err}\n while computing layout for type {ty:?}" ) ,
514
- ) ;
515
- None
516
- }
517
- }
518
- } ;
519
-
520
- // e.g., `Rc<()>`
521
- let unit_receiver_ty =
522
- receiver_for_self_ty ( tcx, receiver_ty, tcx. types . unit , method. def_id ) ;
523
-
524
- match abi_of_ty ( unit_receiver_ty) {
525
- Some ( Abi :: Scalar ( ..) ) => ( ) ,
526
- abi => {
527
- tcx. dcx ( ) . span_delayed_bug (
528
- tcx. def_span ( method. def_id ) ,
529
- format ! (
530
- "receiver when `Self = ()` should have a Scalar ABI; found {abi:?}"
531
- ) ,
532
- ) ;
533
- }
534
- }
535
-
536
- let trait_object_ty = object_ty_for_trait ( tcx, trait_def_id, tcx. lifetimes . re_static ) ;
537
-
538
- // e.g., `Rc<dyn Trait>`
539
- let trait_object_receiver =
540
- receiver_for_self_ty ( tcx, receiver_ty, trait_object_ty, method. def_id ) ;
541
-
542
- match abi_of_ty ( trait_object_receiver) {
543
- Some ( Abi :: ScalarPair ( ..) ) => ( ) ,
544
- abi => {
545
- tcx. dcx ( ) . span_delayed_bug (
546
- tcx. def_span ( method. def_id ) ,
547
- format ! (
548
- "receiver when `Self = {trait_object_ty}` should have a ScalarPair ABI; found {abi:?}"
549
- ) ,
550
- ) ;
551
- }
552
- }
509
+ // We confirm that the `receiver_is_dispatchable` is accurate later,
510
+ // see `check_receiver_correct`. It should be kept in sync with this code.
553
511
}
554
512
}
555
513
@@ -610,6 +568,55 @@ fn virtual_call_violations_for_method<'tcx>(
610
568
errors
611
569
}
612
570
571
+ /// This code checks that `receiver_is_dispatchable` is correctly implemented.
572
+ ///
573
+ /// This check is outlined from the object safety check to avoid cycles with
574
+ /// layout computation, which relies on knowing whether methods are object safe.
575
+ pub fn check_receiver_correct < ' tcx > ( tcx : TyCtxt < ' tcx > , trait_def_id : DefId , method : ty:: AssocItem ) {
576
+ if !is_vtable_safe_method ( tcx, trait_def_id, method) {
577
+ return ;
578
+ }
579
+
580
+ let method_def_id = method. def_id ;
581
+ let sig = tcx. fn_sig ( method_def_id) . instantiate_identity ( ) ;
582
+ let param_env = tcx. param_env ( method_def_id) ;
583
+ let receiver_ty = tcx. liberate_late_bound_regions ( method_def_id, sig. input ( 0 ) ) ;
584
+
585
+ if receiver_ty == tcx. types . self_param {
586
+ // Assumed OK, may change later if unsized_locals permits `self: Self` as dispatchable.
587
+ return ;
588
+ }
589
+
590
+ // e.g., `Rc<()>`
591
+ let unit_receiver_ty = receiver_for_self_ty ( tcx, receiver_ty, tcx. types . unit , method_def_id) ;
592
+ match tcx. layout_of ( param_env. and ( unit_receiver_ty) ) . map ( |l| l. abi ) {
593
+ Ok ( Abi :: Scalar ( ..) ) => ( ) ,
594
+ abi => {
595
+ tcx. dcx ( ) . span_delayed_bug (
596
+ tcx. def_span ( method_def_id) ,
597
+ format ! ( "receiver {unit_receiver_ty:?} when `Self = ()` should have a Scalar ABI; found {abi:?}" ) ,
598
+ ) ;
599
+ }
600
+ }
601
+
602
+ let trait_object_ty = object_ty_for_trait ( tcx, trait_def_id, tcx. lifetimes . re_static ) ;
603
+
604
+ // e.g., `Rc<dyn Trait>`
605
+ let trait_object_receiver =
606
+ receiver_for_self_ty ( tcx, receiver_ty, trait_object_ty, method_def_id) ;
607
+ match tcx. layout_of ( param_env. and ( trait_object_receiver) ) . map ( |l| l. abi ) {
608
+ Ok ( Abi :: ScalarPair ( ..) ) => ( ) ,
609
+ abi => {
610
+ tcx. dcx ( ) . span_delayed_bug (
611
+ tcx. def_span ( method_def_id) ,
612
+ format ! (
613
+ "receiver {trait_object_receiver:?} when `Self = {trait_object_ty}` should have a ScalarPair ABI; found {abi:?}"
614
+ ) ,
615
+ ) ;
616
+ }
617
+ }
618
+ }
619
+
613
620
/// Performs a type instantiation to produce the version of `receiver_ty` when `Self = self_ty`.
614
621
/// For example, for `receiver_ty = Rc<Self>` and `self_ty = Foo`, returns `Rc<Foo>`.
615
622
fn receiver_for_self_ty < ' tcx > (
0 commit comments