Index: src/ResolvExpr/CastCost.cc
===================================================================
--- src/ResolvExpr/CastCost.cc	(revision 0f6a775253ac135c7aefa8bf075ce817231ec7d1)
+++ src/ResolvExpr/CastCost.cc	(revision 3c89751935492115e8058617f8a19718dfab085f)
@@ -16,4 +16,8 @@
 #include <cassert>                       // for assert
 
+#include "AST/Print.hpp"
+#include "AST/SymbolTable.hpp"
+#include "AST/Type.hpp"
+#include "AST/TypeEnvironment.hpp"
 #include "ConversionCost.h"              // for ConversionCost
 #include "Cost.h"                        // for Cost, Cost::infinity
@@ -31,7 +35,7 @@
 
 namespace ResolvExpr {
-	struct CastCost : public ConversionCost {
+	struct CastCost_old : public ConversionCost {
 	  public:
-		CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
+		CastCost_old( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
 
 		using ConversionCost::previsit;
@@ -78,6 +82,5 @@
 			});
 		} else {
-			#warning cast on castCost artifact of having two functions, remove when port done
-			PassVisitor<CastCost> converter( 
+			PassVisitor<CastCost_old> converter( 
 				dest, indexer, env, 
 				(Cost (*)( Type *, Type *, const SymTab::Indexer &, const TypeEnvironment & ))
@@ -93,9 +96,9 @@
 	}
 
-	CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
+	CastCost_old::CastCost_old( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
 		: ConversionCost( dest, indexer, env, costFunc ) {
 	}
 
-	void CastCost::postvisit( BasicType *basicType ) {
+	void CastCost_old::postvisit( BasicType *basicType ) {
 		PointerType *destAsPointer = dynamic_cast< PointerType* >( dest );
 		if ( destAsPointer && basicType->isInteger() ) {
@@ -107,5 +110,5 @@
 	}
 
-	void CastCost::postvisit( PointerType *pointerType ) {
+	void CastCost_old::postvisit( PointerType *pointerType ) {
 		if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
 			if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
@@ -130,13 +133,110 @@
 	}
 
-	Cost castCost( 
-		const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 
-		const ast::TypeEnvironment & env 
-	) {
-		#warning unimplmented
-		(void)src; (void)dst; (void)symtab; (void)env;
-		assert(false);
+namespace {
+	struct CastCost_new : public ConversionCost_new {
+		using ConversionCost_new::previsit;
+		using ConversionCost_new::postvisit;
+
+		CastCost_new( 
+			const ast::Type * dst, const ast::SymbolTable & symtab, 
+			const ast::TypeEnvironment & env, CostCalculation costFunc )
+		: ConversionCost_new( dst, symtab, env, costFunc ) {}
+
+		void postvisit( const ast::BasicType * basicType ) {
+			auto ptr = dynamic_cast< const ast::PointerType * >( dst );
+			if ( ptr && basicType->isInteger() ) {
+				// needed for, e.g. unsigned long => void *
+				cost = Cost::unsafe;
+			} else {
+				cost = conversionCost( basicType, dst, symtab, env );
+			}
+		}
+
+		void postvisit( const ast::PointerType * pointerType ) {
+			if ( auto ptr = dynamic_cast< const ast::PointerType * >( dst ) ) {
+				if (
+					pointerType->qualifiers <= ptr->qualifiers
+					&& typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, symtab, env )
+				) {
+					cost = Cost::safe;
+				} else {
+					ast::TypeEnvironment newEnv{ env };
+					if ( auto wParams = pointerType->base.as< ast::ParameterizedType >() ) {
+						newEnv.add( wParams->forall );
+					}
+					int castResult = ptrsCastable( pointerType->base, ptr->base, symtab, newEnv );
+					if ( castResult > 0 ) {
+						cost = Cost::safe;
+					} else if ( castResult < 0 ) {
+						cost = Cost::infinity;
+					}
+				}
+			} else if ( auto basic = dynamic_cast< const ast::BasicType * >( dst ) ) {
+				if ( basic->isInteger() ) {
+					// necessary for, e.g. void * => unsigned long
+					cost = Cost::unsafe;
+				}
+			}
+		}
+	};
+} // anonymous namespace
+
+Cost castCost( 
+	const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 
+	const ast::TypeEnvironment & env 
+) {
+	if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
+		if ( const ast::EqvClass * eqvClass = env.lookup( typeInst->name ) ) {
+			// check cast cost against bound type, if present
+			if ( eqvClass->bound ) {
+				return castCost( src, eqvClass->bound, symtab, env );
+			} else {
+				return Cost::infinity;
+			}
+		} else if ( const ast::NamedTypeDecl * named = symtab.lookupType( typeInst->name ) ) {
+			// all typedefs should be gone by now
+			auto type = strict_dynamic_cast< const ast::TypeDecl * >( named );
+			if ( type->base ) {
+				return castCost( src, type->base, symtab, env ) + Cost::safe;
+			}
+		}
+	}
+
+	PRINT(
+		std::cerr << "castCost ::: src is ";
+		ast::print( std::cerr, src );
+		std::cerr << std::endl << "dest is ";
+		ast::print( std::cerr, dst );
+		std::cerr << std::endl << "env is" << std::endl;
+		ast::print( std::cerr, env, 2 );
+	)
+
+	if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
+		PRINT( std::cerr << "compatible!" << std::endl; )
 		return Cost::zero;
-	}
+	} else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
+		return Cost::safe;
+	} else if ( auto refType = dynamic_cast< const ast::ReferenceType * >( dst ) ) {
+		PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
+		#warning cast on ptrsCastable artifact of having two functions, remove when port done
+		return convertToReferenceCost( 
+			src, refType, symtab, env, 
+			( int (*)( 
+				const ast::Type *, const ast::Type *, const ast::SymbolTable &, 
+				const ast::TypeEnvironment & )
+			) ptrsCastable );
+	} else {
+		#warning cast on castCost artifact of having two functions, remove when port done
+		ast::Pass< CastCost_new > converter{
+			dst, symtab, env, 
+			( Cost (*)( 
+				const ast::Type *, const ast::Type *, const ast::SymbolTable &, 
+				const ast::TypeEnvironment & )
+			) castCost };
+		src->accept( converter );
+		return converter.pass.cost;
+	}
+}
+
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/ConversionCost.h
===================================================================
--- src/ResolvExpr/ConversionCost.h	(revision 0f6a775253ac135c7aefa8bf075ce817231ec7d1)
+++ src/ResolvExpr/ConversionCost.h	(revision 3c89751935492115e8058617f8a19718dfab085f)
@@ -74,6 +74,7 @@
 	const ast::SymbolTable &, const ast::TypeEnvironment &)>;
 
-// TODO: When the old ConversionCost is removed, get ride of the _new suffix.
+#warning when the old ConversionCost is removed, get ride of the _new suffix.
 class ConversionCost_new : public ast::WithShortCircuiting {
+protected:
 	const ast::Type * dst;
 	const ast::SymbolTable & symtab;
Index: src/ResolvExpr/PtrsCastable.cc
===================================================================
--- src/ResolvExpr/PtrsCastable.cc	(revision 0f6a775253ac135c7aefa8bf075ce817231ec7d1)
+++ src/ResolvExpr/PtrsCastable.cc	(revision 3c89751935492115e8058617f8a19718dfab085f)
@@ -14,4 +14,8 @@
 //
 
+#include "AST/Decl.hpp"
+#include "AST/Pass.hpp"
+#include "AST/Type.hpp"
+#include "AST/TypeEnvironment.hpp"
 #include "Common/PassVisitor.h"
 #include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
@@ -23,7 +27,7 @@
 
 namespace ResolvExpr {
-	struct PtrsCastable : public WithShortCircuiting  {
+	struct PtrsCastable_old : public WithShortCircuiting  {
 	  public:
-		PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
+		PtrsCastable_old( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
 
 		int get_result() const { return result; }
@@ -86,5 +90,5 @@
 			return objectCast( src, env, indexer );
 		} else {
-			PassVisitor<PtrsCastable> ptrs( dest, env, indexer );
+			PassVisitor<PtrsCastable_old> ptrs( dest, env, indexer );
 			src->accept( ptrs );
 			return ptrs.pass.get_result();
@@ -92,38 +96,38 @@
 	}
 
-	PtrsCastable::PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer )
+	PtrsCastable_old::PtrsCastable_old( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer )
 		: dest( dest ), result( 0 ), env( env ), indexer( indexer )	{
 	}
 
-	void PtrsCastable::postvisit( VoidType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable::postvisit( BasicType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable::postvisit( PointerType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable::postvisit( ArrayType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable::postvisit( FunctionType * ) {
+	void PtrsCastable_old::postvisit( VoidType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( BasicType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( PointerType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( ArrayType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( FunctionType * ) {
 		// result = -1;
 		result = functionCast( dest, env, indexer );
 	}
 
-	void PtrsCastable::postvisit( StructInstType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable::postvisit( UnionInstType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable::postvisit( EnumInstType * ) {
+	void PtrsCastable_old::postvisit( StructInstType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( UnionInstType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( EnumInstType * ) {
 		if ( dynamic_cast< EnumInstType* >( dest ) ) {
 			result = 1;
@@ -139,26 +143,158 @@
 	}
 
-	void PtrsCastable::postvisit( TraitInstType * ) {}
-
-	void PtrsCastable::postvisit(TypeInstType *inst) {
+	void PtrsCastable_old::postvisit( TraitInstType * ) {}
+
+	void PtrsCastable_old::postvisit(TypeInstType *inst ) {
 		//result = objectCast( inst, env, indexer ) > 0 && objectCast( dest, env, indexer ) > 0 ? 1 : -1;
 		result = objectCast( inst, env, indexer ) == objectCast( dest, env, indexer ) ? 1 : -1;
 	}
 
-	void PtrsCastable::postvisit( TupleType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable::postvisit( VarArgsType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable::postvisit( ZeroType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable::postvisit( OneType * ) {
-		result = objectCast( dest, env, indexer );
-	}
+	void PtrsCastable_old::postvisit( TupleType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( VarArgsType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( ZeroType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( OneType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+namespace {
+	// can this type be cast to an object (1 for yes, -1 for no)
+	int objectCast( 
+		const ast::Type * src, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab 
+	) {
+		if ( dynamic_cast< const ast::FunctionType * >( src ) ) {
+			return -1;
+		} else if ( auto inst = dynamic_cast< const ast::TypeInstType * >( src ) ) {
+			if ( const ast::NamedTypeDecl * named = symtab.lookupType( inst->name ) ) {
+				if ( auto tyDecl = dynamic_cast< const ast::TypeDecl * >( named ) ) {
+					if ( tyDecl->kind == ast::TypeVar::Ftype ) {
+						return -1;
+					}
+				}
+			} else if ( const ast::EqvClass * eqvClass = env.lookup( inst->name ) ) {
+				if ( eqvClass->data.kind == ast::TypeVar::Ftype ) {
+					return -1;
+				}
+			}
+		}
+
+		return 1;
+	}
+
+	// can this type be cast to a function (inverse of objectCast)
+	int functionCast( 
+		const ast::Type * src, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab 
+	) {
+		return -1 * objectCast( src, env, symtab );
+	}
+
+	class PtrsCastable_new : public ast::WithShortCircuiting {
+		const ast::Type * dst;
+		const ast::TypeEnvironment & env;
+		const ast::SymbolTable & symtab;
+	public:
+		int result;
+
+		PtrsCastable_new( 
+			const ast::Type * d, const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
+		: dst( d ), env( e ), symtab( syms ), result( 0 ) {}
+
+		void previsit( const ast::Type * ) { visit_children = false; }
+
+		void postvisit( const ast::VoidType * ) {
+			result = objectCast( dst, env, symtab );
+		}
+
+		void postvisit( const ast::BasicType * ) {
+			result = objectCast( dst, env, symtab );
+		}
+
+		void postvisit( const ast::PointerType * ) {
+			result = objectCast( dst, env, symtab );
+		}
+
+		void postvisit( const ast::ArrayType * ) {
+			result = objectCast( dst, env, symtab );
+		}
+
+		void postvisit( const ast::FunctionType * ) {
+			result = functionCast( dst, env, symtab );
+		}
+
+		void postvisit( const ast::StructInstType * ) {
+			result = objectCast( dst, env, symtab );
+		}
+
+		void postvisit( const ast::UnionInstType * ) {
+			result = objectCast( dst, env, symtab );
+		}
+
+		void postvisit( const ast::EnumInstType * ) {
+			if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) {
+				result = 1;
+			} else if ( auto bt = dynamic_cast< const ast::BasicType * >( dst ) ) {
+				if ( bt->kind == ast::BasicType::SignedInt ) {
+					result = 0;
+				} else {
+					result = 1;
+				}
+			} else {
+				result = objectCast( dst, env, symtab );
+			}
+		}
+
+		void postvisit( const ast::TraitInstType * ) {}
+
+		void postvisit( const ast::TypeInstType * inst ) {
+			// check trait and destination type are both object or both function
+			result = objectCast( inst, env, symtab ) == objectCast( dst, env, symtab ) ? 1 : -1;
+		}
+
+		void postvisit( const ast::TupleType * ) {
+			result = objectCast( dst, env, symtab );
+		}
+
+		void postvisit( const ast::VarArgsType * ) {
+			result = objectCast( dst, env, symtab );
+		}
+
+		void postvisit( const ast::ZeroType * ) {
+			result = objectCast( dst, env, symtab );
+		}
+
+		void postvisit( const ast::OneType * ) {
+			result = objectCast( dst, env, symtab );
+		}
+
+	};
+} // anonymous namespace
+
+int ptrsCastable( 
+	const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 
+	const ast::TypeEnvironment & env 
+) {
+	if ( auto inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
+		if ( const ast::EqvClass * eqvClass = env.lookup( inst->name ) ) {
+			return ptrsAssignable( src, eqvClass->bound, env );
+		}
+	}
+
+	if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
+		return objectCast( src, env, symtab );
+	} else {
+		ast::Pass< PtrsCastable_new > ptrs{ dst, env, symtab };
+		src->accept( ptrs );
+		return ptrs.pass.result;
+	}
+}
+
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 0f6a775253ac135c7aefa8bf075ce817231ec7d1)
+++ src/ResolvExpr/Resolver.cc	(revision 3c89751935492115e8058617f8a19718dfab085f)
@@ -1337,6 +1337,5 @@
 		if ( type->dimension ) {
 			#warning should use new equivalent to Validate::SizeType rather than sizeType here
-			ast::ptr< ast::Type > sizeType = 
-				new ast::BasicType{ ast::BasicType::LongLongUnsignedInt };
+			ast::ptr< ast::Type > sizeType = new ast::BasicType{ ast::BasicType::LongUnsignedInt };
 			ast::mutate_field( 
 				type, &PtrType::dimension, 
Index: src/ResolvExpr/typeops.h
===================================================================
--- src/ResolvExpr/typeops.h	(revision 0f6a775253ac135c7aefa8bf075ce817231ec7d1)
+++ src/ResolvExpr/typeops.h	(revision 3c89751935492115e8058617f8a19718dfab085f)
@@ -99,4 +99,7 @@
 	// in PtrsCastable.cc
 	int ptrsCastable( Type *src, Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
+	int ptrsCastable( 
+		const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 
+		const ast::TypeEnvironment & env );
 
 	// in Unify.cc
