compiler: cast comparison function result to expected bool type
Otherwise cases like type mybool bool var b mybool = [10]string{} == [10]string{} get an incorrect type checking error. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/274446
This commit is contained in:
parent
cd34d5f2c4
commit
17c9cf3c17
@ -1,4 +1,4 @@
|
||||
5364d15082de77d2759a01f254208d4cb4f579e3
|
||||
b3a0b068f7fa2d65ba781271b2c0479d103b7d7b
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
@ -6287,8 +6287,21 @@ Binary_expression::lower_array_comparison(Gogo* gogo,
|
||||
args->push_back(this->operand_address(inserter, this->left_));
|
||||
args->push_back(this->operand_address(inserter, this->right_));
|
||||
|
||||
Expression* ret = Expression::make_call(func, args, false, loc);
|
||||
Call_expression* ce = Expression::make_call(func, args, false, loc);
|
||||
|
||||
// Record that this is a call to a generated equality function. We
|
||||
// need to do this because a comparison returns an abstract boolean
|
||||
// type, but the function necessarily returns "bool". The
|
||||
// difference shows up in code like
|
||||
// type mybool bool
|
||||
// var b mybool = [10]string{} == [10]string{}
|
||||
// The comparison function returns "bool", but since a comparison
|
||||
// has an abstract boolean type we need an implicit conversion to
|
||||
// "mybool". The implicit conversion is inserted in
|
||||
// Call_expression::do_flatten.
|
||||
ce->set_is_equal_function();
|
||||
|
||||
Expression* ret = ce;
|
||||
if (this->op_ == OPERATOR_NOTEQ)
|
||||
ret = Expression::make_unary(OPERATOR_NOT, ret, loc);
|
||||
|
||||
@ -11163,6 +11176,13 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*,
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Add an implicit conversion to a boolean type, if needed. See the
|
||||
// comment in Binary_expression::lower_array_comparison.
|
||||
if (this->is_equal_function_
|
||||
&& this->type_ != NULL
|
||||
&& this->type_ != Type::lookup_bool_type())
|
||||
return Expression::make_cast(this->type_, this, this->location());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -11938,7 +11958,7 @@ Call_expression::do_type()
|
||||
// parameter types to set the types of the arguments.
|
||||
|
||||
void
|
||||
Call_expression::do_determine_type(const Type_context*)
|
||||
Call_expression::do_determine_type(const Type_context* context)
|
||||
{
|
||||
if (!this->determining_types())
|
||||
return;
|
||||
@ -11985,6 +12005,22 @@ Call_expression::do_determine_type(const Type_context*)
|
||||
(*pa)->determine_type_no_context();
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a call to a generated equality function, we determine
|
||||
// the type based on the context. See the comment in
|
||||
// Binary_expression::lower_array_comparison.
|
||||
if (this->is_equal_function_
|
||||
&& !context->may_be_abstract
|
||||
&& context->type != NULL
|
||||
&& context->type->is_boolean_type()
|
||||
&& context->type != Type::lookup_bool_type())
|
||||
{
|
||||
go_assert(this->type_ == NULL
|
||||
|| this->type_ == Type::lookup_bool_type()
|
||||
|| this->type_ == context->type
|
||||
|| this->type_->is_error());
|
||||
this->type_ = context->type;
|
||||
}
|
||||
}
|
||||
|
||||
// Called when determining types for a Call_expression. Return true
|
||||
|
@ -2326,8 +2326,8 @@ class Call_expression : public Expression
|
||||
fn_(fn), args_(args), type_(NULL), call_(NULL), call_temp_(NULL)
|
||||
, expected_result_count_(0), is_varargs_(is_varargs),
|
||||
varargs_are_lowered_(false), types_are_determined_(false),
|
||||
is_deferred_(false), is_concurrent_(false), issued_error_(false),
|
||||
is_multi_value_arg_(false), is_flattened_(false)
|
||||
is_deferred_(false), is_concurrent_(false), is_equal_function_(false),
|
||||
issued_error_(false), is_multi_value_arg_(false), is_flattened_(false)
|
||||
{ }
|
||||
|
||||
// The function to call.
|
||||
@ -2408,6 +2408,11 @@ class Call_expression : public Expression
|
||||
set_is_concurrent()
|
||||
{ this->is_concurrent_ = true; }
|
||||
|
||||
// Note that this is a call to a generated equality function.
|
||||
void
|
||||
set_is_equal_function()
|
||||
{ this->is_equal_function_ = true; }
|
||||
|
||||
// We have found an error with this call expression; return true if
|
||||
// we should report it.
|
||||
bool
|
||||
@ -2545,6 +2550,8 @@ class Call_expression : public Expression
|
||||
bool is_deferred_;
|
||||
// True if the call is an argument to a go statement.
|
||||
bool is_concurrent_;
|
||||
// True if this is a call to a generated equality function.
|
||||
bool is_equal_function_;
|
||||
// True if we reported an error about a mismatch between call
|
||||
// results and uses. This is to avoid producing multiple errors
|
||||
// when there are multiple Call_result_expressions.
|
||||
|
Loading…
Reference in New Issue
Block a user