Index: src/GenPoly/Specialize.cc
===================================================================
--- src/GenPoly/Specialize.cc	(revision f5392c1db4bb1b778c34b7d634a0224a8c9615d2)
+++ src/GenPoly/Specialize.cc	(revision 623ecf34b307c3d929499dc0514c51d2c330f23e)
@@ -168,4 +168,26 @@
 	}
 
+	struct EnvTrimmer : public Visitor {
+		TypeSubstitution * env, * newEnv;
+		EnvTrimmer( TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
+		virtual void visit( TypeDecl * tyDecl ) {
+			// transfer known bindings for seen type variables
+			if ( Type * t = env->lookup( tyDecl->get_name() ) ) {
+				newEnv->add( tyDecl->get_name(), t );
+			}
+		}
+	};
+
+	/// reduce environment to just the parts that are referenced in a given expression
+	TypeSubstitution * trimEnv( ApplicationExpr * expr, TypeSubstitution * env ) {
+		if ( env ) {
+			TypeSubstitution * newEnv = new TypeSubstitution();
+			EnvTrimmer trimmer( env, newEnv );
+			expr->accept( trimmer );
+			return newEnv;
+		}
+		return nullptr;
+	}
+
 	/// Generates a thunk that calls `actual` with type `funType` and returns its address
 	Expression * Specialize::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) {
@@ -211,5 +233,5 @@
 		}
 
-		appExpr->set_env( maybeClone( env ) );
+		appExpr->set_env( trimEnv( appExpr, env ) );
 		if ( inferParams ) {
 			appExpr->get_inferParams() = *inferParams;
