diff --git a/src/librustc/middle/ty/cast.rs b/src/librustc/middle/ty/cast.rs index ac308f564340..b25d6e0476d9 100644 --- a/src/librustc/middle/ty/cast.rs +++ b/src/librustc/middle/ty/cast.rs @@ -69,9 +69,7 @@ impl<'tcx> 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, } } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 2ea0df280db2..7168873c1b8a 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -235,6 +235,20 @@ impl<'tcx> CastCheck<'tcx> { 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) }