Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/AST/Expr.cpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -30,5 +30,5 @@
 #include "Common/SemanticError.h"
 #include "GenPoly/Lvalue.h"        // for referencesPermissable
-#include "ResolvExpr/typeops.h"    // for extractResultType
+#include "ResolvExpr/Unify.h"      // for extractResultType
 #include "Tuples/Tuples.h"         // for makeTupleType
 
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/AST/Node.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -19,5 +19,4 @@
 #include <cstddef>     // for nullptr_t
 #include <iosfwd>
-#include <type_traits> // for remove_reference
 
 #include "Common/ErrorObjects.h"  // for SemanticErrorException
@@ -36,6 +35,6 @@
 	Node(const Node&) : strong_count(0), weak_count(0) {}
 	Node(Node&&) : strong_count(0), weak_count(0) {}
-	Node& operator= (const Node&) = delete;
-	Node& operator= (Node&&) = delete;
+	Node& operator=(const Node&) = delete;
+	Node& operator=(Node&&) = delete;
 	virtual ~Node() {}
 
Index: src/AST/SymbolTable.cpp
===================================================================
--- src/AST/SymbolTable.cpp	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/AST/SymbolTable.cpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -22,5 +22,5 @@
 #include "Inspect.hpp"
 #include "Type.hpp"
-#include "CodeGen/OperatorTable.h"  // for isCtorDtorAssign
+#include "CodeGen/OperatorTable.h"         // for isCtorDtorAssign
 #include "Common/SemanticError.h"
 #include "Common/Stats/Counter.h"
@@ -28,5 +28,6 @@
 #include "InitTweak/InitTweak.h"
 #include "ResolvExpr/Cost.h"
-#include "ResolvExpr/typeops.h"
+#include "ResolvExpr/CandidateFinder.hpp"  // for referenceToRvalueConversion
+#include "ResolvExpr/Unify.h"
 #include "SymTab/Mangler.h"
 
Index: src/Common/ScopedMap.h
===================================================================
--- src/Common/ScopedMap.h	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/Common/ScopedMap.h	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -37,5 +37,5 @@
 		template<typename N>
 		Scope(N && n) : map(), note(std::forward<N>(n)) {}
-		
+
 		Scope() = default;
 		Scope(const Scope &) = default;
@@ -46,5 +46,6 @@
 	typedef std::vector< Scope > ScopeList;
 
-	ScopeList scopes; ///< scoped list of maps
+	/// Scoped list of maps.
+	ScopeList scopes;
 public:
 	typedef typename MapType::key_type key_type;
@@ -58,158 +59,7 @@
 	typedef typename MapType::const_pointer const_pointer;
 
-	class iterator : public std::iterator< std::bidirectional_iterator_tag, value_type > {
-	friend class ScopedMap;
-	friend class const_iterator;
-		typedef typename ScopedMap::MapType::iterator wrapped_iterator;
-		typedef typename ScopedMap::ScopeList scope_list;
-		typedef typename scope_list::size_type size_type;
-
-		/// Checks if this iterator points to a valid item
-		bool is_valid() const {
-			return it != (*scopes)[level].map.end();
-		}
-
-		/// Increments on invalid
-		iterator & next_valid() {
-			if ( ! is_valid() ) { ++(*this); }
-			return *this;
-		}
-
-		/// Decrements on invalid
-		iterator & prev_valid() {
-			if ( ! is_valid() ) { --(*this); }
-			return *this;
-		}
-
-		iterator(scope_list & _scopes, const wrapped_iterator & _it, size_type inLevel)
-			: scopes(&_scopes), it(_it), level(inLevel) {}
-	public:
-		iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
-		iterator & operator= (const iterator & that) {
-			scopes = that.scopes; level = that.level; it = that.it;
-			return *this;
-		}
-
-		reference operator* () { return *it; }
-		pointer operator-> () const { return it.operator->(); }
-
-		iterator & operator++ () {
-			if ( it == (*scopes)[level].map.end() ) {
-				if ( level == 0 ) return *this;
-				--level;
-				it = (*scopes)[level].map.begin();
-			} else {
-				++it;
-			}
-			return next_valid();
-		}
-		iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
-
-		iterator & operator-- () {
-			// may fail if this is the begin iterator; allowed by STL spec
-			if ( it == (*scopes)[level].map.begin() ) {
-				++level;
-				it = (*scopes)[level].map.end();
-			}
-			--it;
-			return prev_valid();
-		}
-		iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
-
-		bool operator== (const iterator & that) const {
-			return scopes == that.scopes && level == that.level && it == that.it;
-		}
-		bool operator!= (const iterator & that) const { return !( *this == that ); }
-
-		size_type get_level() const { return level; }
-
-		Note & get_note() { return (*scopes)[level].note; }
-		const Note & get_note() const { return (*scopes)[level].note; }
-
-	private:
-		scope_list *scopes;
-		wrapped_iterator it;
-		size_type level;
-	};
-
-	class const_iterator : public std::iterator< std::bidirectional_iterator_tag,
-	                                             value_type > {
-	friend class ScopedMap;
-		typedef typename ScopedMap::MapType::iterator wrapped_iterator;
-		typedef typename ScopedMap::MapType::const_iterator wrapped_const_iterator;
-		typedef typename ScopedMap::ScopeList scope_list;
-		typedef typename scope_list::size_type size_type;
-
-		/// Checks if this iterator points to a valid item
-		bool is_valid() const {
-			return it != (*scopes)[level].map.end();
-		}
-
-		/// Increments on invalid
-		const_iterator & next_valid() {
-			if ( ! is_valid() ) { ++(*this); }
-			return *this;
-		}
-
-		/// Decrements on invalid
-		const_iterator & prev_valid() {
-			if ( ! is_valid() ) { --(*this); }
-			return *this;
-		}
-
-		const_iterator(scope_list const & _scopes, const wrapped_const_iterator & _it, size_type inLevel)
-			: scopes(&_scopes), it(_it), level(inLevel) {}
-	public:
-		const_iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
-		const_iterator(const const_iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
-		const_iterator & operator= (const iterator & that) {
-			scopes = that.scopes; level = that.level; it = that.it;
-			return *this;
-		}
-		const_iterator & operator= (const const_iterator & that) {
-			scopes = that.scopes; level = that.level; it = that.it;
-			return *this;
-		}
-
-		const_reference operator* () { return *it; }
-		const_pointer operator-> () { return it.operator->(); }
-
-		const_iterator & operator++ () {
-			if ( it == (*scopes)[level].map.end() ) {
-				if ( level == 0 ) return *this;
-				--level;
-				it = (*scopes)[level].map.begin();
-			} else {
-				++it;
-			}
-			return next_valid();
-		}
-		const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
-
-		const_iterator & operator-- () {
-			// may fail if this is the begin iterator; allowed by STL spec
-			if ( it == (*scopes)[level].map.begin() ) {
-				++level;
-				it = (*scopes)[level].map.end();
-			}
-			--it;
-			return prev_valid();
-		}
-		const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
-
-		bool operator== (const const_iterator & that) const {
-			return scopes == that.scopes && level == that.level && it == that.it;
-		}
-		bool operator!= (const const_iterator & that) const { return !( *this == that ); }
-
-		size_type get_level() const { return level; }
-
-		const Note & get_note() const { return (*scopes)[level].note; }
-
-	private:
-		scope_list const *scopes;
-		wrapped_const_iterator it;
-		size_type level;
-	};
+	// Both iterator types are complete bidrectional iterators, see below.
+	class iterator;
+	class const_iterator;
 
 	/// Starts a new scope
@@ -297,11 +147,4 @@
 	}
 
-	template< typename value_type_t >
-	std::pair< iterator, bool > insert( iterator at, value_type_t && value ) {
-		MapType & scope = (*at.scopes)[ at.level ].map;
-		std::pair< typename MapType::iterator, bool > res = scope.insert( std::forward<value_type_t>( value ) );
-		return std::make_pair( iterator(scopes, std::move( res.first ), at.level), std::move( res.second ) );
-	}
-
 	template< typename value_t >
 	std::pair< iterator, bool > insert( const Key & key, value_t && value ) { return insert( std::make_pair( key, std::forward<value_t>( value ) ) ); }
@@ -324,9 +167,11 @@
 	}
 
-	iterator erase( iterator pos ) {
-		MapType & scope = (*pos.scopes)[ pos.level ].map;
-		const typename iterator::wrapped_iterator & new_it = scope.erase( pos.it );
-		iterator it( *pos.scopes, new_it, pos.level );
-		return it.next_valid();
+	/// Erases element with key in the innermost scope that has it.
+	size_type erase( const Key & key ) {
+		for ( auto it = scopes.rbegin() ; it != scopes.rend() ; ++it ) {
+			size_type i = it->map.erase( key );
+			if ( 0 != i ) return i;
+		}
+		return 0;
 	}
 
@@ -343,4 +188,166 @@
 		return c;
 	}
+
+	bool contains( const Key & key ) const {
+		return find( key ) != cend();
+	}
+};
+
+template<typename Key, typename Value, typename Note>
+class ScopedMap<Key, Value, Note>::iterator :
+		public std::iterator< std::bidirectional_iterator_tag, value_type > {
+	friend class ScopedMap;
+	friend class const_iterator;
+	typedef typename ScopedMap::MapType::iterator wrapped_iterator;
+	typedef typename ScopedMap::ScopeList scope_list;
+	typedef typename scope_list::size_type size_type;
+
+	/// Checks if this iterator points to a valid item
+	bool is_valid() const {
+		return it != (*scopes)[level].map.end();
+	}
+
+	/// Increments on invalid
+	iterator & next_valid() {
+		if ( ! is_valid() ) { ++(*this); }
+		return *this;
+	}
+
+	/// Decrements on invalid
+	iterator & prev_valid() {
+		if ( ! is_valid() ) { --(*this); }
+		return *this;
+	}
+
+	iterator(scope_list & _scopes, const wrapped_iterator & _it, size_type inLevel)
+		: scopes(&_scopes), it(_it), level(inLevel) {}
+public:
+	iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
+	iterator & operator= (const iterator & that) {
+		scopes = that.scopes; level = that.level; it = that.it;
+		return *this;
+	}
+
+	reference operator* () { return *it; }
+	pointer operator-> () const { return it.operator->(); }
+
+	iterator & operator++ () {
+		if ( it == (*scopes)[level].map.end() ) {
+			if ( level == 0 ) return *this;
+			--level;
+			it = (*scopes)[level].map.begin();
+		} else {
+			++it;
+		}
+		return next_valid();
+	}
+	iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
+
+	iterator & operator-- () {
+		// may fail if this is the begin iterator; allowed by STL spec
+		if ( it == (*scopes)[level].map.begin() ) {
+			++level;
+			it = (*scopes)[level].map.end();
+		}
+		--it;
+		return prev_valid();
+	}
+	iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
+
+	bool operator== (const iterator & that) const {
+		return scopes == that.scopes && level == that.level && it == that.it;
+	}
+	bool operator!= (const iterator & that) const { return !( *this == that ); }
+
+	size_type get_level() const { return level; }
+
+	Note & get_note() { return (*scopes)[level].note; }
+	const Note & get_note() const { return (*scopes)[level].note; }
+
+private:
+	scope_list *scopes;
+	wrapped_iterator it;
+	size_type level;
+};
+
+template<typename Key, typename Value, typename Note>
+class ScopedMap<Key, Value, Note>::const_iterator :
+		public std::iterator< std::bidirectional_iterator_tag, value_type > {
+	friend class ScopedMap;
+	typedef typename ScopedMap::MapType::iterator wrapped_iterator;
+	typedef typename ScopedMap::MapType::const_iterator wrapped_const_iterator;
+	typedef typename ScopedMap::ScopeList scope_list;
+	typedef typename scope_list::size_type size_type;
+
+	/// Checks if this iterator points to a valid item
+	bool is_valid() const {
+		return it != (*scopes)[level].map.end();
+	}
+
+	/// Increments on invalid
+	const_iterator & next_valid() {
+		if ( ! is_valid() ) { ++(*this); }
+		return *this;
+	}
+
+	/// Decrements on invalid
+	const_iterator & prev_valid() {
+		if ( ! is_valid() ) { --(*this); }
+		return *this;
+	}
+
+	const_iterator(scope_list const & _scopes, const wrapped_const_iterator & _it, size_type inLevel)
+		: scopes(&_scopes), it(_it), level(inLevel) {}
+public:
+	const_iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
+	const_iterator(const const_iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
+	const_iterator & operator= (const iterator & that) {
+		scopes = that.scopes; level = that.level; it = that.it;
+		return *this;
+	}
+	const_iterator & operator= (const const_iterator & that) {
+		scopes = that.scopes; level = that.level; it = that.it;
+		return *this;
+	}
+
+	const_reference operator* () { return *it; }
+	const_pointer operator-> () { return it.operator->(); }
+
+	const_iterator & operator++ () {
+		if ( it == (*scopes)[level].map.end() ) {
+			if ( level == 0 ) return *this;
+			--level;
+			it = (*scopes)[level].map.begin();
+		} else {
+			++it;
+		}
+		return next_valid();
+	}
+	const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
+
+	const_iterator & operator-- () {
+		// may fail if this is the begin iterator; allowed by STL spec
+		if ( it == (*scopes)[level].map.begin() ) {
+			++level;
+			it = (*scopes)[level].map.end();
+		}
+		--it;
+		return prev_valid();
+	}
+	const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
+
+	bool operator== (const const_iterator & that) const {
+		return scopes == that.scopes && level == that.level && it == that.it;
+	}
+	bool operator!= (const const_iterator & that) const { return !( *this == that ); }
+
+	size_type get_level() const { return level; }
+
+	const Note & get_note() const { return (*scopes)[level].note; }
+
+private:
+	scope_list const *scopes;
+	wrapped_const_iterator it;
+	size_type level;
 };
 
Index: src/Common/SemanticError.h
===================================================================
--- src/Common/SemanticError.h	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/Common/SemanticError.h	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed May  4 14:08:26 2022
-// Update Count     : 35
+// Last Modified On : Thu Feb  2 10:59:10 2023
+// Update Count     : 36
 //
 
@@ -54,12 +54,13 @@
 
 constexpr WarningData WarningFormats[] = {
-	{"self-assign"            , Severity::Warn    , "self assignment of expression: %s"                          },
-	{"reference-conversion"   , Severity::Warn    , "rvalue to reference conversion of rvalue: %s"               },
-	{"qualifiers-zero_t-one_t", Severity::Warn    , "questionable use of type qualifier %s with %s"              },
-	{"aggregate-forward-decl" , Severity::Warn    , "forward declaration of nested aggregate: %s"                },
-	{"superfluous-decl"       , Severity::Warn    , "declaration does not allocate storage: %s"                  },
-	{"superfluous-else"       , Severity::Warn    , "else clause never executed for empty loop conditional"      },
-	{"gcc-attributes"         , Severity::Warn    , "invalid attribute: %s"                                      },
-	{"c++-like-copy"          , Severity::Warn    , "Constructor from reference is not a valid copy constructor" },
+	{"self-assign"              , Severity::Warn    , "self assignment of expression: %s"                          },
+	{"reference-conversion"     , Severity::Warn    , "rvalue to reference conversion of rvalue: %s"               },
+	{"qualifiers-zero_t-one_t"  , Severity::Warn    , "questionable use of type qualifier %s with %s"              },
+	{"aggregate-forward-decl"   , Severity::Warn    , "forward declaration of nested aggregate: %s"                },
+	{"superfluous-decl"         , Severity::Warn    , "declaration does not allocate storage: %s"                  },
+	{"superfluous-else"         , Severity::Warn    , "else clause never executed for empty loop conditional"      },
+	{"gcc-attributes"           , Severity::Warn    , "invalid attribute: %s"                                      },
+	{"c++-like-copy"            , Severity::Warn    , "Constructor from reference is not a valid copy constructor" },
+	{"depreciated-trait-syntax" , Severity::Warn    , "trait type-parameters are now specified using the forall clause" },
 };
 
@@ -73,4 +74,5 @@
 	GccAttributes,
 	CppCopy,
+	DeprecTraitSyntax,
 	NUMBER_OF_WARNINGS, // This MUST be the last warning
 };
