@@ -1645,14 +1645,71 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16451645
16461646 fn check_expr_unsafe_binder_cast (
16471647 & self ,
1648- _kind : hir:: UnsafeBinderCastKind ,
1648+ kind : hir:: UnsafeBinderCastKind ,
16491649 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 > ,
16521652 ) -> 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+ }
16561713 }
16571714
16581715 fn check_expr_array (
0 commit comments