Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 184557ed94d1cdbdc6fd685e497e5375f8968a96)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 5c140301192225f6a3f669eb918000f25962a75e)
@@ -454,5 +454,5 @@
 		}
 
-		#if 0 // cost of assertions accounted for in function creation
+		#if 1 // cost of assertions accounted for in function creation
 		for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) {
 			convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env );
@@ -584,4 +584,5 @@
 	}
 
+#if !1
 	namespace {
 		/// Information required to defer resolution of an expression
@@ -700,4 +701,5 @@
 		}
 	}
+#endif
 
 	template< typename OutputIterator >
@@ -715,5 +717,5 @@
 		// )
 		addToIndexer( have, decls );
-
+#if !1
 		AssertionResnState resn{ newAlt, openVars, indexer };
 
@@ -752,5 +754,5 @@
 		*out++ = newAlt;
 
-#if 0		
+#else		
 		AssertionSet newNeed;
 		PRINT(
@@ -1093,4 +1095,5 @@
 	}
 
+#if !1
 	namespace {
 
@@ -1230,4 +1233,5 @@
 		}
 	}
+#endif
 
 	template<typename OutputIterator>
@@ -1276,5 +1280,9 @@
 
 		// calculate declaration cost of function (+vars-spec)
+#if !1
 		Cost funcCost = declCost( funcType );
+#else
+		Cost funcCost = Cost::zero;
+#endif
 
 		// iteratively build matches, one parameter at a time
Index: src/ResolvExpr/TypeEnvironment.cc
===================================================================
--- src/ResolvExpr/TypeEnvironment.cc	(revision 184557ed94d1cdbdc6fd685e497e5375f8968a96)
+++ src/ResolvExpr/TypeEnvironment.cc	(revision 5c140301192225f6a3f669eb918000f25962a75e)
@@ -27,4 +27,5 @@
 #include "SynTree/Type.h"              // for Type, FunctionType, Type::Fora...
 #include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
+#include "Tuples/Tuples.h"             // for isTtype
 #include "TypeEnvironment.h"
 #include "typeops.h"                   // for occurs
@@ -104,5 +105,5 @@
 		auto tyVar = openVars.find( typeInst->get_name() );
 		assert( tyVar != openVars.end() );
-		if ( ! tyVarCompatible( tyVar->second, other ) ) return false;
+		if ( ! tyVarCompatible( tyVar->second, bindTo ) ) return false;
 
 		if ( occurs( bindTo, typeInst->get_name(), *this ) ) return false;
@@ -135,5 +136,6 @@
 		} else {
 			// make new class consisting entirely of this variable
-			BoundType curData{ bindTo->clone(), widenMode.first && widenMode.second, data };
+			BoundType curData{ 
+				bindTo->clone(), widenMode.widenFirst && widenMode.widenSecond, data };
 			curData.type->get_qualifiers() = Type::Qualifiers{};
 			classes = classes->add( curClass.get_root() );
@@ -146,6 +148,6 @@
 			const TypeDecl::Data& data, AssertionSet& need, AssertionSet& have, 
 			const OpenVarSet& openVars, WidenMode widenMode, const SymTab::Indexer& indexer ) {
-		ClassRef class1 = env.lookup( var1->get_name() );
-		ClassRef class2 = env.lookup( var2->get_name() );
+		ClassRef class1 = lookup( var1->get_name() );
+		ClassRef class2 = lookup( var2->get_name() );
 		
 		// exit early if variables already bound together
@@ -153,5 +155,5 @@
 			BoundType data1 = class1.get_bound();
 			// narrow the binding if needed
-			if ( data1.allowWidening && widenMode.first != widenMode.second ) {
+			if ( data1.allowWidening && widenMode.widenFirst != widenMode.widenSecond ) {
 				data1.allowWidening = false;
 				bindings = bindings->set( class1.get_root(), data1 );
@@ -172,5 +174,6 @@
 					openVars, WidenMode{ widen1, widen2 }, indexer, common ) ) {
 				// merge type variables
-				interned_string root = mergeClasses( class1.update_root(), class2.update_root() );
+				interned_string root = 
+					mergeClasses( class1.update_root(), class2.update_root() ).first;
 				// update bindings
 				data1.allowWidening = widen1 && widen2;
@@ -197,5 +200,5 @@
 				if ( data2.allowWidening != widen2 ) {
 					data2.allowWidening = widen2;
-					bindings = bindings->set( root, data2 );
+					bindings = bindings->set( merged.first, data2 );
 				} else if ( merged.first == class1.get_root() ) {
 					bindings = bindings->set( merged.first, data2 );
@@ -249,5 +252,5 @@
 			// filter overlapping classes out of existing environment
 			// (this is a very shady assumption, but has worked for a long time...)
-			interned_string root = classes->find_or_default( v, not_found );
+			interned_string root = classes->find_or_default( var, not_found );
 			if ( root != not_found ) {
 				classes = classes->remove_class( root );
@@ -262,11 +265,11 @@
 			// add variable to class and bindings
 			classes = classes->add( var );
-			bindings = bindings->set( var, BoundType{ p.second->clone, false, data } );
+			bindings = bindings->set( var, BoundType{ p.second->clone(), false, data } );
 		}
 	}
 
 	void TypeEnvironment::makeSubstitution( TypeSubstitution &sub ) const {
-		bindings->apply_to_all([classes, &sub]( interned_string root, const BoundType& bound ){
-			classes->apply_to_class(root, [&]( interned_string var ) {
+		bindings->for_each([&]( interned_string root, const BoundType& bound ){
+			classes->for_class(root, [&]( interned_string var ) {
 				if ( bound.type ) {
 					sub.add( var, bound.type );
@@ -282,11 +285,11 @@
 
 	void TypeEnvironment::print( std::ostream &os, Indenter indent ) const {
-		bindings->apply_to_all([classes,&]( interned_string root, const BoundType& bound ) {
+		bindings->for_each([&]( interned_string root, const BoundType& bound ) {
 			os << "( ";
-			classes->apply_to_class( root, [&os]( interned_string var ) { os << var << " "; } );
+			classes->for_class( root, [&os]( interned_string var ) { os << var << " "; } );
 			os << ")";
 			if ( bound.type ) {
 				os << " -> ";
-				type->print( os, indent+1 );
+				bound.type->print( os, indent+1 );
 			}
 			if ( ! bound.allowWidening ) {
@@ -298,8 +301,8 @@
 
 	void TypeEnvironment::simpleCombine( const TypeEnvironment &o ) {
-		o.bindings->apply_to_all( [&]( interned_string root, const BoundType& bound ) {
+		o.bindings->for_each( [&]( interned_string root, const BoundType& bound ) {
 			// add members of new class
 			interned_string new_root{nullptr};
-			o.classes->apply_to_class( root, [this,&new_root]( interned_string var ) {
+			o.classes->for_class( root, [this,&new_root]( interned_string var ) {
 				classes = classes->add( var );
 				new_root = new_root ? mergeClasses( new_root, var ).first : var;
@@ -311,6 +314,6 @@
 
 	void TypeEnvironment::extractOpenVars( OpenVarSet &openVars ) const {
-		bindings->apply_to_all( [classes,&openVars]( interned_string root, const BoundType& bound ) {
-			classes->apply_to_class( root, [&openVars,&bound]( interned_string var ) {
+		bindings->for_each( [&]( interned_string root, const BoundType& bound ) {
+			classes->for_class( root, [&openVars,&bound]( interned_string var ) {
 				openVars[ var ] = bound.data;
 			} );
@@ -319,8 +322,8 @@
 
 	void TypeEnvironment::addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars ) {
-		actualEnv.bindings->apply_to_all( [&]( interned_string root, const BoundType& bound ) {
+		actualEnv.bindings->for_each( [&]( interned_string root, const BoundType& bound ) {
 			// add members of new class, setting openVars concurrently
 			interned_string new_root{nullptr};
-			actualEnv.classes->apply_to_class( root, [&]( interned_string var ) {
+			actualEnv.classes->for_class( root, [&]( interned_string var ) {
 				classes = classes->add( var );
 				new_root = new_root ? mergeClasses( new_root, var ).first : var;
@@ -334,5 +337,5 @@
 
 	void TypeEnvironment::forbidWidening() {
-		bindings = bindings->apply_to_all([]( const interned_string& k, BoundType& c ) {
+		bindings = bindings->mutate_each([]( const interned_string&, BoundType& c ) {
 			if ( c.allowWidening ) {
 				option<BoundType> ret = c;
Index: src/ResolvExpr/TypeEnvironment.h
===================================================================
--- src/ResolvExpr/TypeEnvironment.h	(revision 184557ed94d1cdbdc6fd685e497e5375f8968a96)
+++ src/ResolvExpr/TypeEnvironment.h	(revision 5c140301192225f6a3f669eb918000f25962a75e)
@@ -189,5 +189,4 @@
 		/// returned root variable will be valid regardless
 		ClassRef lookup( interned_string var ) const;
-		ClassRef lookup( const std::string &var ) const { return lookup( var ); }
 
 		/// Binds a type variable to a type; returns false if fails
@@ -202,4 +201,6 @@
 
 	public:
+		TypeEnvironment() : classes{ new Classes{} }, bindings{ new Bindings{} } {}
+
 		void add( const Type::ForallList &tyDecls );
 		void add( const TypeSubstitution & sub );
@@ -224,6 +225,6 @@
 		void forbidWidening();
 
-		iterator begin() { return { this, bindings->begin() }; }
-		iterator end() { return { this, bindings->end() }; }
+		iterator begin() const { return { this, bindings->begin() }; }
+		iterator end() const { return { this, bindings->end() }; }
 	};
 
@@ -234,5 +235,5 @@
 		T vars;
 		if ( ! env->classes->count( root ) ) return vars;
-		env->classes->apply_to_class( root, [&vars]( interned_string var ) {
+		env->classes->for_class( root, [&vars]( interned_string var ) {
 			vars.insert( vars.end(), var );
 		} );
