go/types, types2: adjust Checker.recordCommaOkTypes signature

By changing the signature to accept a slice rather than an
array, we can avoid creating the array in the first place.

Functionally, we now also record comma-ok types if the
corresponding assignment was incorrect. But this change
provides more (not less) information through the API and
only so if the program is incorrect in the first place.

Change-Id: I0d629441f2f890a37912171fb26ef0e75827ce23
Reviewed-on: https://go-review.googlesource.com/c/go/+/478218
Auto-Submit: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Robert Griesemer 2023-03-21 17:21:17 -07:00 committed by Gopher Robot
parent 0ed364a463
commit bd7b19356f
4 changed files with 33 additions and 32 deletions

View File

@ -373,11 +373,9 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnStmt sy
}
if commaOk {
var a [2]Type
for i := range a {
a[i] = check.initVar(lhs[i], rhs[i], context)
}
check.recordCommaOkTypes(orig_rhs[0], a)
check.initVar(lhs[0], rhs[0], context)
check.initVar(lhs[1], rhs[1], context)
check.recordCommaOkTypes(orig_rhs[0], rhs)
return
}
@ -412,11 +410,9 @@ func (check *Checker) assignVars(lhs, orig_rhs []syntax.Expr) {
}
if commaOk {
var a [2]Type
for i := range a {
a[i] = check.assignVar(lhs[i], rhs[i])
}
check.recordCommaOkTypes(orig_rhs[0], a)
check.assignVar(lhs[0], rhs[0])
check.assignVar(lhs[1], rhs[1])
check.recordCommaOkTypes(orig_rhs[0], rhs)
return
}

View File

@ -504,22 +504,27 @@ func (check *Checker) recordBuiltinType(f syntax.Expr, sig *Signature) {
}
}
func (check *Checker) recordCommaOkTypes(x syntax.Expr, a [2]Type) {
// recordCommaOkTypes updates recorded types to reflect that x is used in a commaOk context
// (and therefore has tuple type).
func (check *Checker) recordCommaOkTypes(x syntax.Expr, a []*operand) {
assert(x != nil)
if a[0] == nil || a[1] == nil {
assert(len(a) == 2)
if a[0].mode == invalid {
return
}
assert(isTyped(a[0]) && isTyped(a[1]) && (isBoolean(a[1]) || a[1] == universeError))
t0, t1 := a[0].typ, a[1].typ
assert(isTyped(t0) && isTyped(t1) && (isBoolean(t1) || t1 == universeError))
if m := check.Types; m != nil {
for {
tv := m[x]
assert(tv.Type != nil) // should have been recorded already
pos := x.Pos()
tv.Type = NewTuple(
NewVar(pos, check.pkg, "", a[0]),
NewVar(pos, check.pkg, "", a[1]),
NewVar(pos, check.pkg, "", t0),
NewVar(pos, check.pkg, "", t1),
)
m[x] = tv
// if x is a parenthesized expression (p.X), update p.X
p, _ := x.(*syntax.ParenExpr)
if p == nil {
break
@ -535,8 +540,8 @@ func (check *Checker) recordCommaOkTypes(x syntax.Expr, a [2]Type) {
assert(tv.Type != nil) // should have been recorded already
pos := x.Pos()
tv.Type = NewTuple(
NewVar(pos, check.pkg, "", a[0]),
NewVar(pos, check.pkg, "", a[1]),
NewVar(pos, check.pkg, "", t0),
NewVar(pos, check.pkg, "", t1),
)
x.SetTypeInfo(tv)
p, _ := x.(*syntax.ParenExpr)

View File

@ -365,11 +365,9 @@ func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnStmt ast.St
}
if commaOk {
var a [2]Type
for i := range a {
a[i] = check.initVar(lhs[i], rhs[i], context)
}
check.recordCommaOkTypes(origRHS[0], a)
check.initVar(lhs[0], rhs[0], context)
check.initVar(lhs[1], rhs[1], context)
check.recordCommaOkTypes(origRHS[0], rhs)
return
}
@ -394,11 +392,9 @@ func (check *Checker) assignVars(lhs, origRHS []ast.Expr) {
}
if commaOk {
var a [2]Type
for i := range a {
a[i] = check.assignVar(lhs[i], rhs[i])
}
check.recordCommaOkTypes(origRHS[0], a)
check.assignVar(lhs[0], rhs[0])
check.assignVar(lhs[1], rhs[1])
check.recordCommaOkTypes(origRHS[0], rhs)
return
}

View File

@ -478,20 +478,24 @@ func (check *Checker) recordBuiltinType(f ast.Expr, sig *Signature) {
}
}
func (check *Checker) recordCommaOkTypes(x ast.Expr, a [2]Type) {
// recordCommaOkTypes updates recorded types to reflect that x is used in a commaOk context
// (and therefore has tuple type).
func (check *Checker) recordCommaOkTypes(x ast.Expr, a []*operand) {
assert(x != nil)
if a[0] == nil || a[1] == nil {
assert(len(a) == 2)
if a[0].mode == invalid {
return
}
assert(isTyped(a[0]) && isTyped(a[1]) && (isBoolean(a[1]) || a[1] == universeError))
t0, t1 := a[0].typ, a[1].typ
assert(isTyped(t0) && isTyped(t1) && (isBoolean(t1) || t1 == universeError))
if m := check.Types; m != nil {
for {
tv := m[x]
assert(tv.Type != nil) // should have been recorded already
pos := x.Pos()
tv.Type = NewTuple(
NewVar(pos, check.pkg, "", a[0]),
NewVar(pos, check.pkg, "", a[1]),
NewVar(pos, check.pkg, "", t0),
NewVar(pos, check.pkg, "", t1),
)
m[x] = tv
// if x is a parenthesized expression (p.X), update p.X