compiler: look through aliases for type compatibility

Aliases are supposed to be identical to the type being aliased, so
questions about type compatibility need to always ignore aliases,
except for error messages involving the type name.

The test case for this is https://golang.org/cl/94995.

Fixes golang/go#23912

Change-Id: Ic3500b9689476239367d73dfd987ee91ea649a13
Reviewed-on: https://go-review.googlesource.com/94996
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/go/types.cc b/go/types.cc
index 40eccfc..11924e6 100644
--- a/go/types.cc
+++ b/go/types.cc
@@ -597,10 +597,10 @@
 	  return false;
 	}
 
-      if (t1->named_type() != NULL)
-	return t1->named_type()->named_type_is_comparable(reason);
-      else if (t2->named_type() != NULL)
-	return t2->named_type()->named_type_is_comparable(reason);
+      if (t1->unalias()->named_type() != NULL)
+	return t1->unalias()->named_type()->named_type_is_comparable(reason);
+      else if (t2->unalias()->named_type() != NULL)
+	return t2->unalias()->named_type()->named_type_is_comparable(reason);
       else if (t1->struct_type() != NULL)
 	{
 	  if (t1->struct_type()->is_struct_incomparable())
@@ -678,6 +678,12 @@
   if (Type::are_identical(lhs, rhs, true, reason))
     return true;
 
+  // Ignore aliases, except for error messages.
+  const Type* lhs_orig = lhs;
+  const Type* rhs_orig = rhs;
+  lhs = lhs->unalias();
+  rhs = rhs->unalias();
+
   // The types are assignable if they have identical underlying types
   // and either LHS or RHS is not a named type.
   if (((lhs->named_type() != NULL && rhs->named_type() == NULL)
@@ -740,15 +746,16 @@
     {
       if (rhs->interface_type() != NULL)
 	reason->assign(_("need explicit conversion"));
-      else if (lhs->named_type() != NULL && rhs->named_type() != NULL)
+      else if (lhs_orig->named_type() != NULL
+	       && rhs_orig->named_type() != NULL)
 	{
-	  size_t len = (lhs->named_type()->name().length()
-			+ rhs->named_type()->name().length()
+	  size_t len = (lhs_orig->named_type()->name().length()
+			+ rhs_orig->named_type()->name().length()
 			+ 100);
 	  char* buf = new char[len];
 	  snprintf(buf, len, _("cannot use type %s as type %s"),
-		   rhs->named_type()->message_name().c_str(),
-		   lhs->named_type()->message_name().c_str());
+		   rhs_orig->named_type()->message_name().c_str(),
+		   lhs_orig->named_type()->message_name().c_str());
 	  reason->assign(buf);
 	  delete[] buf;
 	}
@@ -768,6 +775,10 @@
   if (Type::are_assignable(lhs, rhs, reason))
     return true;
 
+  // Ignore aliases.
+  lhs = lhs->unalias();
+  rhs = rhs->unalias();
+
   // A pointer to a regular type may not be converted to a pointer to
   // a type that may not live in the heap, except when converting from
   // unsafe.Pointer.