Index: src/ResolvExpr/AdjustExprType.cc
===================================================================
--- src/ResolvExpr/AdjustExprType.cc	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/AdjustExprType.cc	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -14,4 +14,5 @@
 //
 
+#include "Common/PassVisitor.h"
 #include "SymTab/Indexer.h"       // for Indexer
 #include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Kind::Ftype
@@ -21,25 +22,27 @@
 
 namespace ResolvExpr {
-	class AdjustExprType : public Mutator {
-		typedef Mutator Parent;
-		using Parent::mutate;
+	class AdjustExprType : public WithShortCircuiting {
 	  public:
 		AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer );
+		void premutate( VoidType * ) { visit_children = false; }
+		void premutate( BasicType * ) { visit_children = false; }
+		void premutate( PointerType * ) { visit_children = false; }
+		void premutate( ArrayType * ) { visit_children = false; }
+		void premutate( FunctionType * ) { visit_children = false; }
+		void premutate( StructInstType * ) { visit_children = false; }
+		void premutate( UnionInstType * ) { visit_children = false; }
+		void premutate( EnumInstType * ) { visit_children = false; }
+		void premutate( TraitInstType * ) { visit_children = false; }
+		void premutate( TypeInstType * ) { visit_children = false; }
+		void premutate( TupleType * ) { visit_children = false; }
+		void premutate( VarArgsType * ) { visit_children = false; }
+		void premutate( ZeroType * ) { visit_children = false; }
+		void premutate( OneType * ) { visit_children = false; }
+
+		Type * postmutate( ArrayType *arrayType );
+		Type * postmutate( FunctionType *functionType );
+		Type * postmutate( TypeInstType *aggregateUseType );
+
 	  private:
-		virtual Type* mutate( VoidType *voidType );
-		virtual Type* mutate( BasicType *basicType );
-		virtual Type* mutate( PointerType *pointerType );
-		virtual Type* mutate( ArrayType *arrayType );
-		virtual Type* mutate( FunctionType *functionType );
-		virtual Type* mutate( StructInstType *aggregateUseType );
-		virtual Type* mutate( UnionInstType *aggregateUseType );
-		virtual Type* mutate( EnumInstType *aggregateUseType );
-		virtual Type* mutate( TraitInstType *aggregateUseType );
-		virtual Type* mutate( TypeInstType *aggregateUseType );
-		virtual Type* mutate( TupleType *tupleType );
-		virtual Type* mutate( VarArgsType *varArgsType );
-		virtual Type* mutate( ZeroType *zeroType );
-		virtual Type* mutate( OneType *oneType );
-
 		const TypeEnvironment &env;
 		const SymTab::Indexer &indexer;
@@ -47,5 +50,5 @@
 
 	void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
-		AdjustExprType adjuster( env, indexer );
+		PassVisitor<AdjustExprType> adjuster( env, indexer );
 		Type *newType = type->acceptMutator( adjuster );
 		type = newType;
@@ -56,45 +59,16 @@
 	}
 
-	Type *AdjustExprType::mutate( VoidType *voidType ) {
-		return voidType;
-	}
-
-	Type *AdjustExprType::mutate( BasicType *basicType ) {
-		return basicType;
-	}
-
-	Type *AdjustExprType::mutate( PointerType *pointerType ) {
-		return pointerType;
-	}
-
-	Type *AdjustExprType::mutate( ArrayType *arrayType ) {
-		// need to recursively mutate the base type in order for multi-dimensional arrays to work.
-		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->get_base()->clone()->acceptMutator( *this ) );
+	Type * AdjustExprType::postmutate( ArrayType * arrayType ) {
+		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base );
+		arrayType->base = nullptr;
 		delete arrayType;
 		return pointerType;
 	}
 
-	Type *AdjustExprType::mutate( FunctionType *functionType ) {
-		PointerType *pointerType = new PointerType( Type::Qualifiers(), functionType );
-		return pointerType;
+	Type * AdjustExprType::postmutate( FunctionType * functionType ) {
+		return new PointerType( Type::Qualifiers(), functionType );
 	}
 
-	Type *AdjustExprType::mutate( StructInstType *aggregateUseType ) {
-		return aggregateUseType;
-	}
-
-	Type *AdjustExprType::mutate( UnionInstType *aggregateUseType ) {
-		return aggregateUseType;
-	}
-
-	Type *AdjustExprType::mutate( EnumInstType *aggregateUseType ) {
-		return aggregateUseType;
-	}
-
-	Type *AdjustExprType::mutate( TraitInstType *aggregateUseType ) {
-		return aggregateUseType;
-	}
-
-	Type *AdjustExprType::mutate( TypeInstType *typeInst ) {
+	Type * AdjustExprType::postmutate( TypeInstType * typeInst ) {
 		EqvClass eqvClass;
 		if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
@@ -113,20 +87,4 @@
 		return typeInst;
 	}
-
-	Type *AdjustExprType::mutate( TupleType *tupleType ) {
-		return tupleType;
-	}
-
-	Type *AdjustExprType::mutate( VarArgsType *varArgsType ) {
-		return varArgsType;
-	}
-
-	Type *AdjustExprType::mutate( ZeroType *zeroType ) {
-		return zeroType;
-	}
-
-	Type *AdjustExprType::mutate( OneType *oneType ) {
-		return oneType;
-	}
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/Alternative.cc
===================================================================
--- src/ResolvExpr/Alternative.cc	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/Alternative.cc	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -66,17 +66,17 @@
 	}
 
-	void Alternative::print( std::ostream &os, int indent ) const {
-		os << std::string( indent, ' ' ) << "Cost " << cost << ": ";
+	void Alternative::print( std::ostream &os, Indenter indent ) const {
+		os << "Cost " << cost << ": ";
 		if ( expr ) {
-			expr->print( os, indent );
-			os << "(types:" << std::endl;
-			os << std::string( indent+4, ' ' );
-			expr->get_result()->print( os, indent + 4 );
-			os << std::endl << ")" << std::endl;
+			expr->print( os, indent+1 );
+			os << std::endl << indent << "(types:" << std::endl;
+			os << indent+1;
+			expr->result->print( os, indent+1 );
+			os << std::endl << indent << ")" << std::endl;
 		} else {
 			os << "Null expression!" << std::endl;
 		} // if
-		os << std::string( indent, ' ' ) << "Environment: ";
-		env.print( os, indent+2 );
+		os << indent << "Environment: ";
+		env.print( os, indent+1 );
 		os << std::endl;
 	}
Index: src/ResolvExpr/Alternative.h
===================================================================
--- src/ResolvExpr/Alternative.h	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/Alternative.h	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -39,5 +39,5 @@
 		~Alternative();
 
-		void print( std::ostream &os, int indent = 0 ) const;
+		void print( std::ostream &os, Indenter indent = {} ) const;
 
 		Cost cost;
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -76,5 +76,6 @@
 
 	namespace {
-		void printAlts( const AltList &list, std::ostream &os, int indent = 0 ) {
+		void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt = 0 ) {
+			Indenter indent = { Indenter::tabsize, indentAmt };
 			for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
 				i->print( os, indent );
@@ -122,4 +123,8 @@
 						)
 						mapPlace->second.isAmbiguous = true;
+					} else {
+						PRINT(
+							std::cerr << "cost " << candidate->cost << " loses to " << mapPlace->second.candidate->cost << std::endl;
+						)
 					}
 				} else {
@@ -127,8 +132,4 @@
 				}
 			}
-
-			PRINT(
-				std::cerr << "there are " << selected.size() << " alternatives before elimination" << std::endl;
-			)
 
 			// accept the alternatives that were unambiguous
@@ -145,12 +146,12 @@
 			expr->get_result()->accept( global_renamer );
 		}
-
-		void referenceToRvalueConversion( Expression *& expr ) {
-			if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
-				// cast away reference from expr
-				expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() );
-			}
-		}
 	} // namespace
+
+	void referenceToRvalueConversion( Expression *& expr ) {
+		if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
+			// cast away reference from expr
+			expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() );
+		}
+	}
 
 	template< typename InputIterator, typename OutputIterator >
@@ -175,15 +176,11 @@
 	}
 
-	void AlternativeFinder::find( Expression *expr, bool adjust, bool prune ) {
+	void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) {
 		expr->accept( *this );
-		if ( alternatives.empty() ) {
+		if ( failFast && alternatives.empty() ) {
 			throw SemanticError( "No reasonable alternatives for expression ", expr );
 		}
-		for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
-			if ( adjust ) {
-				adjustExprType( i->expr->get_result(), i->env, indexer );
-			}
-		}
 		if ( prune ) {
+			auto oldsize = alternatives.size();
 			PRINT(
 				std::cerr << "alternatives before prune:" << std::endl;
@@ -192,18 +189,27 @@
 			AltList::iterator oldBegin = alternatives.begin();
 			pruneAlternatives( alternatives.begin(), alternatives.end(), front_inserter( alternatives ) );
-			if ( alternatives.begin() == oldBegin ) {
+			if ( failFast && alternatives.begin() == oldBegin ) {
 				std::ostringstream stream;
 				AltList winners;
 				findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
-				stream << "Cannot choose between " << winners.size() << " alternatives for expression ";
+				stream << "Cannot choose between " << winners.size() << " alternatives for expression\n";
 				expr->print( stream );
-				stream << "Alternatives are:";
-				printAlts( winners, stream, 8 );
+				stream << "Alternatives are:\n";
+				printAlts( winners, stream, 1 );
 				throw SemanticError( stream.str() );
 			}
 			alternatives.erase( oldBegin, alternatives.end() );
+			PRINT(
+				std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl;
+			)
 			PRINT(
 				std::cerr << "there are " << alternatives.size() << " alternatives after elimination" << std::endl;
 			)
+		}
+		// adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted
+		for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
+			if ( adjust ) {
+				adjustExprType( i->expr->get_result(), i->env, indexer );
+			}
 		}
 
@@ -215,6 +221,14 @@
 	}
 
-	void AlternativeFinder::findWithAdjustment( Expression *expr, bool prune ) {
-		find( expr, true, prune );
+	void AlternativeFinder::findWithAdjustment( Expression *expr ) {
+		find( expr, true );
+	}
+
+	void AlternativeFinder::findWithoutPrune( Expression * expr ) {
+		find( expr, true, false );
+	}
+
+	void AlternativeFinder::maybeFind( Expression * expr ) {
+		find( expr, true, true, false );
 	}
 
@@ -299,5 +313,5 @@
 		Cost convCost = conversionCost( actualType, formalType, indexer, env );
 		PRINT(
-			std::cerr << std::endl << "cost is" << convCost << std::endl;
+			std::cerr << std::endl << "cost is " << convCost << std::endl;
 		)
 		if ( convCost == Cost::infinity ) {
@@ -305,4 +319,7 @@
 		}
 		convCost.incPoly( polyCost( formalType, env, indexer ) + polyCost( actualType, env, indexer ) );
+		PRINT(
+			std::cerr << "cost with polycost is " << convCost << std::endl;
+		)
 		return convCost;
 	}
@@ -310,9 +327,8 @@
 	Cost computeExpressionConversionCost( Expression *& actualExpr, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) {
 		Cost convCost = computeConversionCost( actualExpr->result, formalType, indexer, env );
-		// if ( convCost != Cost::zero ) {
-
-		// xxx - temporary -- ignore poly cost, since this causes some polymorphic functions to be cast, which causes the specialize
-		// pass to try to specialize them, which currently does not work. Once that is fixed, remove the next 3 lines and uncomment the
-		// previous line.
+
+		// if there is a non-zero conversion cost, ignoring poly cost, then the expression requires conversion.
+		// ignore poly cost for now, since this requires resolution of the cast to infer parameters and this
+		// does not currently work for the reason stated below.
 		Cost tmpCost = convCost;
 		tmpCost.incPoly( -tmpCost.get_polyCost() );
@@ -357,4 +373,5 @@
 				if ( function->get_isVarArgs() ) {
 					convCost.incUnsafe();
+					PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; )
 					// convert reference-typed expressions to value-typed expressions
 					referenceToRvalueConversion( *actualExpr );
@@ -365,13 +382,4 @@
 			}
 			Type * formalType = (*formal)->get_type();
-			PRINT(
-				std::cerr << std::endl << "converting ";
-				actualType->print( std::cerr, 8 );
-				std::cerr << std::endl << " to ";
-				formalType->print( std::cerr, 8 );
-				std::cerr << std::endl << "environment is: ";
-				alt.env.print( std::cerr, 8 );
-				std::cerr << std::endl;
-			)
 			convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env );
 			++formal; // can't be in for-loop update because of the continue
