Skip to content

Commit 4b1ac7b

Browse files
griesemergopherbot
authored andcommitted
go/types, types2: remove references to core type in append
Writing explicit code for this case turned out to be simpler and easier to reason about then relying on a helper functions (except for typeset). While at it, make append error messages more consistent. For #70128. Change-Id: I3dc79774249929de5061b4301ab2506d4b3da0d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/653095 Reviewed-by: Robert Findley <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Robert Griesemer <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent f48b53f commit 4b1ac7b

File tree

3 files changed

+93
-52
lines changed

3 files changed

+93
-52
lines changed

src/cmd/compile/internal/types2/builtins.go

+44-24
Original file line numberDiff line numberDiff line change
@@ -82,41 +82,61 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
8282

8383
switch id {
8484
case _Append:
85-
// append(s S, x ...T) S, where T is the element type of S
86-
// spec: "The variadic function append appends zero or more values x to s of type
87-
// S, which must be a slice type, and returns the resulting slice, also of type S.
88-
// The values x are passed to a parameter of type ...T where T is the element type
85+
// append(s S, x ...E) S, where E is the element type of S
86+
// spec: "The variadic function append appends zero or more values x to a slice s
87+
// of type S and returns the resulting slice, also of type S.
88+
// The values x are passed to a parameter of type ...E where E is the element type
8989
// of S and the respective parameter passing rules apply."
9090
S := x.typ
91-
var T Type
92-
if s, _ := coreType(S).(*Slice); s != nil {
93-
T = s.elem
94-
} else {
95-
var cause string
96-
switch {
97-
case x.isNil():
98-
cause = "have untyped nil"
99-
case isTypeParam(S):
100-
if u := coreType(S); u != nil {
101-
cause = check.sprintf("%s has core type %s", x, u)
91+
92+
// determine E
93+
var E Type
94+
typeset(S, func(_, u Type) bool {
95+
s, _ := u.(*Slice)
96+
if s == nil {
97+
var cause string
98+
if x.isNil() {
99+
// Printing x in this case would just print "nil".
100+
// Special case this so we can emphasize "untyped".
101+
cause = "untyped nil"
102102
} else {
103-
cause = check.sprintf("%s has no core type", x)
103+
cause = check.sprintf("%s", x)
104104
}
105-
default:
106-
cause = check.sprintf("have %s", x)
105+
check.errorf(x, InvalidAppend, "invalid append: first argument must be a slice; have %s", cause)
106+
E = nil
107+
return false
107108
}
108-
// don't use invalidArg prefix here as it would repeat "argument" in the error message
109-
check.errorf(x, InvalidAppend, "first argument to append must be a slice; %s", cause)
109+
if E == nil {
110+
E = s.elem
111+
} else if !Identical(E, s.elem) {
112+
check.errorf(x, InvalidAppend, "invalid append: mismatched slice element types %s and %s in %s", E, s.elem, x)
113+
E = nil
114+
return false
115+
}
116+
return true
117+
})
118+
if E == nil {
110119
return
111120
}
112121

113122
// spec: "As a special case, append also accepts a first argument assignable
114123
// to type []byte with a second argument of string type followed by ... .
115-
// This form appends the bytes of the string.
124+
// This form appends the bytes of the string."
116125
if nargs == 2 && hasDots(call) {
117126
if ok, _ := x.assignableTo(check, NewSlice(universeByte), nil); ok {
118-
y := args[1]
119-
if t := coreString(y.typ); t != nil && isString(t) {
127+
y := args[1] // valid if != nil
128+
typeset(y.typ, func(_, u Type) bool {
129+
if s, _ := u.(*Slice); s != nil && Identical(s.elem, universeByte) {
130+
return true
131+
}
132+
if isString(u) {
133+
return true
134+
}
135+
y = nil
136+
return false
137+
})
138+
139+
if y != nil {
120140
if check.recordTypes() {
121141
sig := makeSig(S, S, y.typ)
122142
sig.variadic = true
@@ -130,7 +150,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
130150
}
131151

132152
// check general case by creating custom signature
133-
sig := makeSig(S, S, NewSlice(T)) // []T required for variadic signature
153+
sig := makeSig(S, S, NewSlice(E)) // []E required for variadic signature
134154
sig.variadic = true
135155
check.arguments(call, sig, nil, nil, args, nil) // discard result (we know the result type)
136156
// ok to continue even if check.arguments reported errors

src/go/types/builtins.go

+44-24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/internal/types/testdata/fixedbugs/issue49735.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
package p
66

7-
func _[P1 any, P2 ~byte](s1 P1, s2 P2) {
8-
_ = append(nil /* ERROR "first argument to append must be a slice; have untyped nil" */ , 0)
9-
_ = append(s1 /* ERRORx `s1 .* has no core type` */ , 0)
10-
_ = append(s2 /* ERRORx `s2 .* has core type byte` */ , 0)
7+
func _[P1 any, P2 ~byte, P3 []int | []byte](s1 P1, s2 P2, s3 P3) {
8+
_ = append(nil /* ERROR "invalid append: first argument must be a slice; have untyped nil" */, 0)
9+
_ = append(s1 /* ERROR "invalid append: first argument must be a slice; have s1 (variable of type P1 constrained by any)" */, 0)
10+
_ = append(s2 /* ERROR "invalid append: first argument must be a slice; have s2 (variable of type P2 constrained by ~byte)" */, 0)
11+
_ = append(s3 /* ERROR "invalid append: mismatched slice element types int and byte in s3 (variable of type P3 constrained by []int | []byte)" */, 0)
1112
}

0 commit comments

Comments
 (0)