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`
Index: src/ResolvExpr/CurrentObject.cc
===================================================================
--- src/ResolvExpr/CurrentObject.cc	(revision 5684736fd985e020109cb45c53aa88513ff724e3)
+++ src/ResolvExpr/CurrentObject.cc	(revision 60aaa51d44506578dbfd9b89b996a9ca2a971c8a)
@@ -16,4 +16,5 @@
 #include <stddef.h>                    // for size_t
 #include <cassert>                     // for assertf, assert, safe_dynamic_...
+#include <deque>
 #include <iostream>                    // for ostream, operator<<, basic_ost...
 #include <stack>                       // for stack
@@ -21,6 +22,8 @@
 
 #include "AST/Expr.hpp"                // for InitAlternative
+#include "AST/GenericSubstitution.hpp" // for genericSubstitution
 #include "AST/Init.hpp"                // for Designation
 #include "AST/Node.hpp"                // for readonly
+#include "AST/Type.hpp"
 #include "Common/Indenter.h"           // for Indenter, operator<<
 #include "Common/SemanticError.h"      // for SemanticError
@@ -583,19 +586,6 @@
 
 namespace ast {
-
-	/// Iterates members of a type by initializer
-	class MemberIterator {
-	public:
-		virtual ~MemberIterator() {}
-
-		/// retrieve the list of possible (Type,Designation) pairs for the current position in the 
-		/// current object
-		virtual std::vector< InitAlternative > operator* () const = 0;
-	
-	protected:
-		/// helper for operator*; aggregates must add designator to each init alternative, but 
-		/// adding designators in operator* creates duplicates
-		virtual std::vector< InitAlternative > first() const = 0;
-	};
+	/// create a new MemberIterator that traverses a type correctly
+	MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type );
 
 	/// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry
@@ -606,8 +596,28 @@
 		SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
 
-		std::vector< InitAlternative > operator* () const override { return first(); }
-
-	protected:
-		std::vector< InitAlternative > first() const override {
+		void setPosition( 
+			std::deque< ptr< Expr > >::const_iterator begin, 
+			std::deque< ptr< Expr > >::const_iterator end
+		) override {
+			if ( begin != end ) {
+				SemanticError( location, "Un-designated initializer given non-empty designator" );
+			}
+		}
+
+		std::deque< InitAlternative > operator* () const override { return first(); }
+
+		operator bool() const override { return type; }
+
+		SimpleIterator & bigStep() override { return smallStep(); }
+		SimpleIterator & smallStep() override {
+			type = nullptr;  // empty on increment because no members
+			return *this;
+		}
+
+		const Type * getType() override { return type; }
+
+		const Type * getNext() override { return type; }
+
+		std::deque< InitAlternative > first() const override {
 			if ( type ) return { InitAlternative{ type, new Designation{ location } } };
 			return {};
@@ -615,12 +625,366 @@
 	};
 
+	/// Iterates array types
+	class ArrayIterator final : public MemberIterator {
+		CodeLocation location;
+		readonly< ArrayType > array = nullptr;
+		readonly< Type > base = nullptr;
+		size_t index = 0;
+		size_t size = 0;
+		std::unique_ptr< MemberIterator > memberIter;
+
+		void setSize( const Expr * expr ) {
+			auto res = eval(expr);
+			if ( ! res.second ) {
+				SemanticError( location, 
+					toString("Array designator must be a constant expression: ", expr ) );
+			}
+			size = res.first;
+		}
+
+	public:
+		ArrayIterator( const CodeLocation & loc, const ArrayType * at ) 
+		: location( loc ), array( at ), base( at->base ) {
+			PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
+			memberIter.reset( createMemberIterator( loc, base ) );
+			if ( at->isVarLen ) {
+				SemanticError( location, at, "VLA initialization does not support @=: " );
+			}
+			setSize( at->dimension );
+		}
+
+		void setPosition( const Expr * expr ) {
+			// need to permit integer-constant-expressions, including: integer constants, 
+			// enumeration constants, character constants, sizeof expressions, alignof expressions, 
+			// cast expressions
+			if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
+				try {
+					index = constExpr->intValue();
+				} catch ( SemanticErrorException & ) {
+					SemanticError( expr, 
+						"Constant expression of non-integral type in array designator: " );
+				}
+			} else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) {
+				setPosition( castExpr->arg );
+			} else if ( 
+				dynamic_cast< const SizeofExpr * >( expr ) 
+				|| dynamic_cast< const AlignofExpr * >( expr ) 
+			) {
+				index = 0;
+			} else {
+				assertf( false, 
+					"bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
+			}
+		}
+
+		void setPosition( 
+			std::deque< ptr< Expr > >::const_iterator begin, 
+			std::deque< ptr< Expr > >::const_iterator end
+		) override {
+			if ( begin == end ) return;
+
+			setPosition( *begin );
+			memberIter->setPosition( ++begin, end );
+		}
+
+		std::deque< InitAlternative > operator* () const override { return first(); }
+
+		operator bool() const override { return index < size; }
+
+		ArrayIterator & bigStep() override {
+			PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
+			++index;
+			memberIter.reset( index < size ? createMemberIterator( location, base ) : nullptr );
+			return *this;
+		}
+
+		ArrayIterator & smallStep() override {
+			PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
+			if ( memberIter ) {
+				PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
+				memberIter->smallStep();
+				if ( *memberIter ) {
+					PRINT( std::cerr << "has valid member iter" << std::endl; )
+					return *this;
+				}
+			}
+			return bigStep();
+		}
+
+		const Type * getType() override { return array; }
+
+		const Type * getNext() override { return base; }
+
+		std::deque< InitAlternative > first() const override {
+			PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
+			if ( memberIter && *memberIter ) {
+				std::deque< InitAlternative > ret = memberIter->first();
+				for ( InitAlternative & alt : ret ) {
+					alt.designation.get_and_mutate()->designators.emplace_front(
+						ConstantExpr::from_ulong( location, index ) );
+				}
+				return ret;
+			}
+			return {};
+		}
+	};
+
+	class AggregateIterator : public MemberIterator {
+	protected:
+		using MemberList = std::vector< ptr< Decl > >;
+
+		CodeLocation location;
+		std::string kind;  // for debug
+		std::string name;
+		const Type * inst;
+		const MemberList & members;
+		MemberList::const_iterator curMember;
+		bool atbegin = true;  // false at first {small,big}Step
+		const Type * curType = nullptr;
+		std::unique_ptr< MemberIterator > memberIter = nullptr;
+		TypeSubstitution sub;
+
+		bool init() {
+			PRINT( std::cerr << "--init()--" << members.size() << std::endl; )
+			if ( curMember != members.end() ) {
+				if ( auto field = curMember->as< ObjectDecl >() ) {
+					PRINT( std::cerr << "incremented to field: " << field << std::endl; )
+					curType = field->get_type();
+					memberIter.reset( createMemberIterator( location, curType ) );
+					return true;
+				}
+			}
+			return false;
+		}
+
+		AggregateIterator( 
+			const CodeLocation & loc, const std::string k, const std::string & n, const Type * i, 
+			const MemberList & ms )
+		: location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ), 
+		  sub( genericSubstitution( i ) ) {
+			PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
+			init();
+		}
+
+	public:
+		void setPosition( 
+			std::deque< ptr< Expr > >::const_iterator begin, 
+			std::deque< ptr< Expr > >::const_iterator end
+		) final {
+			if ( begin == end ) return;
+
+			if ( auto varExpr = begin->as< VariableExpr >() ) {
+				for ( curMember = members.begin(); curMember != members.end(); ++curMember ) {
+					if ( *curMember != varExpr->var ) continue;
+
+					++begin;
+
+					memberIter.reset( createMemberIterator( location, varExpr->result ) );
+					curType = varExpr->result;
+					atbegin = curMember == members.begin() && begin == end;
+					memberIter->setPosition( begin, end );
+					return;
+				}
+				assertf( false, 
+					"could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
+			} else {
+				assertf( false, 
+					"bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() );
+			}
+		}
+
+		std::deque< InitAlternative > operator* () const final {
+			if ( memberIter && *memberIter ) {
+				std::deque< InitAlternative > ret = memberIter->first();
+				PRINT( std::cerr << "sub: " << sub << std::endl; )
+				for ( InitAlternative & alt : ret ) {
+					PRINT( std::cerr << "iterating and adding designators" << std::endl; )
+					alt.designation.get_and_mutate()->designators.emplace_front(
+						new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
+					// need to substitute for generic types so that casts are to concrete types
+					PRINT( std::cerr << "  type is: " << alt.type; )
+					sub.apply( alt.type ); // also apply to designation??
+					PRINT( std::cerr << " ==> " << alt.type << std::endl; )
+				}
+				return ret;
+			}
+			return {};
+		}
+
+		AggregateIterator & smallStep() final {
+			PRINT( std::cerr << "smallStep in " << kind << std::endl; )
+			atbegin = false;
+			if ( memberIter ) {
+				PRINT( std::cerr << "has member iter, incrementing..." << std::endl; )
+				memberIter->smallStep();
+				if ( *memberIter ) {
+					PRINT( std::cerr << "success!" << std::endl; )
+					return *this;
+				}
+			}
+			return bigStep();
+		}
+
+		AggregateIterator & bigStep() override = 0;
+
+		const Type * getType() final { return inst; }
+
+		const Type * getNext() final {
+			return ( memberIter && *memberIter ) ? memberIter->getType() : nullptr;
+		}
+
+		std::deque< InitAlternative > first() const final {
+			std::deque< InitAlternative > ret;
+			PRINT( std::cerr << "first " << kind << std::endl; )
+			if ( memberIter && *memberIter ) {
+				PRINT( std::cerr << "adding children" << std::endl; )
+				ret = memberIter->first();
+				for ( InitAlternative & alt : ret ) {
+					PRINT( std::cerr << "iterating and adding designators" << std::endl; )
+					alt.designation.get_and_mutate()->designators.emplace_front( 
+						new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
+				}
+			}
+			if ( atbegin ) {
+				// only add self if at the very beginning of the structure
+				PRINT( std::cerr << "adding self" << std::endl; )
+				ret.emplace_front( inst, new Designation{ location } );
+			}
+			return ret;
+		}
+	};
+
+	class StructIterator final : public AggregateIterator {
+	public:
+		StructIterator( const CodeLocation & loc, const StructInstType * inst )
+		: AggregateIterator( loc, "StructIterator", inst->name, inst, inst->base->members ) {}
+
+		operator bool() const override {
+			return curMember != members.end() || (memberIter && *memberIter);
+		}
+
+		StructIterator & bigStep() override {
+			PRINT( std::cerr << "bigStep in " << kind << std::endl; )
+			atbegin = false;
+			memberIter = nullptr;
+			curType = nullptr;
+			while ( curMember != members.end() ) {
+				++curMember;
+				if ( init() ) return *this;
+			}
+			return *this;
+		}
+	};
+
+	class UnionIterator final : public AggregateIterator {
+	public:
+		UnionIterator( const CodeLocation & loc, const UnionInstType * inst )
+		: AggregateIterator( loc, "UnionIterator", inst->name, inst, inst->base->members ) {}
+
+		operator bool() const override { return memberIter && *memberIter; }
+
+		UnionIterator & bigStep() override {
+			// unions only initialize one member
+			PRINT( std::cerr << "bigStep in " << kind << std::endl; )
+			atbegin = false;
+			memberIter = nullptr;
+			curType = nullptr;
+			curMember = members.end();
+			return *this;
+		}
+	};
+
+	class TupleIterator final : public AggregateIterator {
+	public:
+		TupleIterator( const CodeLocation & loc, const TupleType * inst ) 
+		: AggregateIterator( 
+			loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members 
+		) {}
+
+		operator bool() const override {
+			return curMember != members.end() || (memberIter && *memberIter);
+		}
+
+		TupleIterator & bigStep() override {
+			PRINT( std::cerr << "bigStep in " << kind << std::endl; )
+			atbegin = false;
+			memberIter = nullptr;
+			curType = nullptr;
+			while ( curMember != members.end() ) {
+				++curMember;
+				if ( init() ) return *this;
+			}
+			return *this;
+		}
+	};
+
+	MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) {
+		if ( auto aggr = dynamic_cast< const ReferenceToType * >( type ) ) {
+			if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) {
+				return new StructIterator{ loc, sit };
+			} else if ( auto uit = dynamic_cast< const UnionInstType * >( aggr ) ) {
+				return new UnionIterator{ loc, uit };
+			} else {
+				assertf( 
+					dynamic_cast< const EnumInstType * >( aggr ) 
+						|| dynamic_cast< const TypeInstType * >( aggr ), 
+					"Encountered unhandled ReferenceToType in createMemberIterator: %s",
+						toString( type ).c_str() );
+				return new SimpleIterator{ loc, type };
+			}
+		} else if ( auto at = dynamic_cast< const ArrayType * >( type ) ) {
+			return new ArrayIterator{ loc, at };
+		} else if ( auto tt = dynamic_cast< const TupleType * >( type ) ) {
+			return new TupleIterator{ loc, tt };
+		} else {
+			return new SimpleIterator{ loc, type };
+		}
+	}
+
 	CurrentObject::CurrentObject( const CodeLocation & loc, const Type * type ) : objStack() {
 		objStack.emplace_back( new SimpleIterator{ loc, type } );
 	}
 
-	std::vector< InitAlternative > CurrentObject::getOptions() {
+	void CurrentObject::setNext( const ast::Designation * designation ) {
+		PRINT( std::cerr << "____setNext" << designation << std::endl; )
+		assertf( ! objStack.empty(), "obj stack empty in setNext" );
+		objStack.back()->setPosition( designation->designators );
+	}
+
+	void CurrentObject::increment() {
+		PRINT( std::cerr << "____increment" << std::endl; )
+		if ( objStack.empty() ) return;
+		PRINT( std::cerr << *objStack.back() << std::endl; )
+		objStack.back()->smallStep();
+	}
+
+	void CurrentObject::enterListInit( const CodeLocation & loc ) {
+		PRINT( std::cerr << "____entering list init" << std::endl; )
+		assertf( ! objStack.empty(), "empty obj stack entering list init" );
+		const ast::Type * type = objStack.back()->getNext();
+		assert( type );
+		objStack.emplace_back( createMemberIterator( loc, type ) );
+	}
+
+	void CurrentObject::exitListInit() {
+		PRINT( std::cerr << "____exiting list init" << std::endl; )
+		assertf( ! objStack.empty(), "objstack empty" );
+		objStack.pop_back();
+		if ( ! objStack.empty() ) {
+			PRINT( std::cerr << *objStack.back() << std::endl; )
+			objStack.back()->bigStep();
+		}
+	}
+
+	std::deque< InitAlternative > CurrentObject::getOptions() {
 		PRINT( std::cerr << "____getting current options" << std::endl; )
 		assertf( ! objStack.empty(), "objstack empty in getOptions" );
 		return **objStack.back();
+	}
+
+	const Type * CurrentObject::getCurrentType() {
+		PRINT( std::cerr << "____getting current type" << std::endl; )
+		assertf( ! objStack.empty(), "objstack empty in getCurrentType" );
+		return objStack.back()->getNext();
 	}
 }
Index: src/ResolvExpr/CurrentObject.h
===================================================================
--- src/ResolvExpr/CurrentObject.h	(revision 5684736fd985e020109cb45c53aa88513ff724e3)
+++ src/ResolvExpr/CurrentObject.h	(revision 60aaa51d44506578dbfd9b89b996a9ca2a971c8a)
@@ -16,4 +16,5 @@
 #pragma once
 
+#include <deque>
 #include <list>   // for list
 #include <memory> // for unique_ptr
@@ -21,4 +22,5 @@
 #include <vector>
 
+#include "AST/Node.hpp"  // for ptr
 #include "Common/CodeLocation.h"
 
@@ -59,9 +61,45 @@
 	// AST class types
 	class Designation;
-	class InitAlternative;
+	struct InitAlternative;
 	class Type;
 
-	// forward declaration of internal detail
-	class MemberIterator;
+	/// Iterates members of a type by initializer
+	class MemberIterator {
+	public:
+		virtual ~MemberIterator() {}
+
+		/// Internal set position based on iterator ranges
+		virtual void setPosition( 
+			std::deque< ptr< Expr > >::const_iterator it, 
+			std::deque< ptr< Expr > >::const_iterator end ) = 0;
+
+		/// walks the current object using the given designators as a guide
+		void setPosition( const std::deque< ptr< Expr > > & designators ) {
+			setPosition( designators.begin(), designators.end() );
+		}
+
+		/// retrieve the list of possible (Type,Designation) pairs for the current position in the 
+		/// current object
+		virtual std::deque< InitAlternative > operator* () const = 0;
+
+		/// true if the iterator is not currently at the end
+		virtual operator bool() const = 0;
+
+		/// moves the iterator by one member in the current object
+		virtual MemberIterator & bigStep() = 0;
+
+		/// moves the iterator by one member in the current subobject
+		virtual MemberIterator & smallStep() = 0;
+
+		/// the type of the current object
+		virtual const Type * getType() = 0;
+
+		/// the type of the current subobject
+		virtual const Type * getNext() = 0;
+	
+		/// helper for operator*; aggregates must add designator to each init alternative, but 
+		/// adding designators in operator* creates duplicates
+		virtual std::deque< InitAlternative > first() const = 0;
+	};
 
 	/// Builds initializer lists in resolution
@@ -73,7 +111,17 @@
 		CurrentObject( const CodeLocation & loc, const Type * type );
 
+		/// sets current position using the resolved designation
+		void setNext( const ast::Designation * designation );
+		/// steps to next sub-object of current object
+		void increment();
+		/// sets new current object for the duration of this brace-enclosed intializer-list
+		void enterListInit( const CodeLocation & loc );
+		/// restores previous current object
+		void exitListInit();
 		/// produces a list of alternatives (Type *, Designation *) for the current sub-object's 
 		/// initializer.
-		std::vector< InitAlternative > getOptions();
+		std::deque< InitAlternative > getOptions();
+		/// produces the type of the current object but no subobjects
+		const Type * getCurrentType();
 	};
 } // namespace ast
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 5684736fd985e020109cb45c53aa88513ff724e3)
+++ src/ResolvExpr/Resolver.cc	(revision 60aaa51d44506578dbfd9b89b996a9ca2a971c8a)
@@ -781,6 +781,5 @@
 	}
 
-	template< typename T >
-	bool isCharType( T t ) {
+	bool isCharType( Type * t ) {
 		if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) {
 			return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar ||
@@ -1071,4 +1070,10 @@
 		};
 
+		/// Swaps argument into expression pointer, saving original environment
+		void swap_and_save_env( ast::ptr< ast::Expr > & expr, const ast::Expr * newExpr ) {
+			ast::ptr< ast::TypeSubstitution > env = expr->env;
+			expr.set_and_mutate( newExpr )->env = env;
+		}
+
 		/// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts)
 		void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) {
@@ -1076,6 +1081,5 @@
 				if ( typesCompatible( castExpr->arg->result, castExpr->result, symtab ) ) {
 					// cast is to the same type as its argument, remove it
-					ast::ptr< ast::TypeSubstitution > env = castExpr->env;
-					expr.set_and_mutate( castExpr->arg )->env = env;
+					swap_and_save_env( expr, castExpr->arg );
 				}
 			}
@@ -1175,4 +1179,14 @@
 			return findKindExpression( untyped, symtab, hasIntegralType, "condition" );
 		}
+
+		/// check if a type is a character type
+		bool isCharType( const ast::Type * t ) {
+			if ( auto bt = dynamic_cast< const ast::BasicType * >( t ) ) {
+				return bt->kind == ast::BasicType::Char 
+					|| bt->kind == ast::BasicType::SignedChar 
+					|| bt->kind == ast::BasicType::UnsignedChar;
+			}
+			return false;
+		}
 	}
 
@@ -1213,6 +1227,6 @@
 		void previsit( const ast::WaitForStmt * );
 
-		void previsit( const ast::SingleInit * );
-		void previsit( const ast::ListInit * );
+		const ast::SingleInit * previsit( const ast::SingleInit * );
+		const ast::ListInit * previsit( const ast::ListInit * );
 		void previsit( const ast::ConstructorInit * );
 	};
@@ -1363,5 +1377,5 @@
 	const ast::CaseStmt * Resolver_new::previsit( const ast::CaseStmt * caseStmt ) {
 		if ( caseStmt->cond ) {
-			std::vector< ast::InitAlternative > initAlts = currentObject.getOptions();
+			std::deque< ast::InitAlternative > initAlts = currentObject.getOptions();
 			assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral "
 				"expression." );
@@ -1374,6 +1388,5 @@
 			// whether it would perform a conversion.
 			if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) {
-				ast::ptr< ast::TypeSubstitution > env = castExpr->env;
-				newExpr.set_and_mutate( castExpr->arg )->env = env;
+				swap_and_save_env( newExpr, castExpr->arg );
 			}
 			
@@ -1438,14 +1451,69 @@
 	}
 
-	void Resolver_new::previsit( const ast::SingleInit * singleInit ) {
-		#warning unimplemented; Resolver port in progress
-		(void)singleInit;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::ListInit * listInit ) {
-		#warning unimplemented; Resolver port in progress
-		(void)listInit;
-		assert(false);
+
+
+	const ast::SingleInit * Resolver_new::previsit( const ast::SingleInit * singleInit ) {
+		visit_children = false;
+		// resolve initialization using the possibilities as determined by the `currentObject` 
+		// cursor.
+		ast::Expr * untyped = new ast::UntypedInitExpr{ 
+			singleInit->location, singleInit->value, currentObject.getOptions() };
+		ast::ptr<ast::Expr> newExpr = findKindExpression( untyped, symtab );
+		const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
+
+		// move cursor to the object that is actually initialized
+		currentObject.setNext( initExpr->designation );
+
+		// discard InitExpr wrapper and retain relevant pieces.
+		// `initExpr` may have inferred params in the case where the expression specialized a 
+		// function pointer, and newExpr may already have inferParams of its own, so a simple 
+		// swap is not sufficient
+		ast::Expr::InferUnion inferred = initExpr->inferred;
+		swap_and_save_env( newExpr, initExpr->expr );
+		newExpr.get_and_mutate()->inferred.splice( std::move(inferred) );
+
+		// get the actual object's type (may not exactly match what comes back from the resolver 
+		// due to conversions)
+		const ast::Type * initContext = currentObject.getCurrentType();
+
+		removeExtraneousCast( newExpr, symtab );
+
+		// check if actual object's type is char[]
+		if ( auto at = dynamic_cast< const ast::ArrayType * >( initContext ) ) {
+			if ( isCharType( at->base ) ) {
+				// check if the resolved type is char*
+				if ( auto pt = newExpr->result.as< ast::PointerType >() ) {
+					if ( isCharType( pt->base ) ) {
+						// strip cast if we're initializing a char[] with a char* 
+						// e.g. char x[] = "hello"
+						if ( auto ce = newExpr.as< ast::CastExpr >() ) {
+							swap_and_save_env( newExpr, ce->arg );
+						}
+					}
+				}
+			}
+		}
+
+		// move cursor to next object in preparation for next initializer
+		currentObject.increment();
+
+		// set initializer expression to resolved expression
+		return ast::mutate_field( singleInit, &ast::SingleInit::value, std::move(newExpr) );
+	}
+
+	const ast::ListInit * Resolver_new::previsit( const ast::ListInit * listInit ) {
+		// move cursor into brace-enclosed initializer-list
+		currentObject.enterListInit( listInit->location );
+
+		assert( listInit->designations.size() == listInit->initializers.size() );
+		for ( unsigned i = 0; i < listInit->designations.size(); ++i ) {
+			// iterate designations and initializers in pairs, moving the cursor to the current 
+			// designated object and resolving the initializer against that object
+			#warning unimplemented; Resolver port in progress
+			assert(false);
+		}
+
+		visit_children = false;
+		return listInit;
 	}
 
