Go patch committed: Correct handling of recursive types

Submitted by Ian Taylor on Dec. 14, 2010, 5:57 p.m.

Details

Message ID mcr62uwxmnv.fsf@google.com
State New
Headers show

Commit Message

Ian Taylor Dec. 14, 2010, 5:57 p.m.
Go permits types to be refer to themselves in ways that can not be
written in C/C++ and are not permitted in GENERIC.  The existing code
looks for specific cases, but it breaks in more complex cases in which
types refer to themselves indirectly via other types.  This patch
simplifies the code so that these cases are handled correctly, or at
least as correctly as they can be given the limitations on GENERIC.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian

Patch hide | download patch | download mbox

diff -r 1c613f1babbc go/types.cc
--- a/go/types.cc	Mon Dec 13 21:53:48 2010 -0800
+++ b/go/types.cc	Tue Dec 14 09:42:36 2010 -0800
@@ -6795,14 +6795,10 @@ 
       break;
 
     case TYPE_FUNCTION:
-      // GENERIC can't handle a pointer to a function type whose
-      // return type is a pointer to the function type itself.  It
-      // does into infinite loops when walking the types.
-      if (this->seen_
-	  && this->function_type()->results() != NULL
-	  && this->function_type()->results()->size() == 1
-	  && (this->function_type()->results()->front().type()->forwarded()
-	      == this))
+      // Don't recur infinitely if a function type refers to itself.
+      // Ideally we would build a circular data structure here, but
+      // GENERIC can't handle them.
+      if (this->seen_)
 	return ptr_type_node;
       this->seen_ = true;
       t = Type::get_named_type_tree(gogo, this->type_);
@@ -6813,9 +6809,10 @@ 
       break;
 
     case TYPE_POINTER:
-      // GENERIC can't handle a pointer type which points to itself.
-      // It goes into infinite loops when walking the types.
-      if (this->seen_ && this->points_to()->forwarded() == this)
+      // Don't recur infinitely if a pointer type refers to itself.
+      // Ideally we would build a circular data structure here, but
+      // GENERIC can't handle them.
+      if (this->seen_)
 	return ptr_type_node;
       this->seen_ = true;
       t = Type::get_named_type_tree(gogo, this->type_);