Handle cycles when printing a value
So this no longer crashes with a stack overflow:
  nix-instantiate -E --eval 'let as = { x = as; }; in as'
Instead it prints:
  { x = { x = <CYCLE>; }; }
			
			
This commit is contained in:
		
							parent
							
								
									a54c263402
								
							
						
					
					
						commit
						022618c794
					
				
					 1 changed files with 23 additions and 5 deletions
				
			
		|  | @ -38,8 +38,14 @@ void Bindings::sort() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| std::ostream & operator << (std::ostream & str, const Value & v) | static void printValue(std::ostream & str, std::set<const Value *> & seen, const Value & v) | ||||||
| { | { | ||||||
|  |     if (seen.find(&v) != seen.end()) { | ||||||
|  |         str << "<CYCLE>"; | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     seen.insert(&v); | ||||||
|  | 
 | ||||||
|     switch (v.type) { |     switch (v.type) { | ||||||
|     case tInt: |     case tInt: | ||||||
|         str << v.integer; |         str << v.integer; | ||||||
|  | @ -69,15 +75,20 @@ std::ostream & operator << (std::ostream & str, const Value & v) | ||||||
|         Sorted sorted; |         Sorted sorted; | ||||||
|         foreach (Bindings::iterator, i, *v.attrs) |         foreach (Bindings::iterator, i, *v.attrs) | ||||||
|             sorted[i->name] = i->value; |             sorted[i->name] = i->value; | ||||||
|         foreach (Sorted::iterator, i, sorted) |         for (auto & i : sorted) { | ||||||
|             str << i->first << " = " << *i->second << "; "; |             str << i.first << " = "; | ||||||
|  |             printValue(str, seen, *i.second); | ||||||
|  |             str << "; "; | ||||||
|  |         } | ||||||
|         str << "}"; |         str << "}"; | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|     case tList: |     case tList: | ||||||
|         str << "[ "; |         str << "[ "; | ||||||
|         for (unsigned int n = 0; n < v.list.length; ++n) |         for (unsigned int n = 0; n < v.list.length; ++n) { | ||||||
|             str << *v.list.elems[n] << " "; |             printValue(str, seen, *v.list.elems[n]); | ||||||
|  |             str << " "; | ||||||
|  |         } | ||||||
|         str << "]"; |         str << "]"; | ||||||
|         break; |         break; | ||||||
|     case tThunk: |     case tThunk: | ||||||
|  | @ -96,6 +107,13 @@ std::ostream & operator << (std::ostream & str, const Value & v) | ||||||
|     default: |     default: | ||||||
|         throw Error("invalid value"); |         throw Error("invalid value"); | ||||||
|     } |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | std::ostream & operator << (std::ostream & str, const Value & v) | ||||||
|  | { | ||||||
|  |     std::set<const Value *> seen; | ||||||
|  |     printValue(str, seen, v); | ||||||
|     return str; |     return str; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue