Index: src/SynTree/TypeSubstitution.cc
===================================================================
--- src/SynTree/TypeSubstitution.cc	(revision a8a2b0a3efd9013002c3385d3dd01fc2cf2103c1)
+++ src/SynTree/TypeSubstitution.cc	(revision 507e7a25c43d01f94faa1f5f24b309ae36bd70d6)
@@ -104,4 +104,28 @@
 bool TypeSubstitution::empty() const {
 	return typeEnv.empty() && varEnv.empty();
+}
+
+namespace {
+	struct EnvTrimmer {
+		TypeSubstitution * env, * newEnv;
+		EnvTrimmer( TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
+		void previsit( TypeDecl * tyDecl ) {
+			// transfer known bindings for seen type variables
+			if ( Type * t = env->lookup( tyDecl->name ) ) {
+				newEnv->add( tyDecl->name, t );
+			}
+		}
+	};
+} // namespace
+
+/// reduce environment to just the parts that are referenced in a given expression
+TypeSubstitution * TypeSubstitution::newFromExpr( Expression * expr, TypeSubstitution * env ) {
+	if ( env ) {
+		TypeSubstitution * newEnv = new TypeSubstitution();
+		PassVisitor<EnvTrimmer> trimmer( env, newEnv );
+		expr->accept( trimmer );
+		return newEnv;
+	}
+	return nullptr;
 }
 
Index: src/SynTree/TypeSubstitution.h
===================================================================
--- src/SynTree/TypeSubstitution.h	(revision a8a2b0a3efd9013002c3385d3dd01fc2cf2103c1)
+++ src/SynTree/TypeSubstitution.h	(revision 507e7a25c43d01f94faa1f5f24b309ae36bd70d6)
@@ -54,4 +54,7 @@
 	template< typename TypeInstListIterator >
 	void extract( TypeInstListIterator begin, TypeInstListIterator end, TypeSubstitution &result );
+
+	/// create a new TypeSubstitution using bindings from env containing all of the type variables in expr
+	static TypeSubstitution * newFromExpr( Expression * expr, TypeSubstitution * env );
 
 	void normalize();
