@@ -574,8 +574,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
574
574
self . check_expr_index ( base, idx, expr, brackets_span)
575
575
}
576
576
ExprKind :: Yield ( value, _) => self . check_expr_yield ( value, expr) ,
577
- ExprKind :: UnsafeBinderCast ( kind, expr , ty) => {
578
- self . check_expr_unsafe_binder_cast ( kind, expr , ty, expected)
577
+ ExprKind :: UnsafeBinderCast ( kind, inner_expr , ty) => {
578
+ self . check_expr_unsafe_binder_cast ( expr . span , kind, inner_expr , ty, expected)
579
579
}
580
580
ExprKind :: Err ( guar) => Ty :: new_error ( tcx, guar) ,
581
581
}
@@ -1649,14 +1649,91 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1649
1649
1650
1650
fn check_expr_unsafe_binder_cast (
1651
1651
& self ,
1652
- _kind : hir:: UnsafeBinderCastKind ,
1653
- expr : & ' tcx hir:: Expr < ' tcx > ,
1654
- _hir_ty : Option < & ' tcx hir:: Ty < ' tcx > > ,
1655
- _expected : Expectation < ' tcx > ,
1652
+ span : Span ,
1653
+ kind : hir:: UnsafeBinderCastKind ,
1654
+ inner_expr : & ' tcx hir:: Expr < ' tcx > ,
1655
+ hir_ty : Option < & ' tcx hir:: Ty < ' tcx > > ,
1656
+ expected : Expectation < ' tcx > ,
1656
1657
) -> Ty < ' tcx > {
1657
- let guar =
1658
- self . dcx ( ) . struct_span_err ( expr. span , "unsafe binders are not yet implemented" ) . emit ( ) ;
1659
- Ty :: new_error ( self . tcx , guar)
1658
+ self . dcx ( ) . span_err ( inner_expr. span , "unsafe binder casts are not fully implemented" ) ;
1659
+
1660
+ match kind {
1661
+ hir:: UnsafeBinderCastKind :: Wrap => {
1662
+ let ascribed_ty =
1663
+ hir_ty. map ( |hir_ty| self . lower_ty_saving_user_provided_ty ( hir_ty) ) ;
1664
+ let expected_ty = expected. only_has_type ( self ) ;
1665
+ let binder_ty = match ( ascribed_ty, expected_ty) {
1666
+ ( Some ( ascribed_ty) , Some ( expected_ty) ) => {
1667
+ self . demand_eqtype ( inner_expr. span , expected_ty, ascribed_ty) ;
1668
+ expected_ty
1669
+ }
1670
+ ( Some ( ty) , None ) | ( None , Some ( ty) ) => ty,
1671
+ ( None , None ) => self . next_ty_var ( inner_expr. span ) ,
1672
+ } ;
1673
+
1674
+ let binder_ty = self . structurally_resolve_type ( inner_expr. span , binder_ty) ;
1675
+ let hint_ty = match * binder_ty. kind ( ) {
1676
+ ty:: UnsafeBinder ( binder) => self . instantiate_binder_with_fresh_vars (
1677
+ inner_expr. span ,
1678
+ infer:: BoundRegionConversionTime :: HigherRankedType ,
1679
+ binder. into ( ) ,
1680
+ ) ,
1681
+ ty:: Error ( e) => Ty :: new_error ( self . tcx , e) ,
1682
+ _ => {
1683
+ let guar = self
1684
+ . dcx ( )
1685
+ . struct_span_err (
1686
+ hir_ty. map_or ( span, |hir_ty| hir_ty. span ) ,
1687
+ format ! (
1688
+ "`wrap_binder!()` can only wrap into unsafe binder, not {}" ,
1689
+ binder_ty. sort_string( self . tcx)
1690
+ ) ,
1691
+ )
1692
+ . with_note ( "unsafe binders are the only valid output of wrap" )
1693
+ . emit ( ) ;
1694
+ Ty :: new_error ( self . tcx , guar)
1695
+ }
1696
+ } ;
1697
+
1698
+ self . check_expr_has_type_or_error ( inner_expr, hint_ty, |_| { } ) ;
1699
+
1700
+ binder_ty
1701
+ }
1702
+ hir:: UnsafeBinderCastKind :: Unwrap => {
1703
+ let ascribed_ty =
1704
+ hir_ty. map ( |hir_ty| self . lower_ty_saving_user_provided_ty ( hir_ty) ) ;
1705
+ let hint_ty = ascribed_ty. unwrap_or_else ( || self . next_ty_var ( inner_expr. span ) ) ;
1706
+ // FIXME(unsafe_binders): coerce here if needed?
1707
+ let binder_ty = self . check_expr_has_type_or_error ( inner_expr, hint_ty, |_| { } ) ;
1708
+
1709
+ // Unwrap the binder. This will be ambiguous if it's an infer var, and will error
1710
+ // if it's not an unsafe binder.
1711
+ let binder_ty = self . structurally_resolve_type ( inner_expr. span , binder_ty) ;
1712
+ match * binder_ty. kind ( ) {
1713
+ ty:: UnsafeBinder ( binder) => self . instantiate_binder_with_fresh_vars (
1714
+ inner_expr. span ,
1715
+ infer:: BoundRegionConversionTime :: HigherRankedType ,
1716
+ binder. into ( ) ,
1717
+ ) ,
1718
+ ty:: Error ( e) => Ty :: new_error ( self . tcx , e) ,
1719
+ _ => {
1720
+ let guar = self
1721
+ . dcx ( )
1722
+ . struct_span_err (
1723
+ hir_ty. map_or ( inner_expr. span , |hir_ty| hir_ty. span ) ,
1724
+ format ! (
1725
+ "expected unsafe binder, found {} as input of \
1726
+ `unwrap_binder!()`",
1727
+ binder_ty. sort_string( self . tcx)
1728
+ ) ,
1729
+ )
1730
+ . with_note ( "only an unsafe binder type can be unwrapped" )
1731
+ . emit ( ) ;
1732
+ Ty :: new_error ( self . tcx , guar)
1733
+ }
1734
+ }
1735
+ }
1736
+ }
1660
1737
}
1661
1738
1662
1739
fn check_expr_array (
0 commit comments