Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/CodeGen/CodeGenerator.cc	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -195,7 +195,5 @@
 		}
 
-		output << kind;
-		if ( aggDecl->get_name() != "" )
-			output << aggDecl->get_name();
+		output << kind << aggDecl->get_name();
 
 		if ( aggDecl->has_body() ) {
@@ -233,6 +231,5 @@
 		genAttributes( enumDecl->get_attributes() );
 
-		if ( enumDecl->get_name() != "" )
-			output << enumDecl->get_name();
+		output << enumDecl->get_name();
 
 		std::list< Declaration* > &memb = enumDecl->get_members();
@@ -260,5 +257,9 @@
 	}
 
-	void CodeGenerator::visit( __attribute__((unused)) TraitDecl * traitDecl ) {}
+	void CodeGenerator::visit( TraitDecl * traitDecl ) {
+		assertf( ! genC, "TraitDecl nodes should not reach code generation." );
+		extension( traitDecl );
+		handleAggregate( traitDecl, "trait " );
+	}
 
 	void CodeGenerator::visit( TypedefDecl * typeDecl ) {
@@ -760,5 +761,5 @@
 		for ( Statement * stmt : stmts ) {
 			updateLocation( stmt );
-			output << printLabels( stmt->get_labels() );
+			output << indent << printLabels( stmt->get_labels() );
 			if ( i+1 == numStmts ) {
 				// last statement in a statement expression needs to be handled specially -
Index: src/CodeGen/Generate.cc
===================================================================
--- src/CodeGen/Generate.cc	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/CodeGen/Generate.cc	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -21,4 +21,5 @@
 #include "CodeGenerator.h"           // for CodeGenerator, doSemicolon, oper...
 #include "GenType.h"                 // for genPrettyType
+#include "Common/PassVisitor.h"      // for PassVisitor
 #include "Parser/LinkageSpec.h"      // for isBuiltin, isGeneratable
 #include "SynTree/BaseSyntaxNode.h"  // for BaseSyntaxNode
@@ -29,5 +30,22 @@
 
 namespace CodeGen {
+	namespace {
+		/// Removes misc. nodes that should not exist in CodeGen
+		struct TreeCleaner {
+			void visit( CompoundStmt * stmt );
+
+			static bool shouldClean( Declaration * );
+		};
+
+		void cleanTree( std::list< Declaration * > & translationUnit ) {
+			PassVisitor<TreeCleaner> cleaner;
+			filter( translationUnit, [](Declaration * decl) { return TreeCleaner::shouldClean(decl); }, false );
+			acceptAll( translationUnit, cleaner );
+		} // cleanTree
+	} // namespace
+
 	void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty, bool generateC, bool lineMarks ) {
+		cleanTree( translationUnit );
+
 		CodeGen::CodeGenerator cgv( os, pretty, generateC, lineMarks );
 		for ( auto & dcl : translationUnit ) {
@@ -52,4 +70,19 @@
 		os << std::endl;
 	}
+
+	namespace {
+		void TreeCleaner::visit( CompoundStmt * cstmt ) {
+			filter( cstmt->kids, [](Statement * stmt) {
+				if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
+					return shouldClean( declStmt->decl );
+				}
+				return false;
+			}, false );
+		}
+
+		bool TreeCleaner::shouldClean( Declaration * decl ) {
+			return dynamic_cast< TraitDecl * >( decl );
+		}
+	} // namespace
 } // namespace CodeGen
 
Index: src/Common/utility.h
===================================================================
--- src/Common/utility.h	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/Common/utility.h	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -172,4 +172,19 @@
 auto filter(Args&&... args) -> decltype(std::copy_if(std::forward<Args>(args)...)) {
   return std::copy_if(std::forward<Args>(args)...);
+}
+
+template <typename E, typename UnaryPredicate, template< typename, typename...> class Container, typename... Args >
+void filter( Container< E *, Args... > & container, UnaryPredicate pred, bool doDelete ) {
+	auto i = begin( container );
+	while ( i != end( container ) ) {
+		auto it = next( i );
+		if ( pred( *i ) ) {
+			if ( doDelete ) {
+				delete *i;
+			} // if
+			container.erase( i );
+		} // if
+		i = it;
+	} // while
 }
 
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/GenPoly/Box.cc	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -141,4 +141,5 @@
 			virtual StructDecl *mutate( StructDecl *structDecl ) override;
 			virtual UnionDecl *mutate( UnionDecl *unionDecl ) override;
+			virtual TraitDecl *mutate( TraitDecl *unionDecl ) override;
 			virtual TypeDecl *mutate( TypeDecl *typeDecl ) override;
 			virtual TypedefDecl *mutate( TypedefDecl *typedefDecl ) override;
@@ -216,5 +217,4 @@
 		  private:
 		};
-
 	} // anonymous namespace
 
