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