@@ -481,5 +489,5 @@
 				Alternative newerAlt( newAlt );
 				newerAlt.env = newEnv;
-				assert( (*candidate)->get_uniqueId() );
+				assertf( (*candidate)->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( *candidate ).c_str() );
 				DeclarationWithType *candDecl = static_cast< DeclarationWithType* >( Declaration::declFromId( (*candidate)->get_uniqueId() ) );
 
@@ -507,7 +515,6 @@
 					std::cerr << std::endl;
 				)
-				ApplicationExpr *appExpr = static_cast< ApplicationExpr* >( newerAlt.expr );
 				// follow the current assertion's ID chain to find the correct set of inferred parameters to add the candidate to (i.e. the set of inferred parameters belonging to the entity which requested the assertion parameter).
-				InferredParams * inferParameters = &appExpr->get_inferParams();
+				InferredParams * inferParameters = &newerAlt.expr->get_inferParams();
 				for ( UniqueId id : cur->second.idChain ) {
 					inferParameters = (*inferParameters)[ id ].inferParams.get();
@@ -786,21 +793,21 @@
 		
 		return ! results.empty();
-	}
+	}	
 
 	template<typename OutputIterator>
-	void AlternativeFinder::makeFunctionAlternatives( const Alternative& func, 
-			FunctionType* funcType, const std::vector< AlternativeFinder >& args, 
+	void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, 
+			FunctionType *funcType, const std::vector< AlternativeFinder > &args, 
 			OutputIterator out ) {
 		OpenVarSet funcOpenVars;
 		AssertionSet funcNeed, funcHave;
-		TypeEnvironment funcEnv;
+		TypeEnvironment funcEnv( func.env );
 		makeUnifiableVars( funcType, funcOpenVars, funcNeed );
 		// add all type variables as open variables now so that those not used in the parameter 
 		// list are still considered open.
 		funcEnv.add( funcType->get_forall() );
-
+		
 		if ( targetType && ! targetType->isVoid() && ! funcType->get_returnVals().empty() ) {
 			// attempt to narrow based on expected target type
-			Type* returnType = funcType->get_returnVals().front()->get_type();
+			Type * returnType = funcType->get_returnVals().front()->get_type();
 			if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars, 
 					indexer ) ) {
@@ -905,14 +912,11 @@
 
 		// find function operators
+		static NameExpr *opExpr = new NameExpr( "?()" );
 		AlternativeFinder funcOpFinder( indexer, env );
-		NameExpr *opExpr = new NameExpr( "?()" );
-		try {
-			funcOpFinder.findWithAdjustment( opExpr );
-		} catch( SemanticError &e ) {
-			// it's ok if there aren't any defined function ops
-		}
+		// it's ok if there aren't any defined function ops
+		funcOpFinder.maybeFind( opExpr);
 		PRINT(
 			std::cerr << "known function ops:" << std::endl;
-			printAlts( funcOpFinder.alternatives, std::cerr, 8 );
+			printAlts( funcOpFinder.alternatives, std::cerr, 1 );
 		)
 
@@ -1028,5 +1032,5 @@
 	bool isLvalue( Expression *expr ) {
 		// xxx - recurse into tuples?
-		return expr->has_result() && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
+		return expr->result && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
 	}
 
@@ -1103,9 +1107,5 @@
 				thisCost.incSafe( discardedValues );
 				Alternative newAlt( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost );
-				// xxx - this doesn't work at the moment, since inferParameters requires an ApplicationExpr as the alternative.
-				// Once this works, it should be possible to infer parameters on a cast expression and specialize any function.
-
-				// inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
-				candidates.emplace_back( std::move( newAlt ) );
+				inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
 			} // if
 		} // for
@@ -1123,6 +1123,5 @@
 		AlternativeFinder finder( indexer, env );
 		// don't prune here, since it's guaranteed all alternatives will have the same type
-		// (giving the alternatives different types is half of the point of ConstructorExpr nodes)
-		finder.findWithAdjustment( castExpr->get_arg(), false );
+		finder.findWithoutPrune( castExpr->get_arg() );
 		for ( Alternative & alt : finder.alternatives ) {
 			alternatives.push_back( Alternative(
@@ -1163,5 +1162,5 @@
 		PRINT( std::cerr << "nameExpr is " << nameExpr->get_name() << std::endl; )
 		for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) {
-			VariableExpr newExpr( *i, nameExpr->get_argName() );
+			VariableExpr newExpr( *i );
 			alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
 			PRINT(
@@ -1398,5 +1397,4 @@
 		findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), back_inserter( subExprAlternatives ) );
 		std::list< AltList > possibilities;
-		// TODO re-write to use iterative method
 		combos( subExprAlternatives.begin(), subExprAlternatives.end(), back_inserter( possibilities ) );
 		for ( std::list< AltList >::const_iterator i = possibilities.begin(); i != possibilities.end(); ++i ) {
@@ -1422,5 +1420,5 @@
 		// don't prune here, since it's guaranteed all alternatives will have the same type
 		// (giving the alternatives different types is half of the point of ConstructorExpr nodes)
-		finder.findWithAdjustment( ctorExpr->get_callExpr(), false );
+		finder.findWithoutPrune( ctorExpr->get_callExpr() );
 		for ( Alternative & alt : finder.alternatives ) {
 			alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) );
@@ -1459,5 +1457,5 @@
 		// O(N^2) checks of d-types with e-types
 		for ( InitAlternative & initAlt : initExpr->get_initAlts() ) {
-			Type * toType = resolveTypeof( initAlt.type, indexer );
+			Type * toType = resolveTypeof( initAlt.type->clone(), indexer );
 			SymTab::validateType( toType, &indexer );
 			adjustExprType( toType, env, indexer );
@@ -1488,5 +1486,6 @@
 					// count one safe conversion for each value that is thrown away
 					thisCost.incSafe( discardedValues );
-					candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) );
+					Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost );
+					inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
 				}
 			}
Index: src/ResolvExpr/AlternativeFinder.h
===================================================================
--- src/ResolvExpr/AlternativeFinder.h	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/AlternativeFinder.h	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -61,7 +61,11 @@
 		}
 
-		void find( Expression *expr, bool adjust = false, bool prune = true );
+		void find( Expression *expr, bool adjust = false, bool prune = true, bool failFast = true );
 		/// Calls find with the adjust flag set; adjustment turns array and function types into equivalent pointer types
-		void findWithAdjustment( Expression *expr, bool prune = true );
+		void findWithAdjustment( Expression *expr );
+		/// Calls find with the adjust flag set and prune flag unset; pruning ensures there is at most one alternative per result type
+		void findWithoutPrune( Expression *expr );
+		/// Calls find with the adjust and prune flags set, failFast flags unset; fail fast ensures that there is at least one resulting alternative
+		void maybeFind( Expression *expr );
 		AltList &get_alternatives() { return alternatives; }
 
@@ -77,4 +81,9 @@
 		const SymTab::Indexer &get_indexer() const { return indexer; }
 		const TypeEnvironment &get_environ() const { return env; }
+
+		/// Runs a new alternative finder on each element in [begin, end)
+		/// and writes each alternative finder to out.
+		template< typename InputIterator, typename OutputIterator >
+		void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out );
 	  private:
 		virtual void visit( ApplicationExpr *applicationExpr );
@@ -108,8 +117,4 @@
 		virtual void visit( StmtExpr *stmtExpr );
 		virtual void visit( UntypedInitExpr *initExpr );
-		/// Runs a new alternative finder on each element in [begin, end)
-		/// and writes each alternative finder to out.
-		template< typename InputIterator, typename OutputIterator >
-		void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out );
 
 		/// Adds alternatives for anonymous members
@@ -134,4 +139,5 @@
 
 	Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env );
+	void referenceToRvalueConversion( Expression *& expr );
 
 	template< typename InputIterator, typename OutputIterator >
Index: src/ResolvExpr/CastCost.cc
===================================================================
--- src/ResolvExpr/CastCost.cc	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/CastCost.cc	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -24,4 +24,9 @@
 #include "typeops.h"                     // for typesCompatibleIgnoreQualifiers
 
+#if 0
+#define PRINT(x) x
+#else
+#define PRINT(x)
+#endif
 
 namespace ResolvExpr {
@@ -52,9 +57,21 @@
 			} // if
 		} // if
+
+		PRINT(
+			std::cerr << "castCost ::: src is ";
+			src->print( std::cerr );
+			std::cerr << std::endl << "dest is ";
+			dest->print( std::cerr );
+			std::cerr << std::endl << "env is" << std::endl;
+			env.print( std::cerr, 8 );
+		)
+
 		if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
+			PRINT( std::cerr << "compatible!" << std::endl; )
 			return Cost::zero;
 		} else if ( dynamic_cast< VoidType* >( dest ) ) {
 			return Cost::safe;
 		} else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
