Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/AST/Expr.cpp	(revision 2890212a2b66d8b4d2e668cc354f6205f1c666bd)
@@ -20,4 +20,5 @@
 #include <vector>
 
+#include "Copy.hpp"                // for shallowCopy
 #include "Eval.hpp"                // for call
 #include "GenericSubstitution.hpp"
@@ -174,6 +175,7 @@
 	assert( var );
 	assert( var->get_type() );
-	result = var->get_type();
-	add_qualifiers( result, CV::Lvalue );
+	auto r = shallowCopy( var->get_type() );
+	r->qualifiers |= CV::Lvalue;
+	result = r;
 }
 
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/AST/Node.hpp	(revision 2890212a2b66d8b4d2e668cc354f6205f1c666bd)
@@ -96,5 +96,5 @@
 	assertf(
 		node->weak_count == 0,
-		"Error: mutating node with weak references to it will invalided some references"
+		"Error: mutating node with weak references to it will invalidate some references"
 	);
 	return node->clone();
@@ -106,5 +106,5 @@
 	// skip mutate if equivalent
 	if ( node->*field == val ) return node;
-	
+
 	// mutate and return
 	node_t * ret = mutate( node );
Index: src/AST/TypeEnvironment.hpp
===================================================================
--- src/AST/TypeEnvironment.hpp	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/AST/TypeEnvironment.hpp	(revision 2890212a2b66d8b4d2e668cc354f6205f1c666bd)
@@ -38,20 +38,20 @@
 /// Adding this comparison operator significantly improves assertion satisfaction run time for
 /// some cases. The current satisfaction algorithm's speed partially depends on the order of
-/// assertions. Assertions which have fewer possible matches should appear before assertions 
-/// which have more possible matches. This seems to imply that this could be further improved 
-/// by providing an indexer as an additional argument and ordering based on the number of 
+/// assertions. Assertions which have fewer possible matches should appear before assertions
+/// which have more possible matches. This seems to imply that this could be further improved
+/// by providing an indexer as an additional argument and ordering based on the number of
 /// matches of the same kind (object, function) for the names of the declarations.
 ///
-/// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this 
+/// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this
 /// comparator.
 ///
