1
+ use crate :: message:: Message ;
1
2
use crate :: syntax:: atom:: Atom :: * ;
2
3
use crate :: syntax:: attrs:: { self , OtherAttrs } ;
3
4
use crate :: syntax:: cfg:: { CfgExpr , ComputedCfg } ;
@@ -9,6 +10,7 @@ use crate::syntax::report::Errors;
9
10
use crate :: syntax:: symbol:: Symbol ;
10
11
use crate :: syntax:: trivial:: TrivialReason ;
11
12
use crate :: syntax:: types:: ConditionalImpl ;
13
+ use crate :: syntax:: unpin:: UnpinReason ;
12
14
use crate :: syntax:: {
13
15
self , check, mangle, Api , Doc , Enum , ExternFn , ExternType , FnKind , Lang , Lifetimes , Pair ,
14
16
Signature , Struct , Trait , Type , TypeAlias , Types ,
@@ -1424,13 +1426,92 @@ fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream {
1424
1426
TrivialReason :: StructField ( _)
1425
1427
| TrivialReason :: FunctionArgument ( _)
1426
1428
| TrivialReason :: FunctionReturn ( _)
1427
- | TrivialReason :: SliceElement { .. }
1428
- | TrivialReason :: UnpinnedMut ( _) => require_extern_type_trivial = true ,
1429
+ | TrivialReason :: SliceElement { .. } => require_extern_type_trivial = true ,
1429
1430
}
1430
1431
}
1431
1432
}
1432
1433
1433
- if require_unpin {
1434
+ if let Some ( reason) = types. required_unpin . get ( ident) {
1435
+ let ampersand;
1436
+ let reference_lifetime;
1437
+ let mutability;
1438
+ let mut inner;
1439
+ let generics;
1440
+ let shorthand;
1441
+ match reason {
1442
+ UnpinReason :: Receiver ( receiver) => {
1443
+ ampersand = & receiver. ampersand ;
1444
+ reference_lifetime = & receiver. lifetime ;
1445
+ mutability = & receiver. mutability ;
1446
+ inner = receiver. ty . rust . clone ( ) ;
1447
+ generics = & receiver. ty . generics ;
1448
+ shorthand = receiver. shorthand ;
1449
+ if receiver. shorthand {
1450
+ inner. set_span ( receiver. var . span ) ;
1451
+ }
1452
+ }
1453
+ UnpinReason :: Ref ( mutable_reference) => {
1454
+ ampersand = & mutable_reference. ampersand ;
1455
+ reference_lifetime = & mutable_reference. lifetime ;
1456
+ mutability = & mutable_reference. mutability ;
1457
+ let Type :: Ident ( inner_type) = & mutable_reference. inner else {
1458
+ unreachable ! ( ) ;
1459
+ } ;
1460
+ inner = inner_type. rust . clone ( ) ;
1461
+ generics = & inner_type. generics ;
1462
+ shorthand = false ;
1463
+ }
1464
+ }
1465
+ let trait_name = format_ident ! ( "ReferenceToUnpin_{ident}" ) ;
1466
+ let message =
1467
+ format ! ( "mutable reference to C++ type requires a pin -- use Pin<&mut {ident}>" ) ;
1468
+ let label = {
1469
+ let mut label = Message :: new ( ) ;
1470
+ write ! ( label, "use `" ) ;
1471
+ if shorthand {
1472
+ write ! ( label, "self: " ) ;
1473
+ }
1474
+ write ! ( label, "Pin<&" ) ;
1475
+ if let Some ( reference_lifetime) = reference_lifetime {
1476
+ write ! ( label, "{reference_lifetime} " ) ;
1477
+ }
1478
+ write ! ( label, "mut {ident}" ) ;
1479
+ if !generics. lifetimes . is_empty ( ) {
1480
+ write ! ( label, "<" ) ;
1481
+ for ( i, lifetime) in generics. lifetimes . iter ( ) . enumerate ( ) {
1482
+ if i > 0 {
1483
+ write ! ( label, ", " ) ;
1484
+ }
1485
+ write ! ( label, "{lifetime}" ) ;
1486
+ }
1487
+ write ! ( label, ">" ) ;
1488
+ } else if shorthand && !alias. generics . lifetimes . is_empty ( ) {
1489
+ write ! ( label, "<" ) ;
1490
+ for i in 0 ..alias. generics . lifetimes . len ( ) {
1491
+ if i > 0 {
1492
+ write ! ( label, ", " ) ;
1493
+ }
1494
+ write ! ( label, "'_" ) ;
1495
+ }
1496
+ write ! ( label, ">" ) ;
1497
+ }
1498
+ write ! ( label, ">`" ) ;
1499
+ label
1500
+ } ;
1501
+ let lifetimes = generics. to_underscore_lifetimes ( ) ;
1502
+ verify. extend ( quote ! {
1503
+ #attrs
1504
+ let _ = {
1505
+ #[ diagnostic:: on_unimplemented( message = #message, label = #label) ]
1506
+ trait #trait_name {
1507
+ fn check_unpin( ) { }
1508
+ }
1509
+ #[ diagnostic:: do_not_recommend]
1510
+ impl <' a, T : ?:: cxx:: core:: marker:: Sized + :: cxx:: core:: marker:: Unpin > #trait_name for & ' a mut T { }
1511
+ <#ampersand #mutability #inner #lifetimes as #trait_name>:: check_unpin
1512
+ } ;
1513
+ } ) ;
1514
+ } else if require_unpin {
1434
1515
verify. extend ( quote ! {
1435
1516
#attrs
1436
1517
const _: fn ( ) = :: cxx:: private:: require_unpin:: <#ident #lifetimes>;
0 commit comments