Index: src/AST/Type.cpp
===================================================================
--- src/AST/Type.cpp	(revision 88ac843eb869c0f0f1ca2437581fdc20d4b4c080)
+++ src/AST/Type.cpp	(revision 22a0e87773a1349ca1fc9e5424761686202011e2)
@@ -147,4 +147,10 @@
 // --- TypeInstType
 
+bool TypeInstType::operator==( const TypeInstType & other ) const {
+	return base == other.base
+		&& formal_usage == other.formal_usage
+		&& expr_id == other.expr_id;
+}
+
 TypeInstType::TypeInstType( const TypeDecl * b,
 	CV::Qualifiers q, std::vector<ptr<Attribute>> && as )
@@ -157,4 +163,33 @@
 
 bool TypeInstType::isComplete() const { return base->sized; }
+
+std::string TypeInstType::TypeEnvKey::typeString() const {
+	return std::string("_") + std::to_string(formal_usage)
+		+ "_" + std::to_string(expr_id) + "_" + base->name;
+}
+
+bool TypeInstType::TypeEnvKey::operator==(
+		const TypeInstType::TypeEnvKey & other ) const {
+	return base == other.base
+		&& formal_usage == other.formal_usage
+		&& expr_id == other.expr_id;
+}
+
+bool TypeInstType::TypeEnvKey::operator<(
+		const TypeInstType::TypeEnvKey & other ) const {
+	// TypeEnvKey ordering is an arbitrary total ordering.
+	// It doesn't mean anything but allows for a sorting.
+	if ( base < other.base ) {
+		return true;
+	} else if ( other.base < base ) {
+		return false;
+	} else if ( formal_usage < other.formal_usage ) {
+		return true;
+	} else if ( other.formal_usage < formal_usage ) {
+		return false;
+	} else {
+		return expr_id < other.expr_id;
+	}
+}
 
 // --- TupleType
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision 88ac843eb869c0f0f1ca2437581fdc20d4b4c080)
+++ src/AST/Type.hpp	(revision 22a0e87773a1349ca1fc9e5424761686202011e2)
@@ -408,11 +408,14 @@
 
 		TypeEnvKey() = default;
-		TypeEnvKey(const TypeDecl * base, int formal_usage = 0, int expr_id = 0): base(base), formal_usage(formal_usage), expr_id(expr_id) {}
-		TypeEnvKey(const TypeInstType & inst): base(inst.base), formal_usage(inst.formal_usage), expr_id(inst.expr_id) {}
-		std::string typeString() const { return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + base->name; }
-		bool operator==(const TypeEnvKey & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; }
+		TypeEnvKey(const TypeDecl * base, int formal_usage = 0, int expr_id = 0)
+		: base(base), formal_usage(formal_usage), expr_id(expr_id) {}
+		TypeEnvKey(const TypeInstType & inst)
+		: base(inst.base), formal_usage(inst.formal_usage), expr_id(inst.expr_id) {}
+		std::string typeString() const;
+		bool operator==(const TypeEnvKey & other) const;
+		bool operator<(const TypeEnvKey & other) const;
 	};
 
