Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision d7a02ae903476ded9a21da3034888ccf8617a83d)
+++ src/AST/Convert.cpp	(revision d60780ce6346125b93e03ce50043a6ffe5b61e92)
@@ -579,4 +579,5 @@
 				tgtInferParams[srcParam.first] = ParamEntry(
 					srcParam.second.decl,
+					get<Declaration>().accept1(srcParam.second.declptr),
 					get<Type>().accept1(srcParam.second.actualType),
 					get<Type>().accept1(srcParam.second.formalType),
@@ -2004,4 +2005,5 @@
 				tgt[old.first] = ast::ParamEntry(
 					old.second.decl,
+					getAccept1<ast::Decl>(old.second.declptr),
 					getAccept1<ast::Type>(old.second.actualType),
 					getAccept1<ast::Type>(old.second.formalType),
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision d7a02ae903476ded9a21da3034888ccf8617a83d)
+++ src/AST/Expr.hpp	(revision d60780ce6346125b93e03ce50043a6ffe5b61e92)
@@ -39,11 +39,12 @@
 struct ParamEntry {
 	UniqueId decl;
+	ptr<Decl> declptr;
 	ptr<Type> actualType;
 	ptr<Type> formalType;
 	ptr<Expr> expr;
 
-	ParamEntry() : decl( 0 ), actualType( nullptr ), formalType( nullptr ), expr( nullptr ) {}
-	ParamEntry( UniqueId id, Type* actual, Type* formal, Expr* e )
-	: decl( id ), actualType( actual ), formalType( formal ), expr( e ) {}
+	ParamEntry() : decl( 0 ), declptr( nullptr ), actualType( nullptr ), formalType( nullptr ), expr( nullptr ) {}
+	ParamEntry( UniqueId id, Decl * declptr, Type* actual, Type* formal, Expr* e )
+	: decl( id ), declptr( declptr ), actualType( actual ), formalType( formal ), expr( e ) {}
 };
 
@@ -137,5 +138,5 @@
 		}
 
-		/// splices other InferUnion into this one. Will fail if one union is in `Slots` mode 
+		/// 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 ) {
@@ -145,5 +146,5 @@
 
 			if ( mode == Slots ){
-				data.resnSlots.insert( 
+				data.resnSlots.insert(
 					data.resnSlots.end(), o.data.resnSlots.begin(), o.data.resnSlots.end() );
 			} else if ( mode == Params ) {
Index: src/GenPoly/Lvalue.cc
===================================================================
--- src/GenPoly/Lvalue.cc	(revision d7a02ae903476ded9a21da3034888ccf8617a83d)
+++ src/GenPoly/Lvalue.cc	(revision d60780ce6346125b93e03ce50043a6ffe5b61e92)
@@ -200,5 +200,4 @@
 				if(i == end) { return appExpr; }
 				for ( auto p : unsafe_group_iterate( appExpr->args, ftype->parameters ) ) {
-					if (i == end) break;
 					Expression *& arg = std::get<0>( p );
 					Type * formal = std::get<1>( p )->get_type();
@@ -245,4 +244,5 @@
 					}
 					++i;
+					if (i == end) break;
 				}
 			}
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision d7a02ae903476ded9a21da3034888ccf8617a83d)
+++ src/InitTweak/FixInit.cc	(revision d60780ce6346125b93e03ce50043a6ffe5b61e92)
@@ -995,4 +995,9 @@
 			)
 
+
+			// std::set_difference requires that the inputs be sorted.
+			lvars.sort();
+			curVars.sort();
+
 			ObjectSet diff;
 			// S_L-S_G results in set of objects whose construction is skipped - it's an error if this set is non-empty
Index: src/ResolvExpr/ResolveAssertions.cc
===================================================================
--- src/ResolvExpr/ResolveAssertions.cc	(revision d7a02ae903476ded9a21da3034888ccf8617a83d)
+++ src/ResolvExpr/ResolveAssertions.cc	(revision d60780ce6346125b93e03ce50043a6ffe5b61e92)
@@ -50,7 +50,7 @@
 		UniqueId resnSlot;              ///< Slot for any recursive assertion IDs
 