Index: src/Concurrency/Actors.cpp
===================================================================
--- src/Concurrency/Actors.cpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
+++ src/Concurrency/Actors.cpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -0,0 +1,481 @@
+//
+// 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.
+//
+// Actors.cpp -- generate code needed by the actor system
+//
+// Author           : Colby Parsons
+// Created On       : Thurs Jan  19 15:34:00 2023
+// Last Modified By : Colby Parsons
+// Last Modified On : Thurs Jan  19 15:34:00 2023
+// Update Count     : 0
+//
+
+#include "AST/Print.hpp"
+#include "AST/Decl.hpp"
+#include "AST/Pass.hpp"
+#include "AST/Type.hpp"
+#include "AST/Stmt.hpp"
+#include "AST/TranslationUnit.hpp"
+#include "AST/Expr.hpp"
+#include <algorithm>
+using namespace ast;
+using namespace std;
+
+namespace Concurrency {
+
+struct CollectactorStructDecls : public ast::WithGuards {
+    unordered_set<const StructDecl *> & actorStructDecls;
+    unordered_set<const StructDecl *>  & messageStructDecls;
+    const StructDecl ** requestDecl;
+    const EnumDecl ** allocationDecl;
+    const StructDecl ** actorDecl;
+    const StructDecl ** msgDecl;
+    StructDecl * parentDecl;
+    bool insideStruct = false;
+    bool namedDecl = false;
+
+    // finds and sets a ptr to the Allocation enum, which is needed in the next pass
+    void previsit( const EnumDecl * decl ) {
+        if( decl->name == "Allocation" ) *allocationDecl = decl;
+    }
+
+    // finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass
+    void previsit( const StructDecl * decl ) {
+        GuardValue(insideStruct);
+        insideStruct = true;
+        parentDecl = mutate( decl );
+        if( decl->name == "actor" ) *actorDecl = decl;
+        if( decl->name == "message" ) *msgDecl = decl;
+        if( decl->name == "request" ) *requestDecl = decl;
+	}
+
+    // this catches structs of the form:
+    //     struct dummy_actor { actor a; };
+    // since they should be:
+    //     struct dummy_actor { inline actor; };
+    void previsit ( const ObjectDecl * decl ) {
+        if ( insideStruct && ! decl->name.empty() ) {
+            GuardValue(namedDecl);
+            namedDecl = true;
+        }
+    }
+
+    // this collects the valid actor and message struct decl pts
+    void postvisit( const StructInstType * node ) {
+        if ( ! *actorDecl || ! *msgDecl ) return;
+        if ( insideStruct && !namedDecl ) {
+            if ( node->aggr() == *actorDecl ) {
+                actorStructDecls.insert( parentDecl );
+            } else if ( node->aggr() == *msgDecl ) {
+                messageStructDecls.insert( parentDecl );
+            }
+        }
+	}
+
+  public:
+    CollectactorStructDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
+        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl ) 
+        : actorStructDecls( actorStructDecls ), messageStructDecls( messageStructDecls ), requestDecl( requestDecl ), 
+        allocationDecl( allocationDecl ), actorDecl(actorDecl), msgDecl(msgDecl) {}
+};
+
+// keeps track of all fwdDecls of message routines so that we can hoist them to right after the appropriate decls
+class FwdDeclTable {
+
+    // tracks which decls we have seen so that we can hoist the FunctionDecl to the highest point possible
+    struct FwdDeclData { 
+        const StructDecl * actorDecl;
+        const StructDecl * msgDecl;
+        FunctionDecl * fwdDecl;
+        bool actorFound;
+        bool msgFound;
+
+        bool readyToInsert() { return actorFound && msgFound; }
+        bool foundActor() { actorFound = true; return readyToInsert(); }
+        bool foundMsg() { msgFound = true; return readyToInsert(); }
+
+        FwdDeclData( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) :
+            actorDecl(actorDecl), msgDecl(msgDecl), fwdDecl(fwdDecl), actorFound(false), msgFound(false) {}
+    };
+
+    // map indexed by actor struct ptr
+    // value is map of all FwdDeclData that contains said actor struct ptr
+    // inner map is indexed by the message struct ptr of FwdDeclData
+    unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> actorMap;
+
+    // this map is the same except the outer map is indexed by message ptr and the inner is indexed by actor ptr
+    unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> msgMap;
+
+    void insert( const StructDecl * decl, const StructDecl * otherDecl, unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map, FwdDeclData * data ) {
+        auto iter = map.find( decl );
+        if ( iter != map.end() ) { // if decl exists in map append data to existing inner map
+            iter->second.emplace( make_pair( otherDecl, data ) );
+        } else { // else create inner map for key
+            map.emplace( make_pair( decl, unordered_map<const StructDecl *, FwdDeclData *>( { make_pair( otherDecl, data ) } ) ) );
+        }
+    }
+
+  public:
+    // insert decl into table so that we can fwd declare it later (average cost: O(1))
+    void insertDecl( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) {
+        FwdDeclData * declToInsert = new FwdDeclData( actorDecl, msgDecl, fwdDecl );
+        insert( actorDecl, msgDecl, actorMap, declToInsert );
+        insert( msgDecl, actorDecl, msgMap, declToInsert );
+    }
+
+    // returns list of decls to insert after current struct decl
+    // Over the entire pass the runtime of this routine is O(r) where r is the # of receive routines
+    list<FunctionDecl *> updateDecl( const StructDecl * decl, bool isMsg ) {
+        unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map = isMsg ? msgMap : actorMap;
+        unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & otherMap =  isMsg ? actorMap : msgMap;
+        auto iter = map.find( decl );
+        list<FunctionDecl *> toInsertAfter; // this is populated with decls that are ready to insert
+        if ( iter == map.end() ) return toInsertAfter;
+        
+        // iterate over inner map
+        unordered_map<const StructDecl *, FwdDeclData *> & currInnerMap = iter->second;
+        for ( auto innerIter = currInnerMap.begin(); innerIter != currInnerMap.end(); ) {
+            FwdDeclData * currentDatum = innerIter->second;
+            bool readyToInsert = isMsg ? currentDatum->foundMsg() : currentDatum->foundActor();
+            if ( ! readyToInsert ) { ++innerIter; continue; }
+            
+            // readyToInsert is true so we are good to insert the forward decl of the message fn
+            toInsertAfter.push_back( currentDatum->fwdDecl );
+
+            // need to remove from other map before deleting
+            // find inner map in other map ( other map is actor map if original is msg map and vice versa )
+            const StructDecl * otherDecl = isMsg ? currentDatum->actorDecl : currentDatum->msgDecl;
+            auto otherMapIter = otherMap.find( otherDecl );
+
+            unordered_map<const StructDecl *, FwdDeclData *> & otherInnerMap = otherMapIter->second;
+
+            // find the FwdDeclData we need to remove in the other inner map
+            auto otherInnerIter = otherInnerMap.find( decl );
+
+            // remove references to deleted FwdDeclData from current inner map
+            innerIter = currInnerMap.erase( innerIter ); // this does the increment so no explicit inc needed
+
+            // remove references to deleted FwdDeclData from other inner map
+            otherInnerMap.erase( otherInnerIter );
+            
+            // if other inner map is now empty, remove key from other outer map
+            if ( otherInnerMap.empty() )
+                otherMap.erase( otherDecl );
+
+            // now we are safe to delete the FwdDeclData since we are done with it
+            // and we have removed all references to it from our data structures
+            delete currentDatum;
+        }
+
+        // if current inner map is now empty, remove key from outer map.
+        // Have to do this after iterating for safety
+        if ( currInnerMap.empty() )
+            map.erase( decl );
+
+        return toInsertAfter;
+    }
+};
+
+#define __ALLOC 0 // C_TODO: complete swap to no-alloc version
+
+struct GenReceiveDecls : public ast::WithDeclsToAdd<> {
+    unordered_set<const StructDecl *> & actorStructDecls;
+    unordered_set<const StructDecl *>  & messageStructDecls;
+    const StructDecl ** requestDecl;
+    const EnumDecl ** allocationDecl;
+    const StructDecl ** actorDecl;
+    const StructDecl ** msgDecl;
+    FwdDeclTable & forwardDecls;
+
+	void postvisit( const FunctionDecl * decl ) {
+        // return if not of the form receive( param1, param2 ) or if it is a forward decl
+        if ( decl->name != "receive" || decl->params.size() != 2 || !decl->stmts ) return;
+
+        // the params should be references
+        const ReferenceType * derivedActorRef = dynamic_cast<const ReferenceType *>(decl->params.at(0)->get_type());
+        const ReferenceType * derivedMsgRef = dynamic_cast<const ReferenceType *>(decl->params.at(1)->get_type());
+        if ( !derivedActorRef || !derivedMsgRef ) return;
+
+        // the references should be to struct instances
+        const StructInstType * arg1InstType = dynamic_cast<const StructInstType *>(derivedActorRef->base.get());
+        const StructInstType * arg2InstType = dynamic_cast<const StructInstType *>(derivedMsgRef->base.get());
+        if ( !arg1InstType || !arg2InstType ) return;
+
+        // If the struct instances are derived actor and message types then generate the message send routine
+        auto actorIter = actorStructDecls.find( arg1InstType->aggr() );
+        auto messageIter = messageStructDecls.find( arg2InstType->aggr() );
+        if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) {
+
+            // check that we have found all the decls we need from <actor.hfa>
+            if ( !*allocationDecl || !*requestDecl ) 
+                SemanticError( decl->location, "using actors requires a header, add #include <actor.hfa>\n" );
+
+            //////////////////////////////////////////////////////////////////////
+            // The following generates this send message operator routine for all receive(derived_actor &, derived_msg &) functions
+            /*
+                static inline derived_actor & ?|?( derived_actor & receiver, derived_msg & msg ) {
+                    request * new_req = alloc();
+                    Allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;
+                    __receive_fn fn = (__receive_fn)my_work_fn;
+                    (*new_req){ &receiver, &msg, fn };
+                    send( receiver, *new_req );
+                    return receiver;
+                }
+            */ // C_TODO: update this with new no alloc version
+            CompoundStmt * sendBody = new CompoundStmt( decl->location );
+
+            #if __ALLOC
+            // Generates: request * new_req = alloc();
+            sendBody->push_back( new DeclStmt(
+                decl->location,
+                new ObjectDecl(
+                    decl->location,
+                    "new_req",
+                    new PointerType( new StructInstType( *requestDecl ) ),
+                    new SingleInit( decl->location, new UntypedExpr( decl->location, new NameExpr( decl->location, "alloc" ), {} ) )
+                )
+            ));
+            #else
+            // Generates: request new_req;
+            sendBody->push_back( new DeclStmt(
+                decl->location,
+                new ObjectDecl(
+                    decl->location,
+                    "new_req",
+                    new StructInstType( *requestDecl )
+                )
+            ));
+            #endif
+            
+            // Function type is: Allocation (*)( derived_actor &, derived_msg & )
+            FunctionType * derivedReceive = new FunctionType();
+            derivedReceive->params.push_back( ast::deepCopy( derivedActorRef ) );
+            derivedReceive->params.push_back( ast::deepCopy( derivedMsgRef ) );
+            derivedReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
+
+            // Generates: Allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;
+            sendBody->push_back( new DeclStmt(
+                decl->location,
+                new ObjectDecl(
+                    decl->location,
+                    "my_work_fn",
+                    new PointerType( derivedReceive ),
+                    new SingleInit( decl->location, new NameExpr( decl->location, "receive" ) )
+                )
+            ));
+
+            // Function type is: Allocation (*)( actor &, messsage & )
+            FunctionType * genericReceive = new FunctionType();
+            genericReceive->params.push_back( new ReferenceType( new StructInstType( *actorDecl ) ) );
+            genericReceive->params.push_back( new ReferenceType( new StructInstType( *msgDecl ) ) );
+            genericReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
+
+            // Generates: Allocation (*fn)( actor &, messsage & ) = (Allocation (*)( actor &, messsage & ))my_work_fn;
+            // More readable synonymous code: 
+            //     typedef Allocation (*__receive_fn)(actor &, message &);
+            //     __receive_fn fn = (__receive_fn)my_work_fn;
+            sendBody->push_back( new DeclStmt(
+                decl->location,
+                new ObjectDecl(
+                    decl->location,
+                    "fn",
+                    new PointerType( genericReceive ),
+                    new SingleInit( decl->location, 
+                        new CastExpr( decl->location, new NameExpr( decl->location, "my_work_fn" ), new PointerType( genericReceive ), ExplicitCast )
+                    )
+                )
+            ));
+
+            #if __ALLOC
+            // Generates: (*new_req){ &receiver, &msg, fn };
+            sendBody->push_back( new ExprStmt(
+                decl->location,
+				new UntypedExpr (
+                    decl->location, 
+					new NameExpr( decl->location, "?{}" ),
+					{
+						new UntypedExpr( decl->location, new NameExpr( decl->location, "*?" ), {  new NameExpr( decl->location, "new_req" ) } ),
+                        new AddressExpr( new NameExpr( decl->location, "receiver" ) ),
+                        new AddressExpr( new NameExpr( decl->location, "msg" ) ),
+                        new NameExpr( decl->location, "fn" )
+					}
+				)
+			));
+
+            // Generates: send( receiver, *new_req );
+            sendBody->push_back( new ExprStmt(
+                decl->location,
+				new UntypedExpr (
+                    decl->location,
+					new NameExpr( decl->location, "send" ),
+					{
+						{
+                            new NameExpr( decl->location, "receiver" ),
+                            new UntypedExpr( decl->location, new NameExpr( decl->location, "*?" ), {  new NameExpr( decl->location, "new_req" ) } )
+                        }
+					}
+				)
+			));
+            #else
+            // Generates: new_req{ &receiver, &msg, fn };
+            sendBody->push_back( new ExprStmt(
+                decl->location,
+				new UntypedExpr (
+                    decl->location, 
+					new NameExpr( decl->location, "?{}" ),
+					{
+						new NameExpr( decl->location, "new_req" ),
+                        new AddressExpr( new NameExpr( decl->location, "receiver" ) ),
+                        new AddressExpr( new NameExpr( decl->location, "msg" ) ),
+                        new NameExpr( decl->location, "fn" )
+					}
+				)
+			));
+
+            // Generates: send( receiver, new_req );
+            sendBody->push_back( new ExprStmt(
+                decl->location,
+				new UntypedExpr (
+                    decl->location,
+					new NameExpr( decl->location, "send" ),
+					{
+						{
+                            new NameExpr( decl->location, "receiver" ),
+                            new NameExpr( decl->location, "new_req" )
+                        }
+					}
+				)
+			));
+            #endif
+            
+            // Generates: return receiver;
+            sendBody->push_back( new ReturnStmt( decl->location, new NameExpr( decl->location, "receiver" ) ) );
+
+            // put it all together into the complete function decl from above
+            FunctionDecl * sendOperatorFunction = new FunctionDecl(
+                decl->location,
+                "?|?",
+                {},                     // forall
+                {
+                    new ObjectDecl(
+                        decl->location,
+                        "receiver",
+                        ast::deepCopy( derivedActorRef )
+                    ),
+                    new ObjectDecl(
+                        decl->location,
+                        "msg",
+                        ast::deepCopy( derivedMsgRef )
+                    )
+                },                      // params
+                { 
+                    new ObjectDecl(
+                        decl->location,
+                        "receiver_ret",
+                        ast::deepCopy( derivedActorRef )
+                    )
+                },
+                nullptr,               // body
+                { Storage::Static },    // storage
+                Linkage::Cforall,       // linkage
+                {},                     // attributes
+                { Function::Inline }
+            );
+            
+            // forward decls to resolve use before decl problem for '|' routines
+            forwardDecls.insertDecl( *actorIter, *messageIter , ast::deepCopy( sendOperatorFunction ) );
+            // forwardDecls.push_back( ast::deepCopy( sendOperatorFunction ) );
+
+            sendOperatorFunction->stmts = sendBody;
+            declsToAddAfter.push_back( sendOperatorFunction );
+        }
+	}
+
+  public:
+    GenReceiveDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
+        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl, 
+        FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls), 
+        requestDecl(requestDecl), allocationDecl(allocationDecl), actorDecl(actorDecl), msgDecl(msgDecl), forwardDecls(forwardDecls) {}
+};
+
+struct GenFwdDecls : public ast::WithDeclsToAdd<> {
+    unordered_set<const StructDecl *> & actorStructDecls;
+    unordered_set<const StructDecl *>  & messageStructDecls;
+    FwdDeclTable & forwardDecls;
+
+    void postvisit( const StructDecl * decl ) {
+        list<FunctionDecl *> toAddAfter;
+        auto actorIter = actorStructDecls.find( decl );
+        if ( actorIter != actorStructDecls.end() ) { // this is a derived actor decl
+            // get list of fwd decls that we can now insert
+            toAddAfter = forwardDecls.updateDecl( decl, false );
+
+            // get rid of decl from actorStructDecls since we no longer need it
+            actorStructDecls.erase( actorIter );
+        } else {
+            auto messageIter = messageStructDecls.find( decl );
+            if ( messageIter == messageStructDecls.end() ) return;
+
+            toAddAfter = forwardDecls.updateDecl( decl, true );
+
+            // get rid of decl from messageStructDecls since we no longer need it
+            messageStructDecls.erase( messageIter );
+        }
+
+        // add the fwd decls to declsToAddAfter
+        for ( FunctionDecl * func : toAddAfter ) {
+            declsToAddAfter.push_back( func );
+        }
+    }
+
+  public:
+    GenFwdDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls, 
+        FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
+        forwardDecls(forwardDecls) {}
+};
+
+void implementActors( TranslationUnit & translationUnit ) {
+    // unordered_maps to collect all derived actor and message types
+    unordered_set<const StructDecl *> actorStructDecls;
+    unordered_set<const StructDecl *> messageStructDecls;
+    FwdDeclTable forwardDecls;
+
+    // for storing through the passes
+    // these are populated with various important struct decls
+    const StructDecl * requestDeclPtr = nullptr;
+    const EnumDecl * allocationDeclPtr = nullptr;
+    const StructDecl * actorDeclPtr = nullptr;
+    const StructDecl * msgDeclPtr = nullptr;
+
+    // double pointer to modify local ptrs above
+    const StructDecl ** requestDecl = &requestDeclPtr;
+    const EnumDecl ** allocationDecl = &allocationDeclPtr;
+    const StructDecl ** actorDecl = &actorDeclPtr;
+    const StructDecl ** msgDecl = &msgDeclPtr;
+
+    // first pass collects ptrs to Allocation enum, request type, and generic receive fn typedef
+    // also populates maps of all derived actors and messages
+    Pass<CollectactorStructDecls>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl, 
+        allocationDecl, actorDecl, msgDecl );
+	
+    // second pass locates all receive() routines that overload the generic receive fn
+    // it then generates the appropriate operator '|' send routines for the receive routines
+    Pass<GenReceiveDecls>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl, 
+        allocationDecl, actorDecl, msgDecl, forwardDecls );
+
+    // The third pass forward declares operator '|' send routines
+    Pass<GenFwdDecls>::run( translationUnit, actorStructDecls, messageStructDecls, forwardDecls );
+}
+
+
+} // namespace Concurrency
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
+
Index: src/Concurrency/Actors.hpp
===================================================================
--- src/Concurrency/Actors.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
+++ src/Concurrency/Actors.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -0,0 +1,32 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Keywords.h -- Implement concurrency constructs from their keywords.
+//
+// Author           : Colby Parsons
+// Created On       : Thurs Jan 19 15:16:42 2023
+// Last Modified By :
+// Last Modified On :
+// Update Count     : 1
+//
+
+#pragma once
+
+
+class Declaration;
+namespace ast {
+	class TranslationUnit;
+}
+
+namespace Concurrency {
+	void implementActors( ast::TranslationUnit & translationUnit );
+};
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Concurrency/module.mk
===================================================================
--- src/Concurrency/module.mk	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/Concurrency/module.mk	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -16,4 +16,6 @@
 
 SRC += \
