@@ -1627,6 +1627,16 @@ impl<M: RemoteMessage> PortHandle<M> {
1627
1627
/// This is used by [`actor::Binder`] implementations to bind actor refs.
1628
1628
/// This is not intended for general use.
1629
1629
pub ( crate ) fn bind_actor_port ( & self ) {
1630
+ let port_id = self . mailbox . actor_id ( ) . port_id ( M :: port ( ) ) ;
1631
+ self . bound
1632
+ . set ( port_id)
1633
+ . map_err ( |p| {
1634
+ format ! (
1635
+ "could not bind port handle {} as {p}: already bound" ,
1636
+ self . port_index
1637
+ )
1638
+ } )
1639
+ . unwrap ( ) ;
1630
1640
self . mailbox . bind_to_actor_port ( self ) ;
1631
1641
}
1632
1642
}
@@ -3746,4 +3756,41 @@ mod tests {
3746
3756
. unwrap ( ) ;
3747
3757
assert_eq ! ( rx. recv( ) . await . unwrap( ) , ( 1 , "hello" . to_string( ) ) ) ;
3748
3758
}
3759
+
3760
+ #[ test]
3761
+ #[ should_panic( expected = "already bound" ) ]
3762
+ fn test_bind_port_handle_to_actor_port_twice ( ) {
3763
+ let mbox = Mailbox :: new_detached ( id ! ( test[ 0 ] . test) ) ;
3764
+ let ( handle, _rx) = mbox. open_port :: < String > ( ) ;
3765
+ handle. bind_actor_port ( ) ;
3766
+ handle. bind_actor_port ( ) ;
3767
+ }
3768
+
3769
+ #[ test]
3770
+ fn test_bind_port_handle_to_actor_port ( ) {
3771
+ let mbox = Mailbox :: new_detached ( id ! ( test[ 0 ] . test) ) ;
3772
+ let default_port = mbox. actor_id ( ) . port_id ( String :: port ( ) ) ;
3773
+ let ( handle, _rx) = mbox. open_port :: < String > ( ) ;
3774
+ // Handle's port index is allocated by mailbox, not the actor port.
3775
+ assert_ne ! ( default_port. index( ) , handle. port_index) ;
3776
+ // Bind the handle to the actor port.
3777
+ handle. bind_actor_port ( ) ;
3778
+ assert_matches ! ( handle. location( ) , PortLocation :: Bound ( port) if port == default_port) ;
3779
+ // bind() can still be used, just it will not change handle's state.
3780
+ handle. bind ( ) ;
3781
+ handle. bind ( ) ;
3782
+ assert_matches ! ( handle. location( ) , PortLocation :: Bound ( port) if port == default_port) ;
3783
+ }
3784
+
3785
+ #[ test]
3786
+ #[ should_panic( expected = "already bound" ) ]
3787
+ fn test_bind_port_handle_to_actor_port_when_already_bound ( ) {
3788
+ let mbox = Mailbox :: new_detached ( id ! ( test[ 0 ] . test) ) ;
3789
+ let ( handle, _rx) = mbox. open_port :: < String > ( ) ;
3790
+ // Bound handle to the port allocated by mailbox.
3791
+ handle. bind ( ) ;
3792
+ assert_matches ! ( handle. location( ) , PortLocation :: Bound ( port) if port. index( ) == handle. port_index) ;
3793
+ // Since handle is already bound, call bind_to() on it will cause panic.
3794
+ handle. bind_actor_port ( ) ;
3795
+ }
3749
3796
}
0 commit comments