Index: src/ResolvExpr/AdjustExprType.cc
===================================================================
--- src/ResolvExpr/AdjustExprType.cc	(revision 5de1e2c6c474afdd7304316fdf69c49d4cdf6e4d)
+++ src/ResolvExpr/AdjustExprType.cc	(revision 00ac42e19976f383d054c37519d503de894b5ba7)
@@ -66,5 +66,5 @@
 
 	Type * AdjustExprType::postmutate( ArrayType * arrayType ) {
-		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base );
+		PointerType *pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base };
 		arrayType->base = nullptr;
 		delete arrayType;
@@ -73,19 +73,16 @@
 
 	Type * AdjustExprType::postmutate( FunctionType * functionType ) {
-		return new PointerType( Type::Qualifiers(), functionType );
+		return new PointerType{ Type::Qualifiers(), functionType };
 	}
 
 	Type * AdjustExprType::postmutate( TypeInstType * typeInst ) {
-		EqvClass eqvClass;
-		if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
-			if ( eqvClass.data.kind == TypeDecl::Ftype ) {
-				PointerType *pointerType = new PointerType( Type::Qualifiers(), typeInst );
-				return pointerType;
+		if ( const EqvClass* eqvClass = env.lookup( typeInst->get_name() ) ) {
+			if ( eqvClass->data.kind == TypeDecl::Ftype ) {
+				return new PointerType{ Type::Qualifiers(), typeInst };
 			}
 		} else if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
 			if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) {
 				if ( tyDecl->get_kind() == TypeDecl::Ftype ) {
-					PointerType *pointerType = new PointerType( Type::Qualifiers(), typeInst );
-					return pointerType;
+					return new PointerType{ Type::Qualifiers(), typeInst };
 				} // if
 			} // if
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 5de1e2c6c474afdd7304316fdf69c49d4cdf6e4d)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 00ac42e19976f383d054c37519d503de894b5ba7)
@@ -102,5 +102,5 @@
 		void addAnonConversions( const Alternative & alt );
 		/// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
-		template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
+		template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name );
 		/// Adds alternatives for member expressions where the left side has tuple type
 		void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
@@ -307,18 +307,12 @@
 
 		if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
-			NameExpr nameExpr( "" );
-			addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr );
+			addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
 		} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
-			NameExpr nameExpr( "" );
-			addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr );
+			addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
 		} // if
 	}
 
 	template< typename StructOrUnionType >
-	void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
-		// by this point, member must be a name expr
-		NameExpr * nameExpr = dynamic_cast< NameExpr * >( member );
-		if ( ! nameExpr ) return;
-		const std::string & name = nameExpr->name;
+	void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) {
 		std::list< Declaration* > members;
 		aggInst->lookup( name, members );
@@ -472,9 +466,5 @@
 	}
 
-	// /// Map of declaration uniqueIds (intended to be the assertions in an AssertionSet) to their parents and the number of times they've been included
-	//typedef std::unordered_map< UniqueId, std::unordered_map< UniqueId, unsigned > > AssertionParentSet;
-
 	static const int recursionLimit = /*10*/ 4;  ///< Limit to depth of recursion satisfaction
-	//static const unsigned recursionParentLimit = 1;  ///< Limit to the number of times an assertion can recursively use itself
 
 	void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) {
@@ -487,6 +477,5 @@
 
 	template< typename ForwardIterator, typename OutputIterator >
-	void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, /*const AssertionParentSet &needParents,*/
-						 int level, const SymTab::Indexer &indexer, OutputIterator out ) {
+	void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out ) {
 		if ( begin == end ) {
 			if ( newNeed.empty() ) {
@@ -506,5 +495,5 @@
 					printAssertionSet( newNeed, std::cerr, 8 );
 				)
-				inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, /*needParents,*/ level+1, indexer, out );
+				inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out );
 				return;
 			}