@@ -896,5 +896,4 @@
 				addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
 				bodyStmt = new ExprStmt( noLabels, adapteeApp );
-//			} else if ( isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
 			} else if ( isDynType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
 				// return type T
@@ -1352,4 +1351,8 @@
 		}
 
+		TraitDecl * Pass2::mutate( TraitDecl *aggDecl ) {
+			return handleAggDecl( aggDecl );
+		}
+
 		TypeDecl * Pass2::mutate( TypeDecl *typeDecl ) {
 			addToTyVarMap( typeDecl, scopeTyVars );
@@ -1377,4 +1380,5 @@
 		Type *Pass2::mutate( FunctionType *funcType ) {
 			scopeTyVars.beginScope();
+
 			makeTyVarMap( funcType, scopeTyVars );
 
@@ -1550,13 +1554,11 @@
 					// (alloca was previously used, but can't be safely used in loops)
 					Type *declType = objectDecl->get_type();
-					std::string bufName = bufNamer.newName();
-					ObjectDecl *newBuf = new ObjectDecl( bufName, Type::StorageClasses(), LinkageSpec::C, 0,
+					ObjectDecl *newBuf = new ObjectDecl( bufNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0,
 						new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::Kind::Char), new NameExpr( sizeofName( mangleType(declType) ) ),
-						true, false, std::list<Attribute*>{ new Attribute( std::string{"aligned"}, std::list<Expression*>{ new ConstantExpr( Constant::from_int(8) ) } ) } ), 0 );
+						true, false, std::list<Attribute*>{ new Attribute( "aligned", std::list<Expression*>{ new ConstantExpr( Constant::from_int(8) ) } ) } ), 0 );
 					stmtsToAdd.push_back( new DeclStmt( noLabels, newBuf ) );
 
 					delete objectDecl->get_init();
-
-					objectDecl->set_init( new SingleInit( new NameExpr( bufName ) ) );
+					objectDecl->set_init( new SingleInit( new VariableExpr( newBuf ) ) );
 				}
 			}
Index: src/GenPoly/GenPoly.cc
===================================================================
--- src/GenPoly/GenPoly.cc	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/GenPoly/GenPoly.cc	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -336,10 +336,10 @@
 				assertf(bparam, "Aggregate parameters should be type expressions");
 
-				// xxx - might need to let VoidType be a wildcard here too; could have some voids 
+				// xxx - might need to let VoidType be a wildcard here too; could have some voids
 				// stuffed in for dtype-statics.
 				// if ( is<VoidType>( aparam->get_type() ) || is<VoidType>( bparam->get_type() ) ) continue;
 				if ( ! typesPolyCompatible( aparam->get_type(), bparam->get_type() ) ) return false;
 			}
-			
+
 			return true;
 		}
@@ -350,9 +350,9 @@
 		// polymorphic types always match
 		if ( aid == type_index{typeid(TypeInstType)} ) return true;
-		
+
 		type_index bid{ typeid(*b) };
 		// polymorphic types always match
 		if ( bid == type_index{typeid(TypeInstType)} ) return true;
-		
+
 		// can't match otherwise if different types
 		if ( aid != bid ) return false;
@@ -377,5 +377,5 @@
 				ConstantExpr *ad = dynamic_cast<ConstantExpr*>( aa->get_dimension() );
 				ConstantExpr *bd = dynamic_cast<ConstantExpr*>( ba->get_dimension() );
-				if ( ad && bd 
+				if ( ad && bd
 						&& ad->get_constant()->get_value() != bd->get_constant()->get_value() )
 					return false;
@@ -433,4 +433,5 @@
 
 	void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {
+		// xxx - should this actually be insert?
 		tyVarMap[ tyVar->get_name() ] = TypeDecl::Data{ tyVar };
 	}
Index: src/Parser/ExpressionNode.cc
===================================================================
--- src/Parser/ExpressionNode.cc	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/Parser/ExpressionNode.cc	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -370,5 +370,5 @@
 Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ) {
 	std::list< Expression * > args;
-	args.push_back(  maybeMoveBuild< Expression >(expr_node) ); // xxx
+	args.push_back(  maybeMoveBuild< Expression >(expr_node) ); // xxx -- this is exactly the same as the val case now, refactor this code.
 	return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
 } // build_unary_ptr
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -749,18 +749,20 @@
 				if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) {
 					if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
-						referenceToRvalueConversion( func->expr );
+						Alternative newFunc( *func );
+						referenceToRvalueConversion( newFunc.expr );
 						for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
 							// XXX
 							//Designators::check_alternative( function, *actualAlt );
-							makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
+							makeFunctionAlternatives( newFunc, function, *actualAlt, std::back_inserter( candidates ) );
 						}
 					}
 				} else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
