Index: src/Validate/HoistStruct.cpp
===================================================================
--- src/Validate/HoistStruct.cpp	(revision eb7586e994c3710bc421ab2b1c131baf040bf98d)
+++ src/Validate/HoistStruct.cpp	(revision d69f71143d903677ae8e0197f438ba2d7efef849)
@@ -27,4 +27,5 @@
 namespace {
 
+/// Is this a declaration can appear in a struct/union and should be hoisted?
 bool shouldHoist( ast::Decl const * decl ) {
 	return dynamic_cast< ast::StructDecl const * >( decl )
@@ -34,8 +35,35 @@
 }
 
-/* This pass also does some renaming and internal field alteration, but the
- * complex part is the actual hoisting. Hoisted declarations should always
+/// Helper that updates an InstType if the base name could be updated.
+template<typename InstType>
+InstType const * preInstType( InstType const * type ) {
+	assert( type->base );
+	if ( nullptr == type->base->parent ) return type;
+	auto mut = ast::mutate( type );
+	mut->name = mut->base->name;
+	return mut;
+}
+
+/// Update StructInstType and UnionInstType names.
+struct NameUpdater {
+	ast::StructInstType const * previsit( ast::StructInstType const * type ) {
+		return preInstType( type );
+	}
+
+	ast::UnionInstType const * previsit( ast::UnionInstType const * type ) {
+		return preInstType( type );
+	}
+};
+
+ast::Decl const * updateNames( ast::Decl const * decl ) {
+	ast::Pass<NameUpdater> visitor;
+	return decl->accept( visitor );
+}
+
+/* This pass hoists from structs/unions. Hoisted declarations should always
  * appear before the declaration they are hoisted out of and if two types are
  * nested in the same declaration their order should not change.
+ * It also sets up parent relationships, does name mangling of hoisted types
+ * and updates instance types of the hoisted types.
  */
 struct HoistStructCore final :
@@ -96,5 +124,4 @@
 		auto mut = ast::mutate( decl );
 		mut->parent = parent;
-		mut->name = qualifiedName( mut );
 		extendParams( mut->params, parent->params );
 		decl = mut;
@@ -116,4 +143,18 @@
 		}
 	}
+	// Is this a nested type? Then update the name, after the parent's name
+	// has been updated (hence the post visit).
+	if ( mut->parent ) {
+		mut->name = qualifiedName( mut );
+	// Top level type that has hoisted? Then do a second pass subpass to make
+	// sure we update instance type names after the declaration is renamed.
+	} else if ( !declsToAddBefore.empty() ) {
+		for ( ast::ptr<ast::Decl> & member : mut->members ) {
+			member = updateNames( member.get() );
+		}
+		for ( ast::ptr<ast::Decl> & declToAdd : declsToAddBefore ) {
+			declToAdd = updateNames( declToAdd );
+		}
+	}
 	return mut;
 }
@@ -167,12 +208,4 @@
 }
 
-template<typename InstType>
-InstType const * preInstType( InstType const * type ) {
-	assert( type->base );
-	auto mut = ast::mutate( type );
-	mut->name = mut->base->name;
-	return mut;
-}
-
 ast::StructInstType const * HoistStructCore::previsit( ast::StructInstType const * type ) {
 	return preInstType( preCollectionInstType( type ) );
