Index: src/Common/GC.cc
===================================================================
--- src/Common/GC.cc	(revision 5af7306aa8aedc45c7e1b675f42139b19edd2a7c)
+++ src/Common/GC.cc	(revision 2efe4b8f0141e181a04fcc0495d13a8c7a0a06b9)
@@ -77,7 +77,8 @@
 }
 
-void GC::new_generation() {
+GC_Guard GC::new_generation() {
 	if ( ++g == gens.size() ) { gens.emplace_back(); }  // ensure new generation available
 	mark = !mark;  // switch mark so aged young objects will still be unmarked in old
+	return { *this, g };
 }
 
Index: src/Common/GC.h
===================================================================
--- src/Common/GC.h	(revision 5af7306aa8aedc45c7e1b675f42139b19edd2a7c)
+++ src/Common/GC.h	(revision 2efe4b8f0141e181a04fcc0495d13a8c7a0a06b9)
@@ -16,12 +16,20 @@
 #pragma once
 
+#include <cassert>
 #include <vector>
 
 class GC_Object;
 class BaseSyntaxNode;
+class GC_Guard;
 
 /// Manually traced and called garbage collector
 class GC {
 	friend class GcTracer;
+	friend class GC_Guard;
+
+	/// Collects the youngest generation, placing survivors in previous generation.
+	/// Young generation objects cannot be kept alive by pointers from older generation.
+	/// Older generation is used for subsequent new objects.
+	void collect_young();
 public:
 	/// Gets singleton GC instance
@@ -38,13 +46,8 @@
 
 	/// Start new generation for subsequent new objects
-	void new_generation();
+	GC_Guard new_generation();
 
 	/// Traces all static roots
 	void trace_static_roots();
-
-	/// Collects the youngest generation, placing survivors in previous generation.
-	/// Young generation objects cannot be kept alive by pointers from older generation.
-	/// Older generation is used for subsequent new objects.
-	void collect_young();
 
 	/// Collects oldest generation; use oldest generation afterward.
@@ -68,6 +71,22 @@
 };
 
+/// Cleanup object for young generation
+class GC_Guard {
+	friend class GC;
+
+	GC& gc;      ///< GC associated with
+	unsigned g;  ///< Generation constructed for
+
+	GC_Guard( GC& gc, unsigned g ) : gc(gc), g(g) {}
+
+public:
+	~GC_Guard() {
+		assert( gc.g == g && "collecting current generation" );
+		gc.collect_young();
+	}
+};
+
 /// Use young generation until next collection
-inline void new_generation() { GC::get().new_generation(); }
+inline GC_Guard new_generation() { return GC::get().new_generation(); }
 
 // /// no-op default trace
@@ -84,14 +103,13 @@
 }
 
-/// Traces young-generation roots and does a young collection
+/// Traces roots without collecting
 template<typename... Args>
-inline void collect_young(Args&... roots) {
+inline void trace(Args&... roots) {
 	GC& gc = GC::get();
 	traceAll(gc, roots...);
 	gc.trace_static_roots();
-	gc.collect_young();
 }
 
-/// Traces roots and collects other elements
+/// Traces roots and collects other elements; should not be any young generations live
 template<typename... Args>
 inline void collect(Args&... roots) {
