Index: src/AST/Pass.cpp
===================================================================
--- src/AST/Pass.cpp	(revision b0abc8a02c452bd4a4675437c5aa0ca43e19893c)
+++ src/AST/Pass.cpp	(revision b0abc8a02c452bd4a4675437c5aa0ca43e19893c)
@@ -0,0 +1,23 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Pass.cpp --
+//
+// Author           : Thierry Delisle
+// Created On       : Wed May 22 15:00:33 2019
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+#include "Pass.hpp"
+
+namespace ast {
+
+PassVisitorStats pass_visitor_stats;
+// Stats::Counters::SimpleCounter * BaseSyntaxNode::new_nodes = nullptr;
+
+};
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 09ab71a33bf6acba21dbc6a63bf0ce4f84b24eab)
+++ src/AST/Pass.impl.hpp	(revision b0abc8a02c452bd4a4675437c5aa0ca43e19893c)
@@ -841,5 +841,5 @@
 		for( const auto & clause : node->clauses ) {
 
-			Expr * func = clause.target.func ? clause.target.func->accept(*this) : nullptr;
+			const Expr * func = clause.target.func ? clause.target.func->accept(*this) : nullptr;
 			if(func != clause.target.func) mutated = true;
 
@@ -852,8 +852,8 @@
 			}
 
-			Stmt * stmt = clause.stmt ? clause.stmt->accept(*this) : nullptr;
+			const Stmt * stmt = clause.stmt ? clause.stmt->accept(*this) : nullptr;
 			if(stmt != clause.stmt) mutated = true;
 
-			Expr * cond = clause.cond ? clause.cond->accept(*this) : nullptr;
+			const Expr * cond = clause.cond ? clause.cond->accept(*this) : nullptr;
 			if(cond != clause.cond) mutated = true;
 
