Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 133a1611de9a6da9c88c798d33b16838b0530ae5)
+++ src/AST/Convert.cpp	(revision 8e9d5672850a71de36345a3b6fbd1d76a7399b89)
@@ -167,5 +167,5 @@
 			LinkageSpec::Spec( node->linkage.val ),
 			bfwd,
-			type,
+			type->clone(),
 			init,
 			attr,
Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision 133a1611de9a6da9c88c798d33b16838b0530ae5)
+++ src/AST/Print.cpp	(revision 8e9d5672850a71de36345a3b6fbd1d76a7399b89)
@@ -237,4 +237,12 @@
 	void postprint( const ast::Expr * node ) {
 		print( node->inferred );
+
+		if ( node->result ) {
+			os << endl << indent << "... with resolved type:" << endl;
+			++indent;
+			os << indent;
+			node->result->accept( *this );
+			--indent;
+		}
 
 		if ( node->env ) {
Index: src/AST/TypeSubstitution.hpp
===================================================================
--- src/AST/TypeSubstitution.hpp	(revision 133a1611de9a6da9c88c798d33b16838b0530ae5)
+++ src/AST/TypeSubstitution.hpp	(revision 8e9d5672850a71de36345a3b6fbd1d76a7399b89)
@@ -195,5 +195,5 @@
 	assert( input );
 	Pass<Substituter> sub( *this, true );
-	input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
+	input = strict_dynamic_cast< const SynTreeClass * >( deepCopy(input)->accept( sub ) );
 	return { input, sub.core.subCount };
 }
Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision 133a1611de9a6da9c88c798d33b16838b0530ae5)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision 8e9d5672850a71de36345a3b6fbd1d76a7399b89)
@@ -1473,5 +1473,5 @@
 					// unification run for side-effects
 					unify( toType, cand->expr->result, env, need, have, open, symtab );
-					Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
+					Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),
 							symtab, env );
 
@@ -1483,5 +1483,5 @@
 								initExpr->location, restructureCast( cand->expr, toType ),
 								initAlt.designation },
-							copy( cand->env ), move( open ), move( need ), cand->cost, thisCost );
+							move(env), move( open ), move( need ), cand->cost, thisCost );
 						inferParameters( newCand, matches );
 					}
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision 133a1611de9a6da9c88c798d33b16838b0530ae5)
+++ src/ResolvExpr/Unify.cc	(revision 8e9d5672850a71de36345a3b6fbd1d76a7399b89)
@@ -791,6 +791,9 @@
 			for ( const ast::DeclWithType * d : src ) {
 				ast::Pass<TtypeExpander_new> expander{ env };
-				d = d->accept( expander );
-				auto types = flatten( d->get_type() );
+				// TtypeExpander pass is impure (may mutate nodes in place)
+				// need to make nodes shared to prevent accidental mutation
+				ast::ptr<ast::DeclWithType> dc = d;
+				dc = dc->accept( expander );
+				auto types = flatten( dc->get_type() );
 				for ( ast::ptr< ast::Type > & t : types ) {
 					// outermost const, volatile, _Atomic qualifiers in parameters should not play
@@ -801,5 +804,5 @@
 					// requirements than a non-mutex function
 					remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
-					dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } );
+					dst.emplace_back( new ast::ObjectDecl{ dc->location, "", t } );
 				}
 			}
@@ -1110,6 +1113,9 @@
 
 			ast::Pass<TtypeExpander_new> expander{ tenv };
-			const ast::Type * flat = tuple->accept( expander );
-			const ast::Type * flat2 = tuple2->accept( expander );
+
+			ast::ptr<ast::TupleType> tuplec = tuple;
+			ast::ptr<ast::TupleType> tuple2c = tuple2;
+			const ast::Type * flat = tuplec->accept( expander );
+			const ast::Type * flat2 = tuple2c->accept( expander );
 
 			auto types = flatten( flat );
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision 133a1611de9a6da9c88c798d33b16838b0530ae5)
+++ src/SynTree/Expression.cc	(revision 8e9d5672850a71de36345a3b6fbd1d76a7399b89)
@@ -69,4 +69,10 @@
 void Expression::print( std::ostream & os, Indenter indent ) const {
 	printInferParams( inferParams, os, indent+1, 0 );
+
+	if ( result ) {
+		os << std::endl << indent << "with resolved type:" << std::endl;
+		os << (indent+1);
+		result->print( os, indent+1 );
+	}
 
 	if ( env ) {
Index: src/Tuples/Explode.cc
===================================================================
--- src/Tuples/Explode.cc	(revision 133a1611de9a6da9c88c798d33b16838b0530ae5)
+++ src/Tuples/Explode.cc	(revision 8e9d5672850a71de36345a3b6fbd1d76a7399b89)
@@ -161,5 +161,5 @@
 			castAdded = false;
 			const ast::Type * newType = getReferenceBase( newNode->result );
-			return new ast::CastExpr{ newNode->location, node, newType };
+			return new ast::CastExpr{ newNode->location, newNode, newType };
 		}
 		return newNode;