+	Concurrency/Actors.cpp \
+	Concurrency/Actors.hpp \
 	Concurrency/KeywordsNew.cpp \
 	Concurrency/Keywords.cc \
@@ -21,3 +23,3 @@
 	Concurrency/WaitforNew.cpp \
 	Concurrency/Waitfor.cc \
-	Concurrency/Waitfor.h
+	Concurrency/Waitfor.h 
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/GenPoly/Box.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -14,4 +14,6 @@
 //
 
+#include "Box.h"
+
 #include <algorithm>                     // for mismatch
 #include <cassert>                       // for assert, strict_dynamic_cast
@@ -23,6 +25,4 @@
 #include <string>                        // for string, allocator, basic_string
 #include <utility>                       // for pair
-
-#include "Box.h"
 
 #include "CodeGen/OperatorTable.h"
@@ -37,5 +37,5 @@
 #include "InitTweak/InitTweak.h"         // for getFunctionName, isAssignment
 #include "Lvalue.h"                      // for generalizedLvalue
-#include "ResolvExpr/typeops.h"          // for typesCompatible
+#include "ResolvExpr/Unify.h"            // for typesCompatible
 #include "ScopedSet.h"                   // for ScopedSet, ScopedSet<>::iter...
 #include "ScrubTyVars.h"                 // for ScrubTyVars
@@ -488,5 +488,5 @@
 				for ( FunctionType const * const funType : functions ) {
 					std::string mangleName = mangleAdapterName( funType, scopeTyVars );
-					if ( adapters.find( mangleName ) == adapters.end() ) {
+					if ( !adapters.contains( mangleName ) ) {
 						std::string adapterName = makeAdapterName( mangleName );
 						adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, nullptr, new PointerType( Type::Qualifiers(), makeAdapterType( funType, scopeTyVars ) ), nullptr ) ) );
@@ -911,33 +911,31 @@
 
 			for ( FunctionType const * const funType : functions ) {
-				FunctionType *originalFunction = funType->clone();
-				FunctionType *realFunction = funType->clone();
-				std::string mangleName = SymTab::Mangler::mangle( realFunction );
+				std::string mangleName = SymTab::Mangler::mangle( funType );
 
 				// only attempt to create an adapter or pass one as a parameter if we haven't already done so for this
 				// pre-substitution parameter function type.
 				// The second part of the insert result is "is the value new".
-				if ( adaptersDone.insert( mangleName ).second ) {
-
-					// apply substitution to type variables to figure out what the adapter's type should look like
-					assert( env );
-					env->apply( realFunction );
-					mangleName = SymTab::Mangler::mangle( realFunction );
-					mangleName += makePolyMonoSuffix( originalFunction, exprTyVars );
-
-					typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
-					AdapterIter adapter = adapters.find( mangleName );
-					if ( adapter == adapters.end() ) {
-						// adapter has not been created yet in the current scope, so define it
-						FunctionDecl *newAdapter = makeAdapter( funType, realFunction, mangleName, exprTyVars );
-						std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
-						adapter = answer.first;
-						stmtsToAddBefore.push_back( new DeclStmt( newAdapter ) );
-					} // if
-					assert( adapter != adapters.end() );
-
-					// add the appropriate adapter as a parameter
-					appExpr->get_args().push_front( new VariableExpr( adapter->second ) );
+				if ( !adaptersDone.insert( mangleName ).second ) continue;
+
+				// Apply substitution to type variables to figure out what the adapter's type should look like.
+				assert( env );
+				FunctionType *realType = funType->clone();
+				env->apply( realType );
+				mangleName = SymTab::Mangler::mangle( realType );
+				mangleName += makePolyMonoSuffix( funType, exprTyVars );
+
+				typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
+				AdapterIter adapter = adapters.find( mangleName );
+				if ( adapter == adapters.end() ) {
+					// Adapter has not been created yet in the current scope, so define it.
+					FunctionDecl *newAdapter = makeAdapter( funType, realType, mangleName, exprTyVars );
+					std::pair< AdapterIter, bool > answer = adapters.insert( mangleName, newAdapter );
+					adapter = answer.first;
+					stmtsToAddBefore.push_back( new DeclStmt( newAdapter ) );
 				} // if
+				assert( adapter != adapters.end() );
+
+				// Add the appropriate adapter as a parameter.
+				appExpr->args.push_front( new VariableExpr( adapter->second ) );
 			} // for
 		} // passAdapters
@@ -1489,5 +1487,5 @@
 					if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
 						// do not try to monomorphize generic parameters
