Index: src/AST/Type.cpp
===================================================================
--- src/AST/Type.cpp	(revision cfaa2873f31b6edf27dbf9fb7a544ce6a7bb2a93)
+++ src/AST/Type.cpp	(revision 7030dab75c493bbd89de53cb88e496019c794ff4)
@@ -21,5 +21,7 @@
 
 #include "Decl.hpp"
+#include "ForallSubstitutor.hpp" // for substituteForall
 #include "Init.hpp"
+#include "Common/utility.h"      // for copy, move
 #include "InitTweak/InitTweak.h" // for getPointerBase
 #include "Tuples/Tuples.h"       // for isTtype
@@ -90,5 +92,22 @@
 // GENERATED END
 
+// --- ParameterizedType
+
+void ParameterizedType::initWithSub( 
+	const ParameterizedType & o, Pass< ForallSubstitutor > & sub 
+) {
+	forall = sub.pass( o.forall );
+}
+
 // --- FunctionType
+
+FunctionType::FunctionType( const FunctionType & o )
+: ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(), 
+  isVarArgs( o.isVarArgs ) {
+	Pass< ForallSubstitutor > sub;
+	initWithSub( o, sub );           // initialize substitution map
+	returns = sub.pass( o.returns ); // apply to return and parameter types
+	params = sub.pass( o.params );
+}
 
 namespace {
@@ -106,4 +125,17 @@
 
 // --- ReferenceToType
+
+void ReferenceToType::initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ) {
+	ParameterizedType::initWithSub( o, sub ); // initialize substitution
+	params = sub.pass( o.params );            // apply to parameters
+}
+
+ReferenceToType::ReferenceToType( const ReferenceToType & o )
+: ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ), 
+  hoistType( o.hoistType ) {
+	Pass< ForallSubstitutor > sub;
+	initWithSub( o, sub );
+}
+
 std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {
 	assertf( aggr(), "Must have aggregate to perform lookup" );
@@ -118,7 +150,7 @@
 // --- StructInstType
 
-StructInstType::StructInstType( const StructDecl * b, CV::Qualifiers q,
-	std::vector<ptr<Attribute>>&& as )
-: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
+StructInstType::StructInstType( 
+	const StructDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
+: ReferenceToType( b->name, q, move(as) ), base( b ) {}
 
 bool StructInstType::isComplete() const { return base ? base->body : false; }
@@ -126,7 +158,7 @@
 // --- UnionInstType
 
-UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q,
-	std::vector<ptr<Attribute>>&& as )
-: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
+UnionInstType::UnionInstType( 
+	const UnionDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
+: ReferenceToType( b->name, q, move(as) ), base( b ) {}
 
 bool UnionInstType::isComplete() const { return base ? base->body : false; }
@@ -134,7 +166,7 @@
 // --- EnumInstType
 
-EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q,
-	std::vector<ptr<Attribute>>&& as )
-: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
+EnumInstType::EnumInstType( 
+	const EnumDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
+: ReferenceToType( b->name, q, move(as) ), base( b ) {}
 
 bool EnumInstType::isComplete() const { return base ? base->body : false; }
@@ -142,9 +174,16 @@
 // --- TraitInstType
 
-TraitInstType::TraitInstType( const TraitDecl * b, CV::Qualifiers q,
-	std::vector<ptr<Attribute>>&& as )
-: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
+TraitInstType::TraitInstType( 
+	const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
+: ReferenceToType( b->name, q, move(as) ), base( b ) {}
 
 // --- TypeInstType
+
+TypeInstType::TypeInstType( const TypeInstType & o ) 
+: ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {
+	Pass< ForallSubstitutor > sub;
+	initWithSub( o, sub );      // initialize substitution
+	base = sub.pass( o.base );  // apply to base type
+}
 
 void TypeInstType::set_base( const TypeDecl * b ) {
@@ -158,5 +197,5 @@
 
 TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q )
-: Type( q ), types( std::move(ts) ), members() {
+: Type( q ), types( move(ts) ), members() {
 	// This constructor is awkward. `TupleType` needs to contain objects so that members can be
 	// named, but members without initializer nodes end up getting constructors, which breaks
