Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision 6380f7877cde845f32dac6bfe1878417869955c0)
+++ src/AST/Expr.cpp	(revision 76ed81f81d14c3e5db5597f0020c3ea79b4b7b8c)
@@ -159,13 +159,13 @@
 	assert( aggregate->result );
 
+	// #warning Needs GenericSubsitution.cpp building to work correctly
+	// result.set_and_mutate( mem->get_type() )->qualifiers |= aggregate->result->qualifiers | CV::Lvalue;  // FIXME temporary patch
+
 	// take ownership of member type
-	Type * res = result.set_and_mutate( mem->get_type() );
+	result = mem->get_type();
 	// substitute aggregate generic parameters into member type
-	genericSubsitution( aggregate->result ).apply( res );
+	genericSubsitution( aggregate->result ).apply( result );
 	// ensure lvalue and appropriate restrictions from aggregate type
-	res->set_lvalue( true );
-	res->qualifiers |= aggregate->result->qualifiers;
-	// ensure changes propegated back into result
-	result = res;
+	result.get_and_mutate()->qualifiers |= aggregate->result->qualifiers | CV::Lvalue;
 }
 
Index: src/AST/GenericSubstitution.cpp
===================================================================
--- src/AST/GenericSubstitution.cpp	(revision 6380f7877cde845f32dac6bfe1878417869955c0)
+++ src/AST/GenericSubstitution.cpp	(revision 76ed81f81d14c3e5db5597f0020c3ea79b4b7b8c)
@@ -31,18 +31,21 @@
 		TypeSubstitution sub;
 
-		void previsit( const Type * ty ) {
+		const Type * previsit( const Type * ty ) {
 			assertf( false, "Attempted generic substitution for non-aggregate type: %s", 
 				toString( ty ).c_str() );
+			return ty;
 		}
 
-		void previsit( const ReferenceType * ) {
+		const ReferenceType * previsit( const ReferenceType * ty ) {
 			// do nothing; allows substitution from base type
+			return ty;
 		}
 
-		void previsit( const ReferenceToType * ty ) {
+		const ReferenceToType * previsit( 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() };
-			visit_children = false;
+			return ty;
 		}
 	};
Index: src/AST/Node.cpp
===================================================================
--- src/AST/Node.cpp	(revision 6380f7877cde845f32dac6bfe1878417869955c0)
+++ src/AST/Node.cpp	(revision 76ed81f81d14c3e5db5597f0020c3ea79b4b7b8c)
@@ -35,10 +35,6 @@
 void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node ) { node->decrement(ref_t); }
 
-/// Sets this pointer to a mutated version of a pointer (possibly) owned elsehere.
-/// Returns a mutable version of the pointer in this node.
-template< typename node_t, enum ast::Node::ref_type ref_t >
-node_t * ast::ptr_base<node_t, ref_t>::set_and_mutate( const node_t * n ) {
-	// ensure ownership of `n` by this node to avoid spurious single-owner mutates
-	assign( n );
+template< typename node_t, enum ast::Node::ref_type ref_t >
+node_t * ast::ptr_base<node_t, ref_t>::get_and_mutate() {
 	// get mutable version of `n`
 	auto r = mutate( node );
@@ -46,4 +42,12 @@
 	assign( r );
 	return r;
+}
+
+template< typename node_t, enum ast::Node::ref_type ref_t >
+node_t * ast::ptr_base<node_t, ref_t>::set_and_mutate( const node_t * n ) {
+	// ensure ownership of `n` by this node to avoid spurious single-owner mutates
+	assign( n );
+	// return mutable version
+	return get_and_mutate();
 }
 
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision 6380f7877cde845f32dac6bfe1878417869955c0)
+++ src/AST/Node.hpp	(revision 76ed81f81d14c3e5db5597f0020c3ea79b4b7b8c)
@@ -147,4 +147,7 @@
 	const o_node_t * as() const { return dynamic_cast<const o_node_t *>(node); }
 
