]> git.lizzy.rs Git - rust.git/commitdiff
typeck: Introduce reification for fn ptr casts.
authorEduard Burtescu <edy.burt@gmail.com>
Thu, 18 Feb 2016 13:18:46 +0000 (15:18 +0200)
committerEduard Burtescu <edy.burt@gmail.com>
Wed, 9 Mar 2016 14:45:29 +0000 (16:45 +0200)
src/librustc/middle/ty/cast.rs
src/librustc_typeck/check/cast.rs

index ac308f564340c318c934c7990a70f1d6e0ce465c..b25d6e0476d9847c4151121baba40ee2b68d9d57 100644 (file)
@@ -69,9 +69,7 @@ pub fn from_ty(t: Ty<'tcx>) -> Option<CastTy<'tcx>> {
                 Some(CastTy::Int(IntTy::CEnum)),
             ty::TyRawPtr(ref mt) => Some(CastTy::Ptr(mt)),
             ty::TyRef(_, ref mt) => Some(CastTy::RPtr(mt)),
-            // FIXME: Treating TyFnDef as a pointer here is a bit dubious;
-            // we should be coercing the operand to an actual pointer.
-            ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(CastTy::FnPtr),
+            ty::TyFnPtr(..) => Some(CastTy::FnPtr),
             _ => None,
         }
     }
index 2ea0df280db216acd409130656059a103fd99502..7168873c1b8a8239ecd9e0589adabb7df776416d 100644 (file)
@@ -235,6 +235,20 @@ fn do_check<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError> {
         let (t_from, t_cast) = match (CastTy::from_ty(self.expr_ty),
                                       CastTy::from_ty(self.cast_ty)) {
             (Some(t_from), Some(t_cast)) => (t_from, t_cast),
+            // Function item types may need to be reified before casts.
+            (None, Some(t_cast)) => {
+                if let ty::TyFnDef(_, _, f) = self.expr_ty.sty {
+                    // Attempt a coercion to a fn pointer type.
+                    let res = coercion::mk_assignty(fcx, &self.expr,
+                        self.expr_ty, fcx.tcx().mk_ty(ty::TyFnPtr(f)));
+                    if !res.is_ok() {
+                        return Err(CastError::NonScalar);
+                    }
+                    (FnPtr, t_cast)
+                } else {
+                    return Err(CastError::NonScalar);
+                }
+            }
             _ => {
                 return Err(CastError::NonScalar)
             }