@@ -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,94 @@ 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
+ // This will always cause a structural resolve error, but we do it
1672
+ // so we don't need to manually report an E0282 both on this codepath
1673
+ // and in the others; it all happens in `structurally_resolve_type`.
1674
+ ( None , None ) => self . next_ty_var ( inner_expr. span ) ,
1675
+ } ;
1676
+
1677
+ let binder_ty = self . structurally_resolve_type ( inner_expr. span , binder_ty) ;
1678
+ let hint_ty = match * binder_ty. kind ( ) {
1679
+ ty:: UnsafeBinder ( binder) => self . instantiate_binder_with_fresh_vars (
1680
+ inner_expr. span ,
1681
+ infer:: BoundRegionConversionTime :: HigherRankedType ,
1682
+ binder. into ( ) ,
1683
+ ) ,
1684
+ ty:: Error ( e) => Ty :: new_error ( self . tcx , e) ,
1685
+ _ => {
1686
+ let guar = self
1687
+ . dcx ( )
1688
+ . struct_span_err (
1689
+ hir_ty. map_or ( span, |hir_ty| hir_ty. span ) ,
1690
+ format ! (
1691
+ "`wrap_binder!()` can only wrap into unsafe binder, not {}" ,
1692
+ binder_ty. sort_string( self . tcx)
1693
+ ) ,
1694
+ )
1695
+ . with_note ( "unsafe binders are the only valid output of wrap" )
1696
+ . emit ( ) ;
1697
+ Ty :: new_error ( self . tcx , guar)
1698
+ }
1699
+ } ;
1700
+
1701
+ self . check_expr_has_type_or_error ( inner_expr, hint_ty, |_| { } ) ;
1702
+
1703
+ binder_ty
1704
+ }
1705
+ hir:: UnsafeBinderCastKind :: Unwrap => {
1706
+ let ascribed_ty =
1707
+ hir_ty. map ( |hir_ty| self . lower_ty_saving_user_provided_ty ( hir_ty) ) ;
1708
+ let hint_ty = ascribed_ty. unwrap_or_else ( || self . next_ty_var ( inner_expr. span ) ) ;
1709
+ // FIXME(unsafe_binders): coerce here if needed?
1710
+ let binder_ty = self . check_expr_has_type_or_error ( inner_expr, hint_ty, |_| { } ) ;
1711
+
1712
+ // Unwrap the binder. This will be ambiguous if it's an infer var, and will error
1713
+ // if it's not an unsafe binder.
1714
+ let binder_ty = self . structurally_resolve_type ( inner_expr. span , binder_ty) ;
1715
+ match * binder_ty. kind ( ) {
1716
+ ty:: UnsafeBinder ( binder) => self . instantiate_binder_with_fresh_vars (
1717
+ inner_expr. span ,
1718
+ infer:: BoundRegionConversionTime :: HigherRankedType ,
1719
+ binder. into ( ) ,
1720
+ ) ,
1721
+ ty:: Error ( e) => Ty :: new_error ( self . tcx , e) ,
1722
+ _ => {
1723
+ let guar = self
1724
+ . dcx ( )
1725
+ . struct_span_err (
1726
+ hir_ty. map_or ( inner_expr. span , |hir_ty| hir_ty. span ) ,
1727
+ format ! (
1728
+ "expected unsafe binder, found {} as input of \
1729
+ `unwrap_binder!()`",
1730
+ binder_ty. sort_string( self . tcx)
1731
+ ) ,
1732
+ )
1733
+ . with_note ( "only an unsafe binder type can be unwrapped" )
1734
+ . emit ( ) ;
1735
+ Ty :: new_error ( self . tcx , guar)
1736
+ }
1737
+ }
1738
+ }
1739
+ }
1660
1740
}
1661
1741
1662
1742
fn check_expr_array (
0 commit comments