Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision eca3d10a1ab4edc7bc00f5acdf10a9a1f592d8da)
+++ src/GenPoly/Box.cc	(revision 1cb758f27ecd2c57c8b7af48401267ff564acac8)
@@ -756,5 +756,5 @@
 				Type * newType = arg->get_result()->clone();
 				if ( env ) env->apply( newType );
-				std::auto_ptr<Type> manager( newType );
+				std::unique_ptr<Type> manager( newType );
 				if ( isPolyType( newType ) ) {
 					// if the argument's type is polymorphic, we don't need to box again!
@@ -774,5 +774,5 @@
 					newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
 					stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
-					UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
+					UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); // TODO: why doesn't this just use initialization syntax?
 					assign->get_args().push_back( new VariableExpr( newObj ) );
 					assign->get_args().push_back( arg );
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision eca3d10a1ab4edc7bc00f5acdf10a9a1f592d8da)
+++ src/InitTweak/InitTweak.cc	(revision 1cb758f27ecd2c57c8b7af48401267ff564acac8)
@@ -418,4 +418,6 @@
 			assertf( ! tuple->get_exprs().empty(), "TupleAssignExpr somehow has empty tuple expr." );
 			return getCallArg( tuple->get_exprs().front(), pos );
+		} else if ( ImplicitCopyCtorExpr * copyCtor = dynamic_cast< ImplicitCopyCtorExpr * >( callExpr ) ) {
+			return getCallArg( copyCtor->callExpr, pos );
 		} else {
 			assertf( false, "Unexpected expression type passed to getCallArg: %s", toString( callExpr ).c_str() );
@@ -450,6 +452,8 @@
 			} else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( func ) ) {
 				return handleDerefName( appExpr );
+			} else if ( ConstructorExpr * ctorExpr = dynamic_cast< ConstructorExpr * >( func ) ) {
+				return funcName( getCallArg( ctorExpr->get_callExpr(), 0 ) );
 			} else {
-				assertf( false, "Unexpected expression type being called as a function in call expression" );
+				assertf( false, "Unexpected expression type being called as a function in call expression: %s", toString( func ).c_str() );
 			}
 		}
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision eca3d10a1ab4edc7bc00f5acdf10a9a1f592d8da)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 1cb758f27ecd2c57c8b7af48401267ff564acac8)
@@ -698,9 +698,4 @@
 
 	void AlternativeFinder::visit( UntypedExpr *untypedExpr ) {
-		bool doneInit = false;
-		AlternativeFinder funcOpFinder( indexer, env );
-
-		AlternativeFinder funcFinder( indexer, env );
-
 		{
 			std::string fname = InitTweak::getFunctionName( untypedExpr );
@@ -715,5 +710,9 @@
 		}
 
+		AlternativeFinder funcFinder( indexer, env );
 		funcFinder.findWithAdjustment( untypedExpr->get_function() );
+		// if there are no function alternatives, then proceeding is a waste of time.
+		if ( funcFinder.alternatives.empty() ) return;
+
 		std::list< AlternativeFinder > argAlternatives;
 		findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), back_inserter( argAlternatives ) );
@@ -725,4 +724,17 @@
 		// if not tuple assignment, assignment is taken care of as a normal function call
 		Tuples::handleTupleAssignment( *this, untypedExpr, possibilities );
+
+		// find function operators
+		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
+		}
+		PRINT(
+			std::cerr << "known function ops:" << std::endl;
+			printAlts( funcOpFinder.alternatives, std::cerr, 8 );
+		)
 
 		AltList candidates;
@@ -754,35 +766,21 @@
 						} // if
 					} // if
-				} else {
-					// seek a function operator that's compatible
-					if ( ! doneInit ) {
-						doneInit = true;
-						NameExpr *opExpr = new NameExpr( "?()" );
-						try {
-							funcOpFinder.findWithAdjustment( opExpr );
-						} catch( SemanticError &e ) {
-							// it's ok if there aren't any defined function ops
-						}
-						PRINT(
-							std::cerr << "known function ops:" << std::endl;
-							printAlts( funcOpFinder.alternatives, std::cerr, 8 );
-						)
-					}
-
-					for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
-						// check if the type is pointer to function
-						if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) {
-							if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
-								referenceToRvalueConversion( funcOp->expr );
-								for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
-									AltList currentAlt;
-									currentAlt.push_back( *func );
-									currentAlt.insert( currentAlt.end(), actualAlt->begin(), actualAlt->end() );
-									makeFunctionAlternatives( *funcOp, function, currentAlt, std::back_inserter( candidates ) );
-								} // for
-							} // if
+				}
+
+				// try each function operator ?() with the current function alternative and each of the argument combinations
+				for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
+					// check if the type is pointer to function
+					if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) {
+						if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
+							referenceToRvalueConversion( funcOp->expr );
+							for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
+								AltList currentAlt;
+								currentAlt.push_back( *func );
+								currentAlt.insert( currentAlt.end(), actualAlt->begin(), actualAlt->end() );
+								makeFunctionAlternatives( *funcOp, function, currentAlt, std::back_inserter( candidates ) );
+							} // for
 						} // if
