Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 85f07136d59ad0958d13142535210855683cd8a9)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision d06010a28ab857436d2ccf1a935d3b872798b7aa)
@@ -19,4 +19,7 @@
 #include <functional>
 #include <cassert>
+#include <unordered_map>
+#include <utility>
+#include <vector>
 
 #include "AlternativeFinder.h"
@@ -408,5 +411,9 @@
 	}
 
-	static const int recursionLimit = 10;
+	/// Map of declaration uniqueIds (intended to be the assertions in an AssertionSet) to their parents and the number of times they've been included
+	typedef std::unordered_map< UniqueId, std::unordered_map< UniqueId, unsigned > > AssertionParentSet;
+	
+	static const int recursionLimit = 10;  ///< Limit to depth of recursion satisfaction
+	static const unsigned recursionParentLimit = 1;  ///< Limit to the number of times an assertion can recursively use itself
 
 	void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) {
@@ -417,7 +424,8 @@
 		}
 	}
-
+	
 	template< typename ForwardIterator, typename OutputIterator >
-	void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out ) {
+	void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, const AssertionParentSet &needParents, 
+						 int level, const SymTab::Indexer &indexer, OutputIterator out ) {
 		if ( begin == end ) {
 			if ( newNeed.empty() ) {
@@ -432,5 +440,5 @@
 					printAssertionSet( newNeed, std::cerr, 8 );
 				)
-				inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out );
+				inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, needParents, level+1, indexer, out );
 				return;
 			}
@@ -439,5 +447,5 @@
 		ForwardIterator cur = begin++;
 		if ( ! cur->second ) {
-			inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out );
+			inferRecursive( begin, end, newAlt, openVars, decls, newNeed, needParents, level, indexer, out );
 		}
 		DeclarationWithType *curDecl = cur->first;
@@ -456,4 +464,5 @@
 				std::cerr << std::endl;
 			)
+			
 			AssertionSet newHave, newerNeed( newNeed );
 			TypeEnvironment newEnv( newAlt.env );
@@ -478,5 +487,9 @@
 				newerAlt.env = newEnv;
 				assert( (*candidate)->get_uniqueId() );
-				Expression *varExpr = new VariableExpr( static_cast< DeclarationWithType* >( Declaration::declFromId( (*candidate)->get_uniqueId() ) ) );
+				DeclarationWithType *candDecl = static_cast< DeclarationWithType* >( Declaration::declFromId( (*candidate)->get_uniqueId() ) );
+				AssertionParentSet newNeedParents( needParents );
+				// skip repeatingly-self-recursive assertion satisfaction
+				if ( newNeedParents[ curDecl->get_uniqueId() ][ candDecl->get_uniqueId() ]++ > recursionParentLimit ) continue;
+				Expression *varExpr = new VariableExpr( candDecl );
 				deleteAll( varExpr->get_results() );
 				varExpr->get_results().clear();
@@ -492,5 +505,5 @@
 				// XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions
 				appExpr->get_inferParams()[ curDecl->get_uniqueId() ] = ParamEntry( (*candidate)->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
-				inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out );
+				inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, newNeedParents, level, indexer, out );
 			} else {
 				delete adjType;
@@ -514,5 +527,6 @@
 		addToIndexer( have, decls );
 		AssertionSet newNeed;
-		inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out );
+		AssertionParentSet needParents;
+		inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, needParents, 0, indexer, out );
 //	PRINT(
 //	    std::cerr << "declaration 14 is ";
Index: src/ResolvExpr/RenameVars.cc
===================================================================
--- src/ResolvExpr/RenameVars.cc	(revision 85f07136d59ad0958d13142535210855683cd8a9)
+++ src/ResolvExpr/RenameVars.cc	(revision d06010a28ab857436d2ccf1a935d3b872798b7aa)
@@ -45,7 +45,5 @@
 	void RenameVars::visit( PointerType *pointerType ) {
 		typeBefore( pointerType );
-///   std::cout << "do pointer" << std::endl;
 		maybeAccept( pointerType->get_base(), *this );
-///   std::cout << "done pointer" << std::endl;
 		typeAfter( pointerType );
 	}
@@ -60,9 +58,6 @@
 	void RenameVars::visit( FunctionType *functionType ) {
 		typeBefore( functionType );
-///   std::cout << "return vals" << std::endl;
 		acceptAll( functionType->get_returnVals(), *this );
-///   std::cout << functionType->get_parameters().size() << " parameters" << std::endl;
 		acceptAll( functionType->get_parameters(), *this );
-///   std::cout << "done function" << std::endl;
 		typeAfter( functionType );
 	}
