Index: src/ResolvExpr/ResolveAssertions.cc
===================================================================
--- src/ResolvExpr/ResolveAssertions.cc	(revision 4139e3d97cd8420f817d0f2153368bdb2fa372f5)
+++ src/ResolvExpr/ResolveAssertions.cc	(revision c519942642e6eeb1e6281af05f8b60ff0beb335f)
@@ -103,8 +103,9 @@
 			OpenVarSet openVars;
 			std::vector<DeferRef> assns;
+			Cost cost;
 
 			OutType( const TypeEnvironment& env, const OpenVarSet& openVars, 
 				const std::vector<DeferRef>& assns )
-			: env(env), openVars(openVars), assns(assns) {}
+			: env(env), openVars(openVars), assns(assns), cost(Cost::infinity) {}
 		};
 
@@ -140,6 +141,4 @@
 		using Element = CandidateEnvMerger::OutType;
 	private:
-		using Memo = std::unordered_map<const Element*, Cost>;
-		mutable Memo cache;              ///< cache of element costs
 		const SymTab::Indexer& indexer;  ///< Indexer for costing
 
@@ -148,33 +147,40 @@
 
 		/// reports the cost of an element
-		Cost get( const Element& x ) const {
-			Memo::const_iterator it = cache.find( &x );
-			if ( it == cache.end() ) {
-				Cost k = Cost::zero;
-				for ( const auto& assn : x.assns ) {
-					k += computeConversionCost( 
-						assn.match.adjType, assn.decl->get_type(), indexer, x.env );
-					
-					// mark vars+specialization cost on function-type assertions
-					PointerType* ptr = dynamic_cast< PointerType* >( assn.decl->get_type() );
-					if ( ! ptr ) continue;
-					FunctionType* func = dynamic_cast< FunctionType* >( ptr->base );
-					if ( ! func ) continue;
-					
-					for ( DeclarationWithType* formal : func->parameters ) {
-						k.decSpec( specCost( formal->get_type() ) );
-					}
-					k.incVar( func->forall.size() );
-					for ( TypeDecl* td : func->forall ) {
-						k.decSpec( td->assertions.size() );
-					}
-				}
-				it = cache.emplace_hint( it, &x, k );
+		Cost get( Element& x ) const {
+			// check cached cost
+			if ( x.cost != Cost::infinity ) return x.cost;
+
+			// generate cost
+			Cost k = Cost::zero;
+			for ( const auto& assn : x.assns ) {
+				k += computeConversionCost( 
+					assn.match.adjType, assn.decl->get_type(), indexer, x.env );
+				
+				// mark vars+specialization cost on function-type assertions
+				Type* assnType = assn.match.cdata.id->get_type();
+				FunctionType* func;
+				if ( PointerType* ptr = dynamic_cast< PointerType* >( assnType ) ) {
+					func = dynamic_cast< FunctionType* >( ptr->base );
+				} else {
+					func = dynamic_cast< FunctionType* >( assnType );
+				}
+				if ( ! func ) continue;
+				
+				for ( DeclarationWithType* formal : func->parameters ) {
+					k.decSpec( specCost( formal->get_type() ) );
+				}
+				k.incVar( func->forall.size() );
+				for ( TypeDecl* td : func->forall ) {
+					k.decSpec( td->assertions.size() );
+				}
 			}
-			return it->second;
+
+			// cache and return
+			x.cost = k;
+			return k;
 		}
 		
 		/// compares elements by cost
-		bool operator() ( const Element& a, const Element& b ) const {
+		bool operator() ( Element& a, Element& b ) const {
 			return get( a ) < get( b );
 		}