-					} // for
-				} // if
+					} // if
+				} // for
 			} catch ( SemanticError &e ) {
 				errors.append( e );
Index: src/ResolvExpr/CastCost.cc
===================================================================
--- src/ResolvExpr/CastCost.cc	(revision eca3d10a1ab4edc7bc00f5acdf10a9a1f592d8da)
+++ src/ResolvExpr/CastCost.cc	(revision 1cb758f27ecd2c57c8b7af48401267ff564acac8)
@@ -58,5 +58,7 @@
 			return Cost::safe;
 		} else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
-			return convertToReferenceCost( src, refType, indexer, env );
+			return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer & indexer) {
+				return ptrsCastable( t1, t2, env, indexer );
+			});
 		} else {
 			CastCost converter( dest, indexer, env );
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision eca3d10a1ab4edc7bc00f5acdf10a9a1f592d8da)
+++ src/ResolvExpr/ConversionCost.cc	(revision 1cb758f27ecd2c57c8b7af48401267ff564acac8)
@@ -40,5 +40,4 @@
 #define PRINT(x)
 #endif
-
 	Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
 		if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
@@ -78,5 +77,7 @@
 		} else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
 			PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
-			return convertToReferenceCost( src, refType, indexer, env );
+			return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer &){
+				return ptrsAssignable( t1, t2, env );
+			});
 		} else {
 			ConversionCost converter( dest, indexer, env );
@@ -90,14 +91,14 @@
 	}
 
-	Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
+	Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
 		PRINT( 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 );
+			Cost cost = convertToReferenceCost( safe_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env, func );
 			cost.incReference();
 			return cost;
 		} else if ( diff < -1 ) {
 			// TODO: document this
-			Cost cost = convertToReferenceCost( src, safe_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env );
+			Cost cost = convertToReferenceCost( src, safe_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env, func );
 			cost.incReference();
 			return cost;
@@ -110,5 +111,5 @@
 					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 );
+					int assignResult = func( srcAsRef->get_base(), destAsRef->get_base(), env, indexer );
 					PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
 					if ( assignResult < 0 ) {
@@ -157,7 +158,7 @@
 	}
 
-	Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
+	Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
 		int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
-		return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env );
+		return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env, func );
 	}
 
Index: src/ResolvExpr/ConversionCost.h
===================================================================
--- src/ResolvExpr/ConversionCost.h	(revision eca3d10a1ab4edc7bc00f5acdf10a9a1f592d8da)
+++ src/ResolvExpr/ConversionCost.h	(revision 1cb758f27ecd2c57c8b7af48401267ff564acac8)
@@ -16,4 +16,6 @@
 #pragma once
 
+#include <functional>         // for function
+
 #include "Cost.h"             // for Cost
 #include "SynTree/Visitor.h"  // for Visitor
@@ -21,9 +23,9 @@
 
 namespace SymTab {
-class Indexer;
+	class Indexer;
 }  // namespace SymTab
 
 namespace ResolvExpr {
-class TypeEnvironment;
+	class TypeEnvironment;
 
 	class ConversionCost : public Visitor {
@@ -55,5 +57,6 @@
 	};
 
-	Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env );
+	typedef std::function<int(Type *, Type *, const TypeEnvironment &, const SymTab::Indexer &)> PtrsFunction;
+	Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func );
 } // namespace ResolvExpr
 
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision eca3d10a1ab4edc7bc00f5acdf10a9a1f592d8da)
+++ src/SymTab/Indexer.cc	(revision 1cb758f27ecd2c57c8b7af48401267ff564acac8)
@@ -345,5 +345,5 @@
 		leaveScope();
 
-		debugPrint( "Adding context " << aggregateDecl->get_name() << std::endl );
+		debugPrint( "Adding trait " << aggregateDecl->get_name() << std::endl );
 		addTrait( aggregateDecl );
 	}
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision eca3d10a1ab4edc7bc00f5acdf10a9a1f592d8da)
+++ src/SymTab/Validate.cc	(revision 1cb758f27ecd2c57c8b7af48401267ff564acac8)
@@ -467,4 +467,6 @@
 			return;
 		}
+
+		// handle other traits
 		TraitDecl *traitDecl = indexer->lookupTrait( traitInst->get_name() );
 		if ( ! traitDecl ) {
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision eca3d10a1ab4edc7bc00f5acdf10a9a1f592d8da)
+++ src/SynTree/Expression.cc	(revision 1cb758f27ecd2c57c8b7af48401267ff564acac8)
@@ -645,4 +645,8 @@
 		}
 	}
+	// ensure that StmtExpr has a result type
+	if ( ! result ) {
+		set_result( new VoidType( Type::Qualifiers() ) );
+	}
 }
 StmtExpr::StmtExpr( const StmtExpr &other ) : Expression( other ), statements( other.statements->clone() ) {
Index: src/tests/multiDimension.c
===================================================================
--- src/tests/multiDimension.c	(revision eca3d10a1ab4edc7bc00f5acdf10a9a1f592d8da)
+++ src/tests/multiDimension.c	(revision 1cb758f27ecd2c57c8b7af48401267ff564acac8)
@@ -59,4 +59,7 @@
 }
 
+// ensure constructed const arrays continue to compile
+const int global[1] = { -2 };
+
 int main() {
   X abc[4][4] = {