-						if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() && ! genericParams.count( typeInst->name ) ) {
+						if ( scopeTyVars.contains( typeInst->get_name() ) && ! genericParams.count( typeInst->name ) ) {
 							// polymorphic aggregate members should be converted into monomorphic members.
 							// Using char[size_T] here respects the expected sizing rules of an aggregate type.
@@ -1698,5 +1696,5 @@
 
 			if ( auto typeInst = dynamic_cast< TypeInstType const * >( ty ) ) {
-				if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
+				if ( scopeTyVars.contains( typeInst->get_name() ) ) {
 					// NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
 					return true;
@@ -1706,5 +1704,5 @@
 				// check if this type already has a layout generated for it
 				std::string typeName = mangleType( ty );
-				if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
+				if ( knownLayouts.contains( typeName ) ) return true;
 
 				// check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
@@ -1743,5 +1741,5 @@
 				// check if this type already has a layout generated for it
 				std::string typeName = mangleType( ty );
-				if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
+				if ( knownLayouts.contains( typeName ) ) return true;
 
 				// check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
@@ -1834,5 +1832,5 @@
 			} else {
 				std::string offsetName = offsetofName( mangleType( ty ) );
-				if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
+				if ( knownOffsets.contains( offsetName ) ) {
 					// use the already-generated offsets for this type
 					ret = new NameExpr( offsetName );
Index: src/GenPoly/ErasableScopedMap.h
===================================================================
--- src/GenPoly/ErasableScopedMap.h	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/GenPoly/ErasableScopedMap.h	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// ScopedMap.h --
+// ErasableScopedMap.h --
 //
 // Author           : Aaron B. Moss
@@ -51,5 +51,5 @@
 	typedef typename Scope::const_pointer const_pointer;
 
-	// Both iterator types are complete bidirection iterators, defined below.
+	// Both iterator types are complete bidirectional iterators, see below.
 	class iterator;
 	class const_iterator;
@@ -118,4 +118,10 @@
 	std::pair< iterator, bool > insert( const Key &key, const Value &value ) { return insert( std::make_pair( key, value ) ); }
 
+	Value& operator[] ( const Key &key ) {
+		iterator slot = find( key );
+		if ( slot != end() ) return slot->second;
+		return insert( key, Value() ).first->second;
+	}
+
 	/// Marks the given element as erased from this scope inward; returns 1 for erased an element, 0 otherwise
 	size_type erase( const Key &key ) {
@@ -130,8 +136,6 @@
 	}
 
-	Value& operator[] ( const Key &key ) {
-		iterator slot = find( key );
-		if ( slot != end() ) return slot->second;
-		return insert( key, Value() ).first->second;
+	bool contains( const Key & key ) const {
+		return find( key ) != cend();
 	}
 };
Index: src/GenPoly/GenPoly.cc
===================================================================
--- src/GenPoly/GenPoly.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/GenPoly/GenPoly.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -24,5 +24,7 @@
 #include <vector>                       // for vector
 
+#include "AST/Expr.hpp"
 #include "AST/Type.hpp"
+#include "AST/TypeSubstitution.hpp"
 #include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
 #include "ResolvExpr/typeops.h"         // for flatten
@@ -170,5 +172,5 @@
 
 		if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
-			if ( tyVars.find( typeInst->get_name() ) != tyVars.end() ) {
+			if ( tyVars.contains( typeInst->get_name() ) ) {
 				return type;
 			}
@@ -187,5 +189,5 @@
 
 		if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
-			return tyVars.find(typeInst->typeString()) != tyVars.end() ? type : nullptr;
+			if ( tyVars.contains( typeInst->typeString() ) ) return type;
 		} else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
 			return isPolyType( arrayType->base, env );
@@ -203,5 +205,5 @@
 
 	if ( auto inst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
-		if ( typeVars.find( *inst ) != typeVars.end() ) return type;
+		if ( typeVars.contains( *inst ) ) return type;
 	} else if ( auto array = dynamic_cast< const ast::ArrayType * >( type ) ) {
 		return isPolyType( array->base, subst );
@@ -391,5 +393,5 @@
 
 		if ( TypeInstType *typeInstType = dynamic_cast< TypeInstType * >( type ) ) {
-			if ( tyVars.find( typeInstType->get_name() ) != tyVars.end() ) {
+			if ( tyVars.contains( typeInstType->get_name() ) ) {
 				return true;
 			}
@@ -490,4 +492,6 @@
 		}
 
+		/// Flattens a list of types.
+		// There is another flattenList in Unify.
 		void flattenList( vector<ast::ptr<ast::Type>> const & src,
 				vector<ast::ptr<ast::Type>> & out ) {
Index: src/GenPoly/InstantiateGeneric.cc
===================================================================
--- src/GenPoly/InstantiateGeneric.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/GenPoly/InstantiateGeneric.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -28,5 +28,6 @@
 #include "GenPoly.h"                   // for isPolyType, typesPolyCompatible
 #include "InitTweak/InitTweak.h"
-#include "ResolvExpr/typeops.h"
+#include "ResolvExpr/AdjustExprType.hpp"  // for adjustExprType
+#include "ResolvExpr/Unify.h"          // for typesCompatible
 #include "ScopedSet.h"                 // for ScopedSet, ScopedSet<>::iterator
 #include "ScrubTyVars.h"               // for ScrubTyVars
Index: src/GenPoly/InstantiateGenericNew.cpp
===================================================================
--- src/GenPoly/InstantiateGenericNew.cpp	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/GenPoly/InstantiateGenericNew.cpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -32,5 +32,6 @@
 #include "GenPoly/GenPoly.h"           // for isPolyType, typesPolyCompatible
 #include "GenPoly/ScrubTyVars.h"       // for scrubAll
-#include "ResolvExpr/typeops.h"        // for typesCompatible
+#include "ResolvExpr/AdjustExprType.hpp"  // for adjustExprType
+#include "ResolvExpr/Unify.h"          // for typesCompatible
 
 namespace GenPoly {
Index: src/GenPoly/ScopedSet.h
===================================================================
--- src/GenPoly/ScopedSet.h	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/GenPoly/ScopedSet.h	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -21,231 +21,243 @@
 
 namespace GenPoly {
-	/// A set where the items are placed into nested scopes;
-	/// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward
-	template<typename Value>
-	class ScopedSet {
-		typedef std::set< Value > Scope;
-		typedef std::vector< Scope > ScopeList;
-
-		ScopeList scopes; ///< scoped list of sets
-	public:
-		typedef typename Scope::key_type key_type;
-		typedef typename Scope::value_type value_type;
-		typedef typename ScopeList::size_type size_type;
-		typedef typename ScopeList::difference_type difference_type;
-		typedef typename Scope::reference reference;
-		typedef typename Scope::const_reference const_reference;
-		typedef typename Scope::pointer pointer;
-		typedef typename Scope::const_pointer const_pointer;
-
-		class iterator : public std::iterator< std::bidirectional_iterator_tag,
-		                                       value_type > {
-		friend class ScopedSet;
-		friend class const_iterator;
-			typedef typename std::set< Value >::iterator wrapped_iterator;
-			typedef typename std::vector< std::set< Value > > scope_list;
-			typedef typename scope_list::size_type size_type;
-
-			/// Checks if this iterator points to a valid item
-			bool is_valid() const {
-				return it != (*scopes)[i].end();
-			}
-
-			/// Increments on invalid
-			iterator& next_valid() {
-				if ( ! is_valid() ) { ++(*this); }
-				return *this;
-			}
-
-			/// Decrements on invalid
-			iterator& prev_valid() {
-				if ( ! is_valid() ) { --(*this); }
-				return *this;
-			}
-
-			iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i)
-				: scopes(&_scopes), it(_it), i(_i) {}
-		public:
-			iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
-			iterator& operator= (const iterator &that) {
-				scopes = that.scopes; i = that.i; it = that.it;
-				return *this;
-			}
-
-			reference operator* () { return *it; }
-			pointer operator-> () { return it.operator->(); }
-
-			iterator& operator++ () {
-				if ( it == (*scopes)[i].end() ) {
-					if ( i == 0 ) return *this;
-					--i;
-					it = (*scopes)[i].begin();
-				} else {
-					++it;
-				}
-				return next_valid();
-			}
-			iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
-
-			iterator& operator-- () {
-				// may fail if this is the begin iterator; allowed by STL spec
-				if ( it == (*scopes)[i].begin() ) {
-					++i;
-					it = (*scopes)[i].end();
-				}
-				--it;
-				return prev_valid();
-			}
-			iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
-
-			bool operator== (const iterator &that) {
-				return scopes == that.scopes && i == that.i && it == that.it;
-			}
-			bool operator!= (const iterator &that) { return !( *this == that ); }
-
-			size_type get_level() const { return i; }
-
-		private:
-			scope_list const *scopes;
-			wrapped_iterator it;
-			size_type i;
-		};
-
-		class const_iterator : public std::iterator< std::bidirectional_iterator_tag,
-		                                             value_type > {
-		friend class ScopedSet;
-			typedef typename std::set< Value >::iterator wrapped_iterator;
-			typedef typename std::set< Value >::const_iterator wrapped_const_iterator;
-			typedef typename std::vector< std::set< Value > > scope_list;
-			typedef typename scope_list::size_type size_type;
-
-			/// Checks if this iterator points to a valid item
-			bool is_valid() const {
-				return it != (*scopes)[i].end();
-			}
-
-			/// Increments on invalid
-			const_iterator& next_valid() {
-				if ( ! is_valid() ) { ++(*this); }
-				return *this;
-			}
-
-			/// Decrements on invalid
-			const_iterator& prev_valid() {
-				if ( ! is_valid() ) { --(*this); }
-				return *this;
-			}
-
-			const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i)
-				: scopes(&_scopes), it(_it), i(_i) {}
-		public:
-			const_iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
-			const_iterator(const const_iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
-			const_iterator& operator= (const iterator &that) {
-				scopes = that.scopes; i = that.i; it = that.it;
-				return *this;
-			}
-			const_iterator& operator= (const const_iterator &that) {
-				scopes = that.scopes; i = that.i; it = that.it;
-				return *this;
-			}
-
-			const_reference operator* () { return *it; }
-			const_pointer operator-> () { return it.operator->(); }
-
-			const_iterator& operator++ () {
-				if ( it == (*scopes)[i].end() ) {
-					if ( i == 0 ) return *this;
-					--i;
-					it = (*scopes)[i].begin();
-				} else {
-					++it;
-				}
-				return next_valid();
-			}
-			const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
-
-			const_iterator& operator-- () {
-				// may fail if this is the begin iterator; allowed by STL spec
-				if ( it == (*scopes)[i].begin() ) {
-					++i;
-					it = (*scopes)[i].end();
-				}
-				--it;
-				return prev_valid();
-			}
-			const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
-
-			bool operator== (const const_iterator &that) {
-				return scopes == that.scopes && i == that.i && it == that.it;
-			}
-			bool operator!= (const const_iterator &that) { return !( *this == that ); }
-
-			size_type get_level() const { return i; }
-
-		private:
-			scope_list const *scopes;
-			wrapped_const_iterator it;
-			size_type i;
-		};
-
-		/// Starts a new scope
-		void beginScope() {
-			Scope scope;
-			scopes.push_back(scope);
-		}
-
-		/// Ends a scope; invalidates any iterators pointing to elements of that scope
-		void endScope() {
-			scopes.pop_back();
-		}
-
-		/// Default constructor initializes with one scope
-		ScopedSet() { beginScope(); }
-
-		iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
-		const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
-		const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
-		iterator end() { return iterator(scopes, scopes[0].end(), 0); }
-		const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); }
-		const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); }
-
-		/// Gets the index of the current scope (counted from 1)
-		size_type currentScope() const { return scopes.size(); }
-
-		/// Finds the given key in the outermost scope it occurs; returns end() for none such
-		iterator find( const Value &key ) {
-			for ( size_type i = scopes.size() - 1; ; --i ) {
-				typename Scope::iterator val = scopes[i].find( key );
-				if ( val != scopes[i].end() ) return iterator( scopes, val, i );
-				if ( i == 0 ) break;
-			}
-			return end();
-		}
-		const_iterator find( const Value &key ) const {
-			return const_iterator( const_cast< ScopedSet< Value >* >(this)->find( key ) );
-		}
-
-		/// Finds the given key in the outermost scope inside the given scope where it occurs
-		iterator findNext( const_iterator &it, const Value &key ) {
-			if ( it.i == 0 ) return end();
+
+/// A set where the items are placed into nested scopes;
+/// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward
+template<typename Value>
+class ScopedSet {
+	typedef std::set< Value > Scope;
+	typedef std::vector< Scope > ScopeList;
+
+	/// Scoped list of sets.
+	ScopeList scopes;
+public:
+	typedef typename Scope::key_type key_type;
+	typedef typename Scope::value_type value_type;
+	typedef typename ScopeList::size_type size_type;
+	typedef typename ScopeList::difference_type difference_type;
+	typedef typename Scope::reference reference;
+	typedef typename Scope::const_reference const_reference;
+	typedef typename Scope::pointer pointer;
+	typedef typename Scope::const_pointer const_pointer;
+
+	// Both iterator types are complete bidirectional iterators, see below.
+	class iterator;
+	class const_iterator;
+
+	/// Starts a new scope
+	void beginScope() {
+		Scope scope;
+		scopes.push_back(scope);
+	}
+
+	/// Ends a scope; invalidates any iterators pointing to elements of that scope
+	void endScope() {
+		scopes.pop_back();
+	}
+
+	/// Default constructor initializes with one scope
+	ScopedSet() { beginScope(); }
+
+	iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
+	const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
+	const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
+	iterator end() { return iterator(scopes, scopes[0].end(), 0); }
+	const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); }
+	const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); }
+
+	/// Gets the index of the current scope (counted from 1)
+	size_type currentScope() const { return scopes.size(); }
+
+	/// Finds the given key in the outermost scope it occurs; returns end() for none such
+	iterator find( const Value &key ) {
+		for ( size_type i = scopes.size() - 1; ; --i ) {
+			typename Scope::iterator val = scopes[i].find( key );
+			if ( val != scopes[i].end() ) return iterator( scopes, val, i );
+			if ( i == 0 ) break;
+		}
+		return end();
+	}
+	const_iterator find( const Value &key ) const {
+		return const_iterator( const_cast< ScopedSet< Value >* >(this)->find( key ) );
+	}
+
+	/// Finds the given key in the outermost scope inside the given scope where it occurs
+	iterator findNext( const_iterator &it, const Value &key ) {
+		if ( it.i == 0 ) return end();
 			for ( size_type i = it.i - 1; ; --i ) {
-				typename Scope::iterator val = scopes[i].find( key );
-				if ( val != scopes[i].end() ) return iterator( scopes, val, i );
-				if ( i == 0 ) break;
-			}
-			return end();
-		}
-		const_iterator findNext( const_iterator &it, const Value &key ) const {
-			return const_iterator( const_cast< ScopedSet< Value >* >(this)->findNext( it, key ) );
-		}
-
-		/// Inserts the given value into the outermost scope
-		std::pair< iterator, bool > insert( const value_type &value ) {
-			std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value );
-			return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second );
-		}
-
-	};
+			typename Scope::iterator val = scopes[i].find( key );
+			if ( val != scopes[i].end() ) return iterator( scopes, val, i );
+			if ( i == 0 ) break;
+		}
+		return end();
+	}
+	const_iterator findNext( const_iterator &it, const Value &key ) const {
+		return const_iterator( const_cast< ScopedSet< Value >* >(this)->findNext( it, key ) );
+	}
+
+	/// Inserts the given value into the outermost scope
+	std::pair< iterator, bool > insert( const value_type &value ) {
+		std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value );
+		return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second );
+	}
+
+	bool contains( const Value & key ) const {
+		return find( key ) != cend();
+	}
+};
+
+template<typename Value>
+class ScopedSet<Value>::iterator :
+		public std::iterator< std::bidirectional_iterator_tag, value_type > {
+	friend class ScopedSet;
+	friend class const_iterator;
+	typedef typename std::set< Value >::iterator wrapped_iterator;
+	typedef typename std::vector< std::set< Value > > scope_list;
+	typedef typename scope_list::size_type size_type;
+
+	/// Checks if this iterator points to a valid item
+	bool is_valid() const {
+		return it != (*scopes)[i].end();
+	}
+
+	/// Increments on invalid
+	iterator& next_valid() {
+		if ( ! is_valid() ) { ++(*this); }
+		return *this;
+	}
+
+	/// Decrements on invalid
+	iterator& prev_valid() {
+		if ( ! is_valid() ) { --(*this); }
+		return *this;
+	}
+
+	iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i)
+		: scopes(&_scopes), it(_it), i(_i) {}
+public:
+	iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
+	iterator& operator= (const iterator &that) {
+		scopes = that.scopes; i = that.i; it = that.it;
+		return *this;
+	}
+
+	reference operator* () { return *it; }
+	pointer operator-> () { return it.operator->(); }
+
+	iterator& operator++ () {
+		if ( it == (*scopes)[i].end() ) {
+			if ( i == 0 ) return *this;
+			--i;
+			it = (*scopes)[i].begin();
+		} else {
+			++it;
+		}
+		return next_valid();
+	}
+	iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
+
+	iterator& operator-- () {
+		// may fail if this is the begin iterator; allowed by STL spec
+		if ( it == (*scopes)[i].begin() ) {
+			++i;
+			it = (*scopes)[i].end();
+		}
+		--it;
+		return prev_valid();
+	}
+	iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
+
+	bool operator== (const iterator &that) {
+		return scopes == that.scopes && i == that.i && it == that.it;
+	}
+	bool operator!= (const iterator &that) { return !( *this == that ); }
+
+	size_type get_level() const { return i; }
+
+private:
+	scope_list const *scopes;
+	wrapped_iterator it;
+	size_type i;
+};
+
+template<typename Value>
+class ScopedSet<Value>::const_iterator :
+		public std::iterator< std::bidirectional_iterator_tag, value_type > {
+	friend class ScopedSet;
+	typedef typename std::set< Value >::iterator wrapped_iterator;
+	typedef typename std::set< Value >::const_iterator wrapped_const_iterator;
+	typedef typename std::vector< std::set< Value > > scope_list;
+	typedef typename scope_list::size_type size_type;
+
+	/// Checks if this iterator points to a valid item
+	bool is_valid() const {
+		return it != (*scopes)[i].end();
+	}
+
+	/// Increments on invalid
+	const_iterator& next_valid() {
+		if ( ! is_valid() ) { ++(*this); }
+		return *this;
+	}
+
+	/// Decrements on invalid
+	const_iterator& prev_valid() {
+		if ( ! is_valid() ) { --(*this); }
+		return *this;
+	}
+
+	const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i)
+		: scopes(&_scopes), it(_it), i(_i) {}
+public:
+	const_iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
+	const_iterator(const const_iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
+	const_iterator& operator= (const iterator &that) {
+		scopes = that.scopes; i = that.i; it = that.it;
+		return *this;
+	}
+	const_iterator& operator= (const const_iterator &that) {
+		scopes = that.scopes; i = that.i; it = that.it;
+		return *this;
+	}
+
+	const_reference operator* () { return *it; }
+	const_pointer operator-> () { return it.operator->(); }
+
+	const_iterator& operator++ () {
+		if ( it == (*scopes)[i].end() ) {
+			if ( i == 0 ) return *this;
+			--i;
+			it = (*scopes)[i].begin();
+		} else {
+			++it;
+		}
+		return next_valid();
+	}
+	const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
+
+	const_iterator& operator-- () {
+		// may fail if this is the begin iterator; allowed by STL spec
+		if ( it == (*scopes)[i].begin() ) {
+			++i;
+			it = (*scopes)[i].end();
+		}
+		--it;
+		return prev_valid();
+	}
+	const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
+
+	bool operator== (const const_iterator &that) {
+		return scopes == that.scopes && i == that.i && it == that.it;
+	}
+	bool operator!= (const const_iterator &that) { return !( *this == that ); }
+
+	size_type get_level() const { return i; }
+
+private:
+	scope_list const *scopes;
+	wrapped_const_iterator it;
+	size_type i;
+};
+
 } // namespace GenPoly
 
