Index: c/Common/CompilerError.h
===================================================================
--- src/Common/CompilerError.h	(revision 641be0a494bfe5614872712c2f94132e76ffa0bd)
+++ 	(revision )
@@ -1,36 +1,0 @@
-//
-// 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.
-//
-// CompilerError.h -- 
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jul 21 22:18:07 2017
-// Update Count     : 4
-//
-
-#pragma once
-
-#include <string>
-
-class CompilerError : public std::exception {
-  public:
-	CompilerError();
-	CompilerError( std::string what ) : what( what ) {}
-	~CompilerError() throw () {}
-
-	std::string get_what() const { return what; }
-	void set_what( std::string newValue ) { what = newValue; }
-  private:
-	std::string what;
-};
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/Common/UnimplementedError.h
===================================================================
--- src/Common/UnimplementedError.h	(revision 641be0a494bfe5614872712c2f94132e76ffa0bd)
+++ 	(revision )
@@ -1,36 +1,0 @@
-//
-// 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.
-//
-// UnimplementedError.h -- 
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jul 21 22:18:35 2017
-// Update Count     : 2
-//
-
-#pragma once
-
-#include <string>
-
-class UnimplementedError : public std::exception {
-  public:
-	UnimplementedError();
-	UnimplementedError( std::string what ) : what( what ) {}
-	~UnimplementedError() throw () {}
-  
-	std::string get_what() const { return what; }
-	void set_what( std::string newValue ) { what = newValue; }
-  private:
-	std::string what;
-};
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/Common/module.mk
===================================================================
--- src/Common/module.mk	(revision 641be0a494bfe5614872712c2f94132e76ffa0bd)
+++ src/Common/module.mk	(revision f6bceeb487d479026bb9480c0a96d4eaf35a7b3d)
@@ -20,5 +20,4 @@
 	Common/CodeLocationTools.hpp \
 	Common/CodeLocationTools.cpp \
-	Common/CompilerError.h \
 	Common/Debug.h \
 	Common/DeclStats.hpp \
@@ -52,5 +51,4 @@
 	Common/Stats/Time.cc \
 	Common/Stats/Time.h \
-	Common/UnimplementedError.h \
 	Common/UniqueName.cc \
 	Common/UniqueName.h \
Index: src/GenPoly/FindFunction.cc
===================================================================
--- src/GenPoly/FindFunction.cc	(revision 641be0a494bfe5614872712c2f94132e76ffa0bd)
+++ src/GenPoly/FindFunction.cc	(revision f6bceeb487d479026bb9480c0a96d4eaf35a7b3d)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Rob Schluntz
-// Last Modified On : Fri Feb 05 12:22:20 2016
-// Update Count     : 6
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Oct  7 17:05:20 2022
+// Update Count     : 7
 //
 
@@ -18,4 +18,6 @@
 #include <utility>                      // for pair
 
+#include "AST/Pass.hpp"                 // for Pass
+#include "AST/Type.hpp"
 #include "Common/PassVisitor.h"         // for PassVisitor
 #include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::iterator
@@ -89,4 +91,94 @@
 		handleForall( pointerType->get_forall() );
 	}