-					referenceToRvalueConversion( func->expr );
 					EqvClass eqvClass;
 					if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
 						if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
+							Alternative newFunc( *func );
+							referenceToRvalueConversion( newFunc.expr );
 							for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
-								makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
+								makeFunctionAlternatives( newFunc, function, *actualAlt, std::back_inserter( candidates ) );
 							} // for
 						} // if
@@ -773,10 +775,11 @@
 					if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) {
 						if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
-							referenceToRvalueConversion( funcOp->expr );
+							Alternative newFunc( *funcOp );
+							referenceToRvalueConversion( newFunc.expr );
 							for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
 								AltList currentAlt;
 								currentAlt.push_back( *func );
 								currentAlt.insert( currentAlt.end(), actualAlt->begin(), actualAlt->end() );
-								makeFunctionAlternatives( *funcOp, function, currentAlt, std::back_inserter( candidates ) );
+								makeFunctionAlternatives( newFunc, function, currentAlt, std::back_inserter( candidates ) );
 							} // for
 						} // if
Index: src/ResolvExpr/RenameVars.cc
===================================================================
--- src/ResolvExpr/RenameVars.cc	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/ResolvExpr/RenameVars.cc	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -88,5 +88,4 @@
 		typeBefore( aggregateUseType );
 		acceptAll( aggregateUseType->get_parameters(), *this );
-		acceptAll( aggregateUseType->get_members(), *this );
 		typeAfter( aggregateUseType );
 	}