-		AssnCandidate( const SymTab::Indexer::IdData& cdata, Type* adjType, TypeEnvironment&& env, 
-			AssertionSet&& have, AssertionSet&& need, OpenVarSet&& openVars, UniqueId resnSlot ) 
-		: cdata(cdata), adjType(adjType), env(std::move(env)), have(std::move(have)), 
+		AssnCandidate( const SymTab::Indexer::IdData& cdata, Type* adjType, TypeEnvironment&& env,
+			AssertionSet&& have, AssertionSet&& need, OpenVarSet&& openVars, UniqueId resnSlot )
+		: cdata(cdata), adjType(adjType), env(std::move(env)), have(std::move(have)),
 			need(std::move(need)), openVars(std::move(openVars)), resnSlot(resnSlot) {}
 	};
@@ -86,5 +86,5 @@
 	using DeferList = std::vector<DeferItem>;
 
-	/// Combo iterator that combines candidates into an output list, merging their environments. 
+	/// Combo iterator that combines candidates into an output list, merging their environments.
 	/// Rejects an appended candidate if the environments cannot be merged.
 	class CandidateEnvMerger {
@@ -97,5 +97,5 @@
 		/// Indexer to use for merges
 		const SymTab::Indexer& indexer;
-	
+
 	public:
 		/// The merged environment/open variables and the list of candidates
@@ -106,10 +106,10 @@
 			Cost cost;
 
-			OutType( const TypeEnvironment& env, const OpenVarSet& openVars, 
+			OutType( const TypeEnvironment& env, const OpenVarSet& openVars,
 				const std::vector<DeferRef>& assns )
 			: env(env), openVars(openVars), assns(assns), cost(Cost::infinity) {}
 		};
 
-		CandidateEnvMerger( const TypeEnvironment& env, const OpenVarSet& openVars, 
+		CandidateEnvMerger( const TypeEnvironment& env, const OpenVarSet& openVars,
 			const SymTab::Indexer& indexer )
 		: crnt(), envs{ env }, varSets{ openVars }, indexer(indexer) {}
@@ -137,5 +137,5 @@
 	};
 
-	/// Comparator for CandidateEnvMerger outputs that sums their costs and caches the stored 
+	/// Comparator for CandidateEnvMerger outputs that sums their costs and caches the stored
 	/// sums
 	struct CandidateCost {
@@ -156,11 +156,11 @@
 			for ( const auto& assn : x.assns ) {
 				// compute conversion cost from satisfying decl to assertion
-				k += computeConversionCost( 
+				k += computeConversionCost(
 					assn.match.adjType, assn.decl->get_type(), indexer, x.env );
-				
+
 				// mark vars+specialization cost on function-type assertions
 				FunctionType* func = GenPoly::getFunctionType( assn.match.cdata.id->get_type() );
 				if ( ! func ) continue;
-				
+
 				for ( DeclarationWithType* formal : func->parameters ) {
 					k.decSpec( specCost( formal->get_type() ) );
@@ -176,5 +176,5 @@
 			return k;
 		}
-		
+
 		/// compares elements by cost
 		bool operator() ( Element& a, Element& b ) const {
@@ -206,12 +206,12 @@
 		/// Updated resolution state with new need-list
 		ResnState( ResnState&& o, IterateFlag )
-		: alt(std::move(o.alt)), need(o.newNeed.begin(), o.newNeed.end()), newNeed(), deferred(), 
+		: alt(std::move(o.alt)), need(o.newNeed.begin(), o.newNeed.end()), newNeed(), deferred(),
 		  inferred(std::move(o.inferred)), indexer(o.indexer) {}
 	};
 
 	/// Binds a single assertion, updating resolution state
-	void bindAssertion( const DeclarationWithType* decl, AssertionSetValue info, Alternative& alt, 
+	void bindAssertion( const DeclarationWithType* decl, AssertionSetValue info, Alternative& alt,
 			AssnCandidate& match, InferCache& inferred ) {
-		
+
 		DeclarationWithType* candidate = match.cdata.id;
 		assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
@@ -224,5 +224,5 @@
 		// place newly-inferred assertion in proper place in cache
 		inferred[ info.resnSlot ][ decl->get_uniqueId() ] = ParamEntry{
-				candidate->get_uniqueId(), match.adjType->clone(), decl->get_type()->clone(), 
+				candidate->get_uniqueId(), candidate->clone(), match.adjType->clone(), decl->get_type()->clone(),
 				varExpr };
 	}
@@ -263,5 +263,5 @@
 
 			// keep unifying candidates
-			if ( unify( assn.decl->get_type(), adjType, newEnv, newNeed, have, newOpenVars, 
+			if ( unify( assn.decl->get_type(), adjType, newEnv, newNeed, have, newOpenVars,
 					resn.indexer ) ) {
 				// set up binding slot for recursive assertions
@@ -274,5 +274,5 @@
 				}
 
-				matches.emplace_back( cdata, adjType, std::move(newEnv), std::move(have), 
+				matches.emplace_back( cdata, adjType, std::move(newEnv), std::move(have),
 					std::move(newNeed), std::move(newOpenVars), crntResnSlot );
 			} else {
@@ -319,5 +319,5 @@
 				}
 				InferredParams& inferParams = it->second;
-				
+
 				// place inferred parameters into proper place in expression
 				for ( auto& entry : inferParams ) {
@@ -373,5 +373,5 @@
 						ss << (tabs-1) << "Could not satisfy assertion:\n";
 						assn.decl->print( ss, tabs );
-						
+
 						errors.emplace_back( ss.str() );
 						goto nextResn;
@@ -403,5 +403,5 @@
 					// resolve deferred assertions by mutual compatibility
 					std::vector<CandidateEnvMerger::OutType> compatible = filterCombos(
-						resn.deferred, 
+						resn.deferred,
 						CandidateEnvMerger{ resn.alt.env, resn.alt.openVars, resn.indexer } );
 					// fail early if no mutually-compatible assertion satisfaction
@@ -466,5 +466,5 @@
 			new_resns.clear();
 		}
-		
+
 		// exceeded recursion limit if reaches here
 		if ( out.empty() ) {
Index: src/SynTree/ApplicationExpr.cc
===================================================================
--- src/SynTree/ApplicationExpr.cc	(revision d7a02ae903476ded9a21da3034888ccf8617a83d)
+++ src/SynTree/ApplicationExpr.cc	(revision d60780ce6346125b93e03ce50043a6ffe5b61e92)
@@ -29,13 +29,14 @@
 
 ParamEntry::ParamEntry( const ParamEntry &other ) :
-		decl( other.decl ), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) )/*, inferParams( new InferredParams( *other.inferParams ) )*/ {
+		decl( other.decl ), declptr( maybeClone( other.declptr ) ), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) )/*, inferParams( new InferredParams( *other.inferParams ) )*/ {
 }
 
 ParamEntry &ParamEntry::operator=( const ParamEntry &other ) {
 	if ( &other == this ) return *this;
-	decl = other.decl;
+	const_cast<UniqueId &>(decl) = other.decl;
+	const_cast<Declaration * &>(declptr) = maybeClone( other.declptr );
 	// xxx - this looks like a memory leak
-	actualType = maybeClone( other.actualType );
-	formalType = maybeClone( other.formalType );
+	const_cast<Type * &>(actualType) = maybeClone( other.actualType );
+	const_cast<Type * &>(formalType) = maybeClone( other.formalType );
 	expr = maybeClone( other.expr );
 	// *inferParams = *other.inferParams;
@@ -44,4 +45,5 @@
 
 ParamEntry::~ParamEntry() {
+	delete declptr;
 	delete actualType;
 	delete formalType;
@@ -50,7 +52,8 @@
 
 ParamEntry::ParamEntry( ParamEntry && other ) :
-		decl( other.decl ), actualType( other.actualType ), formalType( other.formalType ), expr( other.expr )/*, inferParams( std::move( other.inferParams ) )*/ {
-	other.actualType = nullptr;
-	other.formalType = nullptr;
+		decl( other.decl ), declptr( other.declptr ), actualType( other.actualType ), formalType( other.formalType ), expr( other.expr )/*, inferParams( std::move( other.inferParams ) )*/ {
+	const_cast<Declaration * &>(other.declptr) = nullptr;
+	const_cast<Type * &>(other.actualType) = nullptr;
+	const_cast<Type * &>(other.formalType) = nullptr;
 	other.expr = nullptr;
 }
@@ -58,13 +61,16 @@
 ParamEntry & ParamEntry::operator=( ParamEntry && other ) {
 	if ( &other == this ) return *this;
+	delete declptr;
 	delete actualType;
 	delete formalType;
 	delete expr;
-	decl = other.decl;
-	actualType = other.actualType;
-	formalType = other.formalType;
+	const_cast<UniqueId &>(decl) = other.decl;
+	const_cast<Declaration * &>(declptr) = other.declptr;
+	const_cast<Type * &>(actualType) = other.actualType;
+	const_cast<Type * &>(formalType) = other.formalType;
 	expr = other.expr;
-	other.actualType = nullptr;
-	other.formalType = nullptr;
+	const_cast<Declaration * &>(other.declptr) = nullptr;
+	const_cast<Type * &>(other.actualType) = nullptr;
+	const_cast<Type * &>(other.formalType) = nullptr;
 	other.expr = nullptr;
 	// inferParams = std::move( other.inferParams );
Index: src/SynTree/Declaration.cc
===================================================================
--- src/SynTree/Declaration.cc	(revision d7a02ae903476ded9a21da3034888ccf8617a83d)
+++ src/SynTree/Declaration.cc	(revision d60780ce6346125b93e03ce50043a6ffe5b61e92)
@@ -27,6 +27,4 @@
 
 static UniqueId lastUniqueId = 0;
-typedef std::map< UniqueId, Declaration* > IdMapType;
-static IdMapType idMap;
 
 Declaration::Declaration( const std::string &name, Type::StorageClasses scs, LinkageSpec::Spec linkage )
@@ -45,20 +43,5 @@
 	if ( uniqueId ) return;
 	uniqueId = ++lastUniqueId;
-	idMap[ uniqueId ] = this;
 }
-
-Declaration *Declaration::declFromId( UniqueId id ) {
-	IdMapType::const_iterator i = idMap.find( id );
-	return i != idMap.end() ? i->second : 0;
-}
-
-void Declaration::dumpIds( std::ostream &os ) {
-	for ( IdMapType::const_iterator i = idMap.begin(); i != idMap.end(); ++i ) {
-		os << i->first << " -> ";
-		i->second->printShort( os );
-		os << std::endl;
-	} // for
-}
-
 
 AsmDecl::AsmDecl( AsmStmt *stmt ) : Declaration( "", Type::StorageClasses(), LinkageSpec::C ), stmt( stmt ) {
Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision d7a02ae903476ded9a21da3034888ccf8617a83d)
+++ src/SynTree/Declaration.h	(revision d60780ce6346125b93e03ce50043a6ffe5b61e92)
@@ -68,7 +68,4 @@
 	virtual void printShort( std::ostream &os, Indenter indent = {} ) const = 0;
 
-	static void dumpIds( std::ostream &os );
-	static Declaration *declFromId( UniqueId id );
-
 	UniqueId uniqueId;
 	Type::StorageClasses storageClasses;
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision d7a02ae903476ded9a21da3034888ccf8617a83d)
+++ src/SynTree/Expression.cc	(revision d60780ce6346125b93e03ce50043a6ffe5b61e92)
@@ -38,5 +38,6 @@
 		for ( InferredParams::const_iterator i = inferParams.begin(); i != inferParams.end(); ++i ) {
 			os << indent+1;
-			Declaration::declFromId( i->second.decl )->printShort( os, indent+1 );
+			assert(i->second.declptr);
+			i->second.declptr->printShort( os, indent+1 );
 			os << std::endl;
 			printInferParams( i->second.expr->inferParams, os, indent+1, level+1 );
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision d7a02ae903476ded9a21da3034888ccf8617a83d)
+++ src/SynTree/Expression.h	(revision d60780ce6346125b93e03ce50043a6ffe5b61e92)
@@ -39,6 +39,8 @@
 /// but subject to decay-to-pointer and type parameter renaming
 struct ParamEntry {
-	ParamEntry(): decl( 0 ), actualType( 0 ), formalType( 0 ), expr( 0 )/*, inferParams( new InferredParams )*/ {}
-	ParamEntry( UniqueId decl, Type * actualType, Type * formalType, Expression* expr ): decl( decl ), actualType( actualType ), formalType( formalType ), expr( expr )/*, inferParams( new InferredParams )*/ {}
+	ParamEntry(): decl( 0 ), declptr(nullptr), actualType( 0 ), formalType( 0 ), expr( 0 )/*, inferParams( new InferredParams )*/ {}
+	ParamEntry( UniqueId decl, Declaration * declptr, Type * actualType, Type * formalType, Expression* expr )
+		: decl( decl ), declptr( declptr ), actualType( actualType ), formalType( formalType ), expr( expr )/*, inferParams( new InferredParams )*/ {
+	}
 	ParamEntry( const ParamEntry & other );
 	ParamEntry( ParamEntry && other );
@@ -47,7 +49,8 @@
 	ParamEntry & operator=( ParamEntry && other );
 
-	UniqueId decl;
-	Type * actualType;
-	Type * formalType;
+	UniqueId const decl;
+	Declaration * const declptr;
+	Type * const actualType;
+	Type * const formalType;
 	Expression * expr;
 	// std::unique_ptr< InferredParams > inferParams;
