Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 37cdd97f319c512b8374d214748e986930e2e8f8)
+++ src/AST/Pass.impl.hpp	(revision 7030dab75c493bbd89de53cb88e496019c794ff4)
@@ -127,8 +127,7 @@
 			, decltype( node->accept(*this) )
 		>::type
-
 	{
 		__pedantic_pass_assert( __visit_children() );
-		__pedantic_pass_assert( expr );
+		__pedantic_pass_assert( node );
 
 		static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR");
@@ -323,4 +322,20 @@
 	}
 
+
+	template< typename pass_t >
+	template< typename node_t >
+	void ast::Pass< pass_t >::mutate_forall( const node_t *& node ) {
+		if ( auto subs = __pass::forall::subs( pass, 0 ) ) {
+			// tracking TypeDecl substitution, full clone
+			if ( node->forall.empty() ) return;
+
+			node_t * mut = mutate( node );
+			mut->forall = subs->clone( node->forall, *this );
+			node = mut;
+		} else {
+			// not tracking TypeDecl substitution, just mutate
+			maybe_accept( node, &node_t::forall );
+		}
+	}
 }
 
@@ -429,12 +444,12 @@
 			guard_symtab guard { *this };
 			// implicit add __func__ identifier as specified in the C manual 6.4.2.2
-			static ast::ObjectDecl func(
-				node->location, "__func__",
-				new ast::ArrayType(
-					new ast::BasicType( ast::BasicType::Char, ast::CV::Qualifiers( ast::CV::Const ) ),
+			static ast::ptr< ast::ObjectDecl > func{ new ast::ObjectDecl{ 
+				CodeLocation{}, "__func__",
+				new ast::ArrayType{
+					new ast::BasicType{ ast::BasicType::Char, ast::CV::Const },
 					nullptr, VariableLen, DynamicDim
-				)
-			);
-			__pass::symtab::addId( pass, 0, &func );
+				}
+			} };
+			__pass::symtab::addId( pass, 0, func );
 			VISIT(
 				maybe_accept( node, &FunctionDecl::type );
@@ -610,8 +625,8 @@
 	VISIT({
 		// do not enter a new scope if inFunction is true - needs to check old state before the assignment
-		auto guard1 = makeFuncGuard( [this, inFunction = this->inFunction]() {
-			if ( ! inFunction ) __pass::symtab::enter(pass, 0);
-		}, [this, inFunction = this->inFunction]() {
-			if ( ! inFunction ) __pass::symtab::leave(pass, 0);
+		auto guard1 = makeFuncGuard( [this, inFunctionCpy = this->inFunction]() {
+			if ( ! inFunctionCpy ) __pass::symtab::enter(pass, 0);
+		}, [this, inFunctionCpy = this->inFunction]() {
+			if ( ! inFunctionCpy ) __pass::symtab::leave(pass, 0);
 		});
 		ValueGuard< bool > guard2( inFunction );
@@ -951,7 +966,7 @@
 	// For now this isn't visited, it is unclear if this causes problem
 	// if all tests are known to pass, remove this code
-	// VISIT(
-	// 	maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
-	// )
+	VISIT(
+		maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
+	)
 
 	VISIT_END( Stmt, node );
@@ -1679,9 +1694,10 @@
 	VISIT_START( node );
 
-	VISIT(
-		maybe_accept( node, &FunctionType::forall  );
+	VISIT({
+		guard_forall_subs forall_guard { *this, node };
+		mutate_forall( node );
 		maybe_accept( node, &FunctionType::returns );
 		maybe_accept( node, &FunctionType::params  );
-	)
+	})
 
 	VISIT_END( Type, node );
@@ -1698,5 +1714,6 @@
 	VISIT({
 		guard_symtab guard { *this };
-		maybe_accept( node, &StructInstType::forall );
+		guard_forall_subs forall_guard { *this, node };
+		mutate_forall( node );
 		maybe_accept( node, &StructInstType::params );
 	})
@@ -1711,11 +1728,12 @@
 	VISIT_START( node );
 
-	__pass::symtab::addStruct( pass, 0, node->name );
-
-	{
+	__pass::symtab::addUnion( pass, 0, node->name );
+
+	VISIT({
 		guard_symtab guard { *this };
-		maybe_accept( node, &UnionInstType::forall );
+		guard_forall_subs forall_guard { *this, node };
+		mutate_forall( node );
 		maybe_accept( node, &UnionInstType::params );
-	}
+	})
 
 	VISIT_END( Type, node );
@@ -1728,8 +1746,9 @@
 	VISIT_START( node );
 
-	VISIT(
-		maybe_accept( node, &EnumInstType::forall );
+	VISIT({
+		guard_forall_subs forall_guard { *this, node };
+		mutate_forall( node );
 		maybe_accept( node, &EnumInstType::params );
-	)
+	})
 
 	VISIT_END( Type, node );
@@ -1742,8 +1761,9 @@
 	VISIT_START( node );
 
-	VISIT(
-		maybe_accept( node, &TraitInstType::forall );
+	VISIT({
+		guard_forall_subs forall_guard { *this, node };
+		mutate_forall( node );
 		maybe_accept( node, &TraitInstType::params );
-	)
+	})
 
 	VISIT_END( Type, node );
@@ -1757,6 +1777,11 @@
 
 	VISIT(
-		maybe_accept( node, &TypeInstType::forall );
-		maybe_accept( node, &TypeInstType::params );
+		{
+			guard_forall_subs forall_guard { *this, node };
+			mutate_forall( node );
+			maybe_accept( node, &TypeInstType::params );
+		}
+		// ensure that base re-bound if doing substitution
+		__pass::forall::replace( pass, 0, node );
 	)
 
@@ -1907,5 +1932,5 @@
 				guard_symtab guard { *this };
 				auto new_node = p.second->accept( *this );
-				if (new_node != p.second) mutated = false;
+				if (new_node != p.second) mutated = true;
 				new_map.insert({ p.first, new_node });
 			}
@@ -1923,5 +1948,5 @@
 				guard_symtab guard { *this };
 				auto new_node = p.second->accept( *this );
-				if (new_node != p.second) mutated = false;
+				if (new_node != p.second) mutated = true;
 				new_map.insert({ p.first, new_node });
 			}
