Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision ff03f5cd8341dad2144710b51063ff0071ec6107)
+++ src/SymTab/Indexer.cc	(revision 67cf18c3e5b8ae6e923fa93e69357ba5e746bf57)
@@ -285,4 +285,5 @@
 		addType( typeDecl );
 		acceptAll( typeDecl->get_assertions(), *this );
+		acceptNewScope( typeDecl->get_init(), *this );
 	}
 
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision ff03f5cd8341dad2144710b51063ff0071ec6107)
+++ src/SymTab/Validate.cc	(revision 67cf18c3e5b8ae6e923fa93e69357ba5e746bf57)
@@ -506,4 +506,5 @@
 	void LinkReferenceToTypes::visit( StructDecl *structDecl ) {
 		// visit struct members first so that the types of self-referencing members are updated properly
+		// xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and and their defaults)
 		Parent::visit( structDecl );
 		if ( ! structDecl->get_members().empty() ) {
@@ -844,4 +845,29 @@
 		if ( params != NULL ) {
 			std::list< Expression * > & args = inst->get_parameters();
+
+			// insert defaults arguments when a type argument is missing (currently only supports missing arguments at the end of the list).
+			// A substitution is used to ensure that defaults are replaced correctly, e.g.,
+			//   forall(otype T, otype alloc = heap_allocator(T)) struct vector;
+			//   vector(int) v;
+			// after insertion of default values becomes
+			//   vector(int, heap_allocator(T))
+			// and the substitution is built with T=int so that after substitution, the result is
+			//   vector(int, heap_allocator(int))
+			TypeSubstitution sub;
+			auto paramIter = params->begin();
+			for ( size_t i = 0; paramIter != params->end(); ++paramIter, ++i ) {
+				if ( i < args.size() ) {
+					TypeExpr * expr = safe_dynamic_cast< TypeExpr * >( *std::next( args.begin(), i ) );
+					sub.add( (*paramIter)->get_name(), expr->get_type()->clone() );
+				} else if ( i == args.size() ) {
+					Type * defaultType = (*paramIter)->get_init();
+					if ( defaultType ) {
+						args.push_back( new TypeExpr( defaultType->clone() ) );
+						sub.add( (*paramIter)->get_name(), defaultType->clone() );
+					}
+				}
+			}
+
+			sub.apply( inst );
 			if ( args.size() < params->size() ) throw SemanticError( "Too few type arguments in generic type ", inst );
 			if ( args.size() > params->size() ) throw SemanticError( "Too many type arguments in generic type ", inst );
