Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision b46e3bd5b2d8744c0e03f9a699c26f6faa6d35bb)
+++ src/ResolvExpr/ConversionCost.cc	(revision 89be1c68ce6af5c822ac429caef167ce24a3cf97)
@@ -45,5 +45,5 @@
 				assert( type );
 				if ( type->get_base() ) {
-					return conversionCost( src, type->get_base(), indexer, env ) + Cost( 0, 0, 1 );
+					return conversionCost( src, type->get_base(), indexer, env ) + Cost::safe;
 				} // if
 			} // if
@@ -58,7 +58,7 @@
 		if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
 ///     std::cout << "compatible!" << std::endl;
-			return Cost( 0, 0, 0 );
+			return Cost::zero;
 		} else if ( dynamic_cast< VoidType* >( dest ) ) {
-			return Cost( 0, 0, 1 );
+			return Cost::safe;
 		} else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
 			// std::cerr << "conversionCost: dest is reference" << std::endl;
@@ -70,48 +70,77 @@
 				return Cost::infinity;
 			} else {
-				return converter.get_cost() + Cost( 0, 0, 0 );
-			} // if
-		} // if
-	}
-
-	Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
-		// std::cerr << "convert to reference cost..." << std::endl;
-		if ( ReferenceType *srcAsRef = dynamic_cast< ReferenceType * >( src ) ) { // pointer-like conversions between references
-			// std::cerr << "converting between references" << std::endl;
-			if ( srcAsRef->get_base()->get_qualifiers() <= dest->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), dest->get_base(), indexer, env ) ) {
-				return Cost( 0, 0, 1 );
-			} else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
-				int assignResult = ptrsAssignable( srcAsRef->get_base(), dest->get_base(), env );
-				if ( assignResult < 0 ) {
-					return Cost( 0, 0, 1 );
-				} else if ( assignResult > 0 ) {
-					return Cost( 1, 0, 0 );
-				} // if
-			} // if
-		} else if ( typesCompatibleIgnoreQualifiers( src, dest->get_base(), indexer, env ) ) {
-			// std::cerr << "converting compatible base type" << std::endl;
-			if ( src->get_lvalue() ) {
-				// std::cerr << "lvalue to reference conversion" << std::endl;
-				// lvalue-to-reference conversion:  cv lvalue T => cv T &
-				if ( src->get_qualifiers() == dest->get_base()->get_qualifiers() ) {
-					return Cost( 0, 0, 1 ); // cost needs to be non-zero to add cast
-				} if ( src->get_qualifiers() < dest->get_base()->get_qualifiers() ) {
-					return Cost( 0, 0, 2 ); // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
+				return converter.get_cost() + Cost::zero;
+			} // if
+		} // if
+	}
+
+	Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
+		std::cerr << "convert to reference cost..." << std::endl;
+		if ( diff > 0 ) {
+			// TODO: document this
+			Cost cost = convertToReferenceCost( safe_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env );
+			// TODO: increment reference cost
+			cost.incSafe();
+			return cost;
+		} else if ( diff < -1 ) {
+			// TODO: document this
+			Cost cost = convertToReferenceCost( src, safe_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env );
+			// TODO: increment reference cost
+			cost.incSafe();
+			return cost;
+		} else if ( diff == 0 ) {
+			ReferenceType * srcAsRef = dynamic_cast< ReferenceType * >( src );
+			ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
+			if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
+				std::cerr << "converting between references" << std::endl;
+				if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) {
+					return Cost::safe;
+				} else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
+					int assignResult = ptrsAssignable( srcAsRef->get_base(), destAsRef->get_base(), env );
+					if ( assignResult < 0 ) {
+						return Cost::safe;
+					} else if ( assignResult > 0 ) {
+						return Cost::unsafe;
+					} // if
+				} // if
+			} else {
+				std::cerr << "reference to rvalue conversion" << std::endl;
+				ConversionCost converter( dest, indexer, env );
+				src->accept( converter );
+				return converter.get_cost();
+			} // if
+		} else {
+			ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
+			assert( diff == -1 && destAsRef );
+			if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) {
+				std::cerr << "converting compatible base type" << std::endl;
+				if ( src->get_lvalue() ) {
+					std::cerr << "lvalue to reference conversion" << std::endl;
+					// lvalue-to-reference conversion:  cv lvalue T => cv T &
+					if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) {
+						return Cost::safe; // cost needs to be non-zero to add cast
+					} if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) {
+						return Cost::safe + Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
+					} else {
+						return Cost::unsafe;
+					} // if
+				} else if ( destAsRef->get_base()->get_const() ) {
+					std::cerr << "rvalue to const ref conversion" << std::endl;
+					// rvalue-to-const-reference conversion: T => const T &
+					return Cost::safe;
 				} else {
-					return Cost( 1, 0, 0 );
-				}
-			} else if ( dest->get_base()->get_const() ) {
-				// std::cerr << "rvalue to const ref conversion" << std::endl;
-				// rvalue-to-const-reference conversion: T => const T &
-				return Cost( 0, 0, 1 );
-			} else {
-				// std::cerr << "rvalue to non-const reference conversion" << std::endl;
-				// rvalue-to-reference conversion: T => T &
-				return Cost( 1, 0, 0 );
-			}
-		} else {
-			// std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl;
+					// std::cerr << "rvalue to non-const reference conversion" << std::endl;
+					// rvalue-to-reference conversion: T => T &
+					return Cost::unsafe;
+				} // if
+			} // if
+			std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl;
 		}
 		return Cost::infinity;