+
+namespace {
+
+struct FindFunctionCore :
+		public ast::WithGuards,
+		public ast::WithShortCircuiting,
+		public ast::WithVisitorRef<FindFunctionCore> {
+	FindFunctionCore(
+		std::vector<ast::ptr<ast::FunctionType>> & functions,
+		const TypeVarMap & typeVars, FindFunctionPred predicate,
+		bool replaceMode );
+
+	void previsit( ast::FunctionType const * type );
+	ast::Type const * postvisit( ast::FunctionType const * type );
+	void previsit( ast::PointerType const * type );
+private:
+	void handleForall( const ast::FunctionType::ForallList & forall );
+
+	std::vector<ast::ptr<ast::FunctionType>> &functions;
+	TypeVarMap typeVars;
+	FindFunctionPred predicate;
+	bool replaceMode;
+};
+
+FindFunctionCore::FindFunctionCore(
+		std::vector<ast::ptr<ast::FunctionType>> & functions,
+		const TypeVarMap &typeVars, FindFunctionPred predicate,
+		bool replaceMode ) :
+	functions( functions ), typeVars( typeVars ),
+	predicate( predicate ), replaceMode( replaceMode ) {}
+
+void FindFunctionCore::handleForall( const ast::FunctionType::ForallList & forall ) {
+	for ( const ast::ptr<ast::TypeInstType> & td : forall ) {
+		TypeVarMap::iterator var = typeVars.find( *td );
+		if ( var != typeVars.end() ) {
+			typeVars.erase( var->first );
+		} // if
+	} // for
+}
+
+void FindFunctionCore::previsit( ast::FunctionType const * type ) {
+	visit_children = false;
+	GuardScope( typeVars );
+	handleForall( type->forall );
+	//ast::accept_all( type->returns, *visitor );
+	// This might have to become ast::mutate_each with return.
+	ast::accept_each( type->returns, *visitor );
+}
+
+ast::Type const * FindFunctionCore::postvisit( ast::FunctionType const * type ) {
+	ast::Type const * ret = type;
+	if ( predicate( type, typeVars ) ) {
+		functions.push_back( type );
+		if ( replaceMode ) {
+			// replace type parameters in function type with void*
+			ret = scrubTypeVars( ast::deepCopy( type ), typeVars );
+		} // if
+	} // if
+	return ret;
+}
+
+void FindFunctionCore::previsit( ast::PointerType const * /*type*/ ) {
+	GuardScope( typeVars );
+	//handleForall( type->forall );
+}
+
+} // namespace
+
+void findFunction( const ast::Type * type,
+		std::vector<ast::ptr<ast::FunctionType>> & functions,
+		const TypeVarMap & typeVars, FindFunctionPred predicate ) {
+	ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, false );
+	type->accept( pass );
+	//(void)type;
+	//(void)functions;
+	//(void)typeVars;
+	//(void)predicate;
+}
+
+const ast::Type * findAndReplaceFunction( const ast::Type * type,
+		std::vector<ast::ptr<ast::FunctionType>> & functions,
+		const TypeVarMap & typeVars, FindFunctionPred predicate ) {
+	ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, true );
+	return type->accept( pass );
+	//(void)functions;
+	//(void)typeVars;
+	//(void)predicate;
+	//return type;
+}
+
 } // namespace GenPoly
 
Index: src/GenPoly/FindFunction.h
===================================================================
--- src/GenPoly/FindFunction.h	(revision 641be0a494bfe5614872712c2f94132e76ffa0bd)
+++ src/GenPoly/FindFunction.h	(revision f6bceeb487d479026bb9480c0a96d4eaf35a7b3d)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul 22 09:23:36 2017
-// Update Count     : 2
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Oct  7 10:30:00 2022
+// Update Count     : 3
 //
 
@@ -30,4 +30,17 @@
 	/// like `findFunction`, but also replaces the function type with void ()(void)
 	void findAndReplaceFunction( Type *&type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate );
+
+typedef bool (*FindFunctionPred)( const ast::FunctionType *, const TypeVarMap & );
+
+/// Recursively walks `type`, placing all functions that match `predicate`
+/// under `typeVars` into `functions`.
+void findFunction( const ast::Type * type,
+		std::vector<ast::ptr<ast::FunctionType>> & functions,
+		const TypeVarMap & typeVars, FindFunctionPred predicate );
+/// Like findFunction, but also replaces the function type with `void ()(void)`.
+const ast::Type * findAndReplaceFunction( const ast::Type * type,
+		std::vector<ast::ptr<ast::FunctionType>> & functions,
+		const TypeVarMap & typeVars, FindFunctionPred predicate );
+
 } // namespace GenPoly
 
Index: src/GenPoly/GenPoly.cc
===================================================================
--- src/GenPoly/GenPoly.cc	(revision 641be0a494bfe5614872712c2f94132e76ffa0bd)
+++ src/GenPoly/GenPoly.cc	(revision f6bceeb487d479026bb9480c0a96d4eaf35a7b3d)
@@ -275,4 +275,12 @@
 	}
 
