Index: src/GenPoly/FindFunction.cc
===================================================================
--- src/GenPoly/FindFunction.cc	(revision 5e3f1e14cea1b791454e6f55b046ed4a95c4e041)
+++ src/GenPoly/FindFunction.cc	(revision 44a0ca20cb055d3e45fe4b15fca7d515df7d1c17)
@@ -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 5e3f1e14cea1b791454e6f55b046ed4a95c4e041)
+++ src/GenPoly/FindFunction.h	(revision 44a0ca20cb055d3e45fe4b15fca7d515df7d1c17)
@@ -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 5e3f1e14cea1b791454e6f55b046ed4a95c4e041)
+++ src/GenPoly/GenPoly.cc	(revision 44a0ca20cb055d3e45fe4b15fca7d515df7d1c17)
@@ -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 5e3f1e14cea1b791454e6f55b046ed4a95c4e041)
+++ src/GenPoly/GenPoly.h	(revision 44a0ca20cb055d3e45fe4b15fca7d515df7d1c17)
@@ -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
