Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 2d0f918fccda13d7214a5f8726ab517b71632108)
+++ src/AST/Pass.impl.hpp	(revision bccd70a18277379d29bc911ade6a08acf9c36dbd)
@@ -20,4 +20,5 @@
 #include <unordered_map>
 
+#include "AST/Copy.hpp"
 #include "AST/TranslationUnit.hpp"
 #include "AST/TypeSubstitution.hpp"
Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision 2d0f918fccda13d7214a5f8726ab517b71632108)
+++ src/AST/Print.cpp	(revision bccd70a18277379d29bc911ade6a08acf9c36dbd)
@@ -16,12 +16,13 @@
 #include "Print.hpp"
 
+#include "Attribute.hpp"
 #include "Decl.hpp"
 #include "Expr.hpp"
+#include "Init.hpp"
 #include "Stmt.hpp"
 #include "Type.hpp"
 #include "TypeSubstitution.hpp"
 #include "CompilationState.h"
-
-#include "Common/utility.h" // for group_iterate
+#include "Common/Iterate.hpp"
 
 using namespace std;
Index: src/AST/SymbolTable.cpp
===================================================================
--- src/AST/SymbolTable.cpp	(revision 2d0f918fccda13d7214a5f8726ab517b71632108)
+++ src/AST/SymbolTable.cpp	(revision bccd70a18277379d29bc911ade6a08acf9c36dbd)
@@ -18,4 +18,5 @@
 #include <cassert>
 
+#include "Copy.hpp"
 #include "Decl.hpp"
 #include "Expr.hpp"
Index: src/AST/TypeSubstitution.cpp
===================================================================
--- src/AST/TypeSubstitution.cpp	(revision 2d0f918fccda13d7214a5f8726ab517b71632108)
+++ src/AST/TypeSubstitution.cpp	(revision bccd70a18277379d29bc911ade6a08acf9c36dbd)
@@ -10,15 +10,14 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Mon Jun  3 13:26:00 2017
-// Update Count     : 5
-//
+// Last Modified On : Thr May 25 11:24:00 2023
+// Update Count     : 6
+//
+
+#include "TypeSubstitution.hpp"
 
 #include "Type.hpp"   // for TypeInstType, Type, StructInstType, UnionInstType
-#include "TypeSubstitution.hpp"
+#include "Pass.hpp"   // for Pass, PureVisitor, WithGuards, WithVisitorRef
 
 namespace ast {
-
-
-// size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution");
 
 TypeSubstitution::TypeSubstitution() {
@@ -119,4 +118,29 @@
 }
 
+// definitition must happen after PassVisitor is included so that WithGuards can be used
+struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter>, public PureVisitor {
+	//static size_t traceId;
+
+	Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
+
+	const Type * postvisit( const TypeInstType * aggregateUseType );
+
+	/// Records type variable bindings from forall-statements
+	void previsit( const FunctionType * type );
+	/// Records type variable bindings from forall-statements and instantiations of generic types
+	// void handleAggregateType( const BaseInstType * type );
+
+	// void previsit( const StructInstType * aggregateUseType );
+	// void previsit( const UnionInstType * aggregateUseType );
+
+	const TypeSubstitution & sub;
+	int subCount = 0;
+	bool freeOnly;
+	typedef std::unordered_set< TypeEnvKey > BoundVarsType;
+	BoundVarsType boundVars;
+};
+
+// size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution");
+
 void TypeSubstitution::normalize() {
 	Pass<Substituter> sub( *this, true );
@@ -128,4 +152,12 @@
 		}
 	} while ( sub.core.subCount );
+}
+
+TypeSubstitution::ApplyResult<Node> TypeSubstitution::applyBase(
+		const Node * input, bool isFree ) const {
+	assert( input );
+	Pass<Substituter> sub( *this, isFree );
+	const Node * output = input->accept( sub );
+	return { output, sub.core.subCount };
 }
 
Index: src/AST/TypeSubstitution.hpp
===================================================================
--- src/AST/TypeSubstitution.hpp	(revision 2d0f918fccda13d7214a5f8726ab517b71632108)
+++ src/AST/TypeSubstitution.hpp	(revision bccd70a18277379d29bc911ade6a08acf9c36dbd)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Apr 30 22:52:47 2019
-// Update Count     : 9
+// Last Modified By : Andrew Beach
+// Last Modified On : Thr May 25 12:31:00 2023
+// Update Count     : 10
 //
 
@@ -46,26 +46,33 @@
 	TypeSubstitution &operator=( const TypeSubstitution &other );
 
-	template< typename SynTreeClass >
+	template< typename node_t >
 	struct ApplyResult {
-		ast::ptr<SynTreeClass> node;
+		ast::ptr<node_t> 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 >
+	ApplyResult<node_t> apply( const node_t * input ) const {
+		ApplyResult<Node> ret = applyBase( input, false );
+		return { ret.node.strict_as<node_t>(), ret.count };
+	}
 
 	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();
-		auto ret = apply(p);
-		input = ret.node;
+		ApplyResult<Node> ret = applyBase( input.get(), false );
+		input = ret.node.strict_as<node_t>();
 		return ret.count;
+	}
+
+	template< typename node_t >
+	ApplyResult<node_t> applyFree( const node_t * input ) const {
+		ApplyResult<Node> ret = applyBase( input, true );
+		return { ret.node.strict_as<node_t>(), ret.count };
 	}
 
 	template< typename node_t, enum Node::ref_type ref_t >
 	int applyFree( ptr_base< node_t, ref_t > & input ) const {
-		const node_t * p = input.get();
-		auto ret = applyFree(p);
-		input = ret.node;
+		ApplyResult<Node> ret = applyBase( input.get(), true );
+		input = ret.node.strict_as<node_t>();
 		return ret.count;
 	}
@@ -97,4 +104,5 @@
 	// Mutator that performs the substitution
 	struct Substituter;
+	ApplyResult<Node> applyBase( const Node * input, bool isFree ) const;
 
 	// TODO: worry about traversing into a forall-qualified function type or type decl with assertions
@@ -158,53 +166,4 @@
 } // namespace ast
 
-// include needs to happen after TypeSubstitution is defined so that both TypeSubstitution and
-// PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals.
-#include "Pass.hpp"
-#include "Copy.hpp"
-
-namespace ast {
-
-// definitition must happen after PassVisitor is included so that WithGuards can be used
-struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter>, public PureVisitor {
-		static size_t traceId;
-
-		Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
-
-		const Type * postvisit( const TypeInstType * aggregateUseType );
-
-		/// Records type variable bindings from forall-statements
-		void previsit( const FunctionType * type );
-		/// Records type variable bindings from forall-statements and instantiations of generic types
-		// void handleAggregateType( const BaseInstType * type );
-
-		// void previsit( const StructInstType * aggregateUseType );
-		// void previsit( const UnionInstType * aggregateUseType );
-
-		const TypeSubstitution & sub;
-		int subCount = 0;
-		bool freeOnly;
-		typedef std::unordered_set< TypeEnvKey > BoundVarsType;
-		BoundVarsType boundVars;
-
-};
-
-template< typename SynTreeClass >
-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 ) );
-	return { input, sub.core.subCount };
-}
-
-template< typename SynTreeClass >
-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 ) );
-	return { input, sub.core.subCount };
-}
-
-} // namespace ast
-
 // Local Variables: //
 // tab-width: 4 //