+	/// Returns a mutable version of the pointer in this node.
+	node_t * get_and_mutate();
+
 	/// Sets this pointer to a mutated version of a pointer (possibly) owned elsehere.
 	/// Returns a mutable version of the pointer in this node.
Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision 6380f7877cde845f32dac6bfe1878417869955c0)
+++ src/AST/Print.cpp	(revision 76ed81f81d14c3e5db5597f0020c3ea79b4b7b8c)
@@ -495,4 +495,20 @@
 
 	virtual const ast::TypeSubstitution * visit( const ast::TypeSubstitution     * node ) {
+		os << indent << "Types:" << std::endl;
+		for ( const auto& i : *node ) {
+			os << indent+1 << i.first << " -> ";
+			indent += 2;
+			i.second->accept( *this );
+			indent -= 2;
+			os << std::endl;
+		}
+		os << indent << "Non-types:" << std::endl;
+		for ( auto i = node->beginVar(); i != node->endVar(); ++i ) {
+			os << indent+1 << i->first << " -> ";
+			indent += 2;
+			i->second->accept( *this );
+			indent -= 2;
+			os << std::endl;
+		}
 		return node;
 	}
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision 6380f7877cde845f32dac6bfe1878417869955c0)
+++ src/AST/Type.hpp	(revision 76ed81f81d14c3e5db5597f0020c3ea79b4b7b8c)
@@ -47,9 +47,9 @@
 	bool is_atomic() const { return qualifiers.is_atomic; }
 
-	void set_const( bool v ) { qualifiers.is_const = v; }
-	void set_restrict( bool v ) { qualifiers.is_restrict = v; }
-	void set_lvalue( bool v ) { qualifiers.is_lvalue = v; }
-	void set_mutex( bool v ) { qualifiers.is_mutex = v; }
-	void set_atomic( bool v ) { qualifiers.is_atomic = v; }
+	Type * set_const( bool v ) { qualifiers.is_const = v; return this; }
+	Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; }
+	Type * set_lvalue( bool v ) { qualifiers.is_lvalue = v; return this; }
+	Type * set_mutex( bool v ) { qualifiers.is_mutex = v; return this; }
+	Type * set_atomic( bool v ) { qualifiers.is_atomic = v; return this; }
 
 	/// How many elemental types are represented by this type
Index: src/AST/TypeSubstitution.hpp
===================================================================
--- src/AST/TypeSubstitution.hpp	(revision 6380f7877cde845f32dac6bfe1878417869955c0)
+++ src/AST/TypeSubstitution.hpp	(revision 76ed81f81d14c3e5db5597f0020c3ea79b4b7b8c)
@@ -30,4 +30,5 @@
 #include "Decl.hpp"
 #include "Expr.hpp"
+#include "Node.hpp"
 
 namespace ast {
@@ -43,6 +44,22 @@
 	TypeSubstitution &operator=( const TypeSubstitution &other );
 
-	template< typename SynTreeClass > int apply( SynTreeClass *&input ) const;
-	template< typename SynTreeClass > int applyFree( SynTreeClass *&input ) const;
+	template< typename SynTreeClass > int apply( const SynTreeClass *& input ) const;
+	template< typename SynTreeClass > int applyFree( const SynTreeClass *& input ) const;
+
+	template< typename node_t, enum Node::ref_type ref_t >
+	int apply( ptr_base< node_t, ref_t > & input ) const {
+		const node_t * p = input.get();
+		int ret = apply(p);
+		input = p;
+		return ret;
+	}
+
+	template< typename node_t, enum Node::ref_type ref_t >
+	int applyFree( ptr_base< node_t, ref_t > & input ) const {
+		const node_t * p = input.get();
+		int ret = applyFree(p);
+		input = p;
+		return ret;
+	}
 
 	void add( std::string formalType, const Type *actualType );
@@ -162,8 +179,8 @@
 
 template< typename SynTreeClass >
-int TypeSubstitution::apply( SynTreeClass *&input ) const {
+int TypeSubstitution::apply( const SynTreeClass *& input ) const {
 	assert( input );
 	Pass<Substituter> sub( *this, false );
-	input = strict_dynamic_cast< SynTreeClass * >( input->accept( sub ) );
+	input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
 ///	std::cerr << "substitution result is: ";
 ///	newType->print( std::cerr );
@@ -173,8 +190,8 @@
 
 template< typename SynTreeClass >
-int TypeSubstitution::applyFree( SynTreeClass *&input ) const {
+int TypeSubstitution::applyFree( const SynTreeClass *& input ) const {
 	assert( input );
 	Pass<Substituter> sub( *this, true );
-	input = strict_dynamic_cast< SynTreeClass * >( input->accept( sub ) );
+	input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
 ///	std::cerr << "substitution result is: ";
 ///	newType->print( std::cerr );