+const ast::BaseInstType *isDynRet( const ast::FunctionType * func ) {
+	if ( func->returns.empty() ) return nullptr;
+
+	TypeVarMap forallTypes = { ast::TypeData() };
+	makeTypeVarMap( func, forallTypes );
+	return isDynType( func->returns.front(), forallTypes );
+}
+
 	bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) {
 // 		if ( ! adaptee->get_returnVals().empty() && isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
@@ -319,4 +327,15 @@
 		return 0;
 	}
+
+const ast::Type * isPolyPtr(
+		const ast::Type * type, const TypeVarMap & typeVars,
+		const ast::TypeSubstitution * typeSubs ) {
+	type = replaceTypeInst( type, typeSubs );
+
+	if ( auto * ptr = dynamic_cast<ast::PointerType const *>( type ) ) {
+		return isPolyType( ptr->base, typeVars, typeSubs );
+	}
+	return nullptr;
+}
 
 	Type * hasPolyBase( Type *type, int *levels, const TypeSubstitution *env ) {
@@ -796,6 +815,10 @@
 	}
 
+void addToTypeVarMap( const ast::TypeDecl * decl, TypeVarMap & typeVars ) {
+	typeVars.insert( ast::TypeEnvKey( decl, 0, 0 ), ast::TypeData( decl ) );
+}
+
 void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ) {
-	typeVars.insert( *type, ast::TypeData( type->base ) );
+	typeVars.insert( ast::TypeEnvKey( *type ), ast::TypeData( type->base ) );
 }
 
@@ -822,4 +845,10 @@
 }
 
+void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars ) {
+	for ( auto & typeDecl : decl->type_params ) {
+		addToTypeVarMap( typeDecl, typeVars );
+	}
+}
+
 	void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) {
 		for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) {
Index: src/GenPoly/GenPoly.h
===================================================================
--- src/GenPoly/GenPoly.h	(revision 641be0a494bfe5614872712c2f94132e76ffa0bd)
+++ src/GenPoly/GenPoly.h	(revision f6bceeb487d479026bb9480c0a96d4eaf35a7b3d)
@@ -111,8 +111,10 @@
 	void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap );
 	void addToTypeVarMap( const ast::TypeDecl * type, TypeVarMap & typeVars );
+	void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars );
 
 	/// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap`
 	void makeTyVarMap( Type *type, TyVarMap &tyVarMap );
 	void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars );
+	void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars );
 
 	/// Prints type variable map
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 641be0a494bfe5614872712c2f94132e76ffa0bd)
+++ src/main.cc	(revision f6bceeb487d479026bb9480c0a96d4eaf35a7b3d)
@@ -40,9 +40,7 @@
 #include "CodeTools/TrackLoc.h"             // for fillLocations
 #include "Common/CodeLocationTools.hpp"     // for forceFillCodeLocations
-#include "Common/CompilerError.h"           // for CompilerError
 #include "Common/DeclStats.hpp"             // for printDeclStats
 #include "Common/ResolvProtoDump.hpp"       // for dumpAsResolverProto
 #include "Common/Stats.h"                   // for Stats
-#include "Common/UnimplementedError.h"      // for UnimplementedError
 #include "Common/utility.h"                 // for deleteAll, filter, printAll
 #include "Concurrency/Actors.hpp"           // for implementActors
@@ -480,17 +478,4 @@
 		} // if
 		return EXIT_FAILURE;
-	} catch ( UnimplementedError & e ) {
-		cout << "Sorry, " << e.get_what() << " is not currently implemented" << endl;
-		if ( output != &cout ) {
-			delete output;
-		} // if
-		return EXIT_FAILURE;
-	} catch ( CompilerError & e ) {
-		cerr << "Compiler Error: " << e.get_what() << endl;
-		cerr << "(please report bugs to [REDACTED])" << endl;
-		if ( output != &cout ) {
-			delete output;
-		} // if
-		return EXIT_FAILURE;
 	} catch ( std::bad_alloc & ) {
 		cerr << "*cfa-cpp compilation error* std::bad_alloc" << endl;
