Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision ddcedfe425f9a47680a0484183f57fdb80f59380)
+++ src/AST/Print.cpp	(revision cd6a6ffee16b2e0915b5be3211ed86e60fd011e9)
@@ -205,5 +205,8 @@
 
 	void preprint( const ast::NamedTypeDecl * node ) {
-		if ( ! node->name.empty() ) os << node->name << ": ";
+		if ( ! node->name.empty() ) {
+			if( deterministic_output && isUnboundType(node->name) ) os << "[unbound]:";
+			else os << node->name << ": ";
+		}
 
 		if ( ! short_mode && node->linkage != Linkage::Cforall ) {
@@ -240,11 +243,9 @@
 
 		if ( node->result ) {
-			if (!deterministic_output) {
-				os << endl << indent << "... with resolved type:" << endl;
-				++indent;
-				os << indent;
-				node->result->accept( *this );
-				--indent;
-			}
+			os << endl << indent << "... with resolved type:" << endl;
+			++indent;
+			os << indent;
+			node->result->accept( *this );
+			--indent;
 		}
 
@@ -1382,5 +1383,6 @@
 	virtual const ast::Type * visit( const ast::TypeInstType * node ) override final {
 		preprint( node );
-		os << "instance of type " << node->name
+		const auto & _name = deterministic_output && isUnboundType(node) ? "[unbound]" : node->name;
+		os << "instance of type " << _name
 		   << " (" << (node->kind == ast::TypeDecl::Ftype ? "" : "not ") << "function type)";
 		print( node->params );
Index: src/AST/Type.cpp
===================================================================
--- src/AST/Type.cpp	(revision ddcedfe425f9a47680a0484183f57fdb80f59380)
+++ src/AST/Type.cpp	(revision cd6a6ffee16b2e0915b5be3211ed86e60fd011e9)
@@ -133,5 +133,5 @@
 
 BaseInstType::BaseInstType( const BaseInstType & o )
-: ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ), 
+: ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ),
   hoistType( o.hoistType ) {
 	Pass< ForallSubstitutor > sub;
@@ -222,7 +222,16 @@
 		// TODO: once TypeInstType representation is updated, it should properly check
 		// if the context id is filled. this is a temporary hack for now
-		if (std::count(typeInst->name.begin(), typeInst->name.end(), '_') >= 3) {
-			return true;
-		}
+		return isUnboundType(typeInst->name);
+	}
+	return false;
+}
+
+bool isUnboundType(const std::string & tname) {
+	// xxx - look for a type name produced by renameTyVars.
+
+	// TODO: once TypeInstType representation is updated, it should properly check
+	// if the context id is filled. this is a temporary hack for now
+	if (std::count(tname.begin(), tname.end(), '_') >= 3) {
+		return true;
 	}
 	return false;
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision ddcedfe425f9a47680a0484183f57fdb80f59380)
+++ src/AST/Type.hpp	(revision cd6a6ffee16b2e0915b5be3211ed86e60fd011e9)
@@ -536,4 +536,5 @@
 
 bool isUnboundType(const Type * type);
+bool isUnboundType(const std::string & tname);
 
 }
Index: src/AST/TypeEnvironment.cpp
===================================================================
--- src/AST/TypeEnvironment.cpp	(revision ddcedfe425f9a47680a0484183f57fdb80f59380)
+++ src/AST/TypeEnvironment.cpp	(revision cd6a6ffee16b2e0915b5be3211ed86e60fd011e9)
@@ -34,4 +34,5 @@
 #include "ResolvExpr/Unify.h"      // for unifyInexact
 #include "Tuples/Tuples.h"         // for isTtype
+#include "CompilationState.h"
 
 using ResolvExpr::WidenMode;