@@ -513,5 +502,5 @@
 		ForwardIterator cur = begin++;
 		if ( ! cur->second.isUsed ) {
-			inferRecursive( begin, end, newAlt, openVars, decls, newNeed, /*needParents,*/ level, indexer, out );
+			inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out );
 			return; // xxx - should this continue? previously this wasn't here, and it looks like it should be
 		}
@@ -566,9 +555,4 @@
 				}
 
-				//AssertionParentSet newNeedParents( needParents );
-				// skip repeatingly-self-recursive assertion satisfaction
-				// DOESN'T WORK: grandchild nodes conflict with their cousins
-				//if ( newNeedParents[ curDecl->get_uniqueId() ][ candDecl->get_uniqueId() ]++ > recursionParentLimit ) continue;
-
 				Expression *varExpr = data.combine( newerAlt.cvtCost );
 				delete varExpr->get_result();
@@ -588,5 +572,5 @@
 				// XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions
 				(*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
-				inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, /*newNeedParents,*/ level, indexer, out );
+				inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out );
 			} else {
 				delete adjType;
@@ -610,5 +594,4 @@
 		addToIndexer( have, decls );
 		AssertionSet newNeed;
-		//AssertionParentSet needParents;
 		PRINT(
 			std::cerr << "env is: " << std::endl;
@@ -617,5 +600,5 @@
 		)
 
-		inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, /*needParents,*/ 0, indexer, out );
+		inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out );
 //	PRINT(
 //	    std::cerr << "declaration 14 is ";
@@ -1096,5 +1079,5 @@
 		AlternativeFinder funcOpFinder( indexer, env );
 		// it's ok if there aren't any defined function ops
-		funcOpFinder.maybeFind( opExpr);
+		funcOpFinder.maybeFind( opExpr );
 		PRINT(
 			std::cerr << "known function ops:" << std::endl;
@@ -1133,7 +1116,6 @@
 					}
 				} else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->result->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
-					EqvClass eqvClass;
-					if ( func->env.lookup( typeInst->name, eqvClass ) && eqvClass.type ) {
-						if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
+					if ( const EqvClass *eqvClass = func->env.lookup( typeInst->name ) ) {
+						if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass->type ) ) {
 							Alternative newFunc( *func );
 							referenceToRvalueConversion( newFunc.expr, newFunc.cost );
@@ -1350,4 +1332,13 @@
 	}
 
+	namespace {
+		/// Gets name from untyped member expression (member must be NameExpr)
+		const std::string& get_member_name( UntypedMemberExpr *memberExpr ) {
+			NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() );
+			assert( nameExpr );
+			return nameExpr->get_name();
+		}
+	}
+
 	void AlternativeFinder::Finder::postvisit( UntypedMemberExpr *memberExpr ) {
 		AlternativeFinder funcFinder( indexer, env );
@@ -1362,7 +1353,7 @@
 			// find member of the given type
 			if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
-				addAggMembers( structInst, aggrExpr, cost, agg->env, memberExpr->get_member() );
+				addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
 			} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
-				addAggMembers( unionInst, aggrExpr, cost, agg->env, memberExpr->get_member() );
+				addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
 			} else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
 				addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );
Index: src/ResolvExpr/CastCost.cc
===================================================================
--- src/ResolvExpr/CastCost.cc	(revision 5de1e2c6c474afdd7304316fdf69c49d4cdf6e4d)
+++ src/ResolvExpr/CastCost.cc	(revision 00ac42e19976f383d054c37519d503de894b5ba7)
@@ -43,13 +43,11 @@
 	Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
 		if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
