Index: libcfa/src/concurrency/locks.hfa
===================================================================
--- libcfa/src/concurrency/locks.hfa	(revision 61a20af043ec0a53cd1f0a9780a7e6405e34db62)
+++ libcfa/src/concurrency/locks.hfa	(revision 576aadb6340fb78139a0b6ee9c874f97e91cbb73)
@@ -32,6 +32,4 @@
 #include "select.hfa"
 
-#include <fstream.hfa>
-
 // futex headers
 #include <linux/futex.h>      /* Definition of FUTEX_* constants */
Index: libcfa/src/containers/lockfree.hfa
===================================================================
--- libcfa/src/containers/lockfree.hfa	(revision 61a20af043ec0a53cd1f0a9780a7e6405e34db62)
+++ libcfa/src/containers/lockfree.hfa	(revision 576aadb6340fb78139a0b6ee9c874f97e91cbb73)
@@ -199,9 +199,12 @@
 
 forall( T & )
+struct LinkData {
+	T * volatile top;								// pointer to stack top
+	uintptr_t count;								// count each push
+};
+
+forall( T & )
 union Link {
-	struct {											// 32/64-bit x 2
-		T * volatile top;								// pointer to stack top
-		uintptr_t count;								// count each push
-	};
+	LinkData(T) data;
 	#if __SIZEOF_INT128__ == 16
 	__int128											// gcc, 128-bit integer
@@ -220,10 +223,10 @@
 		void ?{}( StackLF(T) & this ) with(this) { stack.atom = 0; }
 
-		T * top( StackLF(T) & this ) with(this) { return stack.top; }
+		T * top( StackLF(T) & this ) with(this) { return stack.data.top; }
 
 		void push( StackLF(T) & this, T & n ) with(this) {
 			*( &n )`next = stack;						// atomic assignment unnecessary, or use CAA
 			for () {									// busy wait
-			  if ( __atomic_compare_exchange_n( &stack.atom, &( &n )`next->atom, (Link(T))@{ {&n, ( &n )`next->count + 1} }.atom, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ) break; // attempt to update top node
+				if ( __atomic_compare_exchange_n( &stack.atom, &( &n )`next->atom, (Link(T))@{ (LinkData(T))@{ &n, ( &n )`next->data.count + 1} }.atom, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ) break; // attempt to update top node
 			} // for
 		} // push
@@ -232,6 +235,7 @@
 			Link(T) t @= stack;							// atomic assignment unnecessary, or use CAA
 			for () {									// busy wait
-			  if ( t.top == 0p ) return 0p;				// empty stack ?
-			  if ( __atomic_compare_exchange_n( &stack.atom, &t.atom, (Link(T))@{ {( t.top )`next->top, t.count} }.atom, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ) return t.top; // attempt to update top node
+				if ( t.data.top == 0p ) return 0p;				// empty stack ?
+				Link(T) * next = ( t.data.top )`next;
+				if ( __atomic_compare_exchange_n( &stack.atom, &t.atom, (Link(T))@{ (LinkData(T))@{ next->data.top, t.data.count } }.atom, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ) return t.data.top; // attempt to update top node
 			} // for
 		} // pop
@@ -239,11 +243,13 @@
 		bool unsafe_remove( StackLF(T) & this, T * node ) with(this) {
 			Link(T) * link = &stack;
-			for() {
-				T * next = link->top;
-				if( next == node ) {
-					link->top = ( node )`next->top;
+			for () {
+				// TODO: Avoiding some problems with double fields access.
+				LinkData(T) * data = &link->data;
+				T * next = (T *)&(*data).top;
+				if ( next == node ) {
+					data->top = ( node )`next->data.top;
 					return true;
 				}
-				if( next == 0p ) return false;
+				if ( next == 0p ) return false;
 				link = ( next )`next;
 			}
Index: src/AST/DeclReplacer.hpp
===================================================================
--- src/AST/DeclReplacer.hpp	(revision 61a20af043ec0a53cd1f0a9780a7e6405e34db62)
+++ src/AST/DeclReplacer.hpp	(revision 576aadb6340fb78139a0b6ee9c874f97e91cbb73)
@@ -18,21 +18,26 @@
 #include <unordered_map>
 
-#include "Node.hpp"
+namespace ast {
+	class DeclWithType;
+	class Expr;
+	class Node;
+	class TypeDecl;
+}
 
 namespace ast {
-	class DeclWithType;
-	class TypeDecl;
-	class Expr;
 
-	namespace DeclReplacer {
-		using DeclMap = std::unordered_map< const DeclWithType *, const DeclWithType * >;
-		using TypeMap = std::unordered_map< const TypeDecl *, const TypeDecl * >;
-		using ExprMap = std::unordered_map< const DeclWithType *, const Expr * >;
+namespace DeclReplacer {
 
-		const Node * replace( const Node * node, const DeclMap & declMap, bool debug = false );
-		const Node * replace( const Node * node, const TypeMap & typeMap, bool debug = false );
-		const Node * replace( const Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
-		const Node * replace( const Node * node, const ExprMap & exprMap);
-	}
+using DeclMap = std::unordered_map< const DeclWithType *, const DeclWithType * >;
+using TypeMap = std::unordered_map< const TypeDecl *, const TypeDecl * >;
+using ExprMap = std::unordered_map< const DeclWithType *, const Expr * >;
+
+const Node * replace( const Node * node, const DeclMap & declMap, bool debug = false );
+const Node * replace( const Node * node, const TypeMap & typeMap, bool debug = false );
+const Node * replace( const Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
+const Node * replace( const Node * node, const ExprMap & exprMap);
+
+}
+
 }
 
Index: src/AST/Util.cpp
===================================================================
--- src/AST/Util.cpp	(revision 61a20af043ec0a53cd1f0a9780a7e6405e34db62)
+++ src/AST/Util.cpp	(revision 576aadb6340fb78139a0b6ee9c874f97e91cbb73)
@@ -83,4 +83,23 @@
 }
 
+/// Check that the MemberExpr has an aggregate type and matching member.
+void memberMatchesAggregate( const MemberExpr * expr ) {
+	const Type * aggrType = expr->aggregate->result->stripReferences();
+	const AggregateDecl * decl = nullptr;
+	if ( auto inst = dynamic_cast<const StructInstType *>( aggrType ) ) {
+		decl = inst->base;
+	} else if ( auto inst = dynamic_cast<const UnionInstType *>( aggrType ) ) {
+		decl = inst->base;
+	}
+	assertf( decl, "Aggregate of member not correct type." );
+
+	for ( auto aggrMember : decl->members ) {
+		if ( expr->member == aggrMember ) {
+			return;
+		}
+	}
+	assertf( false, "Member not found." );
+}
+
 struct InvariantCore {
 	// To save on the number of visits: this is a kind of composed core.
@@ -108,4 +127,9 @@
 	}
 
+	void previsit( const MemberExpr * node ) {
+		previsit( (const ParseNode *)node );
+		memberMatchesAggregate( node );
+	}
+
 	void postvisit( const Node * node ) {
 		no_strong_cycles.postvisit( node );
Index: src/Validate/HoistStruct.cpp
===================================================================
--- src/Validate/HoistStruct.cpp	(revision 61a20af043ec0a53cd1f0a9780a7e6405e34db62)
+++ src/Validate/HoistStruct.cpp	(revision 576aadb6340fb78139a0b6ee9c874f97e91cbb73)
@@ -18,6 +18,8 @@
 #include <sstream>
 
+#include "AST/DeclReplacer.hpp"
 #include "AST/Pass.hpp"
 #include "AST/TranslationUnit.hpp"
+#include "AST/Vector.hpp"
 
 namespace Validate {
@@ -51,4 +53,6 @@
 	template<typename AggrDecl>
 	AggrDecl const * postAggregate( AggrDecl const * );
+	template<typename InstType>
+	InstType const * preCollectionInstType( InstType const * type );
 
 	ast::AggregateDecl const * parent = nullptr;
@@ -66,4 +70,22 @@
 	qualifiedName( decl, ss );
 	return ss.str();
+}
+
+void extendParams( ast::vector<ast::TypeDecl> & dstParams,
+		ast::vector<ast::TypeDecl> const & srcParams ) {
+	if ( srcParams.empty() ) return;
+
+	ast::DeclReplacer::TypeMap newToOld;
+	ast::vector<ast::TypeDecl> params;
+	for ( ast::ptr<ast::TypeDecl> const & srcParam : srcParams ) {
+		ast::TypeDecl * dstParam = ast::deepCopy( srcParam.get() );
+		dstParam->init = nullptr;
+		newToOld.emplace( srcParam, dstParam );
+		for ( auto assertion : dstParam->assertions ) {
+			assertion = ast::DeclReplacer::replace( assertion, newToOld );
+		}
+		params.emplace_back( dstParam );
+	}
+	spliceBegin( dstParams, params );
 }
 
@@ -74,9 +96,9 @@
 		mut->parent = parent;
 		mut->name = qualifiedName( mut );
-		return mut;
-	} else {
-		GuardValue( parent ) = decl;
-		return decl;
-	}
+		extendParams( mut->params, parent->params );
+		decl = mut;
+	}
+	GuardValue( parent ) = decl;
+	return decl;
 }
 
@@ -112,4 +134,36 @@
 }
 
+ast::AggregateDecl const * commonParent(
+		ast::AggregateDecl const * lhs, ast::AggregateDecl const * rhs ) {
+	for ( auto outer = lhs ; outer ; outer = outer->parent ) {
+		for ( auto inner = rhs ; inner ; inner = inner->parent ) {
+			if ( outer == inner ) {
+				return outer;
+			}
+		}
+	}
+	return nullptr;
+}
+
+template<typename InstType>
+InstType const * HoistStructCore::preCollectionInstType( InstType const * type ) {
+    if ( !type->base->parent ) return type;
+    if ( type->base->params.empty() ) return type;
+
+    InstType * mut = ast::mutate( type );
+    ast::AggregateDecl const * parent =
+        commonParent( this->parent, mut->base->parent );
+    assert( parent );
+
+    std::vector<ast::ptr<ast::Expr>> args;
+    for ( const ast::ptr<ast::TypeDecl> & param : parent->params ) {
+        args.emplace_back( new ast::TypeExpr( param->location,
+            new ast::TypeInstType( param )
+        ) );
+    }
+    spliceBegin( mut->params, args );
+    return mut;
+}
+
 template<typename InstType>
 InstType const * preInstType( InstType const * type ) {
@@ -121,9 +175,9 @@
 
 ast::StructInstType const * HoistStructCore::previsit( ast::StructInstType const * type ) {
-	return preInstType( type );
+	return preInstType( preCollectionInstType( type ) );
 }
 
 ast::UnionInstType const * HoistStructCore::previsit( ast::UnionInstType const * type ) {
-	return preInstType( type );
+	return preInstType( preCollectionInstType( type ) );
 }
 
Index: tests/concurrency/waituntil/locks.cfa
===================================================================
--- tests/concurrency/waituntil/locks.cfa	(revision 61a20af043ec0a53cd1f0a9780a7e6405e34db62)
+++ tests/concurrency/waituntil/locks.cfa	(revision 576aadb6340fb78139a0b6ee9c874f97e91cbb73)
@@ -2,4 +2,5 @@
 #include <thread.hfa>
 #include <locks.hfa>
+#include <fstream.hfa>
 #include <mutex_stmt.hfa>
 
