Skip to content

Commit a83c4ee

Browse files
committed
[gopls-release-branch.0.17] internal/typesinternal: rollback of Zero{Value,Expr} for gopls
In CL 626537, the gopls behavior of formatting or generating a type expression for the zero value of a types.Type was changed to panic in the presence of invalid types. This leads to multiple panics in gopls (see tests). Fix by selectively rolling back this aspect of the change, as it relates to gopls. Also, add back the replace directive for the release branch. Fixes golang/go#70744 Change-Id: Ife9ae9a0fedf5a9d6b321cfb959f0d16eeec2986 Reviewed-on: https://go-review.googlesource.com/c/tools/+/634923 Reviewed-by: Alan Donovan <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> (cherry picked from commit 82b6f75) Reviewed-on: https://go-review.googlesource.com/c/tools/+/635215
1 parent 8f8dbdc commit a83c4ee

File tree

7 files changed

+78
-7
lines changed

7 files changed

+78
-7
lines changed

gopls/go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@ require (
2626
golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678 // indirect
2727
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
2828
)
29+
30+
replace golang.org/x/tools => ../

gopls/go.sum

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,38 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
1414
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
1515
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
1616
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
17+
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
18+
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
19+
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
1720
golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678 h1:1P7xPZEwZMoBoz0Yze5Nx2/4pxj6nw9ZqHWXqP0iRgQ=
1821
golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
22+
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
23+
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
1924
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
2025
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
26+
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
27+
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
28+
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
29+
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
2130
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
2231
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
32+
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
33+
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
34+
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
35+
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
2336
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
2437
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
38+
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0=
2539
golang.org/x/telemetry v0.0.0-20241106142447-58a1122356f5 h1:TCDqnvbBsFapViksHcHySl/sW4+rTGNIAoJJesHRuMM=
2640
golang.org/x/telemetry v0.0.0-20241106142447-58a1122356f5/go.mod h1:8nZWdGp9pq73ZI//QJyckMQab3yq7hoWi7SI0UIusVI=
41+
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
42+
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
43+
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
2744
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
45+
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
46+
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
2847
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
2948
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
30-
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
31-
golang.org/x/tools v0.27.1-0.20241204210344-1eb875fe7736 h1:FbrmQg54JnK6XU/imxsp4zJQgBNXbUEu4pAjQHxfEQQ=
32-
golang.org/x/tools v0.27.1-0.20241204210344-1eb875fe7736/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
3349
golang.org/x/vuln v1.0.4 h1:SP0mPeg2PmGCu03V+61EcQiOjmpri2XijexKdzv8Z1I=
3450
golang.org/x/vuln v1.0.4/go.mod h1:NbJdUQhX8jY++FtuhrXs2Eyx0yePo9pF7nPlIjo9aaQ=
3551
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

