Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision c3d048c30e5155e5991e6644478b22f70dd89116)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision b7f8cb449799bf83b570f340be3a9cf0ac7f175e)
@@ -581,9 +581,9 @@
 		std::vector<unsigned> tupleEls;  /// Number of elements in current tuple element(s)
 
-		ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 
+		ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have,
 				const OpenVarSet& openVars)
 			: actuals(), env(env), need(need), have(have), openVars(openVars), nextArg(0),
 			  expls(), nextExpl(0), tupleEls() {}
-		
+
 		/// Starts a new tuple expression
 		void beginTuple() {
@@ -620,7 +620,7 @@
 
 	/// Instantiates an argument to match a formal, returns false if no results left
-	bool instantiateArgument( Type* formalType, Initializer* initializer, 
-			const std::vector< AlternativeFinder >& args, 
-			std::vector<ArgPack>& results, std::vector<ArgPack>& nextResults, 
+	bool instantiateArgument( Type* formalType, Initializer* initializer,
+			const std::vector< AlternativeFinder >& args,
+			std::vector<ArgPack>& results, std::vector<ArgPack>& nextResults,
 			const SymTab::Indexer& indexer ) {
 		if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) {
@@ -629,5 +629,5 @@
 			for ( Type* type : *tupleType ) {
 				// xxx - dropping initializer changes behaviour from previous, but seems correct
-				if ( ! instantiateArgument( type, nullptr, args, results, nextResults, indexer ) ) 
+				if ( ! instantiateArgument( type, nullptr, args, results, nextResults, indexer ) )
 					return false;
 			}
@@ -658,8 +658,8 @@
 						Type* argType = result.actuals.back().expr->get_result();
 						if ( result.tupleEls.back() == 1 && Tuples::isTtype( argType ) ) {
-							// the case where a ttype value is passed directly is special, e.g. for 
+							// the case where a ttype value is passed directly is special, e.g. for
 							// argument forwarding purposes
 							// xxx - what if passing multiple arguments, last of which is ttype?
-							// xxx - what would happen if unify was changed so that unifying tuple 
+							// xxx - what would happen if unify was changed so that unifying tuple
 							// types flattened both before unifying lists? then pass in TupleType
 							// (ttype) below.
@@ -671,5 +671,5 @@
 						}
 						// check unification for ttype before adding to final
-						if ( unify( ttype, argType, result.env, result.need, result.have, 
+						if ( unify( ttype, argType, result.env, result.need, result.have,
 								result.openVars, indexer ) ) {
 							finalResults.push_back( std::move(result) );
@@ -684,9 +684,9 @@
 						aResult.env.addActual( actual.env, aResult.openVars );
 						Cost cost = actual.cost;
-		
+
 						// explode argument
 						std::vector<Alternative> exploded;
 						Tuples::explode( actual, indexer, back_inserter( exploded ) );
-						
+
 						// add exploded argument to tuple
 						for ( Alternative& aActual : exploded ) {
@@ -706,5 +706,5 @@
 			return ! results.empty();
 		}
-		
+
 		// iterate each current subresult
 		for ( unsigned iResult = 0; iResult < results.size(); ++iResult ) {
@@ -724,6 +724,6 @@
 					std::cerr << std::endl;
 				)
-				
-				if ( unify( formalType, actualType, result.env, result.need, result.have, 
+
+				if ( unify( formalType, actualType, result.env, result.need, result.have,
 						result.openVars, indexer ) ) {
 					++result.nextExpl;
@@ -736,5 +736,5 @@
 				if ( ConstantExpr* cnstExpr = getDefaultValue( initializer ) ) {
 					if ( Constant* cnst = dynamic_cast<Constant*>( cnstExpr->get_constant() ) ) {
-						if ( unify( formalType, cnst->get_type(), result.env, result.need, 
+						if ( unify( formalType, cnst->get_type(), result.env, result.need,
 								result.have, result.openVars, indexer ) ) {
 							nextResults.push_back( std::move(result.withArg( cnstExpr )) );
@@ -791,11 +791,11 @@
 		results.swap( nextResults );
 		nextResults.clear();
-		
+
 		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;
@@ -803,12 +803,12 @@
 		TypeEnvironment funcEnv( func.env );
 		makeUnifiableVars( funcType, funcOpenVars, funcNeed );
-		// add all type variables as open variables now so that those not used in the parameter 
+		// 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();
-			if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars, 
+			if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars,
 					indexer ) ) {
 				// unification failed, don't pursue this function alternative
@@ -822,5 +822,5 @@
 		for ( DeclarationWithType* formal : funcType->get_parameters() ) {
 			ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal );
-			if ( ! instantiateArgument( 
+			if ( ! instantiateArgument(
 					obj->get_type(), obj->get_init(), args, results, nextResults, indexer ) )
 				return;
@@ -904,5 +904,5 @@
 
 		std::vector< AlternativeFinder > argAlternatives;
-		findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), 
+		findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),
 			back_inserter( argAlternatives ) );
 
@@ -934,5 +934,5 @@
 						Alternative newFunc( *func );
 						referenceToRvalueConversion( newFunc.expr );
-						makeFunctionAlternatives( newFunc, function, argAlternatives, 
+						makeFunctionAlternatives( newFunc, function, argAlternatives,
 							std::back_inserter( candidates ) );
 					}
@@ -943,9 +943,9 @@
 							Alternative newFunc( *func );
 							referenceToRvalueConversion( newFunc.expr );
-							makeFunctionAlternatives( newFunc, function, argAlternatives, 
+							makeFunctionAlternatives( newFunc, function, argAlternatives,
 								std::back_inserter( candidates ) );
 						} // if
 					} // if
-				}			
+				}
 			} catch ( SemanticError &e ) {
 				errors.append( e );
@@ -962,11 +962,11 @@
 				try {
 					// check if type is a pointer to function
-					if ( PointerType* pointer = dynamic_cast<PointerType*>( 
+					if ( PointerType* pointer = dynamic_cast<PointerType*>(
 							funcOp->expr->get_result()->stripReferences() ) ) {
-						if ( FunctionType* function = 
+						if ( FunctionType* function =
 								dynamic_cast<FunctionType*>( pointer->get_base() ) ) {
 							Alternative newFunc( *funcOp );
 							referenceToRvalueConversion( newFunc.expr );
-							makeFunctionAlternatives( newFunc, function, argAlternatives, 
+							makeFunctionAlternatives( newFunc, function, argAlternatives,
 								std::back_inserter( candidates ) );
 						}
@@ -1007,12 +1007,15 @@
 		candidates.splice( candidates.end(), alternatives );
 
-		findMinCost( candidates.begin(), candidates.end(), std::back_inserter( alternatives ) );
+		// use a new list so that alternatives are not examined by addAnonConversions twice.
+		AltList winners;
+		findMinCost( candidates.begin(), candidates.end(), std::back_inserter( winners ) );
 
 		// function may return struct or union value, in which case we need to add alternatives for implicit
 		// conversions to each of the anonymous members, must happen after findMinCost since anon conversions
 		// are never the cheapest expression
-		for ( const Alternative & alt : alternatives ) {
+		for ( const Alternative & alt : winners ) {
 			addAnonConversions( alt );
 		}
+		alternatives.splice( alternatives.begin(), winners );
 
 		if ( alternatives.empty() && targetType && ! targetType->isVoid() ) {
