Skip to content

Commit

Permalink
compiler: finalize methods for type aliases of struct types
Browse files Browse the repository at this point in the history
Previously we would finalize the methods of the alias type itself, but
since its a type alias we really need to finalize the methods of the
aliased type.

Also, handle method expressions of unnamed struct types.

Test case is https://golang.org/cl/251168.

Fixes golang/go#38125

Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/251279
  • Loading branch information
ianlancetaylor committed Sep 21, 2020
1 parent 1e19ecd commit 27edc6c
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 21 deletions.
2 changes: 1 addition & 1 deletion gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
6f309797e4f7eed635950687e902a294126e6fc6
a59167c29d6ad2ddf533b3a12b365f72df0e1476

The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
50 changes: 30 additions & 20 deletions gcc/go/gofrontend/expressions.cc
Expand Up @@ -14529,38 +14529,48 @@ Selector_expression::lower_method_expression(Gogo* gogo)
is_pointer = true;
type = type->points_to();
}
Named_type* nt = type->named_type();
if (nt == NULL)
{
go_error_at(location,
("method expression requires named type or "
"pointer to named type"));
return Expression::make_error(location);
}

Named_type* nt = type->named_type();
Struct_type* st = type->struct_type();
bool is_ambiguous;
Method* method = nt->method_function(name, &is_ambiguous);
Method* method = NULL;
if (nt != NULL)
method = nt->method_function(name, &is_ambiguous);
else if (st != NULL)
method = st->method_function(name, &is_ambiguous);
const Typed_identifier* imethod = NULL;
if (method == NULL && !is_pointer)
{
Interface_type* it = nt->interface_type();
Interface_type* it = type->interface_type();
if (it != NULL)
imethod = it->find_method(name);
}

if ((method == NULL && imethod == NULL)
|| (left_type->named_type() != NULL && left_type->points_to() != NULL))
{
if (!is_ambiguous)
go_error_at(location, "type %<%s%s%> has no method %<%s%>",
is_pointer ? "*" : "",
nt->message_name().c_str(),
Gogo::message_name(name).c_str());
if (nt != NULL)
{
if (!is_ambiguous)
go_error_at(location, "type %<%s%s%> has no method %<%s%>",
is_pointer ? "*" : "",
nt->message_name().c_str(),
Gogo::message_name(name).c_str());
else
go_error_at(location, "method %<%s%s%> is ambiguous in type %<%s%>",
Gogo::message_name(name).c_str(),
is_pointer ? "*" : "",
nt->message_name().c_str());
}
else
go_error_at(location, "method %<%s%s%> is ambiguous in type %<%s%>",
Gogo::message_name(name).c_str(),
is_pointer ? "*" : "",
nt->message_name().c_str());
{
if (!is_ambiguous)
go_error_at(location, "type has no method %<%s%>",
Gogo::message_name(name).c_str());
else
go_error_at(location, "method %<%s%> is ambiguous",
Gogo::message_name(name).c_str());
}
return Expression::make_error(location);
}

Expand Down Expand Up @@ -14657,7 +14667,7 @@ Selector_expression::lower_method_expression(Gogo* gogo)
Expression* ve = Expression::make_var_reference(vno, location);
Expression* bm;
if (method != NULL)
bm = Type::bind_field_or_method(gogo, nt, ve, name, location);
bm = Type::bind_field_or_method(gogo, type, ve, name, location);
else
bm = Expression::make_interface_field_reference(ve, name, location);

Expand Down
4 changes: 4 additions & 0 deletions gcc/go/gofrontend/gogo.cc
Expand Up @@ -3508,6 +3508,10 @@ Finalize_methods::type(Type* t)
case Type::TYPE_NAMED:
{
Named_type* nt = t->named_type();

if (nt->is_alias())
return TRAVERSE_CONTINUE;

Type* rt = nt->real_type();
if (rt->classification() != Type::TYPE_STRUCT)
{
Expand Down

0 comments on commit 27edc6c

Please sign in to comment.