Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision 73ac10e1f458e8c55037fb5326876a41ed58a82b)
+++ src/SymTab/Mangler.cc	(revision ff5caaffaac4f11f28c574b27266ef608324781e)
@@ -15,19 +15,20 @@
 #include "Mangler.h"
 
-#include <algorithm>                // for copy, transform
-#include <cassert>                  // for assert, assertf
-#include <functional>               // for const_mem_fun_t, mem_fun
-#include <iterator>                 // for ostream_iterator, back_insert_ite...
-#include <list>                     // for _List_iterator, list, _List_const...
-#include <string>                   // for string, char_traits, operator<<
-
-#include "CodeGen/OperatorTable.h"  // for OperatorInfo, operatorLookup
+#include <algorithm>                     // for copy, transform
+#include <cassert>                       // for assert, assertf
+#include <functional>                    // for const_mem_fun_t, mem_fun
+#include <iterator>                      // for ostream_iterator, back_insert_ite...
+#include <list>                          // for _List_iterator, list, _List_const...
+#include <string>                        // for string, char_traits, operator<<
+
+#include "CodeGen/OperatorTable.h"       // for OperatorInfo, operatorLookup
 #include "Common/PassVisitor.h"
-#include "Common/SemanticError.h"   // for SemanticError
-#include "Common/utility.h"         // for toString
-#include "Parser/LinkageSpec.h"     // for Spec, isOverridable, AutoGen, Int...
-#include "SynTree/Declaration.h"    // for TypeDecl, DeclarationWithType
-#include "SynTree/Expression.h"     // for TypeExpr, Expression, operator<<
-#include "SynTree/Type.h"           // for Type, ReferenceToType, Type::Fora...
+#include "Common/SemanticError.h"        // for SemanticError
+#include "Common/utility.h"              // for toString
+#include "Parser/LinkageSpec.h"          // for Spec, isOverridable, AutoGen, Int...
+#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
+#include "SynTree/Declaration.h"         // for TypeDecl, DeclarationWithType
+#include "SynTree/Expression.h"          // for TypeExpr, Expression, operator<<
+#include "SynTree/Type.h"                // for Type, ReferenceToType, Type::Fora...
 
 namespace SymTab {
@@ -37,4 +38,5 @@
 			struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler>, public WithGuards {
 				Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
+				Mangler( const ResolvExpr::TypeEnvironment& env );
 				Mangler( const Mangler & ) = delete;
 
@@ -65,6 +67,7 @@
 			  private:
 				std::ostringstream mangleName;  ///< Mangled name being constructed
-				typedef std::map< std::string, std::pair< int, int > > VarMapType;
+				typedef std::map< std::string, std::pair< std::string, int > > VarMapType;
 				VarMapType varNums;             ///< Map of type variables to indices
+				const ResolvExpr::TypeEnvironment* env;  ///< optional environment for substitutions
 				int nextVarNum;                 ///< Next type variable index
 				bool isTopLevel;                ///< Is the Mangler at the top level
@@ -75,4 +78,8 @@
 				bool inQualifiedType = false;   ///< Add start/end delimiters around qualified type
 
+				Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 
+					int nextVarNum, const ResolvExpr::TypeEnvironment* env, 
+					const VarMapType& varNums );
+
 				void mangleDecl( DeclarationWithType *declaration );
 				void mangleRef( ReferenceToType *refType, std::string prefix );
@@ -100,7 +107,27 @@
 		}
 
+		std::string mangleAssnKey( DeclarationWithType* decl, 
+				const ResolvExpr::TypeEnvironment& env ) {
+			PassVisitor<Mangler> mangler( env );
+			maybeAccept( decl, mangler );
+			return mangler.pass.get_mangleName();
+		}
+
 		namespace {
 			Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
-				: nextVarNum( 0 ), isTopLevel( true ), mangleOverridable( mangleOverridable ), typeMode( typeMode ), mangleGenericParams( mangleGenericParams ) {}
+				: nextVarNum( 0 ), env(nullptr), isTopLevel( true ), 
+				mangleOverridable( mangleOverridable ), typeMode( typeMode ), 
+				mangleGenericParams( mangleGenericParams ) {}
+			
+			Mangler::Mangler( const ResolvExpr::TypeEnvironment& env )
+				: nextVarNum( 0 ), env( &env ), isTopLevel( true ), mangleOverridable( false ),
+				typeMode( false ), mangleGenericParams( true ) {}
+			
+			Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 
+				int nextVarNum, const ResolvExpr::TypeEnvironment* env, 
+				const VarMapType& varNums )
+				: nextVarNum( nextVarNum ), varNums( varNums ), env( env ), isTopLevel( false ), 
+				mangleOverridable( mangleOverridable ), typeMode( typeMode ), 
+				mangleGenericParams( mangleGenericParams ) {}
 
 			void Mangler::mangleDecl( DeclarationWithType * declaration ) {
@@ -329,12 +356,27 @@
 							assert( false );
 						} // switch
-						varNums[ (*i)->name ] = std::pair< int, int >( nextVarNum++, (int)(*i)->get_kind() );
+						std::string varName;
+						// replace type with substitution name if environment is available and bound
+						if ( env ) {
+							const EqvClass* varClass = env->lookup( (*i)->name );
+							if ( varClass && varClass->type ) {
+								PassVisitor<Mangler> sub_mangler(
+									mangleOverridable, typeMode, mangleGenericParams, nextVarNum, 
+									env, varNums );
+								varClass->type->accept( sub_mangler );
+								varName = std::string{"%"} + sub_mangler.pass.get_mangleName();
+							}
+						}
+						// otherwise just give type numeric name
+						if ( varName.empty() ) {
+							varName = std::to_string( nextVarNum++ );
+						}
+						varNums[ (*i)->name ] = std::make_pair( varName, (int)(*i)->get_kind() );
 						for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) {
-							PassVisitor<Mangler> sub_mangler( mangleOverridable, typeMode, mangleGenericParams );
-							sub_mangler.pass.nextVarNum = nextVarNum;
-							sub_mangler.pass.isTopLevel = false;
-							sub_mangler.pass.varNums = varNums;
+							PassVisitor<Mangler> sub_mangler( 
+								mangleOverridable, typeMode, mangleGenericParams, nextVarNum, env, 
+								varNums );
 							(*assert)->accept( sub_mangler );
-							assertionNames.push_back( sub_mangler.pass.mangleName.str() );
+							assertionNames.push_back( sub_mangler.pass.get_mangleName() );
 							acount++;
 						} // for
Index: src/SymTab/Mangler.h
===================================================================
--- src/SymTab/Mangler.h	(revision 73ac10e1f458e8c55037fb5326876a41ed58a82b)
+++ src/SymTab/Mangler.h	(revision ff5caaffaac4f11f28c574b27266ef608324781e)
@@ -31,4 +31,8 @@
 // * Currently name compression is not implemented.
 
+namespace ResolvExpr {
+	class TypeEnvironment;
+}
+
 namespace SymTab {
 	namespace Mangler {
@@ -40,4 +44,7 @@
 		/// Mangle ignoring generic type parameters
 		std::string mangleConcrete( Type* ty );
+		/// Mangle for assertion key
+		std::string mangleAssnKey( DeclarationWithType* decl, 
+			const ResolvExpr::TypeEnvironment& env );
 
 		namespace Encoding {