Index: src/GenPoly/ScrubTyVars.cc
===================================================================
--- src/GenPoly/ScrubTyVars.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/GenPoly/ScrubTyVars.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -178,31 +178,27 @@
 
 ast::Type const * ScrubTypeVars::postvisit( ast::TypeInstType const * type ) {
+	ast::TypeDecl::Kind kind;
 	// This implies that mode == ScrubMode::All.
 	if ( !typeVars ) {
-		if ( ast::TypeDecl::Ftype == type->kind ) {
-			return new ast::PointerType(
-				new ast::FunctionType( ast::FixedArgs ) );
-		} else {
-			return new ast::PointerType(
-				new ast::VoidType( type->qualifiers ) );
-		}
-	}
-
-	auto typeVar = typeVars->find( *type );
-	if ( typeVar == typeVars->end() ) {
-		return type;
-	}
-
-	switch ( typeVar->second.kind ) {
-	case ::TypeDecl::Dtype:
-	case ::TypeDecl::Ttype:
+		kind = type->kind;
+	} else {
+		// Otherwise, only scrub the type var if it is in map.
+		auto typeVar = typeVars->find( *type );
+		if ( typeVar == typeVars->end() ) {
+			return type;
+		}
+		kind = typeVar->second.kind;
+	}
+
+	switch ( kind ) {
+	case ast::TypeDecl::Dtype:
+	case ast::TypeDecl::Ttype:
 		return new ast::PointerType(
 			new ast::VoidType( type->qualifiers ) );
-	case ::TypeDecl::Ftype:
+	case ast::TypeDecl::Ftype:
 		return new ast::PointerType(
 			new ast::FunctionType( ast::VariableArgs ) );
 	default:
-		assertf( false,
-			"Unhandled type variable kind: %d", typeVar->second.kind );
+		assertf( false, "Unhandled type variable kind: %d", kind );
 		throw; // Just in case the assert is removed, stop here.
 	}
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/InitTweak/FixInit.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -39,5 +39,5 @@
 #include "InitTweak.h"                 // for getFunctionName, getCallArg
 #include "ResolvExpr/Resolver.h"       // for findVoidExpression
-#include "ResolvExpr/typeops.h"        // for typesCompatible
+#include "ResolvExpr/Unify.h"          // for typesCompatible
 #include "SymTab/Autogen.h"            // for genImplicitCall
 #include "SymTab/Indexer.h"            // for Indexer
Index: src/InitTweak/FixInitNew.cpp
===================================================================
--- src/InitTweak/FixInitNew.cpp	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/InitTweak/FixInitNew.cpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -26,5 +26,5 @@
 #include "GenPoly/GenPoly.h"           // for getFunctionType
 #include "ResolvExpr/Resolver.h"       // for findVoidExpression
-#include "ResolvExpr/typeops.h"        // for typesCompatible
+#include "ResolvExpr/Unify.h"          // for typesCompatible
 #include "SymTab/Autogen.h"            // for genImplicitCall
 #include "SymTab/Indexer.h"            // for Indexer
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/InitTweak/InitTweak.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -35,5 +35,5 @@
 #include "GenPoly/GenPoly.h"       // for getFunctionType
 #include "InitTweak.h"
-#include "ResolvExpr/typeops.h"    // for typesCompatibleIgnoreQualifiers
+#include "ResolvExpr/Unify.h"      // for typesCompatibleIgnoreQualifiers
 #include "SymTab/Autogen.h"
 #include "SymTab/Indexer.h"        // for Indexer
Index: src/Parser/lex.ll
===================================================================
--- src/Parser/lex.ll	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/Parser/lex.ll	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -10,6 +10,6 @@
  * Created On       : Sat Sep 22 08:58:10 2001
  * Last Modified By : Peter A. Buhr
- * Last Modified On : Thu Oct 13 20:46:04 2022
- * Update Count     : 764
+ * Last Modified On : Mon Jan 30 19:03:34 2023
+ * Update Count     : 767
  */
 
@@ -340,4 +340,5 @@
 vtable			{ KEYWORD_RETURN(VTABLE); }				// CFA
 waitfor			{ KEYWORD_RETURN(WAITFOR); }			// CFA
+waituntil		{ KEYWORD_RETURN(WAITUNTIL); }			// CFA
 when			{ KEYWORD_RETURN(WHEN); }				// CFA
 while			{ KEYWORD_RETURN(WHILE); }
@@ -502,5 +503,5 @@
 	SemanticErrorThrow = true;
 	cerr << (yyfilename ? yyfilename : "*unknown file*") << ':' << yylineno << ':' << column - yyleng + 1
-		 << ": " << ErrorHelpers::error_str() << errmsg << " at token \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl;
+		 << ": " << ErrorHelpers::error_str() << errmsg << " before token \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl;
 }
 
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/Parser/parser.yy	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -10,6 +10,6 @@
 // Created On       : Sat Sep  1 20:22:55 2001
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Nov 21 22:34:30 2022
-// Update Count     : 5848
+// Last Modified On : Thu Feb  2 21:36:16 2023
+// Update Count     : 5865
 //
 
@@ -331,5 +331,5 @@
 %token ATTRIBUTE EXTENSION								// GCC
 %token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN
-%token CHOOSE FALLTHRU FALLTHROUGH WITH WHEN WAITFOR	// CFA
+%token CHOOSE FALLTHRU FALLTHROUGH WITH WHEN WAITFOR WAITUNTIL // CFA
 %token DISABLE ENABLE TRY THROW THROWRESUME AT			// CFA
 %token ASM												// C99, extension ISO/IEC 9899:1999 Section J.5.10(1)
@@ -1645,7 +1645,7 @@
 exception_statement:
 	TRY compound_statement handler_clause 					%prec THEN
-		{ $$ = new StatementNode( build_try( $2, $3, 0 ) ); }
+		{ $$ = new StatementNode( build_try( $2, $3, nullptr ) ); }
 	| TRY compound_statement finally_clause
-		{ $$ = new StatementNode( build_try( $2, 0, $3 ) ); }
+		{ $$ = new StatementNode( build_try( $2, nullptr, $3 ) ); }
 	| TRY compound_statement handler_clause finally_clause
 		{ $$ = new StatementNode( build_try( $2, $3, $4 ) ); }
@@ -1699,5 +1699,5 @@
 asm_statement:
 	ASM asm_volatile_opt '(' string_literal ')' ';'
-		{ $$ = new StatementNode( build_asm( $2, $4, 0 ) ); }
+		{ $$ = new StatementNode( build_asm( $2, $4, nullptr ) ); }
 	| ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ')' ';' // remaining GCC
 		{ $$ = new StatementNode( build_asm( $2, $4, $6 ) ); }
@@ -1707,5 +1707,5 @@
 		{ $$ = new StatementNode( build_asm( $2, $4, $6, $8, $10 ) ); }
 	| ASM asm_volatile_opt GOTO '(' string_literal ':' ':' asm_operands_opt ':' asm_clobbers_list_opt ':' label_list ')' ';'
-		{ $$ = new StatementNode( build_asm( $2, $5, 0, $8, $10, $12 ) ); }
+		{ $$ = new StatementNode( build_asm( $2, $5, nullptr, $8, $10, $12 ) ); }
 	;
 
@@ -1880,15 +1880,15 @@
 //	'[' ']' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' // S/R conflict
 //		{
-//			$$ = DeclarationNode::newFunction( $3, DeclarationNode::newTuple( 0 ), $6, 0, true );
+//			$$ = DeclarationNode::newFunction( $3, DeclarationNode::newTuple( 0 ), $6, nullptr, true );
 //		}
 //	'[' ']' identifier '(' push cfa_parameter_ellipsis_list_opt pop ')'
 //		{
 //			typedefTable.setNextIdentifier( *$5 );
-//			$$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
+//			$$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, nullptr, true );
 //		}
 //	| '[' ']' TYPEDEFname '(' push cfa_parameter_ellipsis_list_opt pop ')'
 //		{
 //			typedefTable.setNextIdentifier( *$5 );
-//			$$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
+//			$$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, nullptr, true );
 //		}
 //	| '[' ']' typegen_name
@@ -1902,7 +1902,7 @@
 	cfa_abstract_tuple identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' attribute_list_opt
 		// To obtain LR(1 ), this rule must be factored out from function return type (see cfa_abstract_declarator).
-		{ $$ = DeclarationNode::newFunction( $2, $1, $5, 0 )->addQualifiers( $8 ); }
+		{ $$ = DeclarationNode::newFunction( $2, $1, $5, nullptr )->addQualifiers( $8 ); }
 	| cfa_function_return identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' attribute_list_opt
-		{ $$ = DeclarationNode::newFunction( $2, $1, $5, 0 )->addQualifiers( $8 ); }
+		{ $$ = DeclarationNode::newFunction( $2, $1, $5, nullptr )->addQualifiers( $8 ); }
 	;
 
@@ -1939,4 +1939,5 @@
 	TYPEDEF type_specifier declarator
 		{
+			// if type_specifier is an anon aggregate => name 
 			typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "4" );
 			$$ = $3->addType( $2 )->addTypedef();
@@ -1995,6 +1996,20 @@
 declaration_specifier:									// type specifier + storage class
 	basic_declaration_specifier
+	| type_declaration_specifier
 	| sue_declaration_specifier
-	| type_declaration_specifier
+	| sue_declaration_specifier invalid_types
+		{
+			SemanticError( yylloc,
+						  ::toString( "Missing ';' after end of ",
+									  $1->type->enumeration.name ? "enum" : AggregateDecl::aggrString( $1->type->aggregate.kind ),
+									  " declaration" ) );
+			$$ = nullptr;
+		}
+	;
+
+invalid_types:
+	aggregate_key
+	| basic_type_name
+	| indirect_type
 	;
 
@@ -2065,9 +2080,10 @@
 		{ $$ = DeclarationNode::newTypeQualifier( Type::Atomic ); }
 	| forall
+		{ $$ = DeclarationNode::newForall( $1 ); }
 	;
 
 forall:
 	FORALL '(' type_parameter_list ')'					// CFA
-		{ $$ = DeclarationNode::newForall( $3 ); }
+		{ $$ = $3; }
 	;
 
@@ -2473,4 +2489,6 @@
 	| EXTENSION type_specifier field_declaring_list_opt ';'	// GCC
 		{ $$ = fieldDecl( $2, $3 ); distExt( $$ ); }
