@@ -82,41 +82,61 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
82
82
83
83
switch id {
84
84
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
89
89
// of S and the respective parameter passing rules apply."
90
90
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"
102
102
} else {
103
- cause = check .sprintf ("%s has no core type " , x )
103
+ cause = check .sprintf ("%s" , x )
104
104
}
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
107
108
}
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 {
110
119
return
111
120
}
112
121
113
122
// spec: "As a special case, append also accepts a first argument assignable
114
123
// 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."
116
125
if nargs == 2 && hasDots (call ) {
117
126
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 {
120
140
if check .recordTypes () {
121
141
sig := makeSig (S , S , y .typ )
122
142
sig .variadic = true
@@ -130,7 +150,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
130
150
}
131
151
132
152
// 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
134
154
sig .variadic = true
135
155
check .arguments (call , sig , nil , nil , args , nil ) // discard result (we know the result type)
136
156
// ok to continue even if check.arguments reported errors
0 commit comments