Index: src/SynTree/GcTracer.h
===================================================================
--- src/SynTree/GcTracer.h	(revision 28f3a190cabb48116467ce6e1ebc74a38dac95b7)
+++ src/SynTree/GcTracer.h	(revision d318a182b0b2491a1aa64771c523470334852f01)
@@ -25,6 +25,5 @@
 #include "Common/GC.h"
 #include "Common/PassVisitor.h"
-
-class Expression;
+#include "ResolvExpr/TypeEnvironment.h"
 
 /// Implements `trace` method for syntax nodes
@@ -34,4 +33,7 @@
 public:
 	GcTracer( const GC& gc ) : gc(gc) {}
+
+	template<typename... Args>
+	void traceAll(Args&... args) { ::traceAll(gc, args...); }
 
 	// mark node and children
@@ -151,4 +153,38 @@
 		maybeAccept( type->baseUnion, *visitor );
 	}
+
+private:
+	void visit( const ResolvExpr::TypeEnvironment::Classes* c ) {
+		typedef ResolvExpr::TypeEnvironment::Classes C;
+		// trace all parent classes, short-circuiting at one traced
+		while ( gc.notrace_mark( c ) && c->get_mode() != C::BASE ) { c = c->get_base(); }
+	}
+
+	void visit( const ResolvExpr::TypeEnvironment::Bindings* b ) {
+		typedef ResolvExpr::TypeEnvironment::Bindings B;
+
+		while ( true ) {
+			if ( ! gc.notrace_mark( b ) ) return;  // short-circuit if already traced
+
+			if ( b->get_mode() == B::BASE ) break; // break if this is a base map
+			
+			if ( b->get_mode() != B::REM ) { // trace bound intermediate elements
+				maybeAccept( b->get_val().type, *visitor );
+			}
+
+			b = b->get_base();
+		}
+
+		// trace bound elements in base binding
+		b->for_each( [&](interned_string, const ResolvExpr::BoundType& bound) {
+			maybeAccept( bound.type, *visitor );  // trace bound elements
+		} );
+	}
+
+public:
+	void visit( const ResolvExpr::TypeEnvironment& env ) {
+		visit( env.classes );
+		visit( env.bindings );
+	}
 };
 