-			EqvClass eqvClass;
-			NamedTypeDecl *namedType;
-			if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
-				if ( eqvClass.type ) {
-					return castCost( src, eqvClass.type, indexer, env );
+			if ( const EqvClass* eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
+				if ( eqvClass->type ) {
+					return castCost( src, eqvClass->type, indexer, env );
 				} else {
 					return Cost::infinity;
 				}
-			} else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) {
+			} else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) {
 				// all typedefs should be gone by this point
 				TypeDecl *type = strict_dynamic_cast< TypeDecl* >( namedType );
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision 5de1e2c6c474afdd7304316fdf69c49d4cdf6e4d)
+++ src/ResolvExpr/ConversionCost.cc	(revision 00ac42e19976f383d054c37519d503de894b5ba7)
@@ -42,14 +42,12 @@
 	Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
 		if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
-			EqvClass eqvClass;
-			NamedTypeDecl *namedType;
 			PRINT( std::cerr << "type inst " << destAsTypeInst->name; )
-			if ( env.lookup( destAsTypeInst->name, eqvClass ) ) {
-				if ( eqvClass.type ) {
-					return conversionCost( src, eqvClass.type, indexer, env );
+			if ( const EqvClass* eqvClass = env.lookup( destAsTypeInst->name ) ) {
+				if ( eqvClass->type ) {
+					return conversionCost( src, eqvClass->type, indexer, env );
 				} else {
 					return Cost::infinity;
 				}
-			} else if ( ( namedType = indexer.lookupType( destAsTypeInst->name ) ) ) {
+			} else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->name ) ) {
 				PRINT( std::cerr << " found" << std::endl; )
 				TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
@@ -369,13 +367,11 @@
 
 	void ConversionCost::postvisit( TypeInstType *inst ) {
-		EqvClass eqvClass;
-		NamedTypeDecl *namedType;
-		if ( env.lookup( inst->name, eqvClass ) ) {
-			cost = costFunc( eqvClass.type, dest, indexer, env );
+		if ( const EqvClass *eqvClass = env.lookup( inst->name ) ) {
+			cost = costFunc( eqvClass->type, dest, indexer, env );
 		} else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) {
 			if ( inst->name == destAsInst->name ) {
 				cost = Cost::zero;
 			}
-		} else if ( ( namedType = indexer.lookupType( inst->name ) ) ) {
+		} else if ( NamedTypeDecl *namedType = indexer.lookupType( inst->name ) ) {
 			TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
 			// all typedefs should be gone by this point
Index: src/ResolvExpr/Occurs.cc
===================================================================
--- src/ResolvExpr/Occurs.cc	(revision 5de1e2c6c474afdd7304316fdf69c49d4cdf6e4d)
+++ src/ResolvExpr/Occurs.cc	(revision 00ac42e19976f383d054c37519d503de894b5ba7)
@@ -38,7 +38,6 @@
 
 	Occurs::Occurs( std::string varName, const TypeEnvironment & env ) : result( false ), tenv( env ) {
-		EqvClass eqvClass;
-		if ( tenv.lookup( varName, eqvClass ) ) {
-			eqvVars = eqvClass.vars;
+		if ( const EqvClass *eqvClass = tenv.lookup( varName ) ) {
+			eqvVars = eqvClass->vars;
 		} else {
 			eqvVars.insert( varName );
@@ -47,16 +46,15 @@
 
 	void Occurs::previsit( TypeInstType * typeInst ) {
-		EqvClass eqvClass;
-///   std::cerr << "searching for vars: ";
+		///   std::cerr << "searching for vars: ";
 ///   std::copy( eqvVars.begin(), eqvVars.end(), std::ostream_iterator< std::string >( std::cerr, " " ) );
 ///   std::cerr << std::endl;
 		if ( eqvVars.find( typeInst->get_name() ) != eqvVars.end() ) {
 			result = true;
-		} else if ( tenv.lookup( typeInst->get_name(), eqvClass ) ) {
-			if ( eqvClass.type ) {
+		} else if ( const EqvClass *eqvClass = tenv.lookup( typeInst->get_name() ) ) {
+			if ( eqvClass->type ) {
 ///       std::cerr << typeInst->get_name() << " is bound to";
 ///       eqvClass.type->print( std::cerr );
 ///       std::cerr << std::endl;
-				eqvClass.type->accept( *visitor );
+				eqvClass->type->accept( *visitor );
 			} // if
 		} // if
Index: src/ResolvExpr/PolyCost.cc
===================================================================
--- src/ResolvExpr/PolyCost.cc	(revision 5de1e2c6c474afdd7304316fdf69c49d4cdf6e4d)
+++ src/ResolvExpr/PolyCost.cc	(revision 00ac42e19976f383d054c37519d503de894b5ba7)
@@ -39,8 +39,7 @@
 
 	void PolyCost::previsit(TypeInstType * typeInst) {
-		EqvClass eqvClass;
-		if ( tenv.lookup( typeInst->name, eqvClass ) ) {
-			if ( eqvClass.type ) {
-				if ( TypeInstType * otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass.type ) ) {
+		if ( const EqvClass *eqvClass = tenv.lookup( typeInst->name ) ) {
+			if ( eqvClass->type ) {
+				if ( TypeInstType * otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass->type ) ) {
 					if ( indexer.lookupType( otherTypeInst->name ) ) {
 						// bound to opaque type
Index: src/ResolvExpr/PtrsAssignable.cc
===================================================================
--- src/ResolvExpr/PtrsAssignable.cc	(revision 5de1e2c6c474afdd7304316fdf69c49d4cdf6e4d)
+++ src/ResolvExpr/PtrsAssignable.cc	(revision 00ac42e19976f383d054c37519d503de894b5ba7)
@@ -51,7 +51,6 @@
 		// std::cerr << "assignable: " << src << " | " << dest << std::endl;
 		if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
-			EqvClass eqvClass;
-			if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
-				return ptrsAssignable( src, eqvClass.type, env );
+			if ( const EqvClass *eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
+				return ptrsAssignable( src, eqvClass->type, env );
 			} // if
 		} // if
@@ -95,8 +94,9 @@
 	void PtrsAssignable::postvisit(  __attribute__((unused)) TraitInstType *inst ) {}
 	void PtrsAssignable::postvisit( TypeInstType *inst ) {
-		EqvClass eqvClass;
-		if ( env.lookup( inst->get_name(), eqvClass ) && eqvClass.type ) {
-			// T * = S * for any S depends on the type bound to T
-			result = ptrsAssignable( eqvClass.type, dest, env );
+		if ( const EqvClass *eqvClass = env.lookup( inst->get_name() ) ) {
+			if ( eqvClass->type ) {
+				// T * = S * for any S depends on the type bound to T
+				result = ptrsAssignable( eqvClass->type, dest, env );
+			}
 		} // if
 	}
Index: src/ResolvExpr/PtrsCastable.cc
===================================================================
--- src/ResolvExpr/PtrsCastable.cc	(revision 5de1e2c6c474afdd7304316fdf69c49d4cdf6e4d)
+++ src/ResolvExpr/PtrsCastable.cc	(revision 00ac42e19976f383d054c37519d503de894b5ba7)
@@ -57,5 +57,4 @@
 				return -1;
 			} else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( src ) ) {
-				EqvClass eqvClass;
 				if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
 					if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) {
@@ -64,6 +63,6 @@
 						} // if
 					} //if
-				} else if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
-					if ( eqvClass.data.kind == TypeDecl::Ftype ) {
+				} else if ( const EqvClass *eqvClass = env.lookup( typeInst->get_name() ) ) {
+					if ( eqvClass->data.kind == TypeDecl::Ftype ) {
 						return -1;
 					} // if
@@ -79,8 +78,7 @@
 	int ptrsCastable( Type *src, Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
 		if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
-			EqvClass eqvClass;
-			if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
+			if ( const EqvClass *eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
 				// xxx - should this be ptrsCastable?
-				return ptrsAssignable( src, eqvClass.type, env );
+				return ptrsAssignable( src, eqvClass->type, env );
 			} // if
 		} // if
Index: src/ResolvExpr/TypeEnvironment.cc
===================================================================
--- src/ResolvExpr/TypeEnvironment.cc	(revision 5de1e2c6c474afdd7304316fdf69c49d4cdf6e4d)
+++ src/ResolvExpr/TypeEnvironment.cc	(revision 00ac42e19976f383d054c37519d503de894b5ba7)
@@ -17,5 +17,5 @@
 #include <algorithm>                   // for copy, set_intersection
 #include <iterator>                    // for ostream_iterator, insert_iterator
-#include <utility>                     // for pair
+#include <utility>                     // for pair, move
 
 #include "Common/utility.h"            // for maybeClone
@@ -44,6 +44,10 @@
 
 	void EqvClass::initialize( const EqvClass &src, EqvClass &dest ) {
+		initialize( src, dest, src.type );
+	}
+
+	void EqvClass::initialize( const EqvClass &src, EqvClass &dest, const Type *ty ) {
 		dest.vars = src.vars;
-		dest.type = maybeClone( src.type );
+		dest.type = maybeClone( ty );
 		dest.allowWidening = src.allowWidening;
 		dest.data = src.data;
@@ -55,4 +59,8 @@
 	EqvClass::EqvClass( const EqvClass &other ) {
 		initialize( other, *this );
+	}
+
+	EqvClass::EqvClass( const EqvClass &other, const Type *ty ) {
+		initialize( other, *this, ty );
 	}
 
@@ -82,31 +90,38 @@
 	}
 
-	bool TypeEnvironment::lookup( const std::string &var, EqvClass &eqvClass ) const {
+	const EqvClass* TypeEnvironment::lookup( const std::string &var ) const {
 		for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {
 			if ( i->vars.find( var ) != i->vars.end() ) {
 ///       std::cout << var << " is in class ";
 ///       i->print( std::cout );
-				eqvClass = *i;
-				return true;
+				return &*i;
 			}
 ///     std::cout << var << " is not in class ";
 ///     i->print( std::cout );
 		} // for
-		return false;
+		return nullptr;
+	}
+
+	/// Removes any class from env that intersects eqvClass
+	void filterOverlappingClasses( std::list<EqvClass> &env, const EqvClass &eqvClass ) {
+		for ( auto i = env.begin(); i != env.end(); ) {
+			auto next = i;
+			++next;
+			std::set<std::string> intersection;
+			std::set_intersection( i->vars.begin(), i->vars.end(), eqvClass.vars.begin(), eqvClass.vars.end(), 
+				std::inserter( intersection, intersection.begin() ) );
+			if ( ! intersection.empty() ) { env.erase( i ); }
+			i = next;
+		}
 	}
 
 	void TypeEnvironment::add( const EqvClass &eqvClass ) {
-		std::list< EqvClass >::iterator i = env.begin();
-		while ( i != env.end() ) {
-			std::list< EqvClass >::iterator next = i;
-			next++;
-			std::set< std::string > intersection;
-			std::set_intersection( i->vars.begin(), i->vars.end(), eqvClass.vars.begin(), eqvClass.vars.end(), std::inserter( intersection, intersection.begin() ) );
-			if ( ! intersection.empty() ) {
-				env.erase( i );
-			} // if
-			i = next;
-		} // while
-		env.insert( env.end(), eqvClass );
+		filterOverlappingClasses( env, eqvClass );
+		env.push_back( eqvClass );
+	}
+
+	void TypeEnvironment::add( EqvClass &&eqvClass ) {
+		filterOverlappingClasses( env, eqvClass );
+		env.push_back( std::move(eqvClass) );
 	}
 
Index: src/ResolvExpr/TypeEnvironment.h
===================================================================
--- src/ResolvExpr/TypeEnvironment.h	(revision 5de1e2c6c474afdd7304316fdf69c49d4cdf6e4d)
+++ src/ResolvExpr/TypeEnvironment.h	(revision 00ac42e19976f383d054c37519d503de894b5ba7)
@@ -73,6 +73,8 @@
 
 		void initialize( const EqvClass &src, EqvClass &dest );
+		void initialize( const EqvClass &src, EqvClass &dest, const Type *ty );
 		EqvClass();
 		EqvClass( const EqvClass &other );
+		EqvClass( const EqvClass &other, const Type *ty );
 		EqvClass &operator=( const EqvClass &other );
 		~EqvClass();
@@ -82,6 +84,7 @@
 	class TypeEnvironment {
 	  public:
-		bool lookup( const std::string &var, EqvClass &eqvClass ) const;
+		const EqvClass* lookup( const std::string &var ) const;
 		void add( const EqvClass &eqvClass );
+		void add( EqvClass &&eqvClass  );
 		void add( const Type::ForallList &tyDecls );
 		void add( const TypeSubstitution & sub );
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision 5de1e2c6c474afdd7304316fdf69c49d4cdf6e4d)
+++ src/ResolvExpr/Unify.cc	(revision 00ac42e19976f383d054c37519d503de894b5ba7)
@@ -20,5 +20,5 @@
 #include <set>                    // for set
 #include <string>                 // for string, operator==, operator!=, bas...
-#include <utility>                // for pair
+#include <utility>                // for pair, move
 
 #include "Common/PassVisitor.h"   // for PassVisitor
@@ -166,17 +166,14 @@
 			return false;
 		} // if
-		EqvClass curClass;
-		if ( env.lookup( typeInst->get_name(), curClass ) ) {
-			if ( curClass.type ) {
+		if ( const EqvClass *curClass = env.lookup( typeInst->get_name() ) ) {
+			if ( curClass->type ) {
 				Type *common = 0;
 				// attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
-				std::unique_ptr< Type > newType( curClass.type->clone() );
+				std::unique_ptr< Type > newType( curClass->type->clone() );
 				newType->get_qualifiers() = typeInst->get_qualifiers();
-				if ( unifyInexact( newType.get(), other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass.allowWidening, true ), indexer, common ) ) {
+				if ( unifyInexact( newType.get(), other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
 					if ( common ) {
 						common->get_qualifiers() = Type::Qualifiers();
-						delete curClass.type;
-						curClass.type = common;
-						env.add( curClass );
+						env.add( EqvClass{ *curClass, common } );
 					} // if
 					return true;
@@ -185,8 +182,8 @@
 				} // if
 			} else {
-				curClass.type = other->clone();
-				curClass.type->get_qualifiers() = Type::Qualifiers();
-				curClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
-				env.add( curClass );
+				EqvClass newClass { *curClass, other };
+				newClass.type->get_qualifiers() = Type::Qualifiers();
+				newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
+				env.add( std::move(newClass) );
 			} // if
 		} else {
@@ -204,28 +201,26 @@
 	bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
 		bool result = true;
-		EqvClass class1, class2;
-		bool hasClass1 = false, hasClass2 = false;
+		const EqvClass *class1 = env.lookup( var1->get_name() );
+		const EqvClass *class2 = env.lookup( var2->get_name() );
 		bool widen1 = false, widen2 = false;
-		Type *type1 = 0, *type2 = 0;
-
-		if ( env.lookup( var1->get_name(), class1 ) ) {
-			hasClass1 = true;
-			if ( class1.type ) {
-				if ( occurs( class1.type, var2->get_name(), env ) ) {
+		Type *type1 = nullptr, *type2 = nullptr;
+
+		if ( class1 ) {
+			if ( class1->type ) {
+				if ( occurs( class1->type, var2->get_name(), env ) ) {
 					return false;
 				} // if
-				type1 = class1.type->clone();
-			} // if
-			widen1 = widenMode.widenFirst && class1.allowWidening;
-		} // if
-		if ( env.lookup( var2->get_name(), class2 ) ) {
-			hasClass2 = true;
-			if ( class2.type ) {
-				if ( occurs( class2.type, var1->get_name(), env ) ) {
+				type1 = class1->type->clone();
+			} // if
+			widen1 = widenMode.widenFirst && class1->allowWidening;
+		} // if
+		if ( class2 ) {
+			if ( class2->type ) {
+				if ( occurs( class2->type, var1->get_name(), env ) ) {
 					return false;
 				} // if
-				type2 = class2.type->clone();
-			} // if
-			widen2 = widenMode.widenSecond && class2.allowWidening;
+				type2 = class2->type->clone();
+			} // if
+			widen2 = widenMode.widenSecond && class2->allowWidening;
 		} // if
 
@@ -235,33 +230,38 @@
 			Type *common = 0;
 			if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, newWidenMode, indexer, common ) ) {
-				class1.vars.insert( class2.vars.begin(), class2.vars.end() );
-				class1.allowWidening = widen1 && widen2;
+				EqvClass newClass1 = *class1;
+				newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );
+				newClass1.allowWidening = widen1 && widen2;
 				if ( common ) {
 					common->get_qualifiers() = Type::Qualifiers();
-					delete class1.type;
-					class1.type = common;
+					delete newClass1.type;
+					newClass1.type = common;
 				} // if
-				env.add( class1 );
+				env.add( std::move(newClass1) );
 			} else {
 				result = false;
 			} // if
-		} else if ( hasClass1 && hasClass2 ) {
+		} else if ( class1 && class2 ) {
 			if ( type1 ) {
-				class1.vars.insert( class2.vars.begin(), class2.vars.end() );
-				class1.allowWidening = widen1;
-				env.add( class1 );
+				EqvClass newClass1 = *class1;
+				newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );
+				newClass1.allowWidening = widen1;
+				env.add( std::move(newClass1) );
 			} else {
-				class2.vars.insert( class1.vars.begin(), class1.vars.end() );
-				class2.allowWidening = widen2;
-				env.add( class2 );
-			} // if
-		} else if ( hasClass1 ) {
-			class1.vars.insert( var2->get_name() );
-			class1.allowWidening = widen1;
-			env.add( class1 );
-		} else if ( hasClass2 ) {
-			class2.vars.insert( var1->get_name() );
-			class2.allowWidening = widen2;
-			env.add( class2 );
+				EqvClass newClass2 = *class2;
+				newClass2.vars.insert( class1->vars.begin(), class1->vars.end() );
+				newClass2.allowWidening = widen2;
+				env.add( std::move(newClass2) );
+			} // if
+		} else if ( class1 ) {
+			EqvClass newClass1 = *class1;
+			newClass1.vars.insert( var2->get_name() );
+			newClass1.allowWidening = widen1;
+			env.add( std::move(newClass1) );
+		} else if ( class2 ) {
+			EqvClass newClass2 = *class2;
+			newClass2.vars.insert( var1->get_name() );
+			newClass2.allowWidening = widen2;
+			env.add( std::move(newClass2) );
 		} else {
 			EqvClass newClass;
@@ -539,12 +539,9 @@
 		void premutate( TypeInstType * ) { visit_children = false; }
 		Type * postmutate( TypeInstType * typeInst ) {
-			EqvClass eqvClass;
-			if ( tenv.lookup( typeInst->get_name(), eqvClass ) ) {
-				if ( eqvClass.data.kind == TypeDecl::Ttype ) {
-					// expand ttype parameter into its actual type
-					if ( eqvClass.type ) {
-						delete typeInst;
-						return eqvClass.type->clone();
-					}
+			if ( const EqvClass *eqvClass = tenv.lookup( typeInst->get_name() ) ) {
+				// expand ttype parameter into its actual type
+				if ( eqvClass->data.kind == TypeDecl::Ttype && eqvClass->type ) {
+					delete typeInst;
+					return eqvClass->type->clone();
 				}
 			}