gopls/internal/golang/completion/postfix_snippets.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,8 @@ func (a *postfixTmplArgs) TypeName(t types.Type) (string, error) {
442442

443443
// Zero return the zero value representation of type t
444444
func (a *postfixTmplArgs) Zero(t types.Type) string {
445-
return typesinternal.ZeroString(t, a.qf)
445+
// TODO: use typesinternal.ZeroString, once it supports invalid types.
446+
return formatZeroValue(t, a.qf)
446447
}
447448

448449
func (a *postfixTmplArgs) IsIdent() bool {

gopls/internal/golang/completion/statements.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"golang.org/x/tools/gopls/internal/golang"
1616
"golang.org/x/tools/gopls/internal/golang/completion/snippet"
1717
"golang.org/x/tools/gopls/internal/protocol"
18-
"golang.org/x/tools/internal/typesinternal"
1918
)
2019

2120
// addStatementCandidates adds full statement completion candidates
@@ -295,7 +294,7 @@ func (c *completer) addErrCheck() {
295294
} else {
296295
snip.WriteText("return ")
297296
for i := 0; i < result.Len()-1; i++ {
298-
snip.WriteText(typesinternal.ZeroString(result.At(i).Type(), c.qf))
297+
snip.WriteText(formatZeroValue(result.At(i).Type(), c.qf))
299298
snip.WriteText(", ")
300299
}
301300
snip.WritePlaceholder(func(b *snippet.Builder) {
@@ -405,7 +404,7 @@ func (c *completer) addReturnZeroValues() {
405404
fmt.Fprintf(&label, ", ")
406405
}
407406

408-
zero := typesinternal.ZeroString(result.At(i).Type(), c.qf)
407+
zero := formatZeroValue(result.At(i).Type(), c.qf)
409408
snip.WritePlaceholder(func(b *snippet.Builder) {
410409
b.WriteText(zero)
411410
})

gopls/internal/golang/completion/util.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,31 @@ func prevStmt(pos token.Pos, path []ast.Node) ast.Stmt {
277277
return nil
278278
}
279279

280+
// formatZeroValue produces Go code representing the zero value of T. It
281+
// returns the empty string if T is invalid.
282+
//
283+
// TODO(rfindley): use typesinternal.ZeroString once we can sort out how to
284+
// propagate invalid types (see golang/go#70744).
285+
func formatZeroValue(T types.Type, qf types.Qualifier) string {
286+
switch u := T.Underlying().(type) {
287+
case *types.Basic:
288+
switch {
289+
case u.Info()&types.IsNumeric > 0:
290+
return "0"
291+
case u.Info()&types.IsString > 0:
292+
return `""`
293+
case u.Info()&types.IsBoolean > 0:
294+
return "false"
295+
default:
296+
return ""
297+
}
298+
case *types.Pointer, *types.Interface, *types.Chan, *types.Map, *types.Slice, *types.Signature:
299+
return "nil"
300+
default:
301+
return types.TypeString(T, qf) + "{}"
302+
}
303+
}
304+
280305
// isBasicKind returns whether t is a basic type of kind k.
281306
func isBasicKind(t types.Type, k types.BasicInfo) bool {
282307
b, _ := t.Underlying().(*types.Basic)

gopls/internal/test/marker/testdata/completion/statements.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,20 @@ func two() error {
9898
//@snippet("", stmtTwoIfErrReturn, "if s.err != nil {\n\treturn ${1:s.err}\n\\}")
9999
}
100100

101+
-- if_err_check_return3.go --
102+
package statements
103+
104+
import "os"
105+
106+
// Check that completion logic handles an invalid return type.
107+
func badReturn() (NotAType, error) {
108+
_, err := os.Open("foo")
109+
//@snippet("", stmtOneIfErrReturn, "if err != nil {\n\treturn , ${1:err}\n\\}")
110+
111+
_, err = os.Open("foo")
112+
if er //@snippet(" //", stmtOneErrReturn, "err != nil {\n\treturn , ${1:err}\n\\}")
113+
}
114+
101115
-- if_err_check_test.go --
102116
package statements
103117

@@ -132,3 +146,10 @@ func foo() (int, string, error) {
132146
func bar() (int, string, error) {
133147
return //@snippet(" ", stmtReturnZeroValues, "return ${1:0}, ${2:\"\"}, ${3:nil}")
134148
}
149+
150+
151+
//@item(stmtReturnInvalidValues, `return `)
152+
153+
func invalidReturnStatement() NotAType {
154+
return //@snippet(" ", stmtReturnInvalidValues, "return ${1:}")
155+
}

internal/typesinternal/zerovalue.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ func ZeroString(t types.Type, qf types.Qualifier) string {
8080
// ZeroExpr is defined for types that are suitable for variables.
8181
// It may panic for other types such as Tuple or Union.
8282
// See [ZeroString] for a variant that returns a string.
83+
//
84+
// TODO(rfindley): improve the behavior of this function in the presence of
85+
// invalid types. It should probably not return nil for
86+
// types.Typ[types.Invalid], but must to preserve previous behavior.
87+
// (golang/go#70744)
8388
func ZeroExpr(f *ast.File, pkg *types.Package, typ types.Type) ast.Expr {
8489
switch t := typ.(type) {
8590
case *types.Basic:
@@ -94,6 +99,8 @@ func ZeroExpr(f *ast.File, pkg *types.Package, typ types.Type) ast.Expr {
9499
fallthrough
95100
case t.Kind() == types.UntypedNil:
96101
return ast.NewIdent("nil")
102+
case t == types.Typ[types.Invalid]:
103+
return nil
97104
default:
98105
panic(fmt.Sprint("ZeroExpr for unexpected type:", t))
99106
}

0 commit comments

Comments
 (0)