Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 5684736fd985e020109cb45c53aa88513ff724e3)
+++ src/AST/Convert.cpp	(revision 60aaa51d44506578dbfd9b89b996a9ca2a971c8a)
@@ -16,4 +16,5 @@
 #include "Convert.hpp"
 
+#include <deque>
 #include <unordered_map>
 
@@ -575,5 +576,5 @@
 
 		if ( srcInferred.mode == ast::Expr::InferUnion::Params ) {
-			const ast::InferredParams &srcParams = srcInferred.inferParamsConst();
+			const ast::InferredParams &srcParams = srcInferred.inferParams();
 			for (auto srcParam : srcParams) {
 				tgtInferParams[srcParam.first] = ParamEntry(
@@ -585,5 +586,5 @@
 			}
 		} else if ( srcInferred.mode == ast::Expr::InferUnion::Slots  ) {
-			const ast::ResnSlots &srcSlots = srcInferred.resnSlotsConst();
+			const ast::ResnSlots &srcSlots = srcInferred.resnSlots();
 			for (auto srcSlot : srcSlots) {
 				tgtResnSlots.push_back(srcSlot);
@@ -1413,4 +1414,18 @@
 #	define GET_ACCEPT_V(child, type) \
 		getAcceptV< ast::type, decltype( old->child ) >( old->child )
+	
+	template<typename NewT, typename OldC>
+	std::deque< ast::ptr<NewT> > getAcceptD( OldC& old ) {
+		std::deque< ast::ptr<NewT> > ret;
+		for ( auto a : old ) {
+			a->accept( *this );
+			ret.emplace_back( strict_dynamic_cast< NewT * >(node) );
+			node = nullptr;
+		}
+		return ret;
+	}
+
+#	define GET_ACCEPT_D(child, type) \
+		getAcceptD< ast::type, decltype( old->child ) >( old->child )
 
 	ast::Label make_label(Label* old) {
@@ -2449,5 +2464,5 @@
 
 	virtual void visit( UntypedInitExpr * old ) override final {
-		std::vector<ast::InitAlternative> initAlts;
+		std::deque<ast::InitAlternative> initAlts;
 		for (auto ia : old->initAlts) {
 			initAlts.push_back(ast::InitAlternative(
@@ -2714,5 +2729,5 @@
 		this->node = new ast::Designation(
 			old->location,
-			GET_ACCEPT_V(designators, Expr)
+			GET_ACCEPT_D(designators, Expr)
 		);
 	}
Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision 5684736fd985e020109cb45c53aa88513ff724e3)
+++ src/AST/Expr.cpp	(revision 60aaa51d44506578dbfd9b89b996a9ca2a971c8a)
@@ -163,5 +163,5 @@
 	result = mem->get_type();
 	// substitute aggregate generic parameters into member type
-	genericSubsitution( aggregate->result ).apply( result );
+	genericSubstitution( aggregate->result ).apply( result );
 	// ensure lvalue and appropriate restrictions from aggregate type
 	add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue );
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 5684736fd985e020109cb45c53aa88513ff724e3)
+++ src/AST/Expr.hpp	(revision 60aaa51d44506578dbfd9b89b996a9ca2a971c8a)
@@ -17,4 +17,5 @@
 
 #include <cassert>
+#include <deque>
 #include <map>
 #include <string>
@@ -111,5 +112,5 @@
 		}
 
-		const ResnSlots& resnSlotsConst() const {
+		const ResnSlots& resnSlots() const {
 			if (mode == Slots) {
 				return data.resnSlots;
@@ -128,5 +129,5 @@
 		}
 
-		const InferredParams& inferParamsConst() const {
+		const InferredParams& inferParams() const {
 			if (mode == Params) {
 				return data.inferParams;
@@ -134,4 +135,21 @@
 			assert(!"Mode was not already Params");
 			return *((InferredParams*)nullptr);
+		}
+
+		/// splices other InferUnion into this one. Will fail if one union is in `Slots` mode 
+		/// and the other is in `Params`.
+		void splice( InferUnion && o ) {
+			if ( o.mode == Empty ) return;
+			if ( mode == Empty ) { init_from( o ); return; }
+			assert( mode == o.mode && "attempt to splice incompatible InferUnion" );
+
+			if ( mode == Slots ){
+				data.resnSlots.insert( 
+					data.resnSlots.end(), o.data.resnSlots.begin(), o.data.resnSlots.end() );
+			} else if ( mode == Params ) {
+				for ( const auto & p : o.data.inferParams ) {
+					data.inferParams[p.first] = std::move(p.second);
+				}
+			} else assert(!"invalid mode");
 		}
 	};
@@ -695,7 +713,7 @@
 public:
 	ptr<Expr> expr;
-	std::vector<InitAlternative> initAlts;
-
-	UntypedInitExpr( const CodeLocation & loc, const Expr * e, std::vector<InitAlternative> && as )
+	std::deque<InitAlternative> initAlts;
+
+	UntypedInitExpr( const CodeLocation & loc, const Expr * e, std::deque<InitAlternative> && as )
 	: Expr( loc ), expr( e ), initAlts( std::move(as) ) {}
 
Index: src/AST/GenericSubstitution.cpp
===================================================================
--- src/AST/GenericSubstitution.cpp	(revision 5684736fd985e020109cb45c53aa88513ff724e3)
+++ src/AST/GenericSubstitution.cpp	(revision 60aaa51d44506578dbfd9b89b996a9ca2a971c8a)
@@ -31,7 +31,7 @@
 		TypeSubstitution sub;
 
-		void previsit( const Type * ty ) {
-			assertf( false, "Attempted generic substitution for non-aggregate type: %s",
-				toString( ty ).c_str() );
+		void previsit( const Type * ) {
+			// allow empty substitution for non-generic type
+			visit_children = false;
 		}
 
@@ -40,14 +40,24 @@
 		}
 
-		void previsit( const ReferenceToType * ty ) {
+	private:
+		// make substitution for generic type
+		void makeSub( const ReferenceToType * ty ) {
 			visit_children = false;
-			// build substitution from base parameters
 			const AggregateDecl * aggr = ty->aggr();
 			sub = TypeSubstitution{ aggr->params.begin(), aggr->params.end(), ty->params.begin() };
+		}
+
+	public:
+		void previsit( const StructInstType * ty ) {
+			makeSub( ty );
+		}
+
+		void previsit( const UnionInstType * ty ) {
+			makeSub( ty );
 		}
 	};
 }
 
-TypeSubstitution genericSubsitution( const Type * ty ) {
+TypeSubstitution genericSubstitution( const Type * ty ) {
 	Pass<GenericSubstitutionBuilder> builder;
 	maybe_accept( ty, builder );
Index: src/AST/GenericSubstitution.hpp
===================================================================
--- src/AST/GenericSubstitution.hpp	(revision 5684736fd985e020109cb45c53aa88513ff724e3)
+++ src/AST/GenericSubstitution.hpp	(revision 60aaa51d44506578dbfd9b89b996a9ca2a971c8a)
@@ -22,5 +22,5 @@
 class Type;
 
-TypeSubstitution genericSubsitution( const Type * );
+TypeSubstitution genericSubstitution( const Type * );
 
 }
Index: src/AST/Init.hpp
===================================================================
--- src/AST/Init.hpp	(revision 5684736fd985e020109cb45c53aa88513ff724e3)
+++ src/AST/Init.hpp	(revision 60aaa51d44506578dbfd9b89b996a9ca2a971c8a)
@@ -16,4 +16,5 @@
 #pragma once
 
+#include <deque>
 #include <utility>        // for move
 #include <vector>
@@ -35,7 +36,7 @@
 class Designation final : public ParseNode {
 public:
-	std::vector<ptr<Expr>> designators;
+	std::deque<ptr<Expr>> designators;
 
-	Designation( const CodeLocation& loc, std::vector<ptr<Expr>>&& ds = {} )
+	Designation( const CodeLocation& loc, std::deque<ptr<Expr>>&& ds = {} )
 	: ParseNode( loc ), designators( std::move(ds) ) {}
 
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision 5684736fd985e020109cb45c53aa88513ff724e3)
+++ src/AST/Node.hpp	(revision 60aaa51d44506578dbfd9b89b996a9ca2a971c8a)
@@ -154,10 +154,10 @@
 
 	template< enum Node::ref_type o_ref_t >
-	ptr_base( const ptr_base<node_t, o_ref_t> & o ) : node(o.node) {
+	ptr_base( const ptr_base<node_t, o_ref_t> & o ) : node(o.get()) {
 		if( node ) _inc(node);
 	}
 
 	template< enum Node::ref_type o_ref_t >
-	ptr_base( ptr_base<node_t, o_ref_t> && o ) : node(o.node) {
+	ptr_base( ptr_base<node_t, o_ref_t> && o ) : node(o.get()) {
 		if( node ) _inc(node);
 	}
@@ -184,5 +184,5 @@
 	template< enum Node::ref_type o_ref_t >
 	ptr_base & operator=( const ptr_base<node_t, o_ref_t> & o ) {
-		assign(o.node);
+		assign(o.get());
 		return *this;
 	}
@@ -190,5 +190,5 @@
 	template< enum Node::ref_type o_ref_t >
 	ptr_base & operator=( ptr_base<node_t, o_ref_t> && o ) {
-		assign(o.node);
+		assign(o.get());
 		return *this;
 	}
@@ -228,5 +228,4 @@
 	void _check() const;
 
-protected:
 	const node_t * node;
 };
Index: src/AST/porting.md
===================================================================
--- src/AST/porting.md	(revision 5684736fd985e020109cb45c53aa88513ff724e3)
+++ src/AST/porting.md	(revision 60aaa51d44506578dbfd9b89b996a9ca2a971c8a)
@@ -238,4 +238,5 @@
     * also now returns `const AggregateDecl *`
 * `genericSubstitution()` moved to own visitor in `AST/GenericSubstitution.hpp`
+  * subsumes old `makeGenericSubstitution()`
 
 `BasicType`