+	}
+
+	Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
+		int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
+		return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env );
 	}
 
@@ -205,13 +234,14 @@
 			int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
 			if ( tableResult == -1 ) {
-				cost = Cost( 1, 0, 0 );
-			} else {
-				cost = Cost( 0, 0, tableResult );
+				cost = Cost::unsafe;
+			} else {
+				cost = Cost::zero;
+				cost.incSafe( tableResult );
 			} // if
 		} else if ( dynamic_cast< EnumInstType *>( dest ) ) {
 			// xxx - not positive this is correct, but appears to allow casting int => enum
-			cost = Cost( 1, 0, 0 );
+			cost = Cost::unsafe;
 		} else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
-			cost = Cost( 1, 0, 0 );
+			cost = Cost::unsafe;
 		} // if
 	}
@@ -220,15 +250,15 @@
 		if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
 			if ( pointerType->get_base()->get_qualifiers() <= destAsPtr->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
-				cost = Cost( 0, 0, 1 );
+				cost = Cost::safe;
 			} else {  // xxx - this discards pointer qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
 				int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env );
 				if ( assignResult < 0 ) {
-					cost = Cost( 0, 0, 1 );
+					cost = Cost::safe;
 				} else if ( assignResult > 0 ) {
-					cost = Cost( 1, 0, 0 );
+					cost = Cost::unsafe;
 				} // if
 			} // if
 		} else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
-			cost = Cost( 1, 0, 0 );
+			cost = Cost::unsafe;
 		} // if
 	}
@@ -243,4 +273,6 @@
 		// cv can be safely dropped because of 'implicit dereference' behavior.
 		refType->get_base()->accept( *this );
+		// TODO: increment reference cost
+		cost.incSafe();
 	}
 
@@ -267,5 +299,5 @@
 		static BasicType integer( q, BasicType::SignedInt );
 		integer.accept( *this );  // safe if dest >= int
-		if ( cost < Cost( 1, 0, 0 ) ) {
+		if ( cost < Cost::unsafe ) {
 			cost.incSafe();
 		} // if
@@ -289,5 +321,5 @@
 			assert( type );
 			if ( type->get_base() ) {
-				cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost( 0, 0, 1 );
+				cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;
 			} // if
 		} // if
@@ -295,5 +327,5 @@
 
 	void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) {
-		Cost c;
+		Cost c = Cost::zero;
 		if ( TupleType *destAsTuple = dynamic_cast< TupleType* >( dest ) ) {
 			std::list< Type* >::const_iterator srcIt = tupleType->get_types().begin();
@@ -327,10 +359,11 @@
 			int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
 			if ( tableResult == -1 ) {
-				cost = Cost( 1, 0, 0 );
-			} else {
-				cost = Cost( 0, 0, tableResult + 1 );
+				cost = Cost::unsafe;
+			} else {
+				cost = Cost::zero;
+				cost.incSafe( tableResult + 1 );
 			}
 		} else if ( dynamic_cast< PointerType* >( dest ) ) {
-			cost = Cost( 0, 0, 1 );
+			cost = Cost::safe;
 		}
 	}
@@ -343,7 +376,8 @@
 			int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
 			if ( tableResult == -1 ) {
-				cost = Cost( 1, 0, 0 );
-			} else {
-				cost = Cost( 0, 0, tableResult + 1 );
+				cost = Cost::unsafe;
+			} else {
+				cost = Cost::zero;
+				cost.incSafe( tableResult + 1 );
 			}
 		}