+			PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
 			return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer & indexer) {
 				return ptrsCastable( t1, t2, env, indexer );
Index: src/ResolvExpr/CommonType.cc
===================================================================
--- src/ResolvExpr/CommonType.cc	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/CommonType.cc	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 06:59:27 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 16 16:24:31 2017
-// Update Count     : 7
+// Last Modified On : Mon Sep 25 15:18:17 2017
+// Update Count     : 9
 //
 
@@ -61,29 +61,20 @@
 	};
 
-	Type * handleReference( ReferenceType * refType, Type * other, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) {
-		Type * result = nullptr, * common = nullptr;
+	Type * handleReference( Type * t1, Type * t2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) {
+		Type * common = nullptr;
 		AssertionSet have, need;
 		OpenVarSet newOpen( openVars );
 		// need unify to bind type variables
-		if ( unify( refType->get_base(), other, env, have, need, newOpen, indexer, common ) ) {
-			// std::cerr << "unify success" << std::endl;
-			if ( widenSecond ) {
-				// std::cerr << "widen second" << std::endl;
-				if ( widenFirst || other->get_qualifiers() <= refType->get_qualifiers() ) {
-					result = new ReferenceType( refType->get_qualifiers(), common ); // refType->clone();
-					result->get_qualifiers() |= other->get_qualifiers();
-				}
-			} else if ( widenFirst ) {
-				// std::cerr << "widen first" << std::endl;
-				if ( widenSecond || refType->get_qualifiers() <= other->get_qualifiers() ) {
-					result = common;
-					result->get_qualifiers() |= refType->get_qualifiers();
-				}
-			}
-		} else {
-			// std::cerr << "exact unify failed: " << refType << " " << other << std::endl;
-		}
-		// std::cerr << "common type of reference [" << refType << "] and non-reference [" << other << "] is [" << result << "]" << std::endl;
-		return result;
+		if ( unify( t1, t2, env, have, need, newOpen, indexer, common ) ) {
+			// std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl;
+			if ( (widenFirst || t2->get_qualifiers() <= t1->get_qualifiers()) && (widenSecond || t1->get_qualifiers() <= t2->get_qualifiers()) ) {
+				// std::cerr << "widen okay" << std::endl;
+				common->get_qualifiers() |= t1->get_qualifiers();
+				common->get_qualifiers() |= t2->get_qualifiers();
+				return common;
+			}
+		}
+		// std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl;
+		return nullptr;
 	}
 
@@ -99,8 +90,17 @@
 
 			// special case where one type has a reference depth of 1 larger than the other
-			if ( diff > 0 ) {
-				return handleReference( strict_dynamic_cast<ReferenceType *>( type1 ), type2, widenFirst, widenSecond, indexer, env, openVars );
-			} else if ( diff < 0 ) {
-				return handleReference( strict_dynamic_cast<ReferenceType *>( type2 ), type1, widenSecond, widenFirst, indexer, env, openVars );
+			if ( diff > 0 || diff < 0 ) {
+				Type * result = nullptr;
+				if ( ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 ) ) {
+					// formal is reference, so result should be reference
+					result = handleReference( ref1->base, type2, widenFirst, widenSecond, indexer, env, openVars );
+					if ( result ) result = new ReferenceType( ref1->get_qualifiers(), result );
+				} else {
+					// formal is value, so result should be value
+					ReferenceType * ref2 = strict_dynamic_cast< ReferenceType * > ( type2 );
+					result = handleReference( type1, ref2->base, widenFirst, widenSecond, indexer, env, openVars );
+				}
+				// std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is [" << result << "]" << std::endl;
+				return result;
 			}
 			// otherwise, both are reference types of the same depth and this is handled by the CommonType visitor.
@@ -150,26 +150,28 @@
 	static const BasicType::Kind combinedType[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] =
 	{
-/* 		Bool		Char	SignedChar	UnsignedChar	ShortSignedInt	ShortUnsignedInt	SignedInt	UnsignedInt	LongSignedInt	LongUnsignedInt	LongLongSignedInt	LongLongUnsignedInt	Float	Double	LongDouble	FloatComplex	DoubleComplex	LongDoubleComplex	FloatImaginary	DoubleImaginary	LongDoubleImaginary */
-		/* Bool */ 	{ BasicType::Bool,		BasicType::Char,	BasicType::SignedChar,	BasicType::UnsignedChar,	BasicType::ShortSignedInt,	BasicType::ShortUnsignedInt,	BasicType::SignedInt,	BasicType::UnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* Char */ 	{ BasicType::Char,		BasicType::Char,	BasicType::UnsignedChar,	BasicType::UnsignedChar,	BasicType::ShortSignedInt,	BasicType::ShortUnsignedInt,	BasicType::SignedInt,	BasicType::UnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* SignedChar */ 	{ BasicType::SignedChar,	BasicType::UnsignedChar,	BasicType::SignedChar,	BasicType::UnsignedChar,	BasicType::ShortSignedInt,	BasicType::ShortUnsignedInt,	BasicType::SignedInt,	BasicType::UnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* UnsignedChar */ 	{ BasicType::UnsignedChar,	BasicType::UnsignedChar,	BasicType::UnsignedChar,	BasicType::UnsignedChar,	BasicType::ShortSignedInt,	BasicType::ShortUnsignedInt,	BasicType::SignedInt,	BasicType::UnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* ShortSignedInt */ 	{ BasicType::ShortSignedInt,	BasicType::ShortSignedInt,	BasicType::ShortSignedInt,	BasicType::ShortSignedInt,	BasicType::ShortSignedInt,	BasicType::ShortUnsignedInt,	BasicType::SignedInt,	BasicType::UnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* ShortUnsignedInt */ 	{ BasicType::ShortUnsignedInt,	BasicType::ShortUnsignedInt,	BasicType::ShortUnsignedInt,	BasicType::ShortUnsignedInt,	BasicType::ShortUnsignedInt,	BasicType::ShortUnsignedInt,	BasicType::SignedInt,	BasicType::UnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* SignedInt */ 	{ BasicType::SignedInt,		BasicType::SignedInt,	BasicType::SignedInt,	BasicType::SignedInt,	BasicType::SignedInt,	BasicType::SignedInt,	BasicType::SignedInt,	BasicType::UnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* UnsignedInt */ 	{ BasicType::UnsignedInt,		BasicType::UnsignedInt,	BasicType::UnsignedInt,	BasicType::UnsignedInt,	BasicType::UnsignedInt,	BasicType::UnsignedInt,	BasicType::UnsignedInt,	BasicType::UnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* LongSignedInt */ 	{ BasicType::LongSignedInt,		BasicType::LongSignedInt,	BasicType::LongSignedInt,	BasicType::LongSignedInt,	BasicType::LongSignedInt,	BasicType::LongSignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* LongUnsignedInt */ 	{ BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* LongLongSignedInt */ 	{ BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* LongLongUnsignedInt */ 	{ BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* Float */ 	{ BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* Double */ 	{ BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::LongDouble,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* LongDouble */ 	{ BasicType::LongDouble,		BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex },
-		/* FloatComplex */ 	{ BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* DoubleComplex */ 	{ BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex },
-		/* LongDoubleComplex */ 	{ BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex },
-		/* FloatImaginary */ 	{ BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatImaginary,	BasicType::DoubleImaginary,	BasicType::LongDoubleImaginary },
-		/* DoubleImaginary */ 	{ BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::DoubleImaginary,	BasicType::DoubleImaginary,	BasicType::LongDoubleImaginary },
-		/* LongDoubleImaginary */ 	{ BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleImaginary,	BasicType::LongDoubleImaginary,	BasicType::LongDoubleImaginary }
+/* 		Bool		Char	SignedChar	UnsignedChar	ShortSignedInt	ShortUnsignedInt	SignedInt	UnsignedInt	LongSignedInt	LongUnsignedInt	LongLongSignedInt	LongLongUnsignedInt	Float	Double	LongDouble	FloatComplex	DoubleComplex	LongDoubleComplex	FloatImaginary	DoubleImaginary	LongDoubleImaginary   SignedInt128   UnsignedInt128 */
+		/* Bool */ 	{ BasicType::Bool,		BasicType::Char,	BasicType::SignedChar,	BasicType::UnsignedChar,	BasicType::ShortSignedInt,	BasicType::ShortUnsignedInt,	BasicType::SignedInt,	BasicType::UnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::SignedInt128,	BasicType::UnsignedInt128, },
+		/* Char */ 	{ BasicType::Char,		BasicType::Char,	BasicType::UnsignedChar,	BasicType::UnsignedChar,	BasicType::ShortSignedInt,	BasicType::ShortUnsignedInt,	BasicType::SignedInt,	BasicType::UnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::SignedInt128,	BasicType::UnsignedInt128, },
+		/* SignedChar */ 	{ BasicType::SignedChar,	BasicType::UnsignedChar,	BasicType::SignedChar,	BasicType::UnsignedChar,	BasicType::ShortSignedInt,	BasicType::ShortUnsignedInt,	BasicType::SignedInt,	BasicType::UnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::SignedInt128,	BasicType::UnsignedInt128, },
+		/* UnsignedChar */ 	{ BasicType::UnsignedChar,	BasicType::UnsignedChar,	BasicType::UnsignedChar,	BasicType::UnsignedChar,	BasicType::ShortSignedInt,	BasicType::ShortUnsignedInt,	BasicType::SignedInt,	BasicType::UnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::SignedInt128,	BasicType::UnsignedInt128, },
+		/* ShortSignedInt */ 	{ BasicType::ShortSignedInt,	BasicType::ShortSignedInt,	BasicType::ShortSignedInt,	BasicType::ShortSignedInt,	BasicType::ShortSignedInt,	BasicType::ShortUnsignedInt,	BasicType::SignedInt,	BasicType::UnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::SignedInt128,	BasicType::UnsignedInt128, },
+		/* ShortUnsignedInt */ 	{ BasicType::ShortUnsignedInt,	BasicType::ShortUnsignedInt,	BasicType::ShortUnsignedInt,	BasicType::ShortUnsignedInt,	BasicType::ShortUnsignedInt,	BasicType::ShortUnsignedInt,	BasicType::SignedInt,	BasicType::UnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::SignedInt128,	BasicType::UnsignedInt128, },
+		/* SignedInt */ 	{ BasicType::SignedInt,		BasicType::SignedInt,	BasicType::SignedInt,	BasicType::SignedInt,	BasicType::SignedInt,	BasicType::SignedInt,	BasicType::SignedInt,	BasicType::UnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::SignedInt128,	BasicType::UnsignedInt128, },
+		/* UnsignedInt */ 	{ BasicType::UnsignedInt,		BasicType::UnsignedInt,	BasicType::UnsignedInt,	BasicType::UnsignedInt,	BasicType::UnsignedInt,	BasicType::UnsignedInt,	BasicType::UnsignedInt,	BasicType::UnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::SignedInt128,	BasicType::UnsignedInt128, },
+		/* LongSignedInt */ 	{ BasicType::LongSignedInt,		BasicType::LongSignedInt,	BasicType::LongSignedInt,	BasicType::LongSignedInt,	BasicType::LongSignedInt,	BasicType::LongSignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongSignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::SignedInt128,	BasicType::UnsignedInt128, },
+		/* LongUnsignedInt */ 	{ BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongUnsignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::SignedInt128,	BasicType::UnsignedInt128, },
+		/* LongLongSignedInt */ 	{ BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongSignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::SignedInt128,	BasicType::UnsignedInt128, },
+		/* LongLongUnsignedInt */ 	{ BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::LongLongUnsignedInt,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::SignedInt128,	BasicType::UnsignedInt128, },
+		/* Float */ 	{ BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::Float,	BasicType::Float, },
+		/* Double */ 	{ BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::Double,	BasicType::LongDouble,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::Double,	BasicType::Double, },
+		/* LongDouble */ 	{ BasicType::LongDouble,		BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDouble,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDouble,	BasicType::LongDouble, },
+		/* FloatComplex */ 	{ BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::FloatComplex, },
+		/* DoubleComplex */ 	{ BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex, },
+		/* LongDoubleComplex */ 	{ BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex, },
+		/* FloatImaginary */ 	{ BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatImaginary,	BasicType::DoubleImaginary,	BasicType::LongDoubleImaginary,	BasicType::FloatImaginary,	BasicType::FloatImaginary, },
+		/* DoubleImaginary */ 	{ BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::DoubleComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::DoubleImaginary,	BasicType::DoubleImaginary,	BasicType::LongDoubleImaginary,	BasicType::DoubleImaginary,	BasicType::DoubleImaginary, },
+		/* LongDoubleImaginary */ 	{ BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleComplex,	BasicType::LongDoubleImaginary,	BasicType::LongDoubleImaginary,	BasicType::LongDoubleImaginary },
+		/* SignedInt128 */ 	{ BasicType::SignedInt128,	BasicType::SignedInt128,	BasicType::SignedInt128,	BasicType::SignedInt128,	BasicType::SignedInt128,	BasicType::SignedInt128,	BasicType::SignedInt128,	BasicType::SignedInt128,	BasicType::SignedInt128,	BasicType::SignedInt128,	BasicType::SignedInt128,	BasicType::SignedInt128,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::SignedInt128,	BasicType::UnsignedInt128, },
+		/* UnsignedInt128 */ 	{ BasicType::UnsignedInt128,	BasicType::UnsignedInt128,	BasicType::UnsignedInt128,	BasicType::UnsignedInt128,	BasicType::UnsignedInt128,	BasicType::UnsignedInt128,	BasicType::UnsignedInt128,	BasicType::UnsignedInt128,	BasicType::UnsignedInt128,	BasicType::UnsignedInt128,	BasicType::UnsignedInt128,	BasicType::UnsignedInt128,	BasicType::Float,	BasicType::Double,	BasicType::LongDouble,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::FloatComplex,	BasicType::DoubleComplex,	BasicType::LongDoubleComplex,	BasicType::UnsignedInt128,	BasicType::UnsignedInt128, },
 	};
 
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/ConversionCost.cc	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 07:06:19 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar  2 17:35:46 2016
-// Update Count     : 6
+// Last Modified On : Mon Sep 25 15:43:34 2017
+// Update Count     : 10
 //
 
@@ -28,10 +28,10 @@
 
 namespace ResolvExpr {
-	const Cost Cost::zero = Cost( 0, 0, 0, 0 );
-	const Cost Cost::infinity = Cost( -1, -1, -1, -1 );
-	const Cost Cost::unsafe = Cost( 1, 0, 0, 0 );
-	const Cost Cost::poly = Cost( 0, 1, 0, 0 );
-	const Cost Cost::safe = Cost( 0, 0, 1, 0 );
-	const Cost Cost::reference = Cost( 0, 0, 0, 1 );
+	const Cost Cost::zero =      Cost(  0,  0,  0,  0 );
+	const Cost Cost::infinity =  Cost( -1, -1, -1, -1 );
+	const Cost Cost::unsafe =    Cost(  1,  0,  0,  0 );
+	const Cost Cost::poly =      Cost(  0,  1,  0,  0 );
+	const Cost Cost::safe =      Cost(  0,  0,  1,  0 );
+	const Cost Cost::reference = Cost(  0,  0,  0,  1 );
 
 #if 0
@@ -113,7 +113,7 @@
 					int assignResult = func( srcAsRef->get_base(), destAsRef->get_base(), env, indexer );
 					PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
-					if ( assignResult < 0 ) {
+					if ( assignResult > 0 ) {
 						return Cost::safe;
-					} else if ( assignResult > 0 ) {
+					} else if ( assignResult < 0 ) {
 						return Cost::unsafe;
 					} // if
@@ -219,28 +219,31 @@
 */
 
-	static const int costMatrix[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] =
-	{
-	/* Src \ Dest:	Bool	Char	SChar	UChar	Short	UShort	Int 	UInt	Long	ULong	LLong	ULLong	Float	Double	LDbl	FCplex	DCplex	LDCplex	FImag	DImag	LDImag */
-		/* Bool */ 	{ 0,	1,		1,		2,		3,		4,		5,		6,		6,		7,		8,		9,		10,		11,		12,		11,		12,		13,		-1,		-1,		-1 },
-		/* Char */ 	{ -1,	0,		-1,		1,		2,		3,		4,		5,		5,		6,		7,		8,		9,		10,		11,		10,		11,		12,		-1,		-1,		-1 },
-		/* SChar */ { -1,	-1,		0,		1,		2,		3,		4,		5,		5,		6,		7,		8,		9,		10,		11,		10,		11,		12,		-1,		-1,		-1 },
-		/* UChar */ { -1,	-1,		-1,		0,		1,		2,		3,		4,		4,		5,		6,		7,		8,		9,		10,		9,		10,		11,		-1,		-1,		-1 },
-		/* Short */ { -1,	-1,		-1,		-1,		0,		1,		2,		3,		3,		4,		5,		6,		7,		8,		9,		8,		9,		10,		-1,		-1,		-1 },
-		/* UShort */{ -1,	-1,		-1,		-1,		-1,		0,		1,		2,		2,		3,		4,		5,		6,		7,		8,		7,		8,		9,		-1,		-1,		-1 },
-		/* Int */ 	{ -1,	-1,		-1,		-1,		-1,		-1,		0,		1,		1,		2,		3,		4,		5,		6,		7,		6,		7,		8,		-1,		-1,		-1 },
-		/* UInt */ 	{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		0,		-1,		1,		2,		3,		4,		5,		6,		5,		6,		7,		-1,		-1,		-1 },
-		/* Long */ 	{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		2,		3,		4,		5,		6,		5,		6,		7,		-1,		-1,		-1 },
-		/* ULong */ { -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		2,		3,		4,		5,		4,		5,		6,		-1,		-1,		-1 },
-		/* LLong */ { -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		2,		3,		4,		3,		4,		5,		-1,		-1,		-1 },
-		/* ULLong */{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		2,		3,		2,		3,		4,		-1,		-1,		-1 },
-		/* Float */ { -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		2,		1,		2,		3,		-1,		-1,		-1 },
-		/* Double */{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		-1,		1,		2,		-1,		-1,		-1 },
-		/* LDbl */ 	{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		-1,		-1,		1,		-1,		-1,		-1 },
-		/* FCplex */{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		2,		-1,		-1,		-1 },
-		/* DCplex */{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		-1,		-1,		-1 },
-		/* LDCplex */{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		-1,		-1,		-1 },
-		/* FImag */ { -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		1,		2,		3,		0,		1,		2 },
-		/* DImag */ { -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		1,		2,		-1,		0,		1 },
-		/* LDImag */{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		1,		-1,		-1,		0 }
+	static const int costMatrix[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] = {
+	/* Src \ Dest:	Bool	Char	SChar	UChar	Short	UShort	Int 	UInt	Long	ULong	LLong	ULLong	Float	Double	LDbl	FCplex	DCplex	LDCplex	FImag	DImag	LDImag	I128,	U128 */
+		/* Bool */ 	{ 0,	1,		1,		2,		3,		4,		5,		6,		6,		7,		8,		9,		12,		13,		14,		12,		13,		14,		-1,		-1,		-1,		10,		11,	},
+		/* Char */ 	{ -1,	0,		-1,		1,		2,		3,		4,		5,		5,		6,		7,		8,		11,		12,		13,		11,		12,		13,		-1,		-1,		-1,		9,		10,	},
+		/* SChar */ { -1,	-1,		0,		1,		2,		3,		4,		5,		5,		6,		7,		8,		11,		12,		13,		11,		12,		13,		-1,		-1,		-1,		9,		10,	},
+		/* UChar */ { -1,	-1,		-1,		0,		1,		2,		3,		4,		4,		5,		6,		7,		10,		11,		12,		10,		11,		12,		-1,		-1,		-1,		8,		9,	},
+		/* Short */ { -1,	-1,		-1,		-1,		0,		1,		2,		3,		3,		4,		5,		6,		9,		10,		11,		9,		10,		11,		-1,		-1,		-1,		7,		8,	},
+		/* UShort */{ -1,	-1,		-1,		-1,		-1,		0,		1,		2,		2,		3,		4,		5,		8,		9,		10,		8,		9,		10,		-1,		-1,		-1,		6,		7,	},
+		/* Int */ 	{ -1,	-1,		-1,		-1,		-1,		-1,		0,		1,		1,		2,		3,		4,		7,		8,		9,		7,		8,		9,		-1,		-1,		-1,		5,		6,	},
+		/* UInt */ 	{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		0,		-1,		1,		2,		3,		6,		7,		8,		6,		7,		8,		-1,		-1,		-1,		4,		5,	},
+		/* Long */ 	{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		2,		3,		6,		7,		8,		6,		7,		8,		-1,		-1,		-1,		4,		5,	},
+		/* ULong */ { -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		2,		5,		6,		7,		5,		6,		7,		-1,		-1,		-1,		3,		4,	},
+		/* LLong */ { -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		4,		5,		6,		4,		5,		6,		-1,		-1,		-1,		2,		3,	},
+		/* ULLong */{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		3,		4,		5,		3,		4,		5,		-1,		-1,		-1,		1,		2,	},
+
+		/* Float */ { -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		2,		1,		2,		3,		-1,		-1,		-1,		-1,		-1,	},
+		/* Double */{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		-1,		1,		2,		-1,		-1,		-1,		-1,		-1,	},
+		/* LDbl */ 	{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		-1,		-1,		1,		-1,		-1,		-1,		-1,		-1,	},
+		/* FCplex */{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		2,		-1,		-1,		-1,		-1,		-1,	},
+		/* DCplex */{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		1,		-1,		-1,		-1,		-1,		-1,	},
+		/* LDCplex */{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		0,		-1,		-1,		-1,		-1,		-1,	},
+		/* FImag */ { -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		1,		2,		3,		0,		1,		2,		-1,		-1,	},
+		/* DImag */ { -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		1,		2,		-1,		0,		1,		-1,		-1,	},
+		/* LDImag */{ -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		1,		-1,		-1,		0,		-1,		-1,	},
+
+		/* I128 */  { -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		2,		3,		4,		3,		4,		5,		-1,		-1,		-1,		0,		1,	},
+		/* U128 */  { -1,	-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		-1,		1,		2,		3,		2,		3,		4,		-1,		-1,		-1,		-1,		0,	},
 	};
 
@@ -266,5 +269,5 @@
 	}
 
-	void ConversionCost::visit(PointerType *pointerType) {
+	void ConversionCost::visit( PointerType * pointerType ) {
 		if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
 			PRINT( std::cerr << pointerType << " ===> " << destAsPtr; )
@@ -281,21 +284,21 @@
 				}
 			} else {  // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
-				int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env );
+				int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
 				PRINT( std::cerr << " :: " << assignResult << std::endl; )
-				if ( assignResult < 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) {
+				if ( assignResult > 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) {
 					cost = Cost::safe;
-				} else if ( assignResult > 0 ) {
+				} else if ( assignResult < 0 ) {
 					cost = Cost::unsafe;
 				} // if
 				// assignResult == 0 means Cost::Infinity
 			} // if
-		} else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
+		} else if ( dynamic_cast< ZeroType * >( dest ) ) {
 			cost = Cost::unsafe;
 		} // if
 	}
 
-	void ConversionCost::visit(__attribute((unused)) ArrayType *arrayType) {}
-
-	void ConversionCost::visit(ReferenceType *refType) {
+	void ConversionCost::visit( ArrayType * ) {}
+
+	void ConversionCost::visit( ReferenceType * refType ) {
 		// Note: dest can never be a reference, since it would have been caught in an earlier check
 		assert( ! dynamic_cast< ReferenceType * >( dest ) );
@@ -303,8 +306,8 @@
 		// recursively compute conversion cost from T1 to T2.
 		// cv can be safely dropped because of 'implicit dereference' behavior.
-		refType->get_base()->accept( *this );
-		if ( refType->get_base()->get_qualifiers() == dest->get_qualifiers() ) {
+		refType->base->accept( *this );
+		if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) {
 			cost.incReference();  // prefer exact qualifiers
-		} else if ( refType->get_base()->get_qualifiers() < dest->get_qualifiers() ) {
+		} else if ( refType->base->get_qualifiers() < dest->get_qualifiers() ) {
 			cost.incSafe(); // then gaining qualifiers
 		} else {
@@ -314,23 +317,23 @@
 	}
 
-	void ConversionCost::visit(__attribute((unused)) FunctionType *functionType) {}
-
-	void ConversionCost::visit(StructInstType *inst) {
+	void ConversionCost::visit( FunctionType * ) {}
+
+	void ConversionCost::visit( StructInstType * inst ) {
 		if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
-			if ( inst->get_name() == destAsInst->get_name() ) {
-				cost = Cost::zero;
-			} // if
-		} // if
-	}
-
-	void ConversionCost::visit(UnionInstType *inst) {
-		if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
-			if ( inst->get_name() == destAsInst->get_name() ) {
-				cost = Cost::zero;
-			} // if
-		} // if
-	}
-
-	void ConversionCost::visit( __attribute((unused)) EnumInstType *inst ) {
+			if ( inst->name == destAsInst->name ) {
+				cost = Cost::zero;
+			} // if
+		} // if
+	}
+
+	void ConversionCost::visit( UnionInstType * inst ) {
+		if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) {
+			if ( inst->name == destAsInst->name ) {
+				cost = Cost::zero;
+			} // if
+		} // if
+	}
+
+	void ConversionCost::visit( EnumInstType * ) {
 		static Type::Qualifiers q;
 		static BasicType integer( q, BasicType::SignedInt );
@@ -341,8 +344,7 @@
 	}
 
-	void ConversionCost::visit( __attribute((unused)) TraitInstType *inst) {
-	}
-
-	void ConversionCost::visit(TypeInstType *inst) {
+	void ConversionCost::visit( TraitInstType * ) {}
+
+	void ConversionCost::visit( TypeInstType *inst ) {
 		EqvClass eqvClass;
 		NamedTypeDecl *namedType;
@@ -363,9 +365,9 @@
 	}
 
-	void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) {
+	void ConversionCost::visit( TupleType * tupleType ) {
 		Cost c = Cost::zero;
-		if ( TupleType *destAsTuple = dynamic_cast< TupleType* >( dest ) ) {
-			std::list< Type* >::const_iterator srcIt = tupleType->get_types().begin();
-			std::list< Type* >::const_iterator destIt = destAsTuple->get_types().begin();
+		if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) {
+			std::list< Type * >::const_iterator srcIt = tupleType->get_types().begin();
+			std::list< Type * >::const_iterator destIt = destAsTuple->get_types().begin();
 			while ( srcIt != tupleType->get_types().end() && destIt != destAsTuple->get_types().end() ) {
 				Cost newCost = conversionCost( *srcIt++, *destIt++, indexer, env );
@@ -383,5 +385,5 @@
 	}
 
-	void ConversionCost::visit( __attribute((unused)) VarArgsType *varArgsType) {
+	void ConversionCost::visit( VarArgsType * ) {
 		if ( dynamic_cast< VarArgsType* >( dest ) ) {
 			cost = Cost::zero;
@@ -389,6 +391,6 @@
 	}
 
-	void ConversionCost::visit( __attribute((unused)) ZeroType *zeroType) {
-		if ( dynamic_cast< ZeroType* >( dest ) ) {
+	void ConversionCost::visit( ZeroType * ) {
+		if ( dynamic_cast< ZeroType * >( dest ) ) {
 			cost = Cost::zero;
 		} else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
@@ -406,6 +408,6 @@
 	}
 
-	void ConversionCost::visit( __attribute((unused)) OneType *oneType) {
-		if ( dynamic_cast< OneType* >( dest ) ) {
+	void ConversionCost::visit( OneType * ) {
+		if ( dynamic_cast< OneType * >( dest ) ) {
 			cost = Cost::zero;
 		} else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
Index: src/ResolvExpr/CurrentObject.cc
===================================================================
--- src/ResolvExpr/CurrentObject.cc	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/CurrentObject.cc	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -260,4 +260,5 @@
 
 		AggregateIterator( const std::string & kind, const std::string & name, Type * inst, const MemberList & members ) : kind( kind ), name( name ), inst( inst ), members( members ), curMember( members.begin() ), sub( makeGenericSubstitution( inst ) ) {
+			PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
 			init();
 		}
Index: src/ResolvExpr/PolyCost.cc
===================================================================
--- src/ResolvExpr/PolyCost.cc	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/PolyCost.cc	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// PolyCost.cc -- 
+// PolyCost.cc --
 //
 // Author           : Richard C. Bilson
@@ -31,5 +31,5 @@
 	};
 
-	int polyCost( Type *type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
+	int polyCost( Type *type, const TypeEnvironment & env, const SymTab::Indexer &indexer ) {
 		PolyCost coster( env, indexer );
 		type->accept( coster );
@@ -37,16 +37,18 @@
 	}
 
-	PolyCost::PolyCost( const TypeEnvironment &env, const SymTab::Indexer &indexer ) : result( 0 ), env( env ), indexer( indexer ) {
+	PolyCost::PolyCost( const TypeEnvironment & env, const SymTab::Indexer & indexer ) : result( 0 ), env( env ), indexer( indexer ) {
 	}
 
-	void PolyCost::visit(TypeInstType *typeInst) {
+	void PolyCost::visit(TypeInstType * typeInst) {
 		EqvClass eqvClass;
-		if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
+		if ( env.lookup( typeInst->name, eqvClass ) ) {
 			if ( eqvClass.type ) {
-				if ( TypeInstType *otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass.type ) ) {
-					if ( indexer.lookupType( otherTypeInst->get_name() ) ) {
+				if ( TypeInstType * otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass.type ) ) {
+					if ( indexer.lookupType( otherTypeInst->name ) ) {
+						// bound to opaque type
 						result += 1;
 					} // if
 				} else {
+					// bound to concrete type
 					result += 1;
 				} // if
Index: src/ResolvExpr/PtrsAssignable.cc
===================================================================
--- src/ResolvExpr/PtrsAssignable.cc	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/PtrsAssignable.cc	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -47,4 +47,5 @@
 
 	int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env ) {
+		// std::cerr << "assignable: " << src << " | " << dest << std::endl;
 		if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
 			EqvClass eqvClass;
@@ -54,5 +55,7 @@
 		} // if
 		if ( dynamic_cast< VoidType* >( dest ) ) {
-			return 1;
+			// void * = T * for any T is unsafe
+			// xxx - this should be safe, but that currently breaks the build
+			return -1;
 		} else {
 			PtrsAssignable ptrs( dest, env );
@@ -65,8 +68,8 @@
 
 	void PtrsAssignable::visit( __attribute((unused)) VoidType *voidType ) {
-		if ( dynamic_cast< FunctionType* >( dest ) ) {
-			result = 0;
-		} else {
-			result = -1;
+		if ( ! dynamic_cast< FunctionType* >( dest ) ) {
+			// T * = void * is safe for any T that is not a function type.
+			// xxx - this should be unsafe...
+			result = 1;
 		} // if
 	}
@@ -75,7 +78,5 @@
 	void PtrsAssignable::visit( __attribute__((unused)) PointerType *pointerType ) {}
 	void PtrsAssignable::visit( __attribute__((unused)) ArrayType *arrayType ) {}
-	void PtrsAssignable::visit( __attribute__((unused)) FunctionType *functionType ) {
-		result = -1;
-	}
+	void PtrsAssignable::visit( __attribute__((unused)) FunctionType *functionType ) {}
 
 	void PtrsAssignable::visit(  __attribute__((unused)) StructInstType *inst ) {}
@@ -83,8 +84,11 @@
 
 	void PtrsAssignable::visit( EnumInstType * ) {
-		if ( dynamic_cast< EnumInstType* >( dest ) ) {
+		if ( dynamic_cast< BasicType* >( dest ) ) {
+			// int * = E *, etc. is safe. This isn't technically correct, as each
+			// enum has one basic type that it is compatible with, an that type can
+			// differ from enum to enum. Without replicating GCC's internal logic,
+			// there is no way to know which type this particular enum is compatible
+			// with, so punt on this for now.
 			result = 1;
-		} else if ( BasicType *bt = dynamic_cast< BasicType* >( dest ) ) {
-			result = bt->get_kind() == BasicType::SignedInt;
 		}
 	}
@@ -94,7 +98,6 @@
 		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 );
-		} else {
-			result = 0;
 		} // if
 	}
Index: src/ResolvExpr/PtrsCastable.cc
===================================================================
--- src/ResolvExpr/PtrsCastable.cc	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/PtrsCastable.cc	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -50,25 +50,27 @@
 	};
 
-	int objectCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
-		if ( dynamic_cast< FunctionType* >( src ) ) {
-			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 ) ) {
-					if ( tyDecl->get_kind() == TypeDecl::Ftype ) {
+	namespace {
+		int objectCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
+			if ( dynamic_cast< FunctionType* >( src ) ) {
+				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 ) ) {
+						if ( tyDecl->get_kind() == TypeDecl::Ftype ) {
+							return -1;
+						} // if
+					} //if
+				} else if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
+					if ( eqvClass.data.kind == TypeDecl::Ftype ) {
 						return -1;
 					} // if
-				} //if
-			} else if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
-				if ( eqvClass.data.kind == TypeDecl::Ftype ) {
-					return -1;
 				} // if
-			} // if
-		} //if
-		return 1;
-	}
-	int functionCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
-		return -1 * objectCast( src, env, indexer );  // reverse the sense of objectCast
+			} //if
+			return 1;
+		}
+		int functionCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
+			return -1 * objectCast( src, env, indexer );  // reverse the sense of objectCast
+		}
 	}
 
@@ -93,34 +95,34 @@
 	}
 
-	void PtrsCastable::visit( __attribute__((unused)) VoidType *voidType) {
+	void PtrsCastable::visit( VoidType * ) {
 		result = objectCast( dest, env, indexer );
 	}
 
-	void PtrsCastable::visit( __attribute__((unused)) BasicType *basicType) {
+	void PtrsCastable::visit( BasicType * ) {
 		result = objectCast( dest, env, indexer );
 	}
 
-	void PtrsCastable::visit( __attribute__((unused)) PointerType *pointerType) {
+	void PtrsCastable::visit( PointerType * ) {
 		result = objectCast( dest, env, indexer );
 	}
 
-	void PtrsCastable::visit( __attribute__((unused)) ArrayType *arrayType) {
+	void PtrsCastable::visit( ArrayType * ) {
 		result = objectCast( dest, env, indexer );
 	}
 
-	void PtrsCastable::visit( __attribute__((unused)) FunctionType *functionType) {
+	void PtrsCastable::visit( FunctionType * ) {
 		// result = -1;
 		result = functionCast( dest, env, indexer );
 	}
 
-	void PtrsCastable::visit( __attribute__((unused)) StructInstType *inst) {
+	void PtrsCastable::visit( StructInstType * ) {
 		result = objectCast( dest, env, indexer );
 	}
 
-	void PtrsCastable::visit( __attribute__((unused)) UnionInstType *inst) {
+	void PtrsCastable::visit( UnionInstType * ) {
 		result = objectCast( dest, env, indexer );
 	}
 
-	void PtrsCastable::visit( __attribute__((unused)) EnumInstType *inst) {
+	void PtrsCastable::visit( EnumInstType * ) {
 		if ( dynamic_cast< EnumInstType* >( dest ) ) {
 			result = 1;
@@ -136,5 +138,5 @@
 	}
 
-	void PtrsCastable::visit( __attribute__((unused)) TraitInstType *inst ) {}
+	void PtrsCastable::visit( TraitInstType * ) {}
 
 	void PtrsCastable::visit(TypeInstType *inst) {
@@ -143,17 +145,17 @@
 	}
 
-	void PtrsCastable::visit( __attribute__((unused)) TupleType *tupleType) {
+	void PtrsCastable::visit( TupleType * ) {
 		result = objectCast( dest, env, indexer );
 	}
 
-	void PtrsCastable::visit( __attribute__((unused)) VarArgsType *varArgsType) {
+	void PtrsCastable::visit( VarArgsType * ) {
 		result = objectCast( dest, env, indexer );
 	}
 
-	void PtrsCastable::visit( __attribute__((unused)) ZeroType *zeroType) {
+	void PtrsCastable::visit( ZeroType * ) {
 		result = objectCast( dest, env, indexer );
 	}
 
-	void PtrsCastable::visit( __attribute__((unused)) OneType *oneType) {
+	void PtrsCastable::visit( OneType * ) {
 		result = objectCast( dest, env, indexer );
 	}
Index: src/ResolvExpr/ResolveTypeof.cc
===================================================================
--- src/ResolvExpr/ResolveTypeof.cc	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/ResolveTypeof.cc	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -18,4 +18,5 @@
 #include <cassert>               // for assert
 
+#include "Common/PassVisitor.h"  // for PassVisitor
 #include "Resolver.h"            // for resolveInVoidContext
 #include "SynTree/Expression.h"  // for Expression
@@ -41,8 +42,9 @@
 	}
 
-	class ResolveTypeof : public Mutator {
+	class ResolveTypeof : public WithShortCircuiting {
 	  public:
 		ResolveTypeof( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
-		Type *mutate( TypeofType *typeofType );
+		void premutate( TypeofType *typeofType );
+		Type * postmutate( TypeofType *typeofType );
 
 	  private:
@@ -50,20 +52,24 @@
 	};
 
-	Type *resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
-		ResolveTypeof mutator( indexer );
+	Type * resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
+		PassVisitor<ResolveTypeof> mutator( indexer );
 		return type->acceptMutator( mutator );
 	}
 
-	Type *ResolveTypeof::mutate( TypeofType *typeofType ) {
+	void ResolveTypeof::premutate( TypeofType * ) {
+		visit_children = false;
+	}
+
+	Type * ResolveTypeof::postmutate( TypeofType *typeofType ) {
 #if 0
-		std::cout << "resolving typeof: ";
-		typeofType->print( std::cout );
-		std::cout << std::endl;
+		std::cerr << "resolving typeof: ";
+		typeofType->print( std::cerr );
+		std::cerr << std::endl;
 #endif
-		if ( typeofType->get_expr() ) {
-			Expression *newExpr = resolveInVoidContext( typeofType->get_expr(), indexer );
-			assert( newExpr->has_result() && ! newExpr->get_result()->isVoid() );
-			Type *newType = newExpr->get_result();
-			newExpr->set_result( nullptr );
+		if ( typeofType->expr ) {
+			Expression * newExpr = resolveInVoidContext( typeofType->expr, indexer );
+			assert( newExpr->result && ! newExpr->result->isVoid() );
+			Type * newType = newExpr->result;
+			newExpr->result = nullptr;
 			delete typeofType;
 			delete newExpr;
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/Resolver.cc	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -40,4 +40,5 @@
 #include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
 #include "typeops.h"                     // for extractResultType
+#include "Unify.h"                       // for unify
 
 using namespace std;
@@ -52,5 +53,5 @@
 		void previsit( FunctionDecl *functionDecl );
 		void postvisit( FunctionDecl *functionDecl );
-		void previsit( ObjectDecl *functionDecl );
+		void previsit( ObjectDecl *objectDecll );
 		void previsit( TypeDecl *typeDecl );
 		void previsit( EnumDecl * enumDecl );
@@ -71,4 +72,5 @@
 		void previsit( ThrowStmt *throwStmt );
 		void previsit( CatchStmt *catchStmt );
+		void previsit( WaitForStmt * stmt );
 
 		void previsit( SingleInit *singleInit );
@@ -95,4 +97,9 @@
 	}
 
+	void resolveDecl( Declaration * decl, const SymTab::Indexer &indexer ) {
+		PassVisitor<Resolver> resolver( indexer );
+		maybeAccept( decl, resolver );
+	}
+
 	// used in resolveTypeof
 	Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {
@@ -102,40 +109,62 @@
 
 	namespace {
-		void finishExpr( Expression *expr, const TypeEnvironment &env ) {
-			expr->set_env( new TypeSubstitution );
+		void finishExpr( Expression *expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {
+			expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
 			env.makeSubstitution( *expr->get_env() );
 		}
+
+		void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
+			if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
+				if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
+					// cast is to the same type as its argument, so it's unnecessary -- remove it
+					expr = castExpr->arg;
+					castExpr->arg = nullptr;
+					std::swap( expr->env, castExpr->env );
+					delete castExpr;
+				}
+			}
+		}
 	} // namespace
 
-	Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
+	void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
 		global_renamer.reset();
 		TypeEnvironment env;
 		Expression *newExpr = resolveInVoidContext( untyped, indexer, env );
-		finishExpr( newExpr, env );
-		return newExpr;
+		finishExpr( newExpr, env, untyped->env );
+		delete untyped;
+		untyped = newExpr;
+	}
+
+	void findSingleExpression( Expression *&untyped, const SymTab::Indexer &indexer ) {
+		if ( ! untyped ) return;
+		TypeEnvironment env;
+		AlternativeFinder finder( indexer, env );
+		finder.find( untyped );
+		#if 0
+		if ( finder.get_alternatives().size() != 1 ) {
+			std::cerr << "untyped expr is ";
+			untyped->print( std::cerr );
+			std::cerr << std::endl << "alternatives are:";
+			for ( const Alternative & alt : finder.get_alternatives() ) {
+				alt.print( std::cerr );
+			} // for
+		} // if
+		#endif
+		assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." );
+		Alternative &choice = finder.get_alternatives().front();
+		Expression *newExpr = choice.expr->clone();
+		finishExpr( newExpr, choice.env, untyped->env );
+		delete untyped;
+		untyped = newExpr;
+	}
+
+	void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) {
+		assert( untyped && type );
+		untyped = new CastExpr( untyped, type );
+		findSingleExpression( untyped, indexer );
+		removeExtraneousCast( untyped, indexer );
 	}
 
 	namespace {
-		Expression *findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
-			TypeEnvironment env;
-			AlternativeFinder finder( indexer, env );
-			finder.find( untyped );
-#if 0
-			if ( finder.get_alternatives().size() != 1 ) {
-				std::cout << "untyped expr is ";
-				untyped->print( std::cout );
-				std::cout << std::endl << "alternatives are:";
-				for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
-					i->print( std::cout );
-				} // for
-			} // if
-#endif
-			assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." );
-			Alternative &choice = finder.get_alternatives().front();
-			Expression *newExpr = choice.expr->clone();
-			finishExpr( newExpr, choice.env );
-			return newExpr;
-		}
-
 		bool isIntegralType( Type *type ) {
 			if ( dynamic_cast< EnumInstType * >( type ) ) {
@@ -150,5 +179,5 @@
 		}
 
-		Expression *findIntegralExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
+		void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
 			TypeEnvironment env;
 			AlternativeFinder finder( indexer, env );
@@ -179,6 +208,7 @@
 				throw SemanticError( "No interpretations for case control expression", untyped );
 			} // if
-			finishExpr( newExpr, *newEnv );
-			return newExpr;
+			finishExpr( newExpr, *newEnv, untyped->env );
+			delete untyped;
+			untyped = newExpr;
 		}
 
@@ -205,8 +235,5 @@
 	void Resolver::handlePtrType( PtrType * type ) {
 		if ( type->get_dimension() ) {
-			CastExpr *castExpr = new CastExpr( type->get_dimension(), SymTab::SizeType->clone() );
-			Expression *newExpr = findSingleExpression( castExpr, indexer );
-			delete type->get_dimension();
-			type->set_dimension( newExpr );
+			findSingleExpression( type->dimension, SymTab::SizeType->clone(), indexer );
 		}
 	}
@@ -238,5 +265,4 @@
 		functionReturn = ResolvExpr::extractResultType( functionDecl->get_functionType() );
 	}
-
 
 	void Resolver::postvisit( FunctionDecl *functionDecl ) {
@@ -262,19 +288,13 @@
 	void Resolver::previsit( ExprStmt *exprStmt ) {
 		visit_children = false;
-		assertf( exprStmt->get_expr(), "ExprStmt has null Expression in resolver" );
-		Expression *newExpr = findVoidExpression( exprStmt->get_expr(), indexer );
-		delete exprStmt->get_expr();
-		exprStmt->set_expr( newExpr );
+		assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" );
+		findVoidExpression( exprStmt->expr, indexer );
 	}
 
 	void Resolver::previsit( AsmExpr *asmExpr ) {
 		visit_children = false;
-		Expression *newExpr = findVoidExpression( asmExpr->get_operand(), indexer );
-		delete asmExpr->get_operand();
-		asmExpr->set_operand( newExpr );
+		findVoidExpression( asmExpr->operand, indexer );
 		if ( asmExpr->get_inout() ) {
-			newExpr = findVoidExpression( asmExpr->get_inout(), indexer );
-			delete asmExpr->get_inout();
-			asmExpr->set_inout( newExpr );
+			findVoidExpression( asmExpr->inout, indexer );
 		} // if
 	}
@@ -287,26 +307,18 @@
 
 	void Resolver::previsit( IfStmt *ifStmt ) {
-		Expression *newExpr = findSingleExpression( ifStmt->get_condition(), indexer );
-		delete ifStmt->get_condition();
-		ifStmt->set_condition( newExpr );
+		findSingleExpression( ifStmt->condition, indexer );
 	}
 
 	void Resolver::previsit( WhileStmt *whileStmt ) {
-		Expression *newExpr = findSingleExpression( whileStmt->get_condition(), indexer );
-		delete whileStmt->get_condition();
-		whileStmt->set_condition( newExpr );
+		findSingleExpression( whileStmt->condition, indexer );
 	}
 
 	void Resolver::previsit( ForStmt *forStmt ) {
-		if ( forStmt->get_condition() ) {
-			Expression * newExpr = findSingleExpression( forStmt->get_condition(), indexer );
-			delete forStmt->get_condition();
-			forStmt->set_condition( newExpr );
+		if ( forStmt->condition ) {
+			findSingleExpression( forStmt->condition, indexer );
 		} // if
 
-		if ( forStmt->get_increment() ) {
-			Expression * newExpr = findVoidExpression( forStmt->get_increment(), indexer );
-			delete forStmt->get_increment();
-			forStmt->set_increment( newExpr );
+		if ( forStmt->increment ) {
+			findVoidExpression( forStmt->increment, indexer );
 		} // if
 	}
@@ -314,10 +326,7 @@
 	void Resolver::previsit( SwitchStmt *switchStmt ) {
 		GuardValue( currentObject );
-		Expression *newExpr;
-		newExpr = findIntegralExpression( switchStmt->get_condition(), indexer );
-		delete switchStmt->get_condition();
-		switchStmt->set_condition( newExpr );
-
-		currentObject = CurrentObject( newExpr->get_result() );
+		findIntegralExpression( switchStmt->condition, indexer );
+
+		currentObject = CurrentObject( switchStmt->condition->result );
 	}
 
@@ -326,9 +335,10 @@
 			std::list< InitAlternative > initAlts = currentObject.getOptions();
 			assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." );
-			CastExpr * castExpr = new CastExpr( caseStmt->get_condition(), initAlts.front().type->clone() );
-			Expression * newExpr = findSingleExpression( castExpr, indexer );
-			castExpr = strict_dynamic_cast< CastExpr * >( newExpr );
-			caseStmt->set_condition( castExpr->get_arg() );
-			castExpr->set_arg( nullptr );
+			// must remove cast from case statement because RangeExpr cannot be cast.
+			Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() );
+			findSingleExpression( newExpr, indexer );
+			CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( newExpr );
+			caseStmt->condition = castExpr->arg;
+			castExpr->arg = nullptr;
 			delete castExpr;
 		}
@@ -339,10 +349,7 @@
 		// must resolve the argument for a computed goto
 		if ( branchStmt->get_type() == BranchStmt::Goto ) { // check for computed goto statement
-			if ( Expression * arg = branchStmt->get_computedTarget() ) {
-				VoidType v = Type::Qualifiers();		// cast to void * for the alternative finder
-				PointerType pt( Type::Qualifiers(), v.clone() );
-				CastExpr * castExpr = new CastExpr( arg, pt.clone() );
-				Expression * newExpr = findSingleExpression( castExpr, indexer ); // find best expression
-				branchStmt->set_target( newExpr );
+			if ( branchStmt->computedTarget ) {
+				// computed goto argument is void *
+				findSingleExpression( branchStmt->computedTarget, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), indexer );
 			} // if
 		} // if
@@ -351,9 +358,6 @@
 	void Resolver::previsit( ReturnStmt *returnStmt ) {
 		visit_children = false;
-		if ( returnStmt->get_expr() ) {
-			CastExpr *castExpr = new CastExpr( returnStmt->get_expr(), functionReturn->clone() );
-			Expression *newExpr = findSingleExpression( castExpr, indexer );
-			delete castExpr;
-			returnStmt->set_expr( newExpr );
+		if ( returnStmt->expr ) {
+			findSingleExpression( returnStmt->expr, functionReturn->clone(), indexer );
 		} // if
 	}
@@ -366,26 +370,201 @@
 				indexer.lookupStruct( "__cfaehm__base_exception_t" );
 			assert( exception_decl );
-			Expression * wrapped = new CastExpr(
-				throwStmt->get_expr(),
-				new PointerType(
-					noQualifiers,
-					new StructInstType(
-						noQualifiers,
-						exception_decl
-						)
-					)
-				);
-			Expression * newExpr = findSingleExpression( wrapped, indexer );
-			throwStmt->set_expr( newExpr );
+			Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, exception_decl ) );
+			findSingleExpression( throwStmt->expr, exceptType, indexer );
 		}
 	}
 
 	void Resolver::previsit( CatchStmt *catchStmt ) {
-		if ( catchStmt->get_cond() ) {
-			Expression * wrapped = new CastExpr(
-				catchStmt->get_cond(),
-				new BasicType( noQualifiers, BasicType::Bool )
-				);
-			catchStmt->set_cond( findSingleExpression( wrapped, indexer ) );
+		if ( catchStmt->cond ) {
+			findSingleExpression( catchStmt->cond, new BasicType( noQualifiers, BasicType::Bool ), indexer );
+		}
+	}
+
+	template< typename iterator_t >
+	inline bool advance_to_mutex( iterator_t & it, const iterator_t & end ) {
+		while( it != end && !(*it)->get_type()->get_mutex() ) {
+			it++;
+		}
+
+		return it != end;
+	}
+
+	void Resolver::previsit( WaitForStmt * stmt ) {
+		visit_children = false;
+
+		// Resolve all clauses first
+		for( auto& clause : stmt->clauses ) {
+
+			TypeEnvironment env;
+			AlternativeFinder funcFinder( indexer, env );
+
+			// Find all alternatives for a function in canonical form
+			funcFinder.findWithAdjustment( clause.target.function );
+
+			if ( funcFinder.get_alternatives().empty() ) {
+				stringstream ss;
+				ss << "Use of undeclared indentifier '";
+				ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
+				ss << "' in call to waitfor";
+				throw SemanticError( ss.str() );
+			}
+
+			// Find all alternatives for all arguments in canonical form
+			std::list< AlternativeFinder > argAlternatives;
+			funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) );
+
+			// List all combinations of arguments
+			std::list< AltList > possibilities;
+			combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
+
+			AltList                func_candidates;
+			std::vector< AltList > args_candidates;
+
+			// For every possible function :
+			// 	try matching the arguments to the parameters
+			// 	not the other way around because we have more arguments than parameters
+			SemanticError errors;
+			for ( Alternative & func : funcFinder.get_alternatives() ) {
+				try {
+					PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
+					if( !pointer ) {
+						throw SemanticError( "candidate not viable: not a pointer type\n", func.expr->get_result() );
+					}
+
+					FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
+					if( !function ) {
+						throw SemanticError( "candidate not viable: not a function type\n", pointer->get_base() );
+					}
+
+
+					{
+						auto param     = function->parameters.begin();
+						auto param_end = function->parameters.end();
+
+						if( !advance_to_mutex( param, param_end ) ) {
+							throw SemanticError("candidate function not viable: no mutex parameters\n", function);
+						}
+					}
+
+					Alternative newFunc( func );
+					// Strip reference from function
+					referenceToRvalueConversion( newFunc.expr );
+
+					// For all the set of arguments we have try to match it with the parameter of the current function alternative
+					for ( auto & argsList : possibilities ) {
+
+						try {
+							// Declare data structures need for resolution
+							OpenVarSet openVars;
+							AssertionSet resultNeed, resultHave;
+							TypeEnvironment resultEnv;
+
+							// Load type variables from arguemnts into one shared space
+							simpleCombineEnvironments( argsList.begin(), argsList.end(), resultEnv );
+
+							// Make sure we don't widen any existing bindings
+							for ( auto & i : resultEnv ) {
+								i.allowWidening = false;
+							}
+
+							// Find any unbound type variables
+							resultEnv.extractOpenVars( openVars );
+
+							auto param     = function->parameters.begin();
+							auto param_end = function->parameters.end();
+
+							// For every arguments of its set, check if it matches one of the parameter
+							// The order is important
+							for( auto & arg : argsList ) {
+
+								// Ignore non-mutex arguments
+								if( !advance_to_mutex( param, param_end ) ) {
+									// We ran out of parameters but still have arguments
+									// this function doesn't match
+									throw SemanticError("candidate function not viable: too many mutex arguments\n", function);
+								}
+
+								// Check if the argument matches the parameter type in the current scope
+								if( ! unify( (*param)->get_type(), arg.expr->get_result(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
+									// Type doesn't match
+									stringstream ss;
+									ss << "candidate function not viable: no known convertion from '";
+									arg.expr->get_result()->print( ss );
+									ss << "' to '";
+									(*param)->get_type()->print( ss );
+									ss << "'\n";
+									throw SemanticError(ss.str(), function);
+								}
+
+								param++;
+							}
+
+							// All arguments match !
+
+							// Check if parameters are missing
+							if( advance_to_mutex( param, param_end ) ) {
+								// We ran out of arguments but still have parameters left
+								// this function doesn't match
+								throw SemanticError("candidate function not viable: too few mutex arguments\n", function);
+							}
+
+							// All parameters match !
+
+							// Finish the expressions to tie in the proper environments
+							finishExpr( newFunc.expr, resultEnv );
+							for( Alternative & alt : argsList ) {
+								finishExpr( alt.expr, resultEnv );
+							}
+
+							// This is a match store it and save it for later
+							func_candidates.push_back( newFunc );
+							args_candidates.push_back( argsList );
+
+						}
+						catch( SemanticError &e ) {
+							errors.append( e );
+						}
+					}
+				}
+				catch( SemanticError &e ) {
+					errors.append( e );
+				}
+			}
+
+			// Make sure we got the right number of arguments
+			if( func_candidates.empty() )    { SemanticError top( "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
+			if( args_candidates.empty() )    { SemanticError top( "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
+			if( func_candidates.size() > 1 ) { SemanticError top( "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
+			if( args_candidates.size() > 1 ) { SemanticError top( "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
+
+
+			// Swap the results from the alternative with the unresolved values.
+			// Alternatives will handle deletion on destruction
+			std::swap( clause.target.function, func_candidates.front().expr );
+			for( auto arg_pair : group_iterate( clause.target.arguments, args_candidates.front() ) ) {
+				std::swap ( std::get<0>( arg_pair), std::get<1>( arg_pair).expr );
+			}
+
+			// Resolve the conditions as if it were an IfStmt
+			// Resolve the statments normally
+			findSingleExpression( clause.condition, this->indexer );
+			clause.statement->accept( *visitor );
+		}
+
+
+		if( stmt->timeout.statement ) {
+			// Resolve the timeout as an size_t for now
+			// Resolve the conditions as if it were an IfStmt
+			// Resolve the statments normally
+			findSingleExpression( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), this->indexer );
+			findSingleExpression( stmt->timeout.condition, this->indexer );
+			stmt->timeout.statement->accept( *visitor );
+		}
+
+		if( stmt->orelse.statement ) {
+			// Resolve the conditions as if it were an IfStmt
+			// Resolve the statments normally
+			findSingleExpression( stmt->orelse.condition, this->indexer );
+			stmt->orelse.statement->accept( *visitor );
 		}
 	}
@@ -403,6 +582,6 @@
 		visit_children = false;
 		// resolve initialization using the possibilities as determined by the currentObject cursor
-		UntypedInitExpr * untyped = new UntypedInitExpr( singleInit->get_value(), currentObject.getOptions() );
-		Expression * newExpr = findSingleExpression( untyped, indexer );
+		Expression * newExpr = new UntypedInitExpr( singleInit->value, currentObject.getOptions() );
+		findSingleExpression( newExpr, indexer );
 		InitExpr * initExpr = strict_dynamic_cast< InitExpr * >( newExpr );
 
@@ -411,12 +590,14 @@
 
 		// discard InitExpr wrapper and retain relevant pieces
-		newExpr = initExpr->get_expr();
-		newExpr->set_env( initExpr->get_env() );
-		initExpr->set_expr( nullptr );
-		initExpr->set_env( nullptr );
+		newExpr = initExpr->expr;
+		initExpr->expr = nullptr;
+		std::swap( initExpr->env, newExpr->env );
+		std::swap( initExpr->inferParams, newExpr->inferParams ) ;
 		delete initExpr;
 
 		// get the actual object's type (may not exactly match what comes back from the resolver due to conversions)
 		Type * initContext = currentObject.getCurrentType();
+
+		removeExtraneousCast( newExpr, indexer );
 
 		// check if actual object's type is char[]
@@ -426,9 +607,11 @@
 				if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) {
 					if ( isCharType( pt->get_base() ) ) {
-						// strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
-						CastExpr *ce = strict_dynamic_cast< CastExpr * >( newExpr );
-						newExpr = ce->get_arg();
-						ce->set_arg( nullptr );
-						delete ce;
+						if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) {
+							// strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
+							newExpr = ce->get_arg();
+							ce->set_arg( nullptr );
+							std::swap( ce->env, newExpr->env );
+							delete ce;
+						}
 					}
 				}
@@ -437,5 +620,5 @@
 
 		// set initializer expr to resolved express
-		singleInit->set_value( newExpr );
+		singleInit->value = newExpr;
 
 		// move cursor to next object in preparation for next initializer
Index: src/ResolvExpr/Resolver.h
===================================================================
--- src/ResolvExpr/Resolver.h	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/Resolver.h	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -29,6 +29,8 @@
 	/// Checks types and binds syntactic constructs to typed representations
 	void resolve( std::list< Declaration * > translationUnit );
-	Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer );
-	Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer );
+	void resolveDecl( Declaration *, const SymTab::Indexer &indexer );
+	Expression *resolveInVoidContext( Expression * expr, const SymTab::Indexer &indexer );
+	void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer );
+	void findSingleExpression( Expression *& untyped, const SymTab::Indexer &indexer );
 	void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer );
 	void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer );
Index: src/ResolvExpr/TypeEnvironment.cc
===================================================================
--- src/ResolvExpr/TypeEnvironment.cc	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/TypeEnvironment.cc	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -68,11 +68,11 @@
 	}
 
-	void EqvClass::print( std::ostream &os, int indent ) const {
-		os << std::string( indent, ' ' ) << "( ";
+	void EqvClass::print( std::ostream &os, Indenter indent ) const {
+		os << "( ";
 		std::copy( vars.begin(), vars.end(), std::ostream_iterator< std::string >( os, " " ) );
 		os << ")";
 		if ( type ) {
 			os << " -> ";
-			type->print( os, indent );
+			type->print( os, indent+1 );
 		} // if
 		if ( ! allowWidening ) {
@@ -123,13 +123,13 @@
 		for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
 			for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) {
-///       std::cout << "adding " << *theVar;
+///       std::cerr << "adding " << *theVar;
 				if ( theClass->type ) {
-///         std::cout << " bound to ";
-///         theClass->type->print( std::cout );
-///         std::cout << std::endl;
+///         std::cerr << " bound to ";
+///         theClass->type->print( std::cerr );
+///         std::cerr << std::endl;
 					sub.add( *theVar, theClass->type );
 				} else if ( theVar != theClass->vars.begin() ) {
 					TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->data.kind == TypeDecl::Ftype );
-///         std::cout << " bound to variable " << *theClass->vars.begin() << std::endl;
+///         std::cerr << " bound to variable " << *theClass->vars.begin() << std::endl;
 					sub.add( *theVar, newTypeInst );
 					delete newTypeInst;
@@ -144,5 +144,5 @@
 	}
 
-	void TypeEnvironment::print( std::ostream &os, int indent ) const {
+	void TypeEnvironment::print( std::ostream &os, Indenter indent ) const {
 		for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {
 			i->print( os, indent );
Index: src/ResolvExpr/TypeEnvironment.h
===================================================================
--- src/ResolvExpr/TypeEnvironment.h	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/TypeEnvironment.h	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -68,5 +68,5 @@
 		EqvClass &operator=( const EqvClass &other );
 		~EqvClass();
-		void print( std::ostream &os, int indent = 0 ) const;
+		void print( std::ostream &os, Indenter indent = {} ) const;
 	};
 
@@ -80,5 +80,5 @@
 		void makeSubstitution( TypeSubstitution &result ) const;
 		bool isEmpty() const { return env.empty(); }
-		void print( std::ostream &os, int indent = 0 ) const;
+		void print( std::ostream &os, Indenter indent = {} ) const;
 		void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) );
 		void simpleCombine( const TypeEnvironment &second );
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision fae6f21adb40b4f21213c00786146d211814c241)
+++ src/ResolvExpr/Unify.cc	(revision 954908d626141a4efd01f89eddf95232bfd6ef42)
@@ -17,9 +17,10 @@
 #include <iterator>               // for back_insert_iterator, back_inserter
 #include <map>                    // for _Rb_tree_const_iterator, _Rb_tree_i...
-#include <memory>                 // for unique_ptr, auto_ptr
+#include <memory>                 // for unique_ptr
 #include <set>                    // for set
 #include <string>                 // for string, operator==, operator!=, bas...
 #include <utility>                // for pair
 
+#include "Common/PassVisitor.h"   // for PassVisitor
 #include "FindOpenVars.h"         // for findOpenVars
 #include "Parser/LinkageSpec.h"   // for C
@@ -137,5 +138,4 @@
 	bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) {
 		switch ( data.kind ) {
-		  case TypeDecl::Any:
 		  case TypeDecl::Dtype:
 			// to bind to an object type variable, the type must not be a function type.
@@ -169,5 +169,5 @@
 				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::auto_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 ) ) {
@@ -458,9 +458,4 @@
 		if ( otherArray && arrayType->get_isVarLen() == otherArray->get_isVarLen() ) {
 
-			// not positive this is correct in all cases, but it's needed for typedefs
-			if ( arrayType->get_isVarLen() || otherArray->get_isVarLen() ) {
-				return;
-			}
-
 			if ( ! arrayType->get_isVarLen() && ! otherArray->get_isVarLen() &&
 				arrayType->get_dimension() != 0 && otherArray->get_dimension() != 0 ) {
@@ -537,10 +532,11 @@
 	/// If this isn't done then argument lists can have wildly different
 	/// size and structure, when they should be compatible.
-	struct TtypeExpander : public Mutator {
-		TypeEnvironment & env;
-		TtypeExpander( TypeEnvironment & env ) : env( env ) {}
-		Type * mutate( TypeInstType * typeInst ) {
+	struct TtypeExpander : public WithShortCircuiting {
+		TypeEnvironment & tenv;
+		TtypeExpander( TypeEnvironment & tenv ) : tenv( tenv ) {}
+		void premutate( TypeInstType * ) { visit_children = false; }
+		Type * postmutate( TypeInstType * typeInst ) {
 			EqvClass eqvClass;
-			if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
+			if ( tenv.lookup( typeInst->get_name(), eqvClass ) ) {
 				if ( eqvClass.data.kind == TypeDecl::Ttype ) {
 					// expand ttype parameter into its actual type
@@ -560,5 +556,5 @@
 		dst.clear();
 		for ( DeclarationWithType * dcl : src ) {
-			TtypeExpander expander( env );
+			PassVisitor<TtypeExpander> expander( env );
 			dcl->acceptMutator( expander );
 			std::list< Type * > types;
@@ -750,5 +746,5 @@
 			std::list<Type *> types1, types2;
 
-			TtypeExpander expander( env );
+			PassVisitor<TtypeExpander> expander( env );
 			flat1->acceptMutator( expander );
 			flat2->acceptMutator( expander );