Index: src/ResolvExpr/TypeEnvironment.cc
===================================================================
--- src/ResolvExpr/TypeEnvironment.cc	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/ResolvExpr/TypeEnvironment.cc	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -25,53 +25,4 @@
 
 namespace ResolvExpr {
-	// adding this comparison operator significantly improves assertion resolution run time for
-	// some cases. The current resolution algorithm's speed partially depends on the order of
-	// assertions. Assertions which have fewer possible matches should appear before
-	// assertions which have more possible matches. This seems to imply that this could
-	// be further improved by providing an indexer as an additional argument and ordering based
-	// on the number of matches of the same kind (object, function) for the names of the
-	// declarations.
-	//
-	// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator.
-	bool AssertCompare::operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
-			// Objects are always less than functions
-			if ( ObjectDecl * objectDecl1 = dynamic_cast< ObjectDecl * >( d1 ) ) {
-				if ( ObjectDecl * objectDecl2 = dynamic_cast< ObjectDecl * >( d2 ) ) {
-					// objects are ordered by name then type pointer, in that order
-					int cmp = objectDecl1->get_name().compare( objectDecl2->get_name() );
-					return cmp < 0 ||
-						( cmp == 0 && objectDecl1->get_type() < objectDecl2->get_type() );
-				} else {
-					return true;
-				}
-			} else if ( FunctionDecl * funcDecl1 = dynamic_cast< FunctionDecl * >( d1 ) ) {
-				if ( FunctionDecl * funcDecl2 = dynamic_cast< FunctionDecl * >( d2 ) ) {
-					// functions are ordered by name, # parameters, # returnVals, type pointer in that order
-					FunctionType * ftype1 = funcDecl1->get_functionType();
-					FunctionType * ftype2 = funcDecl2->get_functionType();
-					int numThings1 = ftype1->get_parameters().size() + ftype1->get_returnVals().size();
-					int numThings2 = ftype2->get_parameters().size() + ftype2->get_returnVals().size();
-					if ( numThings1 < numThings2 ) return true;
-					if ( numThings1 > numThings2 ) return false;
-
-					// if ( ftype1->get_parameters().size() < ftype2->get_parameters().size() ) return true;
-					// else if ( ftype1->get_parameters().size() > ftype2->get_parameters().size() ) return false;
-					// // same number of parameters
-					// if ( ftype1->get_returnVals().size() < ftype2->get_returnVals().size() ) return true;
-					// else if ( ftype1->get_returnVals().size() > ftype2->get_returnVals().size() ) return false;
-					// same number of return vals
-					// int cmp = funcDecl1->get_name().compare( funcDecl2->get_name() );
-					// if ( cmp < 0 ) return true;
-					// else if ( cmp > 0 ) return false;
-					// // same name
-					return ftype1 < ftype2;
-				} else {
-					return false;
-				}
-			} else {
-				assert( false );
-			}
-		}
-
 	void printAssertionSet( const AssertionSet &assertions, std::ostream &os, int indent ) {
 		for ( AssertionSet::const_iterator i = assertions.begin(); i != assertions.end(); ++i ) {
Index: src/ResolvExpr/TypeEnvironment.h
===================================================================
--- src/ResolvExpr/TypeEnvironment.h	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/ResolvExpr/TypeEnvironment.h	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -28,6 +28,19 @@
 
 namespace ResolvExpr {
+	// adding this comparison operator significantly improves assertion resolution run time for
+	// some cases. The current resolution algorithm's speed partially depends on the order of
+	// assertions. Assertions which have fewer possible matches should appear before
+	// assertions which have more possible matches. This seems to imply that this could
+	// be further improved by providing an indexer as an additional argument and ordering based
+	// on the number of matches of the same kind (object, function) for the names of the
+	// declarations.
+	//
+	// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator.
 	struct AssertCompare {
-		bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const;
+		bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
+			int cmp = d1->get_name().compare( d2->get_name() );
+			return cmp < 0 ||
+				( cmp == 0 && d1->get_type() < d2->get_type() );
+		}
 	};
 	struct AssertionSetValue {
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/SymTab/Indexer.cc	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -554,7 +554,6 @@
 
 
-	void Indexer::visit( TraitInstType *contextInst ) {
-		acceptAll( contextInst->get_parameters(), *this );
-		acceptAll( contextInst->get_members(), *this );
+	void Indexer::visit( TraitInstType *traitInst ) {
+		acceptAll( traitInst->get_parameters(), *this );
 	}
 
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/SymTab/Validate.cc	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -127,13 +127,17 @@
 	  public:
 		LinkReferenceToTypes( bool doDebug, const Indexer *indexer );
-  		using Parent::visit;
+		using Parent::visit;
+		void visit( TypeInstType *typeInst ) final;
+
 		void visit( EnumInstType *enumInst ) final;
 		void visit( StructInstType *structInst ) final;
 		void visit( UnionInstType *unionInst ) final;
-		void visit( TraitInstType *contextInst ) final;
+		void visit( TraitInstType *traitInst ) final;
+
 		void visit( EnumDecl *enumDecl ) final;
 		void visit( StructDecl *structDecl ) final;
 		void visit( UnionDecl *unionDecl ) final;
-		void visit( TypeInstType *typeInst ) final;
+		void visit( TraitDecl * traitDecl ) final;
+
 	  private:
 		const Indexer *indexer;
@@ -287,19 +291,4 @@
 
 	HoistStruct::HoistStruct() : inStruct( false ) {
-	}
-
-	void filter( std::list< Declaration * > &declList, bool (*pred)( Declaration * ), bool doDelete ) {
-		std::list< Declaration * >::iterator i = declList.begin();
-		while ( i != declList.end() ) {
-			std::list< Declaration * >::iterator next = i;
-			++next;
-			if ( pred( *i ) ) {
-				if ( doDelete ) {
-					delete *i;
-				} // if
-				declList.erase( i );
-			} // if
-			i = next;
-		} // while
 	}
 
@@ -453,39 +442,81 @@
 	}
 
-	void LinkReferenceToTypes::visit( TraitInstType *traitInst ) {
+	template< typename Decl >
+	void normalizeAssertions( std::list< Decl * > & assertions ) {
+		// ensure no duplicate trait members after the clone
+		auto pred = [](Decl * d1, Decl * d2) {
+			// only care if they're equal
+			DeclarationWithType * dwt1 = dynamic_cast<DeclarationWithType *>( d1 );
+			DeclarationWithType * dwt2 = dynamic_cast<DeclarationWithType *>( d2 );
+			if ( dwt1 && dwt2 ) {
+				if ( dwt1->get_name() == dwt2->get_name() && ResolvExpr::typesCompatible( dwt1->get_type(), dwt2->get_type(), SymTab::Indexer() ) ) {
+					// std::cerr << "=========== equal:" << std::endl;
+					// std::cerr << "d1: " << d1 << std::endl;
+					// std::cerr << "d2: " << d2 << std::endl;
+					return false;
+				}
+			}
+			return d1 < d2;
+		};
+		std::set<Decl *, decltype(pred)> unique_members( assertions.begin(), assertions.end(), pred );
+		// if ( unique_members.size() != assertions.size() ) {
+		// 	std::cerr << "============different" << std::endl;
+		// 	std::cerr << unique_members.size() << " " << assertions.size() << std::endl;
+		// }
+
+		std::list< Decl * > order;
+		order.splice( order.end(), assertions );
+		std::copy_if( order.begin(), order.end(), back_inserter( assertions ), [&]( Decl * decl ) {
+			return unique_members.count( decl );
+		});
+	}
+
+	// expand assertions from trait instance, performing the appropriate type variable substitutions
+	template< typename Iterator >
+	void expandAssertions( TraitInstType * inst, Iterator out ) {
+		assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toString( inst ).c_str() );
+		std::list< DeclarationWithType * > asserts;
+		for ( Declaration * decl : inst->baseTrait->members ) {
+			asserts.push_back( safe_dynamic_cast<DeclarationWithType *>( decl->clone() ) );
+		}
+		// substitute trait decl parameters for instance parameters
+		applySubstitution( inst->baseTrait->parameters.begin(), inst->baseTrait->parameters.end(), inst->parameters.begin(), asserts.begin(), asserts.end(), out );
+	}
+
+	void LinkReferenceToTypes::visit( TraitDecl * traitDecl ) {
+		Parent::visit( traitDecl );
+
+		if ( traitDecl->name == "sized" ) {
+			// "sized" is a special trait - flick the sized status on for the type variable
+			assertf( traitDecl->parameters.size() == 1, "Built-in trait 'sized' has incorrect number of parameters: %zd", traitDecl->parameters.size() );
+			TypeDecl * td = traitDecl->parameters.front();
+			td->set_sized( true );
+		}
+
+		// move assertions from type parameters into the body of the trait
+		for ( TypeDecl * td : traitDecl->parameters ) {
+			for ( DeclarationWithType * assert : td->assertions ) {
+				if ( TraitInstType * inst = dynamic_cast< TraitInstType * >( assert->get_type() ) ) {
+					expandAssertions( inst, back_inserter( traitDecl->members ) );
+				} else {
+					traitDecl->members.push_back( assert->clone() );
+				}
+			}
+			deleteAll( td->assertions );
+			td->assertions.clear();
+		} // for
+	}
+
+	void LinkReferenceToTypes::visit( TraitInstType * traitInst ) {
 		Parent::visit( traitInst );
-		if ( traitInst->get_name() == "sized" ) {
-			// "sized" is a special trait with no members - just flick the sized status on for the type variable
-			if ( traitInst->get_parameters().size() != 1 ) {
-				throw SemanticError( "incorrect number of trait parameters: ", traitInst );
-			}
-			TypeExpr * param = safe_dynamic_cast< TypeExpr * > ( traitInst->get_parameters().front() );
-			TypeInstType * inst = safe_dynamic_cast< TypeInstType * > ( param->get_type() );
-			TypeDecl * decl = inst->get_baseType();
-			decl->set_sized( true );
-			// since "sized" is special, the next few steps don't apply
-			return;
-		}
-
 		// handle other traits
-		TraitDecl *traitDecl = indexer->lookupTrait( traitInst->get_name() );
+		TraitDecl *traitDecl = indexer->lookupTrait( traitInst->name );
 		if ( ! traitDecl ) {
-			throw SemanticError( "use of undeclared trait " + traitInst->get_name() );
+			throw SemanticError( "use of undeclared trait " + traitInst->name );
 		} // if
 		if ( traitDecl->get_parameters().size() != traitInst->get_parameters().size() ) {
 			throw SemanticError( "incorrect number of trait parameters: ", traitInst );
 		} // if
-
-		for ( TypeDecl * td : traitDecl->get_parameters() ) {
-			for ( DeclarationWithType * assert : td->get_assertions() ) {
-				traitInst->get_members().push_back( assert->clone() );
-			} // for
-		} // for
-
-		// need to clone members of the trait for ownership purposes
-		std::list< Declaration * > members;
-		std::transform( traitDecl->get_members().begin(), traitDecl->get_members().end(), back_inserter( members ), [](Declaration * dwt) { return dwt->clone(); } );
-
-		applySubstitution( traitDecl->get_parameters().begin(), traitDecl->get_parameters().end(), traitInst->get_parameters().begin(), members.begin(), members.end(), back_inserter( traitInst->get_members() ) );
+		traitInst->baseTrait = traitDecl;
 
 		// need to carry over the 'sized' status of each decl in the instance
@@ -498,4 +529,5 @@
 			}
 		}
+		// normalizeAssertions( traitInst->members );
 	}
 
@@ -561,28 +593,26 @@
 	void forallFixer( Type * func ) {
 		for ( TypeDecl * type : func->get_forall() ) {
-			std::list< DeclarationWithType * > toBeDone, nextRound;
-			toBeDone.splice( toBeDone.end(), type->get_assertions() );
-			while ( ! toBeDone.empty() ) {
-				for ( DeclarationWithType * assertion : toBeDone ) {
-					if ( TraitInstType *traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
-						// expand trait instance into all of its members
-						for ( Declaration * member : traitInst->get_members() ) {
-							DeclarationWithType *dwt = safe_dynamic_cast< DeclarationWithType * >( member );
-							nextRound.push_back( dwt->clone() );
-						}
-						delete traitInst;
-					} else {
-						// pass assertion through
-						FixFunction fixer;
-						assertion = assertion->acceptMutator( fixer );
-						if ( fixer.get_isVoid() ) {
-							throw SemanticError( "invalid type void in assertion of function ", func );
-						}
-						type->get_assertions().push_back( assertion );
-					} // if
-				} // for
-				toBeDone.clear();
-				toBeDone.splice( toBeDone.end(), nextRound );
-			} // while
+			std::list< DeclarationWithType * > asserts;
+			asserts.splice( asserts.end(), type->assertions );
+			// expand trait instances into their members
+			for ( DeclarationWithType * assertion : asserts ) {
+				if ( TraitInstType *traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
+					// expand trait instance into all of its members
+					expandAssertions( traitInst, back_inserter( type->assertions ) );
+					delete traitInst;
+				} else {
+					// pass other assertions through
+					type->assertions.push_back( assertion );
+				} // if
+			} // for
+			// apply FixFunction to every assertion to check for invalid void type
+			for ( DeclarationWithType *& assertion : type->assertions ) {
+				FixFunction fixer;
+				assertion = assertion->acceptMutator( fixer );
+				if ( fixer.get_isVoid() ) {
+					throw SemanticError( "invalid type void in assertion of function ", func );
+				} // if
+			} // for
+			// normalizeAssertions( type->assertions );
 		} // for
 	}
@@ -752,15 +782,13 @@
 		CompoundStmt *ret = Mutator::mutate( compoundStmt );
 		scopeLevel -= 1;
-		std::list< Statement * >::iterator i = compoundStmt->get_kids().begin();
-		while ( i != compoundStmt->get_kids().end() ) {
-			std::list< Statement * >::iterator next = i+1;
-			if ( DeclStmt *declStmt = dynamic_cast< DeclStmt * >( *i ) ) {
+		// remove and delete decl stmts
+		filter( compoundStmt->kids, [](Statement * stmt) {
+			if ( DeclStmt *declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
 				if ( dynamic_cast< TypedefDecl * >( declStmt->get_decl() ) ) {
-					delete *i;
-					compoundStmt->get_kids().erase( i );
+					return true;
 				} // if
 			} // if
-			i = next;
-		} // while
+			return false;
+		}, true);
 		typedefNames.endScope();
 		return ret;
@@ -771,13 +799,5 @@
 	template<typename AggDecl>
 	AggDecl *EliminateTypedef::handleAggregate( AggDecl * aggDecl ) {
-		std::list<Declaration *>::iterator it = aggDecl->get_members().begin();
-		for ( ; it != aggDecl->get_members().end(); ) {
-			std::list< Declaration * >::iterator next = it+1;
-			if ( dynamic_cast< TypedefDecl * >( *it ) ) {
-				delete *it;
-				aggDecl->get_members().erase( it );
-			} // if
-			it = next;
-		}
+		filter( aggDecl->members, isTypedef, true );
 		return aggDecl;
 	}
Index: src/SynTree/Mutator.cc
===================================================================
--- src/SynTree/Mutator.cc	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/SynTree/Mutator.cc	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -538,5 +538,4 @@
 Type * Mutator::mutate( TraitInstType *aggregateUseType ) {
 	handleReferenceToType( aggregateUseType );
-	mutateAll( aggregateUseType->get_members(), *this );
 	return aggregateUseType;
 }
Index: src/SynTree/ReferenceToType.cc
===================================================================
--- src/SynTree/ReferenceToType.cc	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/SynTree/ReferenceToType.cc	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -132,10 +132,10 @@
 std::string TraitInstType::typeString() const { return "trait"; }
 
-TraitInstType::TraitInstType( const TraitInstType &other ) : Parent( other ) {
-	cloneAll( other.members, members );
+TraitInstType::TraitInstType( const Type::Qualifiers & tq, TraitDecl * baseTrait, const std::list< Attribute * > & attributes ) : Parent( tq, baseTrait->name, attributes ), baseTrait( baseTrait ) {}
+
+TraitInstType::TraitInstType( const TraitInstType &other ) : Parent( other ), baseTrait( other.baseTrait ) {
 }
 
 TraitInstType::~TraitInstType() {
-	deleteAll( members );
 }
 
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/SynTree/Type.h	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -471,13 +471,12 @@
 	typedef ReferenceToType Parent;
   public:
-	// this member is filled in by the validate pass, which instantiates the members of the correponding
-	// aggregate with the actual type parameters specified for this use of the context
-	std::list< Declaration* > members;
-
-	TraitInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ) {}
+	// this decl is not "owned" by the trait inst; it is merely a pointer to elsewhere in the tree,
+	// where the trait used in this type is actually defined
+	TraitDecl * baseTrait = nullptr;
+
+	TraitInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ) {}
+	TraitInstType( const Type::Qualifiers & tq, TraitDecl * baseTrait, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
 	TraitInstType( const TraitInstType & other );
 	~TraitInstType();
-
-	std::list< Declaration* >& get_members() { return members; }
 
 	virtual bool isComplete() const;
Index: src/SynTree/TypeSubstitution.h
===================================================================
--- src/SynTree/TypeSubstitution.h	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/SynTree/TypeSubstitution.h	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -177,5 +177,5 @@
 void applySubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actual, MemberIterator memberBegin, MemberIterator memberEnd, OutputIterator out ) {
 	TypeSubstitution sub = TypeSubstitution( formalBegin, formalEnd, actual );
-	for ( std::list< Declaration* >::iterator i = memberBegin; i != memberEnd; ++i ) {
+	for ( auto i = memberBegin; i != memberEnd; ++i ) {
 		sub.apply( *i );
 		*out++ = *i;
Index: src/SynTree/Visitor.cc
===================================================================
--- src/SynTree/Visitor.cc	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/SynTree/Visitor.cc	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -429,5 +429,4 @@
 void Visitor::visit( TraitInstType *aggregateUseType ) {
 	handleReferenceToType( static_cast< ReferenceToType * >( aggregateUseType ) );
-	acceptAll( aggregateUseType->get_members(), *this );
 }
 
Index: src/prelude/prelude.cf
===================================================================
--- src/prelude/prelude.cf	(revision 76c62b2f38518c820649b67ff26b4bbaea3060da)
+++ src/prelude/prelude.cf	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -14,4 +14,14 @@
 
 // Section numbers from: http://plg.uwaterloo.ca/~cforall/refrat.pdf
+
+// ------------------------------------------------------------
+//
+// Section 6.7.11 Trait Declarations
+// Note: the sized trait is used in declarations later in this
+// file, so it must be out of order.
+//
+// ------------------------------------------------------------
+
+trait sized(dtype T) {};
 
 // ------------------------------------------------------------
Index: src/tests/.expect/function-operator.txt
===================================================================
--- src/tests/.expect/function-operator.txt	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
+++ src/tests/.expect/function-operator.txt	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -0,0 +1,32 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+Found 5 in x.
+Did not find 5 in y.
+0
+2
+4
+6
+8
+10
+12
+14
+16
+18
Index: src/tests/function-operator.c
===================================================================
--- src/tests/function-operator.c	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
+++ src/tests/function-operator.c	(revision 51c63533f5e27f31fa1953e7742617d789a57ed5)
@@ -0,0 +1,174 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// function-operator.c --
+//
+// Author           : Rob Schluntz
+// Created On       : Fri Aug 25 15:21:11 2017
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri Aug 25 15:31:29 2017
+// Update Count     : 2
+//
+
+#include <fstream>
+#include <stdlib>
+
+#define length(array) (sizeof((array))/sizeof((array)[0]))
+#define begin(array) (&array[0]) // there's currently a bug in passing an array to a polymorphic function, so ensure a pointer is passed instead
+#define end(array) (&array[length(array)])
+
+// STL-like Algorithms
+trait Assignable(dtype T, dtype U) { T ?=?(T &, U); };
+trait Copyable(dtype T) { void ?{}(T &, T); };
+trait Destructable(dtype T) { void ^?{}(T &); };
+
+trait Iterator(dtype iter | sized(iter) | Copyable(iter) | Destructable(iter), otype T) {
+	T & *?(iter);
+	iter ++?(iter &);
+	int ?!=?(iter, iter);
+};
+
+forall(otype Tin, dtype Input | Iterator(Input, Tin), otype Tout, dtype Output | Iterator(Output, Tout) | Assignable(Tout, Tin))
+Output copy(Input first, Input last, Output result) {
+  while (first != last) {
+    *result = *first;
+    ++result; ++first;
+  }
+  return result;
+}
+
+// test ?()(T *, ...) -- ?() with function call-by-pointer
+forall(otype Tin, dtype Input | Iterator(Input, Tin), otype Tout, dtype Output | Iterator(Output, Tout), otype FuncRet, dtype Func | { FuncRet ?()(Func *, Tin); } | Assignable(Tout, FuncRet))
+Output transform (Input first, Input last, Output result, Func * op) {
+  while (first != last) {
+    *result = op(*first);
+    ++result; ++first;
+  }
+  return result;
+}
+
+// test ?()(T, ...) -- ?() with function call-by-value
+forall(dtype Iter, otype T | Iterator(Iter, T), otype Pred | { int ?()(Pred, T); })
+Iter find_if (Iter first, Iter last, Pred pred) {
+  while (first != last) {
+    if (pred(*first)) return first;
+    ++first;
+  }
+  return last;
+}
+
+// test ?()(T, ...) -- ?() with function call-by-reference
+forall(otype Generator, otype GenRet | { GenRet ?()(Generator &); }, dtype Iter, otype T| Iterator(Iter, T) | Assignable(T, GenRet))
+void generate(Iter first, Iter last, Generator & gen) {
+  int i = 0;
+  while (first != last) {
+    *first = gen();
+    ++first;
+  }
+}
+
+// encapsulate a counter that increments by one every time it is called
+struct Counter { int c; };
+void ?{}(Counter & cnt) { cnt.c = 0; }
+int ?()(Counter & cnt) { return cnt.c++; }
+
+// TODO: abstract over os type with ostream trait; resolver is currently too slow for this to be reasonable, but it does work.
+struct os_wrapper {
+  ofstream * out;
+};
+
+// TODO: abstract over (os, T)
+os_wrapper ?=?(os_wrapper & wrapper, int x) {
+  wrapper.out | x | endl;
+  return wrapper;
+}
+
+struct ostream_iterator {
+  os_wrapper * out;
+};
+void ?{}(ostream_iterator & iter, ofstream * out) {
+  iter.out = new(out);
+}
+// no destructor, memory leak. This is necessary for this to work at the moment, since
+// *? requires its parameter by value and returns a reference.
+
+// implement Iterator
+os_wrapper & *?(ostream_iterator iter) {
+  return *iter.out;
+}
+ostream_iterator ++?(ostream_iterator & iter) {
+  // nothing to do
+  return iter;
+}
+int ?!=?(ostream_iterator i1, ostream_iterator i2) {
+  return i1.out->out != i2.out->out;
+}
+
+forall(otype T | { int ?==?(T, T); })
+struct Equals {
+	T val;
+};
+
+forall(otype T | { int ?==?(T, T); })
+int ?()(Equals(T) eq, T x) {
+	return eq.val == x;
+}
+
+forall(otype T | { T ?*?(T, T); })
+struct Multiply {
+	T val;
+};
+
+forall(otype T | { T ?*?(T, T); })
+T ?()(Multiply(T) * mult, T x) {
+	return mult->val * x;
+}
+
+// TODO: generalize to ttype return; doesn't work yet
+// like std::function
+forall(otype Return, ttype Args)
+struct function {
+  Return (*f)(Args);
+};
+// TODO: missing adapter in these functions
+// // value, reference, pointer operators
+// forall(otype Return, ttype Args) Return ?()(function(Return, Args) func, Args args) { return func.f(args); }
+// forall(otype Return, ttype Args) Return ?()(function(Return, Args) & func, Args args) { return func.f(args); }
+// forall(otype Return, ttype Args) Return ?()(function(Return, Args) * func, Args args) { return func->f(args); }
+
+int main() {
+	// generate for array fill
+	Counter c;
+	int x[10], y[10];
+	generate(begin(x), end(x), c);
+	generate(begin(y), end(y), c);
+
+	// copy for output
+	ostream_iterator out_iter = { sout };
+	copy(begin(x), end(x), out_iter);
+	copy(begin(y), end(y), out_iter);
+
+	// find_if for searching
+	Equals(int) is5 = { 5 };
+	if (find_if(begin(x), end(x), is5) != end(y)) {
+		printf("Found 5 in x.\n");
+	} else {
+		printf("Did not find 5 in x.\n");
+	}
+	if (find_if(begin(y), end(y), is5) != end(y)) {
+		printf("Found 5 in y.\n");
+	} else {
+		printf("Did not find 5 in y.\n");
+	}
+
+	Multiply(int) times2 = { 2 };
+	transform(begin(x), end(x), begin(x), &times2);
+	copy(begin(x), end(x), out_iter);
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// End: //