@@ -56,6 +57,12 @@
 
 void print( std::ostream & out, const EqvClass & clz, Indenter indent ) {
-	out << "( ";
-	std::copy( clz.vars.begin(), clz.vars.end(), std::ostream_iterator< std::string >( out, " " ) );
+	out << "(";
+	bool first = true;
+	for(const auto & var : clz.vars) {
+		if(first) first = false;
+		else out << " ";
+		if( deterministic_output && isUnboundType(var) ) out << "[unbound]";
+		else out << var;
+	}
 	out << ")";
 
Index: src/ResolvExpr/TypeEnvironment.cc
===================================================================
--- src/ResolvExpr/TypeEnvironment.cc	(revision ddcedfe425f9a47680a0484183f57fdb80f59380)
+++ src/ResolvExpr/TypeEnvironment.cc	(revision cd6a6ffee16b2e0915b5be3211ed86e60fd011e9)
@@ -107,9 +107,13 @@
 
 	void EqvClass::print( std::ostream &os, Indenter indent ) const {
-		if( !deterministic_output ) {
-			os << "( ";
-			std::copy( vars.begin(), vars.end(), std::ostream_iterator< std::string >( os, " " ) );
-			os << ")";
-		}
+		os << "(";
+		bool first = true;
+		for(const auto & var : vars) {
+			if(first) first = false;
+			else os << " ";
+			if( deterministic_output && isUnboundType(var) ) os << "[unbound]";
+			else os << var;
+		}
+		os << ")";
 		if ( type ) {
 			os << " -> ";
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision ddcedfe425f9a47680a0484183f57fdb80f59380)
+++ src/SynTree/Expression.cc	(revision cd6a6ffee16b2e0915b5be3211ed86e60fd011e9)
@@ -72,9 +72,7 @@
 
 	if ( result ) {
-		if (!deterministic_output) {
-			os << std::endl << indent << "with resolved type:" << std::endl;
-			os << (indent+1);
-			result->print( os, indent+1 );
-		}
+		os << std::endl << indent << "with resolved type:" << std::endl;
+		os << (indent+1);
+		result->print( os, indent+1 );
 	}
 
Index: src/SynTree/NamedTypeDecl.cc
===================================================================
--- src/SynTree/NamedTypeDecl.cc	(revision ddcedfe425f9a47680a0484183f57fdb80f59380)
+++ src/SynTree/NamedTypeDecl.cc	(revision cd6a6ffee16b2e0915b5be3211ed86e60fd011e9)
@@ -22,4 +22,5 @@
 #include "LinkageSpec.h"         // for Spec, Cforall, linkageName
 #include "Type.h"                // for Type, Type::StorageClasses
+#include "CompilationState.h"
 
 NamedTypeDecl::NamedTypeDecl( const std::string &name, Type::StorageClasses scs, Type *base )
@@ -41,5 +42,8 @@
 	using namespace std;
 
-	if ( name != "" ) os << name << ": ";
+	if ( ! name.empty() ) {
+		if( deterministic_output && isUnboundType(name) ) os << "[unbound]:";
+		else os << name << ": ";
+	}
 
 	if ( linkage != LinkageSpec::Cforall ) {
Index: src/SynTree/ReferenceToType.cc
===================================================================
--- src/SynTree/ReferenceToType.cc	(revision ddcedfe425f9a47680a0484183f57fdb80f59380)
+++ src/SynTree/ReferenceToType.cc	(revision cd6a6ffee16b2e0915b5be3211ed86e60fd011e9)
@@ -24,4 +24,5 @@
 #include "Type.h"             // for TypeInstType, StructInstType, UnionInstType
 #include "TypeSubstitution.h" // for TypeSubstitution
+#include "CompilationState.h"
 
 class Attribute;
@@ -205,5 +206,9 @@
 
 	Type::print( os, indent );
-	os << "instance of " << typeString() << " " << get_name() << " (" << ( isFtype ? "" : "not" ) << " function type)";
+	os << "instance of " << typeString() << " ";
+	const auto & name_ = get_name();
+	if( deterministic_output && isUnboundType(name) ) os << "[unbound]";
+	else os << name;
+	os << " (" << ( isFtype ? "" : "not" ) << " function type)";
 	if ( ! parameters.empty() ) {
 		os << endl << indent << "... with parameters" << endl;
Index: src/SynTree/Type.cc
===================================================================
--- src/SynTree/Type.cc	(revision ddcedfe425f9a47680a0484183f57fdb80f59380)
+++ src/SynTree/Type.cc	(revision cd6a6ffee16b2e0915b5be3211ed86e60fd011e9)
@@ -156,4 +156,26 @@
 const Type::Qualifiers noQualifiers;
 
+bool isUnboundType(const Type * type) {
+	if (auto typeInst = dynamic_cast<const TypeInstType *>(type)) {
+		// xxx - look for a type name produced by renameTyVars.
+
+		// TODO: once TypeInstType representation is updated, it should properly check
+		// if the context id is filled. this is a temporary hack for now
+		return isUnboundType(typeInst->name);
+	}
+	return false;
+}
+
+bool isUnboundType(const std::string & tname) {
+	// xxx - look for a type name produced by renameTyVars.
+
+	// TODO: once TypeInstType representation is updated, it should properly check
+	// if the context id is filled. this is a temporary hack for now
+	if (std::count(tname.begin(), tname.end(), '_') >= 3) {
+		return true;
+	}
+	return false;
+}
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision ddcedfe425f9a47680a0484183f57fdb80f59380)
+++ src/SynTree/Type.h	(revision cd6a6ffee16b2e0915b5be3211ed86e60fd011e9)
@@ -733,4 +733,8 @@
 };
 
+
+bool isUnboundType(const Type * type);
+bool isUnboundType(const std::string & tname);
+
 // Local Variables: //
 // tab-width: 4 //