-	bool operator==(const TypeInstType & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; }
+	bool operator==(const TypeInstType & other) const;
 
 	TypeInstType(
Index: src/GenPoly/GenPoly.cc
===================================================================
--- src/GenPoly/GenPoly.cc	(revision 88ac843eb869c0f0f1ca2437581fdc20d4b4c080)
+++ src/GenPoly/GenPoly.cc	(revision 22a0e87773a1349ca1fc9e5424761686202011e2)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri Oct  7 15:25:00 2022
-// Update Count     : 16
+// Last Modified On : Mon Oct 24 15:19:00 2022
+// Update Count     : 17
 //
 
@@ -194,5 +194,5 @@
 
 	if ( auto inst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
-		if ( typeVars.find( inst->typeString() ) != typeVars.end() ) return type;
+		if ( typeVars.find( *inst ) != typeVars.end() ) return type;
 	} else if ( auto array = dynamic_cast< const ast::ArrayType * >( type ) ) {
 		return isPolyType( array->base, subst );
@@ -227,5 +227,5 @@
 
 	if ( auto inst = dynamic_cast<ast::TypeInstType const *>( type ) ) {
-		auto var = typeVars.find( inst->name );
+		auto var = typeVars.find( *inst );
 		if ( var != typeVars.end() && var->second.isComplete ) {
 
@@ -784,5 +784,5 @@
 
 void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ) {
-	typeVars.insert( type->typeString(), ast::TypeDecl::Data( type->base ) );
+	typeVars.insert( *type, ast::TypeDecl::Data( type->base ) );
 }
 
@@ -816,11 +816,4 @@
 	}
 
-void printTypeVarMap( std::ostream &os, const TypeVarMap & typeVars ) {
-	for ( auto const & pair : typeVars ) {
-		os << pair.first << " (" << pair.second << ") ";
-	} // for
-	os << std::endl;
-}
-
 } // namespace GenPoly
 
Index: src/GenPoly/GenPoly.h
===================================================================
--- src/GenPoly/GenPoly.h	(revision 88ac843eb869c0f0f1ca2437581fdc20d4b4c080)
+++ src/GenPoly/GenPoly.h	(revision 22a0e87773a1349ca1fc9e5424761686202011e2)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri Oct  7 15:06:00 2022
-// Update Count     : 9
+// Last Modified On : Mon Oct 24 15:18:00 2022
+// Update Count     : 11
 //
 
@@ -22,4 +22,5 @@
 #include "AST/Decl.hpp"           // for TypeDecl::Data
 #include "AST/Fwd.hpp"            // for ApplicationExpr, BaseInstType, Func...
+#include "AST/Type.hpp"           // for TypeInstType::TypeEnvKey
 #include "SymTab/Mangler.h"       // for Mangler
 #include "SynTree/Declaration.h"  // for TypeDecl::Data, AggregateDecl, Type...
@@ -28,10 +29,10 @@
 namespace GenPoly {
 
-	// TODO Via some tricks this works for ast::TypeDecl::Data as well.
 	typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap;
-	using TypeVarMap = ErasableScopedMap< std::string, ast::TypeDecl::Data >;
+	using TypeVarMap = ErasableScopedMap< ast::TypeInstType::TypeEnvKey, ast::TypeDecl::Data >;
 
 	/// Replaces a TypeInstType by its referrent in the environment, if applicable
 	Type* replaceTypeInst( Type* type, const TypeSubstitution* env );
+	const ast::Type * replaceTypeInst( const ast::Type *, const ast::TypeSubstitution * );
 
 	/// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided
@@ -53,4 +54,5 @@
 	/// true iff function has dynamic-layout return type under the type variable map generated from its forall-parameters
 	ReferenceToType *isDynRet( FunctionType *function );
+	const ast::BaseInstType *isDynRet( const ast::FunctionType * func );
 
 	/// A function needs an adapter if it returns a dynamic-layout value or if any of its parameters have dynamic-layout type
@@ -112,5 +114,4 @@
 	/// Prints type variable map
 	void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap );
-	void printTypeVarMap( std::ostream &os, const TypeVarMap & typeVars );
 
 	/// Gets the mangled name of this type; alias for SymTab::Mangler::mangleType().
@@ -128,4 +129,7 @@
 	/// Gets the name of the layout function for a given aggregate type, given its declaration
 	inline std::string layoutofName( AggregateDecl *decl ) { return std::string( "_layoutof_" ) + decl->get_name(); }
+	inline std::string layoutofName( ast::AggregateDecl const * decl ) {
+		return std::string( "_layoutof_" ) + decl->name;
+	}
 
 } // namespace GenPoly
Index: src/GenPoly/ScrubTyVars.cc
===================================================================
--- src/GenPoly/ScrubTyVars.cc	(revision 88ac843eb869c0f0f1ca2437581fdc20d4b4c080)
+++ src/GenPoly/ScrubTyVars.cc	(revision 22a0e87773a1349ca1fc9e5424761686202011e2)
@@ -20,5 +20,5 @@
 #include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
 #include "ScrubTyVars.h"
-#include "SymTab/Mangler.h"             // for mangle, typeMode
+#include "SymTab/Mangler.h"             // for mangleType
 #include "SynTree/Declaration.h"        // for TypeDecl, TypeDecl::Data, Typ...
 #include "SynTree/Expression.h"         // for Expression (ptr only), NameExpr
@@ -195,5 +195,5 @@
 	}
 
-	auto typeVar = typeVars->find( type->name );
+	auto typeVar = typeVars->find( *type );
 	if ( typeVar == typeVars->end() ) {
 		return type;
@@ -227,5 +227,5 @@
 	if ( dynType ) {
 		return new ast::NameExpr( expr->location,
-			sizeofName( Mangle::mangle( dynType, Mangle::typeMode() ) ) );
+			sizeofName( Mangle::mangleType( dynType ) ) );
 	} else {
 		return expr;
@@ -237,5 +237,5 @@
 	if ( dynType ) {
 		return new ast::NameExpr( expr->location,
-			alignofName( Mangle::mangle( dynType, Mangle::typeMode() ) ) );
+			alignofName( Mangle::mangleType( dynType ) ) );
 	} else {
 		return expr;
Index: src/ResolvExpr/SatisfyAssertions.cpp
===================================================================
--- src/ResolvExpr/SatisfyAssertions.cpp	(revision 88ac843eb869c0f0f1ca2437581fdc20d4b4c080)
+++ src/ResolvExpr/SatisfyAssertions.cpp	(revision 22a0e87773a1349ca1fc9e5424761686202011e2)
@@ -268,5 +268,5 @@
 		ast::ptr< ast::Type > resType = cand.expr->result;
 		cand.env.apply( resType );
-		return Mangle::mangle( resType, Mangle::typeMode() );
+		return Mangle::mangleType( resType );
 	}
 
Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision 88ac843eb869c0f0f1ca2437581fdc20d4b4c080)
+++ src/SymTab/Mangler.cc	(revision 22a0e87773a1349ca1fc9e5424761686202011e2)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 21:40:29 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Jan 11 21:56:06 2021
-// Update Count     : 74
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Oct 21 16:18:00 2022
+// Update Count     : 75
 //
 #include "Mangler.h"
