1
0
mirror of https://github.com/golang/go synced 2024-09-29 01:14:29 -06:00

go/types, types2: factor out maximum type computation

For untyped constant binary operations we need to determine the
"maximum" (untyped) type which includes both constant types.
Factor out this functionality.

Change-Id: If42bd793d38423322885a3063a4321bd56443b36
Reviewed-on: https://go-review.googlesource.com/c/go/+/492619
Reviewed-by: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Robert Griesemer 2023-05-04 14:09:27 -07:00 committed by Gopher Robot
parent 445e520d49
commit 05ca41d3ef
4 changed files with 48 additions and 18 deletions

View File

@ -688,19 +688,14 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] {
return x.typ, nil, 0
}
// x is untyped
if isUntyped(target) {
// both x and target are untyped
xkind := x.typ.(*Basic).kind
tkind := target.(*Basic).kind
if isNumeric(x.typ) && isNumeric(target) {
if xkind < tkind {
return target, nil, 0
}
} else if xkind != tkind {
return nil, nil, InvalidUntypedConversion
if m := maxType(x.typ, target); m != nil {
return m, nil, 0
}
return x.typ, nil, 0
return nil, nil, InvalidUntypedConversion
}
if x.isNil() {

View File

@ -510,3 +510,23 @@ func Default(t Type) Type {
}
return t
}
// maxType returns the "largest" type that encompasses both x and y.
// If x and y are different untyped numeric types, the result is the type of x or y
// that appears later in this list: integer, rune, floating-point, complex.
// Otherwise, if x != y, the result is nil.
func maxType(x, y Type) Type {
// We only care about untyped types (for now), so == is good enough.
// TODO(gri) investigate generalizing this function to simplify code elsewhere
if x == y {
return x
}
if isUntyped(x) && isUntyped(y) && isNumeric(x) && isNumeric(y) {
// untyped types are basic types
if x.(*Basic).kind > y.(*Basic).kind {
return x
}
return y
}
return nil
}

View File

@ -652,19 +652,14 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] {
return x.typ, nil, 0
}
// x is untyped
if isUntyped(target) {
// both x and target are untyped
xkind := x.typ.(*Basic).kind
tkind := target.(*Basic).kind
if isNumeric(x.typ) && isNumeric(target) {
if xkind < tkind {
return target, nil, 0
}
} else if xkind != tkind {
return nil, nil, InvalidUntypedConversion
if m := maxType(x.typ, target); m != nil {
return m, nil, 0
}
return x.typ, nil, 0
return nil, nil, InvalidUntypedConversion
}
switch u := under(target).(type) {

View File

@ -512,3 +512,23 @@ func Default(t Type) Type {
}
return t
}
// maxType returns the "largest" type that encompasses both x and y.
// If x and y are different untyped numeric types, the result is the type of x or y
// that appears later in this list: integer, rune, floating-point, complex.
// Otherwise, if x != y, the result is nil.
func maxType(x, y Type) Type {
// We only care about untyped types (for now), so == is good enough.
// TODO(gri) investigate generalizing this function to simplify code elsewhere
if x == y {
return x
}
if isUntyped(x) && isUntyped(y) && isNumeric(x) && isNumeric(y) {
// untyped types are basic types
if x.(*Basic).kind > y.(*Basic).kind {
return x
}
return y
}
return nil
}