+	| STATIC type_specifier field_declaring_list_opt ';' // CFA
+	   	{ SemanticError( yylloc, "STATIC aggregate field qualifier currently unimplemented." ); $$ = nullptr; }
 	| INLINE type_specifier field_abstract_list_opt ';'	// CFA
 		{
@@ -2595,7 +2613,7 @@
 enum_type_nobody:										// enum - {...}
 	ENUM attribute_list_opt identifier
-		{ typedefTable.makeTypedef( *$3 ); $$ = DeclarationNode::newEnum( $3, 0, false, false )->addQualifiers( $2 ); }
+		{ typedefTable.makeTypedef( *$3 ); $$ = DeclarationNode::newEnum( $3, nullptr, false, false )->addQualifiers( $2 ); }
 	| ENUM attribute_list_opt type_name
-		{ typedefTable.makeTypedef( *$3->type->symbolic.name );	$$ = DeclarationNode::newEnum( $3->type->symbolic.name, 0, false, false )->addQualifiers( $2 ); }
+		{ typedefTable.makeTypedef( *$3->type->symbolic.name );	$$ = DeclarationNode::newEnum( $3->type->symbolic.name, nullptr, false, false )->addQualifiers( $2 ); }
 	;
 
@@ -2938,5 +2956,5 @@
 		{
 			typedefTable.addToEnclosingScope( *$1, TYPEDEFname, "10" );
-			$$ = DeclarationNode::newTypeDecl( $1, 0 );
+			$$ = DeclarationNode::newTypeDecl( $1, nullptr );
 		}
 	| identifier_or_type_name '(' type_parameter_list ')'
@@ -2949,7 +2967,17 @@
 trait_specifier:										// CFA
 	TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' '}'
-		{ $$ = DeclarationNode::newTrait( $2, $4, 0 ); }
+		{
+			SemanticWarning( yylloc, Warning::DeprecTraitSyntax, "" );
+			$$ = DeclarationNode::newTrait( $2, $4, nullptr );
+		}
+	| forall TRAIT identifier_or_type_name '{' '}'		// alternate
+		{ $$ = DeclarationNode::newTrait( $3, $1, nullptr ); }
 	| TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}'
-		{ $$ = DeclarationNode::newTrait( $2, $4, $8 ); }
+		{
+			SemanticWarning( yylloc, Warning::DeprecTraitSyntax, "" );
+			$$ = DeclarationNode::newTrait( $2, $4, $8 );
+		}
+	| forall TRAIT identifier_or_type_name '{' push trait_declaration_list pop '}' // alternate
+		{ $$ = DeclarationNode::newTrait( $3, $1, $6 ); }
 	;
 
@@ -3031,5 +3059,5 @@
 		}
 	| ASM '(' string_literal ')' ';'					// GCC, global assembler statement