@@ -418,5 +418,6 @@
 			void postvisit( const ast::QualifiedType * qualType );
 
-			std::string get_mangleName() { return mangleName; }
+			/// The result is the current constructed mangled name.
+			std::string result() const { return mangleName; }
 		  private:
 			std::string mangleName;         ///< Mangled name being constructed
@@ -444,9 +445,6 @@
 	} // namespace
 
-
 	std::string mangle( const ast::Node * decl, Mangle::Mode mode ) {
-		ast::Pass<Mangler_new> mangler( mode );
-		maybeAccept( decl, mangler );
-		return mangler.core.get_mangleName();
+		return ast::Pass<Mangler_new>::read( decl, mode );
 	}
 
@@ -689,8 +687,7 @@
 					} // for
 					for ( auto & assert : ptype->assertions ) {
-						ast::Pass<Mangler_new> sub_mangler(
-							mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
-						assert->var->accept( sub_mangler );
-						assertionNames.push_back( sub_mangler.core.get_mangleName() );
+						assertionNames.push_back( ast::Pass<Mangler_new>::read(
+							assert->var.get(),
+							mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ) );
 						acount++;
 					} // for
Index: src/SymTab/Mangler.h
===================================================================
--- src/SymTab/Mangler.h	(revision 88ac843eb869c0f0f1ca2437581fdc20d4b4c080)
+++ src/SymTab/Mangler.h	(revision 22a0e87773a1349ca1fc9e5424761686202011e2)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 21:44:03 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul 22 09:45:30 2017
-// Update Count     : 15
+// Last Modified By : Andrew Beach
+// Last Modified On : Thu Oct 27 11:58:00 2022
+// Update Count     : 16
 //
 
@@ -22,5 +22,4 @@
 
 #include "AST/Bitfield.hpp"
-#include "AST/Fwd.hpp"
 #include "SynTree/SynTree.h"  // for Types
 #include "SynTree/Visitor.h"  // for Visitor, maybeAccept
@@ -33,4 +32,7 @@
 // * Currently name compression is not implemented.
 
+namespace ast {
+	class Node;
+}
 namespace ResolvExpr {
 	class TypeEnvironment;
@@ -101,8 +103,11 @@
 	using Mode = bitfield<mangle_flags>;
 
-	static inline Mode typeMode() { return NoOverrideable | Type; }
+	/// Mangle declaration name.
+	std::string mangle( const ast::Node * decl, Mode mode = {} );
 
-	/// Mangle declaration name
-	std::string mangle( const ast::Node * decl, Mode mode = {} );
+	/// Most common mangle configuration for types.
+	static inline std::string mangleType( const ast::Node * type ) {
+		return mangle( type, { NoOverrideable | Type } );
+	}
 
 	namespace Encoding {
Index: src/Virtual/ExpandCasts.cc
===================================================================
--- src/Virtual/ExpandCasts.cc	(revision 88ac843eb869c0f0f1ca2437581fdc20d4b4c080)
+++ src/Virtual/ExpandCasts.cc	(revision 22a0e87773a1349ca1fc9e5424761686202011e2)
@@ -295,6 +295,5 @@
 	// returns the previous declaration for error messages.
 	ast::ObjectDecl const * insert( ast::ObjectDecl const * typeIdDecl ) {
-		std::string const & mangledName =
-				Mangle::mangle( typeIdDecl->type, Mangle::typeMode() );
+		std::string mangledName = Mangle::mangleType( typeIdDecl->type );
 		ast::ObjectDecl const *& value = instances[ mangledName ];
 		if ( value ) {
@@ -310,6 +309,5 @@
 
 	ast::ObjectDecl const * lookup( ast::Type const * typeIdType ) {
-		std::string const & mangledName =
-				Mangle::mangle( typeIdType, Mangle::typeMode() );
+		std::string mangledName = Mangle::mangleType( typeIdType );
 		auto const it = instances.find( mangledName );
 		return ( instances.end() == it ) ? nullptr : it->second;
