Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision 09c72d5b6600e44f191c62a215942254161db898)
+++ src/SynTree/Expression.cc	(revision 0f9e6b20d0ceb4a6228ca16ca5917313cb62a6af)
@@ -345,25 +345,11 @@
 }
 
-namespace {
-	TypeSubstitution makeSub( Type * t ) {
-		if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( t ) ) {
-			return makeSub( refType->get_base() );
-		} else if ( StructInstType * aggInst = dynamic_cast< StructInstType * >( t ) ) {
-			return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->parameters.begin() );
-		} else if ( UnionInstType * aggInst = dynamic_cast< UnionInstType * >( t ) ) {
-			return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->parameters.begin() );
-		} else {
-			assertf( false, "makeSub expects struct or union type for aggregate, but got: %s", toString( t ).c_str() );
-		}
-	}
-}
-
-
 MemberExpr::MemberExpr( DeclarationWithType *member, Expression *aggregate ) :
 		Expression(), member(member), aggregate(aggregate) {
 	assert( member );
 	assert( aggregate );
-
-	TypeSubstitution sub( makeSub( aggregate->get_result() ) );
+	assert( aggregate->result );
+
+	TypeSubstitution sub = aggregate->result->genericSubstitution();
 	Type * res = member->get_type()->clone();
 	sub.apply( res );
Index: src/SynTree/ReferenceToType.cc
===================================================================
--- src/SynTree/ReferenceToType.cc	(revision 09c72d5b6600e44f191c62a215942254161db898)
+++ src/SynTree/ReferenceToType.cc	(revision 0f9e6b20d0ceb4a6228ca16ca5917313cb62a6af)
@@ -14,13 +14,14 @@
 //
 
-#include <cassert>           // for assert
-#include <list>              // for list, _List_const_iterator, list<>::cons...
-#include <ostream>           // for operator<<, basic_ostream, ostream, endl
-#include <string>            // for string, operator<<, char_traits, operator==
-
-#include "Common/utility.h"  // for printAll, cloneAll, deleteAll
-#include "Declaration.h"     // for StructDecl, UnionDecl, EnumDecl, Declara...
-#include "Expression.h"      // for Expression
-#include "Type.h"            // for TypeInstType, StructInstType, UnionInstType
+#include <cassert>            // for assert
+#include <list>               // for list, _List_const_iterator, list<>::cons...
+#include <ostream>            // for operator<<, basic_ostream, ostream, endl
+#include <string>             // for string, operator<<, char_traits, operator==
+
+#include "Common/utility.h"   // for printAll, cloneAll, deleteAll
+#include "Declaration.h"      // for StructDecl, UnionDecl, EnumDecl, Declara...
+#include "Expression.h"       // for Expression
+#include "Type.h"             // for TypeInstType, StructInstType, UnionInstType
+#include "TypeSubstitution.h" // for TypeSubstitution
 
 class Attribute;
@@ -63,4 +64,9 @@
 std::string StructInstType::typeString() const { return "struct"; }
 
+const std::list<TypeDecl*>* StructInstType::get_baseParameters() const {
+	if ( ! baseStruct ) return nullptr;
+	return &baseStruct->get_parameters();
+}
+
 std::list<TypeDecl*>* StructInstType::get_baseParameters() {
 	if ( ! baseStruct ) return nullptr;
@@ -71,4 +77,8 @@
 
 AggregateDecl * StructInstType::getAggr() { return baseStruct; }
+
+TypeSubstitution StructInstType::genericSubstitution() const {
+	return TypeSubstitution( get_baseParameters()->begin(), get_baseParameters()->end(), parameters.begin() );
+}
 
 void StructInstType::lookup( const std::string &name, std::list< Declaration* > &foundDecls ) const {
@@ -102,7 +112,16 @@
 }
 
+const std::list< TypeDecl * > * UnionInstType::get_baseParameters() const {
+	if ( ! baseUnion ) return nullptr;
+	return &baseUnion->get_parameters();
+}
+
 bool UnionInstType::isComplete() const { return baseUnion ? baseUnion->has_body() : false; }
 
 AggregateDecl * UnionInstType::getAggr() { return baseUnion; }
+
+TypeSubstitution UnionInstType::genericSubstitution() const {
+	return TypeSubstitution( get_baseParameters()->begin(), get_baseParameters()->end(), parameters.begin() );
+}
 
 void UnionInstType::lookup( const std::string &name, std::list< Declaration* > &foundDecls ) const {
Index: src/SynTree/ReferenceType.cc
===================================================================
--- src/SynTree/ReferenceType.cc	(revision 09c72d5b6600e44f191c62a215942254161db898)
+++ src/SynTree/ReferenceType.cc	(revision 0f9e6b20d0ceb4a6228ca16ca5917313cb62a6af)
@@ -16,4 +16,5 @@
 #include "Type.h"
 #include "Expression.h"
+#include "TypeSubstitution.h"
 #include "Common/utility.h"
 
@@ -35,4 +36,6 @@
 }
 
+TypeSubstitution ReferenceType::genericSubstitution() const { return base->genericSubstitution(); }
+
 void ReferenceType::print( std::ostream &os, Indenter indent ) const {
 	Type::print( os, indent );
Index: src/SynTree/Type.cc
===================================================================
--- src/SynTree/Type.cc	(revision 09c72d5b6600e44f191c62a215942254161db898)
+++ src/SynTree/Type.cc	(revision 0f9e6b20d0ceb4a6228ca16ca5917313cb62a6af)
@@ -15,9 +15,10 @@
 #include "Type.h"
 
-#include "Attribute.h"               // for Attribute
-#include "Common/utility.h"          // for cloneAll, deleteAll, printAll
-#include "InitTweak/InitTweak.h"     // for getPointerBase
-#include "SynTree/BaseSyntaxNode.h"  // for BaseSyntaxNode
-#include "SynTree/Declaration.h"     // for TypeDecl
+#include "Attribute.h"                // for Attribute
+#include "Common/utility.h"           // for cloneAll, deleteAll, printAll
+#include "InitTweak/InitTweak.h"      // for getPointerBase
+#include "SynTree/BaseSyntaxNode.h"   // for BaseSyntaxNode
+#include "SynTree/Declaration.h"      // for TypeDecl
+#include "SynTree/TypeSubstitution.h" // for TypeSubstitution
 
 using namespace std;
@@ -81,4 +82,6 @@
 int Type::referenceDepth() const { return 0; }
 
+TypeSubstitution Type::genericSubstitution() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
+
 void Type::print( std::ostream &os, Indenter indent ) const {
 	if ( ! forall.empty() ) {
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision 09c72d5b6600e44f191c62a215942254161db898)
+++ src/SynTree/Type.h	(revision 0f9e6b20d0ceb4a6228ca16ca5917313cb62a6af)
@@ -178,5 +178,7 @@
 	virtual bool isComplete() const { return true; }
 
-	virtual AggregateDecl * getAggr() {	assertf( false, "Non-aggregate type: %s", toString( this ).c_str() ); }
+	virtual AggregateDecl * getAggr() { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
+
+	virtual TypeSubstitution genericSubstitution() const;
 
 	virtual Type *clone() const = 0;
@@ -329,4 +331,6 @@
 	virtual unsigned size() const override { return base->size(); }
 
+	virtual TypeSubstitution genericSubstitution() const override;
+
 	virtual ReferenceType *clone() const override { return new ReferenceType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
@@ -406,8 +410,11 @@
 	/// Accesses generic parameters of base struct (NULL if none such)
 	std::list<TypeDecl*> * get_baseParameters();
+	const std::list<TypeDecl*> * get_baseParameters() const;
 
 	virtual bool isComplete() const override;
 
 	virtual AggregateDecl * getAggr() override;
+
+	virtual TypeSubstitution genericSubstitution() const override;
 
 	/// Looks up the members of this struct named "name" and places them into "foundDecls".
@@ -439,9 +446,12 @@
 
 	/// Accesses generic parameters of base union (NULL if none such)
-	std::list< TypeDecl * > * get_baseParameters();
+	std::list<TypeDecl*> * get_baseParameters();
+	const std::list<TypeDecl*> * get_baseParameters() const;
 
 	virtual bool isComplete() const override;
 
 	virtual AggregateDecl * getAggr() override;
+
+	virtual TypeSubstitution genericSubstitution() const override;
 
 	/// looks up the members of this union named "name" and places them into "foundDecls"