@@ -95,11 +90,8 @@
 	void RenameVars::visit( TypeInstType *instType ) {
 		typeBefore( instType );
-///   std::cout << "instance of type " << instType->get_name() << std::endl;
 		std::map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->get_name() );
 		if ( i != mapStack.front().end() ) {
-///     std::cout << "found name " << i->second << std::endl;
 			instType->set_name( i->second );
 		} else {
-///     std::cout << "no name found" << std::endl;
 		} // if
 		acceptAll( instType->get_parameters(), *this );
@@ -120,7 +112,4 @@
 	void RenameVars::typeBefore( Type *type ) {
 		if ( ! type->get_forall().empty() ) {
-///     std::cout << "type with forall: ";
-///     type->print( std::cout );
-///     std::cout << std::endl;
 			// copies current name mapping into new mapping
 			mapStack.push_front( mapStack.front() );
Index: src/ResolvExpr/typeops.h
===================================================================
--- src/ResolvExpr/typeops.h	(revision 85f07136d59ad0958d13142535210855683cd8a9)
+++ src/ResolvExpr/typeops.h	(revision d06010a28ab857436d2ccf1a935d3b872798b7aa)
@@ -54,4 +54,5 @@
   
 	// in AdjustExprType.cc
+	/// Replaces array types with the equivalent pointer, and function types with a pointer-to-function
 	void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer );
 
Index: src/tests/test.py
===================================================================
--- src/tests/test.py	(revision 85f07136d59ad0958d13142535210855683cd8a9)
+++ src/tests/test.py	(revision d06010a28ab857436d2ccf1a935d3b872798b7aa)
@@ -21,12 +21,12 @@
 	return list
 
-def sh(cmd, dry_run):
+def sh(cmd, dry_run = False, print2stdout = True):
 	if dry_run :
 		print("cmd: %s" % cmd)
-		return 0
+		return 0, None
 	else :
-		proc = Popen(cmd, stderr=STDOUT, shell=True)
-		proc.communicate()
-		return proc.returncode
+		proc = Popen(cmd, stdout=None if print2stdout else PIPE, stderr=STDOUT, shell=True)
+		out, err = proc.communicate()
+		return proc.returncode, out
 
 def file_replace(fname, pat, s_after):
@@ -61,5 +61,5 @@
 
 	# build, skipping to next test on error
-	make_ret = sh("%s %s 2> %s 1> /dev/null" % (make_cmd, test, out_file), dry_run)
+	make_ret, _ = sh("%s %s 2> %s 1> /dev/null" % (make_cmd, test, out_file), dry_run)
 
 	if make_ret == 0 :
@@ -71,4 +71,5 @@
 
 	retcode = 0
+	error = None
 
 	fix_MakeLevel(out_file)
@@ -76,10 +77,24 @@
 	if not generate :
 		# diff the output of the files
-		retcode = sh("diff .expect/%s.txt .out/%s.log" % (test, test), dry_run)
+		diff_cmd = ("diff --old-group-format='\t\tmissing lines :\n"
+					"%%<' \\\n"
+					"--new-group-format='\t\tnew lines :\n"
+					"%%>' \\\n"
+					"--unchanged-group-format='%%=' \\"
+					"--changed-group-format='\t\texpected :\n"
+					"%%<\n"
+					"\t\tgot :\n"
+					"%%>' \\\n"
+					"--new-line-format='\t\t%%dn\t%%L' \\\n"
+					"--old-line-format='\t\t%%dn\t%%L' \\\n"
+					"--unchanged-line-format='' \\\n"
+					".expect/%s.txt .out/%s.log")
+
+		retcode, error = sh(diff_cmd % (test, test), dry_run, False)
 
 	# clean the executable
 	sh("rm -f %s > /dev/null 2>&1" % test, dry_run)
 
-	return retcode
+	return retcode, error
 
 def run_tests(tests, generate, dry_run) :
@@ -94,9 +109,11 @@
 		print("%20s  " % t, end="")
 		sys.stdout.flush()
-		test_failed = run_test_instance(t, generate, dry_run)
+		test_failed, error = run_test_instance(t, generate, dry_run)
 		failed = test_failed or failed
 
 		if not generate :
 			print("FAILED" if test_failed else "PASSED")
+			if error :
+				print(error)
 		else :
 			print( "Done" )
