@@ -1645,14 +1645,71 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1645
1645
1646
1646
fn check_expr_unsafe_binder_cast (
1647
1647
& self ,
1648
- _kind : hir:: UnsafeBinderCastKind ,
1648
+ kind : hir:: UnsafeBinderCastKind ,
1649
1649
expr : & ' tcx hir:: Expr < ' tcx > ,
1650
- _hir_ty : Option < & ' tcx hir:: Ty < ' tcx > > ,
1651
- _expected : Expectation < ' tcx > ,
1650
+ hir_ty : Option < & ' tcx hir:: Ty < ' tcx > > ,
1651
+ expected : Expectation < ' tcx > ,
1652
1652
) -> Ty < ' tcx > {
1653
- let guar =
1654
- self . dcx ( ) . struct_span_err ( expr. span , "unsafe binders are not yet implemented" ) . emit ( ) ;
1655
- Ty :: new_error ( self . tcx , guar)
1653
+ match kind {
1654
+ hir:: UnsafeBinderCastKind :: Wrap => {
1655
+ let ascribed_ty =
1656
+ hir_ty. map ( |hir_ty| self . lower_ty_saving_user_provided_ty ( hir_ty) ) ;
1657
+ let expected_ty = expected. only_has_type ( self ) ;
1658
+ let binder_ty = match ( ascribed_ty, expected_ty) {
1659
+ ( Some ( ascribed_ty) , Some ( expected_ty) ) => {
1660
+ self . demand_eqtype ( expr. span , expected_ty, ascribed_ty) ;
1661
+ expected_ty
1662
+ }
1663
+ ( Some ( ty) , None ) | ( None , Some ( ty) ) => ty,
1664
+ ( None , None ) => self . next_ty_var ( expr. span ) ,
1665
+ } ;
1666
+
1667
+ // Unwrap the binder eagerly if we can use it to guide inference on
1668
+ // the inner expr. If not, then we'll error *after* type checking.
1669
+ let hint_ty = if let ty:: UnsafeBinder ( binder) =
1670
+ * self . try_structurally_resolve_type ( expr. span , binder_ty) . kind ( )
1671
+ {
1672
+ self . instantiate_binder_with_fresh_vars (
1673
+ expr. span ,
1674
+ infer:: BoundRegionConversionTime :: HigherRankedType ,
1675
+ binder. into ( ) ,
1676
+ )
1677
+ } else {
1678
+ self . next_ty_var ( expr. span )
1679
+ } ;
1680
+
1681
+ self . check_expr_has_type_or_error ( expr, hint_ty, |_| { } ) ;
1682
+
1683
+ let binder_ty = self . structurally_resolve_type ( expr. span , binder_ty) ;
1684
+ match * binder_ty. kind ( ) {
1685
+ ty:: UnsafeBinder ( ..) => {
1686
+ // Ok
1687
+ }
1688
+ _ => todo ! ( ) ,
1689
+ }
1690
+
1691
+ binder_ty
1692
+ }
1693
+ hir:: UnsafeBinderCastKind :: Unwrap => {
1694
+ let ascribed_ty =
1695
+ hir_ty. map ( |hir_ty| self . lower_ty_saving_user_provided_ty ( hir_ty) ) ;
1696
+ let hint_ty = ascribed_ty. unwrap_or_else ( || self . next_ty_var ( expr. span ) ) ;
1697
+ // FIXME(unsafe_binders): coerce here if needed?
1698
+ let binder_ty = self . check_expr_has_type_or_error ( expr, hint_ty, |_| { } ) ;
1699
+
1700
+ // Unwrap the binder. This will be ambiguous if it's an infer var, and will error
1701
+ // if it's not an unsafe binder.
1702
+ let binder_ty = self . structurally_resolve_type ( expr. span , binder_ty) ;
1703
+ match * binder_ty. kind ( ) {
1704
+ ty:: UnsafeBinder ( binder) => self . instantiate_binder_with_fresh_vars (
1705
+ expr. span ,
1706
+ infer:: BoundRegionConversionTime :: HigherRankedType ,
1707
+ binder. into ( ) ,
1708
+ ) ,
1709
+ _ => todo ! ( ) ,
1710
+ }
1711
+ }
1712
+ }
1656
1713
}
1657
1714
1658
1715
fn check_expr_array (
0 commit comments