-		{ $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, 0 ) ) ); }
+		{ $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, nullptr ) ) ); }
 	| EXTERN STRINGliteral
 		{
@@ -3275,5 +3303,5 @@
 variable_ptr:
 	ptrref_operator variable_declarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| ptrref_operator type_qualifier_list variable_declarator
 		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
@@ -3339,5 +3367,5 @@
 function_ptr:
 	ptrref_operator function_declarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| ptrref_operator type_qualifier_list function_declarator
 		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
@@ -3391,5 +3419,5 @@
 KR_function_ptr:
 	ptrref_operator KR_function_declarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| ptrref_operator type_qualifier_list KR_function_declarator
 		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
@@ -3447,5 +3475,5 @@
 type_ptr:
 	ptrref_operator variable_type_redeclarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| ptrref_operator type_qualifier_list variable_type_redeclarator
 		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
@@ -3505,5 +3533,5 @@
 identifier_parameter_ptr:
 	ptrref_operator identifier_parameter_declarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| ptrref_operator type_qualifier_list identifier_parameter_declarator
 		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
@@ -3562,5 +3590,5 @@
 type_parameter_ptr:
 	ptrref_operator type_parameter_redeclarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| ptrref_operator type_qualifier_list type_parameter_redeclarator
 		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
@@ -3605,9 +3633,9 @@
 abstract_ptr:
 	ptrref_operator
-		{ $$ = DeclarationNode::newPointer( 0, $1 ); }
+		{ $$ = DeclarationNode::newPointer( nullptr, $1 ); }
 	| ptrref_operator type_qualifier_list
 		{ $$ = DeclarationNode::newPointer( $2, $1 ); }
 	| ptrref_operator abstract_declarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| ptrref_operator type_qualifier_list abstract_declarator
 		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
@@ -3638,10 +3666,10 @@
 		// Only the first dimension can be empty.
 	'[' ']'
-		{ $$ = DeclarationNode::newArray( 0, 0, false ); }
+		{ $$ = DeclarationNode::newArray( nullptr, nullptr, false ); }
 	| '[' ']' multi_array_dimension
-		{ $$ = DeclarationNode::newArray( 0, 0, false )->addArray( $3 ); }
+		{ $$ = DeclarationNode::newArray( nullptr, nullptr, false )->addArray( $3 ); }
 		// Cannot use constant_expression because of tuples => semantic check
 	| '[' push assignment_expression pop ',' comma_expression ']' // CFA
-		{ $$ = DeclarationNode::newArray( $3, 0, false )->addArray( DeclarationNode::newArray( $6, 0, false ) ); }
+		{ $$ = DeclarationNode::newArray( $3, nullptr, false )->addArray( DeclarationNode::newArray( $6, nullptr, false ) ); }
 		// { SemanticError( yylloc, "New array dimension is currently unimplemented." ); $$ = nullptr; }
 	| '[' push array_type_list pop ']'					// CFA
@@ -3672,9 +3700,9 @@
 multi_array_dimension:
 	'[' push assignment_expression pop ']'
-		{ $$ = DeclarationNode::newArray( $3, 0, false ); }
+		{ $$ = DeclarationNode::newArray( $3, nullptr, false ); }
 	| '[' push '*' pop ']'								// C99
 		{ $$ = DeclarationNode::newVarArray( 0 ); }
 	| multi_array_dimension '[' push assignment_expression pop ']'
-		{ $$ = $1->addArray( DeclarationNode::newArray( $4, 0, false ) ); }
+		{ $$ = $1->addArray( DeclarationNode::newArray( $4, nullptr, false ) ); }
 	| multi_array_dimension '[' push '*' pop ']'		// C99
 		{ $$ = $1->addArray( DeclarationNode::newVarArray( 0 ) ); }
@@ -3773,10 +3801,10 @@
 array_parameter_1st_dimension:
 	'[' ']'
-		{ $$ = DeclarationNode::newArray( 0, 0, false ); }
+		{ $$ = DeclarationNode::newArray( nullptr, nullptr, false ); }
 		// multi_array_dimension handles the '[' '*' ']' case
 	| '[' push type_qualifier_list '*' pop ']'			// remaining C99
 		{ $$ = DeclarationNode::newVarArray( $3 ); }
 	| '[' push type_qualifier_list pop ']'
-		{ $$ = DeclarationNode::newArray( 0, $3, false ); }
+		{ $$ = DeclarationNode::newArray( nullptr, $3, false ); }
 		// multi_array_dimension handles the '[' assignment_expression ']' case
 	| '[' push type_qualifier_list assignment_expression pop ']'
@@ -3807,9 +3835,9 @@
 variable_abstract_ptr:
 	ptrref_operator
-		{ $$ = DeclarationNode::newPointer( 0, $1 ); }
+		{ $$ = DeclarationNode::newPointer( nullptr, $1 ); }
 	| ptrref_operator type_qualifier_list
 		{ $$ = DeclarationNode::newPointer( $2, $1 ); }
 	| ptrref_operator variable_abstract_declarator
-		{ $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
+		{ $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| ptrref_operator type_qualifier_list variable_abstract_declarator
 		{ $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
@@ -3853,13 +3881,13 @@
 		// No SUE declaration in parameter list.
 	ptrref_operator type_specifier_nobody
-		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
+		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| type_qualifier_list ptrref_operator type_specifier_nobody
 		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
 	| ptrref_operator cfa_abstract_function
-		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
+		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| type_qualifier_list ptrref_operator cfa_abstract_function
 		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
 	| ptrref_operator cfa_identifier_parameter_declarator_tuple
-		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
+		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| type_qualifier_list ptrref_operator cfa_identifier_parameter_declarator_tuple
 		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
@@ -3870,9 +3898,9 @@
 		// shift/reduce conflict with new-style empty (void) function return type.
 	'[' ']' type_specifier_nobody
-		{ $$ = $3->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
+		{ $$ = $3->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
 	| cfa_array_parameter_1st_dimension type_specifier_nobody
 		{ $$ = $2->addNewArray( $1 ); }
 	| '[' ']' multi_array_dimension type_specifier_nobody
-		{ $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
+		{ $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
 	| cfa_array_parameter_1st_dimension multi_array_dimension type_specifier_nobody
 		{ $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
@@ -3881,9 +3909,9 @@
 
 	| '[' ']' cfa_identifier_parameter_ptr
-		{ $$ = $3->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
+		{ $$ = $3->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
 	| cfa_array_parameter_1st_dimension cfa_identifier_parameter_ptr
 		{ $$ = $2->addNewArray( $1 ); }
 	| '[' ']' multi_array_dimension cfa_identifier_parameter_ptr
-		{ $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
+		{ $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
 	| cfa_array_parameter_1st_dimension multi_array_dimension cfa_identifier_parameter_ptr
 		{ $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
@@ -3941,13 +3969,13 @@
 cfa_abstract_ptr:										// CFA
 	ptrref_operator type_specifier
-		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
+		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| type_qualifier_list ptrref_operator type_specifier
 		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
 	| ptrref_operator cfa_abstract_function
-		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
+		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| type_qualifier_list ptrref_operator cfa_abstract_function
 		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
 	| ptrref_operator cfa_abstract_declarator_tuple
-		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
+		{ $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
 	| type_qualifier_list ptrref_operator cfa_abstract_declarator_tuple
 		{ $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
Index: src/ResolvExpr/AdjustExprType.hpp
===================================================================
--- src/ResolvExpr/AdjustExprType.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
+++ src/ResolvExpr/AdjustExprType.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -0,0 +1,56 @@
+//
+// 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.
+//
+// AdjustExprType.hpp --
+//
+// Author           : Andrew Beach
+// Created On       : Wed Jan 18  9:56:00 2023
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Jan 18  9:56:00 2023
+// Update Count     : 0
+//
+
+#pragma once
+
+class Type;
+namespace SymTab {
+	class Indexer;
+}
+namespace ast {
+	class SymbolTable;
+	class Type;
+	class TypeEnvironment;
+}
+
+namespace ResolvExpr {
+
+class TypeEnvironment;
+
+/// Replaces array types with the equivalent pointer, and function types with a pointer-to-function
+void adjustExprType( Type *& type, const TypeEnvironment & env, const SymTab::Indexer & indexer );
+
+/// Replaces array types with the equivalent pointer, and function types with a pointer-to-function using empty TypeEnvironment and Indexer.
+void adjustExprType( Type *& type );
+
+template< typename ForwardIterator >
+void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment & env, const SymTab::Indexer & indexer ) {
+	while ( begin != end ) {
+		adjustExprType( *begin++, env, indexer );
+	} // while
+}
+
+/// Replaces array types with equivalent pointer,
+/// and function types with a pointer-to-function.
+const ast::Type * adjustExprType( const ast::Type * type,
+	const ast::TypeEnvironment & env, const ast::SymbolTable & symtab );
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -14,4 +14,6 @@
 //
 
+#include "AlternativeFinder.h"
+
 #include <algorithm>               // for copy
 #include <cassert>                 // for strict_dynamic_cast, assert, assertf
@@ -26,18 +28,22 @@
 
 #include "CompilationState.h"      // for resolvep
+#include "AdjustExprType.hpp"      // for adjustExprType
 #include "Alternative.h"           // for AltList, Alternative
-#include "AlternativeFinder.h"
 #include "AST/Expr.hpp"
 #include "AST/SymbolTable.hpp"
 #include "AST/Type.hpp"
+#include "CastCost.hpp"            // for castCost
 #include "Common/SemanticError.h"  // for SemanticError
 #include "Common/utility.h"        // for deleteAll, printAll, CodeLocation
+#include "ConversionCost.h"        // for conversionCost
 #include "Cost.h"                  // for Cost, Cost::zero, operator<<, Cost...
 #include "ExplodedActual.h"        // for ExplodedActual
 #include "InitTweak/InitTweak.h"   // for getFunctionName
+#include "PolyCost.hpp"            // for polyCost
 #include "RenameVars.h"            // for RenameVars, global_renamer
 #include "ResolveAssertions.h"     // for resolveAssertions
 #include "ResolveTypeof.h"         // for resolveTypeof
 #include "Resolver.h"              // for resolveStmtExpr
+#include "SpecCost.hpp"            // for specCost
 #include "SymTab/Indexer.h"        // for Indexer
 #include "SymTab/Mangler.h"        // for Mangler
@@ -51,6 +57,6 @@
 #include "Tuples/Explode.h"        // for explode
 #include "Tuples/Tuples.h"         // for isTtype, handleTupleAssignment
+#include "typeops.h"               // for combos
 #include "Unify.h"                 // for unify
-#include "typeops.h"               // for adjustExprType, polyCost, castCost
 
 #define PRINT( text ) if ( resolvep ) { text }
Index: src/ResolvExpr/AlternativeFinder.h
===================================================================
--- src/ResolvExpr/AlternativeFinder.h	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/AlternativeFinder.h	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -34,4 +34,9 @@
 namespace ResolvExpr {
 	struct ArgPack;
+
+	Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue,
+		const SymTab::Indexer & indexer, const TypeEnvironment & env );
+
+	void referenceToRvalueConversion( Expression *& expr, Cost & cost );
 
 	/// First index is which argument, second index is which alternative for that argument,
Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -23,13 +23,18 @@
 #include <vector>
 
+#include "AdjustExprType.hpp"
 #include "Candidate.hpp"
+#include "CastCost.hpp"           // for castCost
 #include "CompilationState.h"
+#include "ConversionCost.h"       // for conversionCast
 #include "Cost.h"
 #include "ExplodedArg.hpp"
+#include "PolyCost.hpp"
 #include "RenameVars.h"           // for renameTyVars
 #include "Resolver.h"
 #include "ResolveTypeof.h"
 #include "SatisfyAssertions.hpp"
-#include "typeops.h"              // for adjustExprType, conversionCost, polyCost, specCost
+#include "SpecCost.hpp"
+#include "typeops.h"              // for combos
 #include "Unify.h"
 #include "AST/Expr.hpp"
Index: src/ResolvExpr/CandidateFinder.hpp
===================================================================
--- src/ResolvExpr/CandidateFinder.hpp	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/CandidateFinder.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -63,4 +63,9 @@
 	const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
 
+/// Create an expression that preforms reference to rvalue conversion on
+/// the given expression and update the cost of the expression.
+const ast::Expr * referenceToRvalueConversion(
+	const ast::Expr * expr, Cost & cost );
+
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/CastCost.cc
===================================================================
--- src/ResolvExpr/CastCost.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/CastCost.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -13,4 +13,6 @@
 // Update Count     : 9
 //
+
+#include "CastCost.hpp"
 
 #include <cassert>                       // for assert
@@ -22,9 +24,12 @@
 #include "ConversionCost.h"              // for ConversionCost
 #include "Cost.h"                        // for Cost, Cost::infinity
+#include "ResolvExpr/ConversionCost.h"   // for conversionCost
+#include "ResolvExpr/PtrsCastable.hpp"   // for ptrsCastable
 #include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment, EqvClass
+#include "ResolvExpr/typeops.h"          // for ptrsCastable
+#include "ResolvExpr/Unify.h"            // for typesCompatibleIgnoreQualifiers
 #include "SymTab/Indexer.h"              // for Indexer
 #include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
 #include "SynTree/Type.h"                // for PointerType, Type, TypeInstType
-#include "typeops.h"                     // for typesCompatibleIgnoreQualifiers
 
 #if 0
Index: src/ResolvExpr/CastCost.hpp
===================================================================
--- src/ResolvExpr/CastCost.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
+++ src/ResolvExpr/CastCost.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -0,0 +1,47 @@
+//
+// 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.
+//
+// CastCost.hpp -- Cost of a cast.
+//
+// Author           : Andrew Beach
+// Created On       : Fri Dec  9 11:28:00 2022
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Dec  9 11:28:00 2022
+// Update Count     : 0
+//
+
+#pragma once
+
+#include "ResolvExpr/Cost.h"     // for Cost
+
+class Type;
+namespace SymTab {
+	class Indexer;
+}
+namespace ast {
+	class SymbolTable;
+	class Type;
+	class TypeEnvironment;
+}
+
+namespace ResolvExpr {
+
+class TypeEnvironment;
+
+Cost castCost(
+	const Type * src, const Type * dest, bool srcIsLvalue,
+	const SymTab::Indexer & indexer, const TypeEnvironment & env );
+Cost castCost(
+	const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
+	const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/ResolvExpr/CommonType.cc
===================================================================
--- src/ResolvExpr/CommonType.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/CommonType.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -13,4 +13,6 @@
 // Update Count     : 24
 //
+
+#include "CommonType.hpp"
 
 #include <cassert>                       // for strict_dynamic_cast
Index: src/ResolvExpr/CommonType.hpp
===================================================================
--- src/ResolvExpr/CommonType.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
+++ src/ResolvExpr/CommonType.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -0,0 +1,47 @@
+//
+// 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.
+//
+// CommonType.hpp --
+//
+// Author           : Andrew Beach
+// Created On       : Tue Jan 17 16:52:00 2023
+// Last Modified By : Andrew Beach
+// Last Modified On : Tue Jan 17 16:52:00 2023
+// Update Count     : 0
+//
+
+#pragma once
+
+#include "AST/Fwd.hpp"
+#include "AST/TypeEnvironment.hpp"  // for AssertionSet, OpenVarSet
+#include "TypeEnvironment.h"        // for AssertionSet, OpenVarSet
+#include "WidenMode.h"              // for WidenMode
+
+class Type;
+namespace SymTab {
+	class Indexer;
+}
+
+namespace ResolvExpr {
+
+Type * commonType(
+	Type * type1, Type * type2, bool widenFirst, bool widenSecond,
+	const SymTab::Indexer & indexer, TypeEnvironment & env,
+	const OpenVarSet & openVars );
+ast::ptr< ast::Type > commonType(
+	const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
+	ast::TypeEnvironment & env,
+	ast::AssertionSet & need, ast::AssertionSet & have,
+	const ast::OpenVarSet & open, WidenMode widen,
+	const ast::SymbolTable & symtab );
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/ConversionCost.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -22,9 +22,9 @@
 #include "ResolvExpr/Cost.h"             // for Cost
 #include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
-#include "ResolvExpr/Unify.h"
+#include "ResolvExpr/Unify.h"            // for typesCompatibleIgnoreQualifiers
+#include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable
 #include "SymTab/Indexer.h"              // for Indexer
 #include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
 #include "SynTree/Type.h"                // for Type, BasicType, TypeInstType
-#include "typeops.h"                     // for typesCompatibleIgnoreQualifiers
 
 
Index: src/ResolvExpr/ConversionCost.h
===================================================================
--- src/ResolvExpr/ConversionCost.h	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/ConversionCost.h	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -32,4 +32,8 @@
 namespace ResolvExpr {
 	class TypeEnvironment;
+
+	Cost conversionCost(
+		const Type * src, const Type * dest, bool srcIsLvalue,
+		const SymTab::Indexer & indexer, const TypeEnvironment & env );
 
 	typedef std::function<Cost(const Type *, const Type *, bool,
@@ -80,4 +84,12 @@
 	const ast::SymbolTable &, const ast::TypeEnvironment &)>;
 
+Cost conversionCost(
+	const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
+	const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
+
+Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
+	bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env,
+	PtrsCalculation func );
+
 #warning when the old ConversionCost is removed, get ride of the _new suffix.
 class ConversionCost_new : public ast::WithShortCircuiting {
@@ -119,8 +131,4 @@
 };
 
-Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
-	bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env,
-	PtrsCalculation func );
-
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/PolyCost.hpp
===================================================================
--- src/ResolvExpr/PolyCost.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
+++ src/ResolvExpr/PolyCost.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -0,0 +1,43 @@
+//
+// 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.
+//
+// PolyCost.hpp --
+//
+// Author           : Andrew Beach
+// Created On       : Tue Jan 17 16:45:00 2023
+// Last Modified By : Andrew Beach
+// Last Modified On : Tue Jan 17 16:45:00 2023
+// Update Count     : 0
+//
+
+#pragma once
+
+class Type;
+namespace SymTab {
+    class Indexer;
+}
+namespace ast {
+    class SymbolTable;
+    class Type;
+    class TypeEnvironment;
+}
+
+namespace ResolvExpr {
+
+class TypeEnvironment;
+
+int polyCost( Type * type,
+	const TypeEnvironment & env, const SymTab::Indexer & indexer );
+int polyCost( const ast::Type * type,
+	const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/ResolvExpr/PtrsAssignable.cc
===================================================================
--- src/ResolvExpr/PtrsAssignable.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/PtrsAssignable.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -14,5 +14,5 @@
 //
 
-#include "typeops.h"
+#include "PtrsAssignable.hpp"
 
 #include "AST/Pass.hpp"
Index: src/ResolvExpr/PtrsAssignable.hpp
===================================================================
--- src/ResolvExpr/PtrsAssignable.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
+++ src/ResolvExpr/PtrsAssignable.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -0,0 +1,39 @@
+//
+// 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.
+//
+// PtrsAssignable.hpp --
+//
+// Author           : Andrew Beach
+// Created On       : Fri Dec  9 11:40:00 2022
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Dec  9 11:40:00 2022
+// Update Count     : 0
+//
+
+#pragma once
+
+class Type;
+namespace ast {
+	class Type;
+	class TypeEnvironment;
+}
+
+namespace ResolvExpr {
+
+class TypeEnvironment;
+
+int ptrsAssignable( const Type * src, const Type * dest,
+	const TypeEnvironment & env );
+int ptrsAssignable( const ast::Type * src, const ast::Type * dst,
+	const ast::TypeEnvironment & env );
+
+} // namespace ResolvExpr
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/ResolvExpr/PtrsCastable.cc
===================================================================
--- src/ResolvExpr/PtrsCastable.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/PtrsCastable.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -14,4 +14,6 @@
 //
 
+#include "PtrsCastable.hpp"
+
 #include "AST/Decl.hpp"
 #include "AST/Pass.hpp"
@@ -19,4 +21,5 @@
 #include "AST/TypeEnvironment.hpp"
 #include "Common/PassVisitor.h"
+#include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable
 #include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
 #include "SymTab/Indexer.h"              // for Indexer
@@ -24,5 +27,4 @@
 #include "SynTree/Type.h"                // for TypeInstType, Type, BasicType
 #include "SynTree/Visitor.h"             // for Visitor
-#include "typeops.h"                     // for ptrsAssignable
 
 namespace ResolvExpr {
@@ -291,7 +293,5 @@
 		return objectCast( src, env, symtab );
 	} else {
-		ast::Pass< PtrsCastable_new > ptrs{ dst, env, symtab };
-		src->accept( ptrs );
-		return ptrs.core.result;
+		return ast::Pass<PtrsCastable_new>::read( src, dst, env, symtab );
 	}
 }
Index: src/ResolvExpr/PtrsCastable.hpp
===================================================================
--- src/ResolvExpr/PtrsCastable.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
+++ src/ResolvExpr/PtrsCastable.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -0,0 +1,45 @@
+//
+// 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.
+//
+// PtrsCastable.hpp --
+//
+// Author           : Andrew Beach
+// Created On       : Mon Jan 16 17:04:00 2023
+// Last Modified By : Andrew Beach
+// Last Modified On : Mon Jan 16 17:04:00 2023
+// Update Count     : 0
+//
+
+#pragma once
+
+class Type;
+namespace SymTab {
+    class Indexer;
+}
+namespace ast {
+    class SymbolTable;
+    class Type;
+    class TypeEnvironment;
+}
+
+namespace ResolvExpr {
+
+class TypeEnvironment;
+
+int ptrsCastable(
+	const Type * src, const Type * dst,
+	const TypeEnvironment & env, const SymTab::Indexer & indexer );
+int ptrsCastable(
+	const ast::Type * src, const ast::Type * dst,
+	const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/ResolvExpr/ResolveAssertions.cc
===================================================================
--- src/ResolvExpr/ResolveAssertions.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/ResolveAssertions.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -26,4 +26,5 @@
 #include <vector>                   // for vector
 
+#include "AdjustExprType.hpp"       // for adjustExprType
 #include "Alternative.h"            // for Alternative, AssertionItem, AssertionList
 #include "Common/FilterCombos.h"    // for filterCombos
@@ -31,10 +32,11 @@
 #include "Common/utility.h"         // for sort_mins
 #include "GenPoly/GenPoly.h"        // for getFunctionType
+#include "ResolvExpr/AlternativeFinder.h"  // for computeConversionCost
 #include "ResolvExpr/RenameVars.h"  // for renameTyVars
+#include "SpecCost.hpp"             // for specCost
 #include "SymTab/Indexer.h"         // for Indexer
 #include "SymTab/Mangler.h"         // for Mangler
 #include "SynTree/Expression.h"     // for InferredParams
 #include "TypeEnvironment.h"        // for TypeEnvironment, etc.
-#include "typeops.h"                // for adjustExprType, specCost
 #include "Unify.h"                  // for unify
 
Index: src/ResolvExpr/SatisfyAssertions.cpp
===================================================================
--- src/ResolvExpr/SatisfyAssertions.cpp	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/SatisfyAssertions.cpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -23,8 +23,11 @@
 #include <vector>
 
+#include "AdjustExprType.hpp"
 #include "Candidate.hpp"
 #include "CandidateFinder.hpp"
+#include "CommonType.hpp"
 #include "Cost.h"
 #include "RenameVars.h"
+#include "SpecCost.hpp"
 #include "typeops.h"
 #include "Unify.h"
Index: src/ResolvExpr/SpecCost.hpp
===================================================================
--- src/ResolvExpr/SpecCost.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
+++ src/ResolvExpr/SpecCost.hpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -0,0 +1,34 @@
+//
+// 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.
+//
+// SpecCost.hpp --
+//
+// Author           : Andrew Beach
+// Created On       : Tue Jan 17 16:49:00 2023
+// Last Modified By : Andrew Beach
+// Last Modified On : Tue Jan 17 16:49:00 2023
+// Update Count     : 0
+//
+
+#pragma once
+
+class Type;
+namespace ast {
+    class Type;
+}
+
+namespace ResolvExpr {
+
+int specCost( Type * type );
+int specCost( const ast::Type * type );
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/Unify.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -33,5 +33,7 @@
 #include "AST/TypeEnvironment.hpp"
 #include "Common/PassVisitor.h"     // for PassVisitor
+#include "CommonType.hpp"           // for commonType
 #include "FindOpenVars.h"           // for findOpenVars
+#include "SpecCost.hpp"             // for SpecCost
 #include "SynTree/LinkageSpec.h"    // for C
 #include "SynTree/Constant.h"       // for Constant
@@ -43,5 +45,5 @@
 #include "Tuples/Tuples.h"          // for isTtype
 #include "TypeEnvironment.h"        // for EqvClass, AssertionSet, OpenVarSet
-#include "typeops.h"                // for flatten, occurs, commonType
+#include "typeops.h"                // for flatten, occurs
 
 namespace ast {
@@ -50,5 +52,5 @@
 
 namespace SymTab {
-class Indexer;
+	class Indexer;
 }  // namespace SymTab
 
@@ -56,4 +58,28 @@
 
 namespace ResolvExpr {
+
+// Template Helpers:
+template< typename Iterator1, typename Iterator2 >
+bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, std::list< Type* > &commonTypes ) {
+	for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
+		Type *commonType = 0;
+		if ( ! unify( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
+			return false;
+		} // if
+		commonTypes.push_back( commonType );
+	} // for
+	return ( list1Begin == list1End && list2Begin == list2End );
+}
+
+template< typename Iterator1, typename Iterator2 >
+bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
+	std::list< Type* > commonTypes;
+	if ( unifyList( list1Begin, list1End, list2Begin, list2End, env, needAssertions, haveAssertions,  openVars, indexer, commonTypes ) ) {
+		deleteAll( commonTypes );
+		return true;
+	} else {
+		return false;
+	} // if
+}
 
 	struct Unify_old : public WithShortCircuiting {
Index: src/ResolvExpr/Unify.h
===================================================================
--- src/ResolvExpr/Unify.h	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/Unify.h	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 13:09:04 2015
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Mon Jun 18 11:58:00 2018
-// Update Count     : 4
+// Last Modified By : Andrew Beach
+// Last Modified On : Tue Jan 17 11:12:00 2023
+// Update Count     : 5
 //
 
@@ -37,56 +37,61 @@
 
 namespace ResolvExpr {
-	bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
-	bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
-	bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
-	bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
 
-	template< typename Iterator1, typename Iterator2 >
-	bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, std::list< Type* > &commonTypes ) {
-		for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
-			Type *commonType = 0;
-			if ( ! unify( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
-				return false;
-			} // if
-			commonTypes.push_back( commonType );
-		} // for
-		if ( list1Begin != list1End || list2Begin != list2End ) {
-			return false;
-		} else {
-			return true;
-		} // if
-	}
+bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
+bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
+bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
+bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
 
-	template< typename Iterator1, typename Iterator2 >
-	bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
-		std::list< Type* > commonTypes;
-		if ( unifyList( list1Begin, list1End, list2Begin, list2End, env, needAssertions, haveAssertions, openVars, indexer, commonTypes ) ) {
-			deleteAll( commonTypes );
-			return true;
-		} else {
-			return false;
-		} // if
-	}
+bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
+bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
 
-	bool unify( 
-		const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 
-		ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 
-		ast::OpenVarSet & open, const ast::SymbolTable & symtab );
+inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
+	TypeEnvironment env;
+	return typesCompatible( t1, t2, indexer, env );
+}
 
-	bool unify( 
-		const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 
-		ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 
-		ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common );
+inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
+	TypeEnvironment env;
+	return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env );
+}
 
-	bool unifyExact( 
-		const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 
-		ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 
-		WidenMode widen, const ast::SymbolTable & symtab );
+bool unify(
+	const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
+	ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
+	ast::OpenVarSet & open, const ast::SymbolTable & symtab );
 
-	bool unifyInexact( 
-		const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 
-		ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 
-		const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab, 
-		ast::ptr<ast::Type> & common );
+bool unify(
+	const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
+	ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
+	ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common );
+
+bool unifyExact(
+	const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
+	ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
+	WidenMode widen, const ast::SymbolTable & symtab );
+
+bool unifyInexact(
+	const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
+	ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
+	const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,
+	ast::ptr<ast::Type> & common );
+
+bool typesCompatible(
+	const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {},
+	const ast::TypeEnvironment & env = {} );
+
+bool typesCompatibleIgnoreQualifiers(
+	const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {},
+	const ast::TypeEnvironment & env = {} );
+
+/// Creates the type represented by the list of returnVals in a FunctionType.
+/// The caller owns the return value.
+Type * extractResultType( FunctionType * functionType );
+/// Creates or extracts the type represented by returns in a `FunctionType`.
+ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func );
+
+std::vector<ast::ptr<ast::Type>> flattenList(
+	const std::vector<ast::ptr<ast::Type>> & src, ast::TypeEnvironment & env
+);
 
 } // namespace ResolvExpr
Index: src/ResolvExpr/WidenMode.h
===================================================================
--- src/ResolvExpr/WidenMode.h	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/WidenMode.h	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -19,5 +19,5 @@
 	struct WidenMode {
 		WidenMode( bool first, bool second ): first( first ), second( second ) {}
-		
+
 		WidenMode &operator|=( const WidenMode &other ) {
 			first |= other.first; second |= other.second; return *this;
@@ -35,5 +35,5 @@
 			WidenMode newWM( *this ); newWM &= other; return newWM;
 		}
-		
+
 		operator bool() { return first && second; }
 
Index: src/ResolvExpr/module.mk
===================================================================
--- src/ResolvExpr/module.mk	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/module.mk	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -17,4 +17,5 @@
 SRC_RESOLVEXPR = \
       ResolvExpr/AdjustExprType.cc \
+      ResolvExpr/AdjustExprType.hpp \
       ResolvExpr/Alternative.cc \
       ResolvExpr/AlternativeFinder.cc \
@@ -26,5 +27,7 @@
       ResolvExpr/Candidate.hpp \
       ResolvExpr/CastCost.cc \
+      ResolvExpr/CastCost.hpp \
       ResolvExpr/CommonType.cc \
+      ResolvExpr/CommonType.hpp \
       ResolvExpr/ConversionCost.cc \
       ResolvExpr/ConversionCost.h \
@@ -40,6 +43,9 @@
       ResolvExpr/Occurs.cc \
       ResolvExpr/PolyCost.cc \
+      ResolvExpr/PolyCost.hpp \
       ResolvExpr/PtrsAssignable.cc \
+      ResolvExpr/PtrsAssignable.hpp \
       ResolvExpr/PtrsCastable.cc \
+      ResolvExpr/PtrsCastable.hpp \
       ResolvExpr/RenameVars.cc \
       ResolvExpr/RenameVars.h \
@@ -54,4 +60,5 @@
       ResolvExpr/SatisfyAssertions.hpp \
       ResolvExpr/SpecCost.cc \
+      ResolvExpr/SpecCost.hpp \
       ResolvExpr/TypeEnvironment.cc \
       ResolvExpr/TypeEnvironment.h \
Index: src/ResolvExpr/typeops.h
===================================================================
--- src/ResolvExpr/typeops.h	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/ResolvExpr/typeops.h	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 07:28:22 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue Oct  1 09:45:00 2019
-// Update Count     : 6
+// Last Modified On : Wed Jan 18 11:54:00 2023
+// Update Count     : 7
 //
 
@@ -18,13 +18,5 @@
 #include <vector>
 
-#include "Cost.h"
-#include "TypeEnvironment.h"
-#include "WidenMode.h"
-#include "AST/Fwd.hpp"
-#include "AST/Node.hpp"
-#include "AST/SymbolTable.hpp"
 #include "AST/Type.hpp"
-#include "AST/TypeEnvironment.hpp"
-#include "SynTree/SynTree.h"
 #include "SynTree/Type.h"
 
@@ -34,4 +26,6 @@
 
 namespace ResolvExpr {
+	class TypeEnvironment;
+
 	// combos: takes a list of sets and returns a set of lists representing every possible way of forming a list by
 	// picking one element out of each set
@@ -61,99 +55,4 @@
 	}
 
-	// in AdjustExprType.cc
-	/// Replaces array types with the equivalent pointer, and function types with a pointer-to-function
-	void adjustExprType( Type *& type, const TypeEnvironment & env, const SymTab::Indexer & indexer );
-
-	/// Replaces array types with the equivalent pointer, and function types with a pointer-to-function using empty TypeEnvironment and Indexer
-	void adjustExprType( Type *& type );
-
-	template< typename ForwardIterator >
-	void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment & env, const SymTab::Indexer & indexer ) {
-		while ( begin != end ) {
-			adjustExprType( *begin++, env, indexer );
-		} // while
-	}
-
-	/// Replaces array types with equivalent pointer, and function types with a pointer-to-function
-	const ast::Type * adjustExprType(
-		const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab );
-
-	// in CastCost.cc
-	Cost castCost( const Type * src, const Type * dest, bool srcIsLvalue,
-		const SymTab::Indexer & indexer, const TypeEnvironment & env );
-	Cost castCost(
-		const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
-		const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
-
-	// in ConversionCost.cc
-	Cost conversionCost( const Type * src, const Type * dest, bool srcIsLvalue,
-		const SymTab::Indexer & indexer, const TypeEnvironment & env );
-	Cost conversionCost(
-		const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
-		const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
-
-	// in AlternativeFinder.cc
-	Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue,
-		const SymTab::Indexer & indexer, const TypeEnvironment & env );
-
-	// in PtrsAssignable.cc
-	int ptrsAssignable( const Type * src, const Type * dest, const TypeEnvironment & env );
-	int ptrsAssignable( const ast::Type * src, const ast::Type * dst,
-		const ast::TypeEnvironment & env );
-
-	// in PtrsCastable.cc
-	int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment & env, const SymTab::Indexer & indexer );
-	int ptrsCastable(
-		const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
-		const ast::TypeEnvironment & env );
-
-	// in Unify.cc
-	bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
-	bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
-
-	inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
-		TypeEnvironment env;
-		return typesCompatible( t1, t2, indexer, env );
-	}
-
-	inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
-		TypeEnvironment env;
-		return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env );
-	}
-
-	bool typesCompatible(
-		const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {},
-		const ast::TypeEnvironment & env = {} );
-
-	bool typesCompatibleIgnoreQualifiers(
-		const ast::Type *, const ast::Type *, const ast::SymbolTable &,
-		const ast::TypeEnvironment & env = {} );
-
-	/// creates the type represented by the list of returnVals in a FunctionType. The caller owns the return value.
-	Type * extractResultType( FunctionType * functionType );
-	/// Creates or extracts the type represented by the list of returns in a `FunctionType`.
-	ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func );
-
-	// in CommonType.cc
-	Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer & indexer, TypeEnvironment & env, const OpenVarSet & openVars );
-	ast::ptr< ast::Type > commonType(
-		const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
-			ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
-			const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab
-	);
-	// in Unify.cc
-	std::vector< ast::ptr< ast::Type > > flattenList(
-		const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
-	);
-
-	// in PolyCost.cc
-	int polyCost( Type * type, const TypeEnvironment & env, const SymTab::Indexer & indexer );
-	int polyCost(
-		const ast::Type * type, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
-
-	// in SpecCost.cc
-	int specCost( Type * type );
-	int specCost( const ast::Type * type );
-
 	// in Occurs.cc
 	bool occurs( const Type * type, const std::string & varName, const TypeEnvironment & env );
@@ -168,9 +67,4 @@
 		return false;
 	}
-
-	// in AlternativeFinder.cc
-	void referenceToRvalueConversion( Expression *& expr, Cost & cost );
-	// in CandidateFinder.cpp
-	const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost );
 
 	/// flatten tuple type into list of types
@@ -218,5 +112,4 @@
 		}
 
-
 		return new ast::TupleType{ std::move(types) };
 	}
@@ -227,6 +120,4 @@
 		return tupleFromTypes( tys.begin(), tys.end() );
 	}
-
-	
 
 	// in TypeEnvironment.cc
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/SymTab/Indexer.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -31,5 +31,6 @@
 #include "InitTweak/InitTweak.h"   // for isConstructor, isCopyFunction, isC...
 #include "Mangler.h"               // for Mangler
-#include "ResolvExpr/typeops.h"    // for typesCompatible
+#include "ResolvExpr/AlternativeFinder.h"  // for referenceToRvalueConversion
+#include "ResolvExpr/Unify.h"      // for typesCompatible
 #include "SynTree/LinkageSpec.h"   // for isMangled, isOverridable, Spec
 #include "SynTree/Constant.h"      // for Constant
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/SymTab/Validate.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -63,5 +63,6 @@
 #include "InitTweak/GenInit.h"         // for fixReturnStatements
 #include "InitTweak/InitTweak.h"       // for isCtorDtorAssign
-#include "ResolvExpr/typeops.h"        // for typesCompatible
+#include "ResolvExpr/typeops.h"        // for extractResultType
+#include "ResolvExpr/Unify.h"          // for typesCompatible
 #include "ResolvExpr/Resolver.h"       // for findSingleExpression
 #include "ResolvExpr/ResolveTypeof.h"  // for resolveTypeof
@@ -862,9 +863,5 @@
 
 	void ReplaceTypedef::premutate( TypeDecl * typeDecl ) {
-		TypedefMap::iterator i = typedefNames.find( typeDecl->name );
-		if ( i != typedefNames.end() ) {
-			typedefNames.erase( i ) ;
-		} // if
-
+		typedefNames.erase( typeDecl->name );
 		typedeclNames.insert( typeDecl->name, typeDecl );
 	}
Index: src/SynTree/ApplicationExpr.cc
===================================================================
--- src/SynTree/ApplicationExpr.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/SynTree/ApplicationExpr.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// ApplicationExpr.cc.cc --
+// ApplicationExpr.cc --
 //
 // Author           : Richard C. Bilson
@@ -26,5 +26,5 @@
 #include "Expression.h"          // for ParamEntry, ApplicationExpr, Expression
 #include "InitTweak/InitTweak.h" // for getFunction
-#include "ResolvExpr/typeops.h"  // for extractResultType
+#include "ResolvExpr/Unify.h"    // for extractResultType
 #include "Type.h"                // for Type, PointerType, FunctionType
 
Index: src/Validate/FixReturnTypes.cpp
===================================================================
--- src/Validate/FixReturnTypes.cpp	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/Validate/FixReturnTypes.cpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -20,5 +20,5 @@
 #include "AST/Type.hpp"
 #include "CodeGen/CodeGenerator.h"
-#include "ResolvExpr/typeops.h"
+#include "ResolvExpr/Unify.h"
 
 namespace ast {
Index: src/Validate/ReplaceTypedef.cpp
===================================================================
--- src/Validate/ReplaceTypedef.cpp	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/Validate/ReplaceTypedef.cpp	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -20,5 +20,5 @@
 #include "Common/UniqueName.h"
 #include "Common/utility.h"
-#include "ResolvExpr/typeops.h"
+#include "ResolvExpr/Unify.h"
 
 namespace Validate {
@@ -186,8 +186,5 @@
 
 void ReplaceTypedefCore::previsit( ast::TypeDecl const * decl ) {
-	TypedefMap::iterator iter = typedefNames.find( decl->name );
-	if ( iter != typedefNames.end() ) {
-		typedefNames.erase( iter );
-	}
+	typedefNames.erase( decl->name );
 	typedeclNames.insert( decl->name, decl );
 }
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 997185e1a79d8e46351af7db167616c955086e6e)
+++ src/main.cc	(revision 2ed94a98ea730a0f11bd4cf49b9352557ebf6cd8)
@@ -46,4 +46,5 @@
 #include "Common/UnimplementedError.h"      // for UnimplementedError
 #include "Common/utility.h"                 // for deleteAll, filter, printAll
+#include "Concurrency/Actors.hpp"           // for implementActors
 #include "Concurrency/Keywords.h"           // for implementMutex, implement...
 #include "Concurrency/Waitfor.h"            // for generateWaitfor
@@ -341,4 +342,6 @@
 		PASS( "Generate Autogen Routines", Validate::autogenerateRoutines( transUnit ) );
 
+        PASS( "Implement Actors", Concurrency::implementActors( transUnit ) );
+
 		PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) );
 		PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) );