-/// Note: since this compares pointers for position, minor changes in the source file that 
-/// affect memory layout can alter compilation time in unpredictable ways. For example, the 
-/// placement of a line directive can reorder type pointers with respect to each other so that 
-/// assertions are seen in different orders, causing a potentially different number of 
-/// unification calls when resolving assertions. I've seen a TU go from 36 seconds to 27 
-/// seconds by reordering line directives alone, so it would be nice to fix this comparison so 
-/// that assertions compare more consistently. I've tried to modify this to compare on mangle 
-/// name instead of type as the second comparator, but this causes some assertions to never be 
+/// Note: since this compares pointers for position, minor changes in the source file that
+/// affect memory layout can alter compilation time in unpredictable ways. For example, the
+/// placement of a line directive can reorder type pointers with respect to each other so that
+/// assertions are seen in different orders, causing a potentially different number of
+/// unification calls when resolving assertions. I've seen a TU go from 36 seconds to 27
+/// seconds by reordering line directives alone, so it would be nice to fix this comparison so
+/// that assertions compare more consistently. I've tried to modify this to compare on mangle
+/// name instead of type as the second comparator, but this causes some assertions to never be
 /// recorded. More investigation is needed.
 struct AssertCompare {
@@ -87,5 +87,5 @@
 void print( std::ostream &, const OpenVarSet &, Indenter indent = {} );
 
-/// Represents an equivalence class of bound type variables, optionally with the concrete type 
+/// Represents an equivalence class of bound type variables, optionally with the concrete type
 /// they bind to.
 struct EqvClass {
@@ -96,7 +96,7 @@
 
 	EqvClass() : vars(), bound(), allowWidening( true ), data() {}
-	
+
 	/// Copy-with-bound constructor
-	EqvClass( const EqvClass & o, const Type * b ) 
+	EqvClass( const EqvClass & o, const Type * b )
 	: vars( o.vars ), bound( b ), allowWidening( o.allowWidening ), data( o.data ) {}
 
@@ -143,16 +143,16 @@
 	void writeToSubstitution( TypeSubstitution & sub ) const;
 
-	template< typename node_t, enum Node::ref_type ref_t >
-	int apply( ptr_base< node_t, ref_t > & type ) const {
+	template< typename node_t >
+	auto apply( node_t && type ) const {
 		TypeSubstitution sub;
 		writeToSubstitution( sub );
-		return sub.apply( type );
-	}
-
-	template< typename node_t, enum Node::ref_type ref_t >
-	int applyFree( ptr_base< node_t, ref_t > & type ) const {
+		return sub.apply( std::forward<node_t>(type) );
+	}
+
+	template< typename node_t >
+	auto applyFree( node_t && type ) const {
 		TypeSubstitution sub;
 		writeToSubstitution( sub );
-		return sub.applyFree( type );
+		return sub.applyFree( std::forward<node_t>(type) );
 	}
 
@@ -173,16 +173,16 @@
 	void addActual( const TypeEnvironment & actualEnv, OpenVarSet & openVars );
 
-	/// Binds the type class represented by `typeInst` to the type `bindTo`; will add the class if 
+	/// Binds the type class represented by `typeInst` to the type `bindTo`; will add the class if
 	/// needed. Returns false on failure.
-	bool bindVar( 
-		const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 
-		AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 
+	bool bindVar(
+		const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data,
+		AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars,
 		ResolvExpr::WidenMode widen, const SymbolTable & symtab );
-	
-	/// Binds the type classes represented by `var1` and `var2` together; will add one or both 
+
+	/// Binds the type classes represented by `var1` and `var2` together; will add one or both
 	/// classes if needed. Returns false on failure.
-	bool bindVarToVar( 
-		const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 
-		AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 
+	bool bindVarToVar(
+		const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data,
+		AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars,
 		ResolvExpr::WidenMode widen, const SymbolTable & symtab );
 
@@ -199,10 +199,10 @@
 
 	/// Unifies the type bound of `to` with the type bound of `from`, returning false if fails
-	bool mergeBound( 
+	bool mergeBound(
 		EqvClass & to, const EqvClass & from, OpenVarSet & openVars, const SymbolTable & symtab );
 
 	/// Merges two type classes from local environment, returning false if fails
-	bool mergeClasses( 
-		ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars, 
+	bool mergeClasses(
+		ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars,
 		const SymbolTable & symtab );
 
Index: src/AST/TypeSubstitution.cpp
===================================================================
--- src/AST/TypeSubstitution.cpp	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/AST/TypeSubstitution.cpp	(revision 2890212a2b66d8b4d2e668cc354f6205f1c666bd)
@@ -146,5 +146,5 @@
 		ptr<Type> newType = i->second; // force clone if needed
 		add_qualifiers( newType, inst->qualifiers );
-		// Note: need to recursively apply substitution to the new type because normalize does not 
+		// Note: need to recursively apply substitution to the new type because normalize does not
 		// substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
 		newType = newType->accept( *visitor );
@@ -159,5 +159,4 @@
 	} else {
 		subCount++;
-		delete nameExpr;
 		return i->second;
 	} // if
Index: src/AST/TypeSubstitution.hpp
===================================================================
--- src/AST/TypeSubstitution.hpp	(revision 4eb43fa21537c79c32be1ee375bd917f2a305475)
+++ src/AST/TypeSubstitution.hpp	(revision 2890212a2b66d8b4d2e668cc354f6205f1c666bd)
@@ -44,13 +44,19 @@
 	TypeSubstitution &operator=( const TypeSubstitution &other );
 
-	template< typename SynTreeClass > int apply( const SynTreeClass *& input ) const;
-	template< typename SynTreeClass > int applyFree( const SynTreeClass *& input ) const;
+	template< typename SynTreeClass >
+	struct ApplyResult {
+		const SynTreeClass * node;
+		int count;
+	};
+
+	template< typename SynTreeClass > ApplyResult<SynTreeClass> apply( const SynTreeClass * input ) const;
+	template< typename SynTreeClass > ApplyResult<SynTreeClass> applyFree( const SynTreeClass * input ) const;
 
 	template< typename node_t, enum Node::ref_type ref_t >
 	int apply( ptr_base< node_t, ref_t > & input ) const {
 		const node_t * p = input.get();
-		int ret = apply(p);
-		input = p;
-		return ret;
+		auto ret = apply(p);
+		input = ret.node;
+		return ret.count;
 	}
 
@@ -58,7 +64,7 @@
 	int applyFree( ptr_base< node_t, ref_t > & input ) const {
 		const node_t * p = input.get();
-		int ret = applyFree(p);
-		input = p;
-		return ret;
+		auto ret = applyFree(p);
+		input = ret.node;
+		return ret.count;
 	}
 
@@ -175,23 +181,17 @@
 
 template< typename SynTreeClass >
-int TypeSubstitution::apply( const SynTreeClass *& input ) const {
+TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::apply( const SynTreeClass * input ) const {
 	assert( input );
 	Pass<Substituter> sub( *this, false );
 	input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
-///	std::cerr << "substitution result is: ";
-///	newType->print( std::cerr );
-///	std::cerr << std::endl;
-	return sub.pass.subCount;
+	return { input, sub.pass.subCount };
 }
 
 template< typename SynTreeClass >
-int TypeSubstitution::applyFree( const SynTreeClass *& input ) const {
+TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::applyFree( const SynTreeClass * input ) const {
 	assert( input );
 	Pass<Substituter> sub( *this, true );
 	input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
-///	std::cerr << "substitution result is: ";
-///	newType->print( std::cerr );
-///	std::cerr << std::endl;
-	return sub.pass.subCount;
+	return { input, sub.pass.subCount };
 }
 