@@ -1567,5 +1567,5 @@
 		bool mutated = false;
 		for( const auto & assoc : node->associations ) {
-			Type * type = nullptr;
+			const Type * type = nullptr;
 			if( assoc.type ) {
 				guard_indexer guard { *this };
@@ -1573,5 +1573,5 @@
 				if( type != assoc.type ) mutated = true;
 			}
-			Expr * expr = nullptr;
+			const Expr * expr = nullptr;
 			if( assoc.expr ) {
 				expr = assoc.expr->accept( *this );
@@ -1685,5 +1685,5 @@
 	VISIT_START( node );
 
-	__pass::indexer::addStruct( node->name, 0, pass );
+	__pass::indexer::addStruct( pass, 0, node->name );
 
 	VISIT({
@@ -1702,5 +1702,5 @@
 	VISIT_START( node );
 
-	__pass::indexer::addStruct( node->name, 0, pass );
+	__pass::indexer::addStruct( pass, 0, node->name );
 
 	{
@@ -1885,46 +1885,46 @@
 }
 
-// //--------------------------------------------------------------------------
-// // TypeSubstitution
-// template< typename pass_t >
-// const ast::TypeSubstitution * ast::Pass< pass_t >::visit( const ast::TypeSubstitution * node ) {
-// 	VISIT_START( node );
-
-// 	VISIT(
-// 		{
-// 			bool mutated = false;
-// 			std::unordered_map< std::string, ast::ptr< ast::Type > > new_map;
-// 			for ( const auto & p : node->typeEnv ) {
-// 				guard_indexer guard { *this };
-// 				auto new_node = p.second->accept( *this );
-// 				if (new_node != p.second) mutated = false;
-// 				new_map.insert({ p.first, new_node });
-// 			}
-// 			if (mutated) {
-// 				auto new_node = mutate( node );
-// 				new_node->typeEnv.swap( new_map );
-// 				node = new_node;
-// 			}
-// 		}
-
-// 		{
-// 			bool mutated = false;
-// 			std::unordered_map< std::string, ast::ptr< ast::Expr > > new_map;
-// 			for ( const auto & p : node->varEnv ) {
-// 				guard_indexer guard { *this };
-// 				auto new_node = p.second->accept( *this );
-// 				if (new_node != p.second) mutated = false;
-// 				new_map.insert({ p.first, new_node });
-// 			}
-// 			if (mutated) {
-// 				auto new_node = mutate( node );
-// 				new_node->varEnv.swap( new_map );
-// 				node = new_node;
-// 			}
-// 		}
-// 	)
-
-// 	VISIT_END( TypeSubstitution, node );
-// }
+//--------------------------------------------------------------------------
+// TypeSubstitution
+template< typename pass_t >
+const ast::TypeSubstitution * ast::Pass< pass_t >::visit( const ast::TypeSubstitution * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		{
+			bool mutated = false;
+			std::unordered_map< std::string, ast::ptr< ast::Type > > new_map;
+			for ( const auto & p : node->typeEnv ) {
+				guard_indexer guard { *this };
+				auto new_node = p.second->accept( *this );
+				if (new_node != p.second) mutated = false;
+				new_map.insert({ p.first, new_node });
+			}
+			if (mutated) {
+				auto new_node = mutate( node );
+				new_node->typeEnv.swap( new_map );
+				node = new_node;
+			}
+		}
+
+		{
+			bool mutated = false;
+			std::unordered_map< std::string, ast::ptr< ast::Expr > > new_map;
+			for ( const auto & p : node->varEnv ) {
+				guard_indexer guard { *this };
+				auto new_node = p.second->accept( *this );
+				if (new_node != p.second) mutated = false;
+				new_map.insert({ p.first, new_node });
+			}
+			if (mutated) {
+				auto new_node = mutate( node );
+				new_node->varEnv.swap( new_map );
+				node = new_node;
+			}
+		}
+	)
+
+	VISIT_END( TypeSubstitution, node );
+}
 
 #undef VISIT_START
Index: src/AST/Pass.proto.hpp
===================================================================
--- src/AST/Pass.proto.hpp	(revision 09ab71a33bf6acba21dbc6a63bf0ce4f84b24eab)
+++ src/AST/Pass.proto.hpp	(revision b0abc8a02c452bd4a4675437c5aa0ca43e19893c)
@@ -126,4 +126,8 @@
 	template<typename pass_t, typename node_t>
 	static inline auto previsit( pass_t & pass, const node_t * & node, int ) -> decltype( pass.previsit( node ), void() ) {
+		static_assert(
+			std::is_base_of<const node_t, typename std::remove_pointer<decltype( pass.previsit( node ) )>::type >::value,
+			"Previsit may not change the type of the node. Use postvisit instead."
+		);
 		node = pass.previsit( node );
 		assert(node);
Index: src/AST/module.mk
===================================================================
--- src/AST/module.mk	(revision 09ab71a33bf6acba21dbc6a63bf0ce4f84b24eab)
+++ src/AST/module.mk	(revision b0abc8a02c452bd4a4675437c5aa0ca43e19893c)
@@ -24,4 +24,5 @@
 	AST/LinkageSpec.cpp \
 	AST/Node.cpp \
+	AST/Pass.cpp \
 	AST/Print.cpp \
 	AST/Stmt.cpp \
Index: src/Makefile.in
===================================================================
--- src/Makefile.in	(revision 09ab71a33bf6acba21dbc6a63bf0ce4f84b24eab)
+++ src/Makefile.in	(revision b0abc8a02c452bd4a4675437c5aa0ca43e19893c)
@@ -169,6 +169,6 @@
 	AST/Expr.$(OBJEXT) AST/Init.$(OBJEXT) \
 	AST/LinkageSpec.$(OBJEXT) AST/Node.$(OBJEXT) \
-	AST/Print.$(OBJEXT) AST/Stmt.$(OBJEXT) AST/Type.$(OBJEXT) \
-	AST/TypeSubstitution.$(OBJEXT)
+	AST/Pass.$(OBJEXT) AST/Print.$(OBJEXT) AST/Stmt.$(OBJEXT) \
+	AST/Type.$(OBJEXT) AST/TypeSubstitution.$(OBJEXT)
 am__objects_2 = CodeGen/CodeGenerator.$(OBJEXT) \
 	CodeGen/FixMain.$(OBJEXT) CodeGen/GenType.$(OBJEXT) \
@@ -577,4 +577,5 @@
 	AST/LinkageSpec.cpp \
 	AST/Node.cpp \
+	AST/Pass.cpp \
 	AST/Print.cpp \
 	AST/Stmt.cpp \
@@ -742,4 +743,5 @@
 	AST/$(DEPDIR)/$(am__dirstamp)
 AST/Node.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
+AST/Pass.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
 AST/Print.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
 AST/Stmt.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
@@ -1174,4 +1176,5 @@
 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/LinkageSpec.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Node.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Pass.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Print.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Stmt.Po@am__quote@
