Index: src/ResolvExpr/RenameVars.cc
===================================================================
--- src/ResolvExpr/RenameVars.cc	(revision b8524ca1420ff28d69347f46888a20baa805f797)
+++ src/ResolvExpr/RenameVars.cc	(revision 9af00d231cf219857c0daa7acd7bcf57da94ac23)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 12:05:18 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Apr 30 17:07:57 2019
-// Update Count     : 7
+// Last Modified By : Andrew Beach
+// Last Modified On : Thr Jun 20 17:39:00 2019
+// Update Count     : 8
 //
 
@@ -19,5 +19,8 @@
 #include <utility>                 // for pair
 
+#include "AST/Pass.hpp"
+#include "AST/Type.hpp"
 #include "Common/PassVisitor.h"
+#include "Common/ScopedMap.h"
 #include "Common/SemanticError.h"  // for SemanticError
 #include "RenameVars.h"
@@ -28,51 +31,29 @@
 
 namespace ResolvExpr {
-	namespace {
-		struct RenameVars {
-			RenameVars();
-			void reset();
 
-			void previsit( TypeInstType * instType );
-			void previsit( Type * );
-			void postvisit( Type * );
+namespace {
+	class RenamingData {
+		int level = 0;
+		int resetCount = 0;
+		ScopedMap< std::string, std::string > nameMap;
 
-		  private:
-			int level, resetCount;
-			std::list< std::unordered_map< std::string, std::string > > mapStack;
-		};
-
-		PassVisitor<RenameVars> global_renamer;
-	} // namespace
-
-	void renameTyVars( Type * t ) {
-		t->accept( global_renamer );
-	}
-
-	void resetTyVarRenaming() {
-		global_renamer.pass.reset();
-	}
-
-	namespace {
-		RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) {
-			mapStack.push_front( std::unordered_map< std::string, std::string >() );
+	public:
+		void reset() {
+			level = 0;
+			++resetCount;
 		}
 
-		void RenameVars::reset() {
-			level = 0;
-			resetCount++;
+		using mapConstIterator = ScopedMap< std::string, std::string >::const_iterator;
+
+		void rename( TypeInstType * type ) {
+			mapConstIterator it = nameMap.find( type->name );
+			if ( it != nameMap.end() ) {
+				type->name = it->second;
+			}
 		}
 
-		void RenameVars::previsit( TypeInstType * instType ) {
-			previsit( (Type *)instType );
-			std::unordered_map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->name );
-			if ( i != mapStack.front().end() ) {
-				instType->name = i->second;
-			} // if
-		}
-
-		void RenameVars::previsit( Type * type ) {
+		void openLevel( Type * type ) {
 			if ( ! type->forall.empty() ) {
-				// copies current name mapping into new mapping
-				mapStack.push_front( mapStack.front() );
+				nameMap.beginScope();
 				// renames all "forall" type names to `_${level}_${name}'
 				for ( auto td : type->forall ) {
@@ -80,5 +61,5 @@
 					output << "_" << resetCount << "_" << level << "_" << td->name;
 					std::string newname( output.str() );
-					mapStack.front()[ td->get_name() ] = newname;
+					nameMap[ td->get_name() ] = newname;
 					td->name = newname;
 					// ditto for assertion names, the next level in
@@ -89,18 +70,101 @@
 		}
 
-		void RenameVars::postvisit( Type * type ) {
-			// clears name mapping added by typeBefore()
-			if ( ! type->forall.empty() ) {
-				mapStack.pop_front();
-			} // if
+		void closeLevel( Type * type ) {
+			if ( !type->forall.empty() ) {
+				nameMap.endScope();
+			}
 		}
-	} // namespace
 
-	const ast::Type * renameTyVars( const ast::Type * t ) {
-		#warning unimplemented; make sure resetTyVarRenaming() updated when implemented
-		(void)t;
-		assert(false);
-		return t;
-	}
+		const ast::TypeInstType * rename( const ast::TypeInstType * type ) {
+			mapConstIterator it = nameMap.find( type->name );
+			if ( it != nameMap.end() ) {
+				ast::TypeInstType * mutType = ast::mutate( type );
+				mutType->name = it->second;
+	            type = mutType;
+			}
+			return type;
+		}
+
+		template<typename NodeT>
+		const NodeT * openLevel( const NodeT * type ) {
+			if ( !type->forall.empty() ) {
+				nameMap.beginScope();
+				// Load new names from this forall clause and perform renaming.
+				NodeT * mutType = ast::mutate( type );
+				for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) {
+					std::ostringstream output;
+					output << "_" << resetCount << "_" << level << "_" << td->name;
+					std::string newname( output.str() );
+					nameMap[ td->name ] = newname;
+					++level;
+
+					ast::TypeDecl * decl = ast::mutate( td.get() );
+					decl->name = newname;
+					td = decl;
+				}
+			}
+			return type;
+		}
+
+		template<typename NodeT>
+		const NodeT * closeLevel( const NodeT * type ) {
+			if ( !type->forall.empty() ) {
+				nameMap.endScope();
+			}
+			return type;
+		}
+	};
+
+	// Global State:
+	RenamingData renaming;
+
+	struct RenameVars {
+		void previsit( TypeInstType * instType ) {
+			renaming.openLevel( (Type*)instType );
+			renaming.rename( instType );
+		}
+		void previsit( Type * type ) {
+			renaming.openLevel( type );
+		}
+		void postvisit( Type * type ) {
+			renaming.closeLevel( type );
+		}
+
+		const ast::FunctionType * previsit( const ast::FunctionType * type ) {
+			return renaming.openLevel( type );
+		}
+		const ast::StructInstType * previsit( const ast::StructInstType * type ) {
+			return renaming.openLevel( type );
+		}
+		const ast::UnionInstType * previsit( const ast::UnionInstType * type ) {
+			return renaming.openLevel( type );
+		}
+		const ast::TraitInstType * previsit( const ast::TraitInstType * type ) {
+			return renaming.openLevel( type );
+		}
+		const ast::TypeInstType * previsit( const ast::TypeInstType * type ) {
+			return renaming.rename( renaming.openLevel( type ) );
+		}
+		const ast::ParameterizedType * postvisit( const ast::ParameterizedType * type ) {
+			return renaming.closeLevel( type );
+		}
+	};
+
+} // namespace
+
+void renameTyVars( Type * t ) {
+	PassVisitor<RenameVars> renamer;
+	t->accept( renamer );
+}
+
+const ast::Type * renameTyVars( const ast::Type * t ) {
+	ast::Pass<RenameVars> renamer;
+	return t->accept( renamer );
+}
+
+void resetTyVarRenaming() {
+	renaming.reset();
+}
+
 } // namespace ResolvExpr
 
