@@ -340,7 +340,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
340
340
self . check_expr_index ( base, idx, expr, brackets_span)
341
341
}
342
342
ExprKind :: Yield ( value, _) => self . check_expr_yield ( value, expr) ,
343
- hir:: ExprKind :: Err ( guar) => Ty :: new_error ( tcx, guar) ,
343
+ ExprKind :: UnsafeBinderCast ( kind, expr, ty) => {
344
+ self . check_expr_unsafe_binder_cast ( kind, expr, ty, expected)
345
+ }
346
+ ExprKind :: Err ( guar) => Ty :: new_error ( tcx, guar) ,
344
347
}
345
348
}
346
349
@@ -1404,6 +1407,75 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1404
1407
}
1405
1408
}
1406
1409
1410
+ fn check_expr_unsafe_binder_cast (
1411
+ & self ,
1412
+ kind : hir:: UnsafeBinderCastKind ,
1413
+ expr : & ' tcx hir:: Expr < ' tcx > ,
1414
+ hir_ty : Option < & ' tcx hir:: Ty < ' tcx > > ,
1415
+ expected : Expectation < ' tcx > ,
1416
+ ) -> Ty < ' tcx > {
1417
+ match kind {
1418
+ hir:: UnsafeBinderCastKind :: Wrap => {
1419
+ let ascribed_ty =
1420
+ hir_ty. map ( |hir_ty| self . lower_ty_saving_user_provided_ty ( hir_ty) ) ;
1421
+ let expected_ty = expected. only_has_type ( self ) ;
1422
+ let binder_ty = match ( ascribed_ty, expected_ty) {
1423
+ ( Some ( ascribed_ty) , Some ( expected_ty) ) => {
1424
+ self . demand_eqtype ( expr. span , expected_ty, ascribed_ty) ;
1425
+ expected_ty
1426
+ }
1427
+ ( Some ( ty) , None ) | ( None , Some ( ty) ) => ty,
1428
+ ( None , None ) => self . next_ty_var ( expr. span ) ,
1429
+ } ;
1430
+
1431
+ // Unwrap the binder eagerly if we can use it to guide inference on
1432
+ // the inner expr. If not, then we'll error *after* type checking.
1433
+ let hint_ty = if let ty:: UnsafeBinder ( binder) =
1434
+ * self . try_structurally_resolve_type ( expr. span , binder_ty) . kind ( )
1435
+ {
1436
+ self . instantiate_binder_with_fresh_vars (
1437
+ expr. span ,
1438
+ infer:: BoundRegionConversionTime :: HigherRankedType ,
1439
+ binder. into ( ) ,
1440
+ )
1441
+ } else {
1442
+ self . next_ty_var ( expr. span )
1443
+ } ;
1444
+
1445
+ self . check_expr_has_type_or_error ( expr, hint_ty, |_| { } ) ;
1446
+
1447
+ let binder_ty = self . structurally_resolve_type ( expr. span , binder_ty) ;
1448
+ match * binder_ty. kind ( ) {
1449
+ ty:: UnsafeBinder ( ..) => {
1450
+ // Ok
1451
+ }
1452
+ _ => todo ! ( ) ,
1453
+ }
1454
+
1455
+ binder_ty
1456
+ }
1457
+ hir:: UnsafeBinderCastKind :: Unwrap => {
1458
+ let ascribed_ty =
1459
+ hir_ty. map ( |hir_ty| self . lower_ty_saving_user_provided_ty ( hir_ty) ) ;
1460
+ let hint_ty = ascribed_ty. unwrap_or_else ( || self . next_ty_var ( expr. span ) ) ;
1461
+ // FIXME(unsafe_binders): coerce here if needed?
1462
+ let binder_ty = self . check_expr_has_type_or_error ( expr, hint_ty, |_| { } ) ;
1463
+
1464
+ // Unwrap the binder. This will be ambiguous if it's an infer var, and will error
1465
+ // if it's not an unsafe binder.
1466
+ let binder_ty = self . structurally_resolve_type ( expr. span , binder_ty) ;
1467
+ match * binder_ty. kind ( ) {
1468
+ ty:: UnsafeBinder ( binder) => self . instantiate_binder_with_fresh_vars (
1469
+ expr. span ,
1470
+ infer:: BoundRegionConversionTime :: HigherRankedType ,
1471
+ binder. into ( ) ,
1472
+ ) ,
1473
+ _ => todo ! ( ) ,
1474
+ }
1475
+ }
1476
+ }
1477
+ }
1478
+
1407
1479
fn check_expr_array (
1408
1480
& self ,
1409
1481
args : & ' tcx [ hir:: Expr < ' tcx > ] ,
0 commit comments