blob: 9ebfbb6d6370296a361a03e11311d46decdb2d66 [file] [log] [blame]
Dan Willemsen6ff23252015-09-15 13:49:18 -07001// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// This file implements typechecking of statements.
6
7package types
8
9import (
Dan Willemsen6ff23252015-09-15 13:49:18 -070010 "go/ast"
11 "go/constant"
12 "go/token"
Dan Willemsene1b3b182018-02-27 19:36:27 -080013 "sort"
Dan Willemsen6ff23252015-09-15 13:49:18 -070014)
15
Dan Willemsenf3f2eb62018-08-28 11:28:58 -070016func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *ast.BlockStmt, iota constant.Value) {
Dan Willemsen31b9b842021-08-31 12:51:40 -070017 if check.conf.IgnoreFuncBodies {
Dan Willemsen59ee7802021-12-15 01:08:25 -080018 panic("function body not ignored")
Dan Willemsen31b9b842021-08-31 12:51:40 -070019 }
20
Dan Willemsen6ff23252015-09-15 13:49:18 -070021 if trace {
Dan Willemsenf3f2eb62018-08-28 11:28:58 -070022 check.trace(body.Pos(), "--- %s: %s", name, sig)
23 defer func() {
24 check.trace(body.End(), "--- <end>")
25 }()
Dan Willemsen6ff23252015-09-15 13:49:18 -070026 }
27
28 // set function scope extent
29 sig.scope.pos = body.Pos()
30 sig.scope.end = body.End()
31
Dan Willemsen59ee7802021-12-15 01:08:25 -080032 // save/restore current environment and set up function environment
Dan Willemsen6ff23252015-09-15 13:49:18 -070033 // (and use 0 indentation at function start)
Dan Willemsen59ee7802021-12-15 01:08:25 -080034 defer func(env environment, indent int) {
35 check.environment = env
Dan Willemsen6ff23252015-09-15 13:49:18 -070036 check.indent = indent
Dan Willemsen59ee7802021-12-15 01:08:25 -080037 }(check.environment, check.indent)
38 check.environment = environment{
Dan Willemsen6ff23252015-09-15 13:49:18 -070039 decl: decl,
40 scope: sig.scope,
Dan Willemsenf3f2eb62018-08-28 11:28:58 -070041 iota: iota,
Dan Willemsen6ff23252015-09-15 13:49:18 -070042 sig: sig,
43 }
44 check.indent = 0
45
46 check.stmtList(0, body.List)
47
48 if check.hasLabel {
49 check.labels(body)
50 }
51
52 if sig.results.Len() > 0 && !check.isTerminating(body, "") {
Colin Cross846c3162021-05-14 11:11:40 -070053 check.error(atPos(body.Rbrace), _MissingReturn, "missing return")
Dan Willemsen6ff23252015-09-15 13:49:18 -070054 }
55
56 // spec: "Implementation restriction: A compiler may make it illegal to
57 // declare a variable inside a function body if the variable is never used."
Dan Willemsen6ff23252015-09-15 13:49:18 -070058 check.usage(sig.scope)
59}
60
61func (check *Checker) usage(scope *Scope) {
Dan Willemsene1b3b182018-02-27 19:36:27 -080062 var unused []*Var
Dan Willemsen59ee7802021-12-15 01:08:25 -080063 for name, elem := range scope.elems {
64 elem = resolve(name, elem)
Dan Willemsene1b3b182018-02-27 19:36:27 -080065 if v, _ := elem.(*Var); v != nil && !v.used {
66 unused = append(unused, v)
Dan Willemsen6ff23252015-09-15 13:49:18 -070067 }
68 }
Dan Willemsene1b3b182018-02-27 19:36:27 -080069 sort.Slice(unused, func(i, j int) bool {
70 return unused[i].pos < unused[j].pos
71 })
72 for _, v := range unused {
Colin Cross846c3162021-05-14 11:11:40 -070073 check.softErrorf(v, _UnusedVar, "%s declared but not used", v.name)
Dan Willemsene1b3b182018-02-27 19:36:27 -080074 }
75
Dan Willemsen6ff23252015-09-15 13:49:18 -070076 for _, scope := range scope.children {
Dan Willemsenf3f2eb62018-08-28 11:28:58 -070077 // Don't go inside function literal scopes a second time;
Dan Willemsene1b3b182018-02-27 19:36:27 -080078 // they are handled explicitly by funcBody.
79 if !scope.isFunc {
80 check.usage(scope)
81 }
Dan Willemsen6ff23252015-09-15 13:49:18 -070082 }
83}
84
85// stmtContext is a bitset describing which
Dan Willemsenbbdf6642017-01-13 22:57:23 -080086// control-flow statements are permissible,
87// and provides additional context information
88// for better error messages.
Dan Willemsen6ff23252015-09-15 13:49:18 -070089type stmtContext uint
90
91const (
Dan Willemsenbbdf6642017-01-13 22:57:23 -080092 // permissible control-flow statements
Dan Willemsen6ff23252015-09-15 13:49:18 -070093 breakOk stmtContext = 1 << iota
94 continueOk
95 fallthroughOk
Dan Willemsenbbdf6642017-01-13 22:57:23 -080096
97 // additional context information
98 finalSwitchCase
Dan Willemsen6ff23252015-09-15 13:49:18 -070099)
100
101func (check *Checker) simpleStmt(s ast.Stmt) {
102 if s != nil {
103 check.stmt(0, s)
104 }
105}
106
Dan Willemsen0c157092016-07-08 13:57:52 -0700107func trimTrailingEmptyStmts(list []ast.Stmt) []ast.Stmt {
108 for i := len(list); i > 0; i-- {
109 if _, ok := list[i-1].(*ast.EmptyStmt); !ok {
110 return list[:i]
111 }
112 }
113 return nil
114}
115
Dan Willemsen6ff23252015-09-15 13:49:18 -0700116func (check *Checker) stmtList(ctxt stmtContext, list []ast.Stmt) {
117 ok := ctxt&fallthroughOk != 0
118 inner := ctxt &^ fallthroughOk
Dan Willemsen0c157092016-07-08 13:57:52 -0700119 list = trimTrailingEmptyStmts(list) // trailing empty statements are "invisible" to fallthrough analysis
Dan Willemsen6ff23252015-09-15 13:49:18 -0700120 for i, s := range list {
121 inner := inner
122 if ok && i+1 == len(list) {
123 inner |= fallthroughOk
124 }
125 check.stmt(inner, s)
126 }
127}
128
129func (check *Checker) multipleDefaults(list []ast.Stmt) {
130 var first ast.Stmt
131 for _, s := range list {
132 var d ast.Stmt
133 switch c := s.(type) {
134 case *ast.CaseClause:
135 if len(c.List) == 0 {
136 d = s
137 }
138 case *ast.CommClause:
139 if c.Comm == nil {
140 d = s
141 }
142 default:
Colin Cross846c3162021-05-14 11:11:40 -0700143 check.invalidAST(s, "case/communication clause expected")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700144 }
145 if d != nil {
146 if first != nil {
Colin Cross846c3162021-05-14 11:11:40 -0700147 check.errorf(d, _DuplicateDefault, "multiple defaults (first at %s)", check.fset.Position(first.Pos()))
Dan Willemsen6ff23252015-09-15 13:49:18 -0700148 } else {
149 first = d
150 }
151 }
152 }
153}
154
Dan Willemsen31b9b842021-08-31 12:51:40 -0700155func (check *Checker) openScope(node ast.Node, comment string) {
156 scope := NewScope(check.scope, node.Pos(), node.End(), comment)
157 check.recordScope(node, scope)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700158 check.scope = scope
159}
160
161func (check *Checker) closeScope() {
162 check.scope = check.scope.Parent()
163}
164
165func assignOp(op token.Token) token.Token {
166 // token_test.go verifies the token ordering this function relies on
167 if token.ADD_ASSIGN <= op && op <= token.AND_NOT_ASSIGN {
168 return op + (token.ADD - token.ADD_ASSIGN)
169 }
170 return token.ILLEGAL
171}
172
173func (check *Checker) suspendedCall(keyword string, call *ast.CallExpr) {
174 var x operand
175 var msg string
Colin Cross846c3162021-05-14 11:11:40 -0700176 var code errorCode
Dan Willemsen59ee7802021-12-15 01:08:25 -0800177 switch check.rawExpr(&x, call, nil, false) {
Dan Willemsen6ff23252015-09-15 13:49:18 -0700178 case conversion:
179 msg = "requires function call, not conversion"
Colin Cross846c3162021-05-14 11:11:40 -0700180 code = _InvalidDefer
181 if keyword == "go" {
182 code = _InvalidGo
183 }
Dan Willemsen6ff23252015-09-15 13:49:18 -0700184 case expression:
185 msg = "discards result of"
Colin Cross846c3162021-05-14 11:11:40 -0700186 code = _UnusedResults
Dan Willemsen6ff23252015-09-15 13:49:18 -0700187 case statement:
188 return
189 default:
190 unreachable()
191 }
Colin Cross846c3162021-05-14 11:11:40 -0700192 check.errorf(&x, code, "%s %s %s", keyword, msg, &x)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700193}
194
Dan Willemsen0c157092016-07-08 13:57:52 -0700195// goVal returns the Go value for val, or nil.
Dan Willemsen59ee7802021-12-15 01:08:25 -0800196func goVal(val constant.Value) any {
Dan Willemsen0c157092016-07-08 13:57:52 -0700197 // val should exist, but be conservative and check
198 if val == nil {
199 return nil
200 }
201 // Match implementation restriction of other compilers.
202 // gc only checks duplicates for integer, floating-point
203 // and string values, so only create Go values for these
204 // types.
205 switch val.Kind() {
206 case constant.Int:
207 if x, ok := constant.Int64Val(val); ok {
208 return x
209 }
210 if x, ok := constant.Uint64Val(val); ok {
211 return x
212 }
213 case constant.Float:
214 if x, ok := constant.Float64Val(val); ok {
215 return x
216 }
217 case constant.String:
218 return constant.StringVal(val)
219 }
220 return nil
221}
222
223// A valueMap maps a case value (of a basic Go type) to a list of positions
224// where the same case value appeared, together with the corresponding case
225// types.
226// Since two case values may have the same "underlying" value but different
227// types we need to also check the value's types (e.g., byte(1) vs myByte(1))
228// when the switch expression is of interface type.
229type (
Dan Willemsen59ee7802021-12-15 01:08:25 -0800230 valueMap map[any][]valueType // underlying Go value -> valueType
Dan Willemsen0c157092016-07-08 13:57:52 -0700231 valueType struct {
232 pos token.Pos
233 typ Type
234 }
235)
236
237func (check *Checker) caseValues(x *operand, values []ast.Expr, seen valueMap) {
238L:
Dan Willemsen6ff23252015-09-15 13:49:18 -0700239 for _, e := range values {
Dan Willemsen0c157092016-07-08 13:57:52 -0700240 var v operand
241 check.expr(&v, e)
242 if x.mode == invalid || v.mode == invalid {
243 continue L
Dan Willemsen6ff23252015-09-15 13:49:18 -0700244 }
Dan Willemsen0c157092016-07-08 13:57:52 -0700245 check.convertUntyped(&v, x.typ)
246 if v.mode == invalid {
247 continue L
Dan Willemsen6ff23252015-09-15 13:49:18 -0700248 }
Dan Willemsen0c157092016-07-08 13:57:52 -0700249 // Order matters: By comparing v against x, error positions are at the case values.
250 res := v // keep original v unchanged
Dan Willemsen14b5f992022-03-10 14:27:21 -0800251 check.comparison(&res, x, token.EQL, true)
Dan Willemsen0c157092016-07-08 13:57:52 -0700252 if res.mode == invalid {
253 continue L
Dan Willemsen6ff23252015-09-15 13:49:18 -0700254 }
Dan Willemsen0c157092016-07-08 13:57:52 -0700255 if v.mode != constant_ {
256 continue L // we're done
257 }
258 // look for duplicate values
259 if val := goVal(v.val); val != nil {
Dan Willemsene1b3b182018-02-27 19:36:27 -0800260 // look for duplicate types for a given value
261 // (quadratic algorithm, but these lists tend to be very short)
262 for _, vt := range seen[val] {
Dan Willemsen59ee7802021-12-15 01:08:25 -0800263 if Identical(v.typ, vt.typ) {
Colin Cross846c3162021-05-14 11:11:40 -0700264 check.errorf(&v, _DuplicateCase, "duplicate case %s in expression switch", &v)
265 check.error(atPos(vt.pos), _DuplicateCase, "\tprevious case") // secondary error, \t indented
Dan Willemsene1b3b182018-02-27 19:36:27 -0800266 continue L
Dan Willemsen0c157092016-07-08 13:57:52 -0700267 }
268 }
Colin Cross846c3162021-05-14 11:11:40 -0700269 seen[val] = append(seen[val], valueType{v.Pos(), v.typ})
Dan Willemsen0c157092016-07-08 13:57:52 -0700270 }
Dan Willemsen6ff23252015-09-15 13:49:18 -0700271 }
272}
273
Dan Willemsen59ee7802021-12-15 01:08:25 -0800274// isNil reports whether the expression e denotes the predeclared value nil.
275func (check *Checker) isNil(e ast.Expr) bool {
276 // The only way to express the nil value is by literally writing nil (possibly in parentheses).
277 if name, _ := unparen(e).(*ast.Ident); name != nil {
278 _, ok := check.lookup(name.Name).(*Nil)
279 return ok
280 }
281 return false
282}
283
Dan Willemsen14b5f992022-03-10 14:27:21 -0800284// If the type switch expression is invalid, x is nil.
285func (check *Checker) caseTypes(x *operand, types []ast.Expr, seen map[Type]ast.Expr) (T Type) {
Dan Willemsen59ee7802021-12-15 01:08:25 -0800286 var dummy operand
Dan Willemsen6ff23252015-09-15 13:49:18 -0700287L:
288 for _, e := range types {
Dan Willemsen59ee7802021-12-15 01:08:25 -0800289 // The spec allows the value nil instead of a type.
290 if check.isNil(e) {
291 T = nil
292 check.expr(&dummy, e) // run e through expr so we get the usual Info recordings
293 } else {
294 T = check.varType(e)
295 if T == Typ[Invalid] {
296 continue L
297 }
Dan Willemsen31b9b842021-08-31 12:51:40 -0700298 }
Dan Willemsen0c157092016-07-08 13:57:52 -0700299 // look for duplicate types
300 // (quadratic algorithm, but type switches tend to be reasonably small)
Colin Cross846c3162021-05-14 11:11:40 -0700301 for t, other := range seen {
Dan Willemsen59ee7802021-12-15 01:08:25 -0800302 if T == nil && t == nil || T != nil && t != nil && Identical(T, t) {
Dan Willemsen6ff23252015-09-15 13:49:18 -0700303 // talk about "case" rather than "type" because of nil case
Dan Willemsen0c157092016-07-08 13:57:52 -0700304 Ts := "nil"
305 if T != nil {
Dan Willemsen59ee7802021-12-15 01:08:25 -0800306 Ts = TypeString(T, check.qualifier)
Dan Willemsen0c157092016-07-08 13:57:52 -0700307 }
Colin Cross846c3162021-05-14 11:11:40 -0700308 check.errorf(e, _DuplicateCase, "duplicate case %s in type switch", Ts)
309 check.error(other, _DuplicateCase, "\tprevious case") // secondary error, \t indented
Dan Willemsen6ff23252015-09-15 13:49:18 -0700310 continue L
311 }
312 }
Colin Cross846c3162021-05-14 11:11:40 -0700313 seen[T] = e
Dan Willemsen14b5f992022-03-10 14:27:21 -0800314 if x != nil && T != nil {
315 check.typeAssertion(e, x, T, true)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700316 }
317 }
318 return
319}
320
Dan Willemsen59ee7802021-12-15 01:08:25 -0800321// TODO(gri) Once we are certain that typeHash is correct in all situations, use this version of caseTypes instead.
322// (Currently it may be possible that different types have identical names and import paths due to ImporterFrom.)
323//
324// func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[string]ast.Expr) (T Type) {
325// var dummy operand
326// L:
327// for _, e := range types {
328// // The spec allows the value nil instead of a type.
329// var hash string
330// if check.isNil(e) {
331// check.expr(&dummy, e) // run e through expr so we get the usual Info recordings
332// T = nil
333// hash = "<nil>" // avoid collision with a type named nil
334// } else {
335// T = check.varType(e)
336// if T == Typ[Invalid] {
337// continue L
338// }
339// hash = typeHash(T, nil)
340// }
341// // look for duplicate types
342// if other := seen[hash]; other != nil {
343// // talk about "case" rather than "type" because of nil case
344// Ts := "nil"
345// if T != nil {
346// Ts = TypeString(T, check.qualifier)
347// }
348// var err error_
349// err.errorf(e, "duplicate case %s in type switch", Ts)
350// err.errorf(other, "previous case")
351// check.report(&err)
352// continue L
353// }
354// seen[hash] = e
355// if T != nil {
356// check.typeAssertion(e.Pos(), x, xtyp, T)
357// }
358// }
359// return
360// }
361
Dan Willemsen6ff23252015-09-15 13:49:18 -0700362// stmt typechecks statement s.
363func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
Dan Willemsen6ff23252015-09-15 13:49:18 -0700364 // statements must end with the same top scope as they started with
365 if debug {
366 defer func(scope *Scope) {
367 // don't check if code is panicking
368 if p := recover(); p != nil {
369 panic(p)
370 }
371 assert(scope == check.scope)
372 }(check.scope)
373 }
374
Dan Willemsenf3f2eb62018-08-28 11:28:58 -0700375 // process collected function literals before scope changes
376 defer check.processDelayed(len(check.delayed))
377
Dan Willemsenbbdf6642017-01-13 22:57:23 -0800378 inner := ctxt &^ (fallthroughOk | finalSwitchCase)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700379 switch s := s.(type) {
380 case *ast.BadStmt, *ast.EmptyStmt:
381 // ignore
382
383 case *ast.DeclStmt:
384 check.declStmt(s.Decl)
385
386 case *ast.LabeledStmt:
387 check.hasLabel = true
388 check.stmt(ctxt, s.Stmt)
389
390 case *ast.ExprStmt:
391 // spec: "With the exception of specific built-in functions,
392 // function and method calls and receive operations can appear
393 // in statement context. Such statements may be parenthesized."
394 var x operand
Dan Willemsen59ee7802021-12-15 01:08:25 -0800395 kind := check.rawExpr(&x, s.X, nil, false)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700396 var msg string
Colin Cross846c3162021-05-14 11:11:40 -0700397 var code errorCode
Dan Willemsen6ff23252015-09-15 13:49:18 -0700398 switch x.mode {
399 default:
400 if kind == statement {
401 return
402 }
403 msg = "is not used"
Colin Cross846c3162021-05-14 11:11:40 -0700404 code = _UnusedExpr
Dan Willemsen6ff23252015-09-15 13:49:18 -0700405 case builtin:
406 msg = "must be called"
Colin Cross846c3162021-05-14 11:11:40 -0700407 code = _UncalledBuiltin
Dan Willemsen6ff23252015-09-15 13:49:18 -0700408 case typexpr:
409 msg = "is not an expression"
Colin Cross846c3162021-05-14 11:11:40 -0700410 code = _NotAnExpr
Dan Willemsen6ff23252015-09-15 13:49:18 -0700411 }
Colin Cross846c3162021-05-14 11:11:40 -0700412 check.errorf(&x, code, "%s %s", &x, msg)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700413
414 case *ast.SendStmt:
Dan Willemsen59ee7802021-12-15 01:08:25 -0800415 var ch, val operand
Dan Willemsen6ff23252015-09-15 13:49:18 -0700416 check.expr(&ch, s.Chan)
Dan Willemsen59ee7802021-12-15 01:08:25 -0800417 check.expr(&val, s.Value)
418 if ch.mode == invalid || val.mode == invalid {
Dan Willemsen6ff23252015-09-15 13:49:18 -0700419 return
420 }
Dan Willemsen14b5f992022-03-10 14:27:21 -0800421 u := coreType(ch.typ)
Dan Willemsen59ee7802021-12-15 01:08:25 -0800422 if u == nil {
Dan Willemsen14b5f992022-03-10 14:27:21 -0800423 check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to %s: no core type", &ch)
Dan Willemsen0c157092016-07-08 13:57:52 -0700424 return
Dan Willemsen6ff23252015-09-15 13:49:18 -0700425 }
Dan Willemsen59ee7802021-12-15 01:08:25 -0800426 uch, _ := u.(*Chan)
427 if uch == nil {
428 check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to non-channel %s", &ch)
Dan Willemsen0c157092016-07-08 13:57:52 -0700429 return
430 }
Dan Willemsen59ee7802021-12-15 01:08:25 -0800431 if uch.dir == RecvOnly {
432 check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to receive-only channel %s", &ch)
433 return
434 }
435 check.assignment(&val, uch.elem, "send")
Dan Willemsen0c157092016-07-08 13:57:52 -0700436
Dan Willemsen6ff23252015-09-15 13:49:18 -0700437 case *ast.IncDecStmt:
438 var op token.Token
439 switch s.Tok {
440 case token.INC:
441 op = token.ADD
442 case token.DEC:
443 op = token.SUB
444 default:
Colin Cross846c3162021-05-14 11:11:40 -0700445 check.invalidAST(inNode(s, s.TokPos), "unknown inc/dec operation %s", s.Tok)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700446 return
447 }
Dan Willemsen0c157092016-07-08 13:57:52 -0700448
Dan Willemsen6ff23252015-09-15 13:49:18 -0700449 var x operand
Dan Willemsen0c157092016-07-08 13:57:52 -0700450 check.expr(&x, s.X)
451 if x.mode == invalid {
452 return
453 }
Dan Willemsen59ee7802021-12-15 01:08:25 -0800454 if !allNumeric(x.typ) {
Colin Cross846c3162021-05-14 11:11:40 -0700455 check.invalidOp(s.X, _NonNumericIncDec, "%s%s (non-numeric type %s)", s.X, s.Tok, x.typ)
Dan Willemsen0c157092016-07-08 13:57:52 -0700456 return
457 }
458
Dan Willemsen6ff23252015-09-15 13:49:18 -0700459 Y := &ast.BasicLit{ValuePos: s.X.Pos(), Kind: token.INT, Value: "1"} // use x's position
Colin Cross846c3162021-05-14 11:11:40 -0700460 check.binary(&x, nil, s.X, Y, op, s.TokPos)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700461 if x.mode == invalid {
462 return
463 }
464 check.assignVar(s.X, &x)
465
466 case *ast.AssignStmt:
467 switch s.Tok {
468 case token.ASSIGN, token.DEFINE:
469 if len(s.Lhs) == 0 {
Colin Cross846c3162021-05-14 11:11:40 -0700470 check.invalidAST(s, "missing lhs in assignment")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700471 return
472 }
473 if s.Tok == token.DEFINE {
Colin Cross846c3162021-05-14 11:11:40 -0700474 check.shortVarDecl(inNode(s, s.TokPos), s.Lhs, s.Rhs)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700475 } else {
476 // regular assignment
477 check.assignVars(s.Lhs, s.Rhs)
478 }
479
480 default:
481 // assignment operations
482 if len(s.Lhs) != 1 || len(s.Rhs) != 1 {
Colin Cross846c3162021-05-14 11:11:40 -0700483 check.errorf(inNode(s, s.TokPos), _MultiValAssignOp, "assignment operation %s requires single-valued expressions", s.Tok)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700484 return
485 }
486 op := assignOp(s.Tok)
487 if op == token.ILLEGAL {
Colin Cross846c3162021-05-14 11:11:40 -0700488 check.invalidAST(atPos(s.TokPos), "unknown assignment operation %s", s.Tok)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700489 return
490 }
491 var x operand
Colin Cross846c3162021-05-14 11:11:40 -0700492 check.binary(&x, nil, s.Lhs[0], s.Rhs[0], op, s.TokPos)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700493 if x.mode == invalid {
494 return
495 }
496 check.assignVar(s.Lhs[0], &x)
497 }
498
499 case *ast.GoStmt:
500 check.suspendedCall("go", s.Call)
501
502 case *ast.DeferStmt:
503 check.suspendedCall("defer", s.Call)
504
505 case *ast.ReturnStmt:
506 res := check.sig.results
Dan Willemsen14b5f992022-03-10 14:27:21 -0800507 // Return with implicit results allowed for function with named results.
508 // (If one is named, all are named.)
509 if len(s.Results) == 0 && res.Len() > 0 && res.vars[0].name != "" {
510 // spec: "Implementation restriction: A compiler may disallow an empty expression
511 // list in a "return" statement if a different entity (constant, type, or variable)
512 // with the same name as a result parameter is in scope at the place of the return."
513 for _, obj := range res.vars {
514 if alt := check.lookup(obj.name); alt != nil && alt != obj {
515 check.errorf(s, _OutOfScopeResult, "result parameter %s not in scope at return", obj.name)
516 check.errorf(alt, _OutOfScopeResult, "\tinner declaration of %s", obj)
517 // ok to continue
Dan Willemsen6ff23252015-09-15 13:49:18 -0700518 }
Dan Willemsen6ff23252015-09-15 13:49:18 -0700519 }
Dan Willemsen14b5f992022-03-10 14:27:21 -0800520 } else {
521 var lhs []*Var
522 if res.Len() > 0 {
523 lhs = res.vars
524 }
525 check.initVars(lhs, s.Results, s)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700526 }
527
528 case *ast.BranchStmt:
529 if s.Label != nil {
530 check.hasLabel = true
531 return // checked in 2nd pass (check.labels)
532 }
533 switch s.Tok {
534 case token.BREAK:
535 if ctxt&breakOk == 0 {
Colin Cross846c3162021-05-14 11:11:40 -0700536 check.error(s, _MisplacedBreak, "break not in for, switch, or select statement")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700537 }
538 case token.CONTINUE:
539 if ctxt&continueOk == 0 {
Colin Cross846c3162021-05-14 11:11:40 -0700540 check.error(s, _MisplacedContinue, "continue not in for statement")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700541 }
542 case token.FALLTHROUGH:
543 if ctxt&fallthroughOk == 0 {
Dan Willemsenbbdf6642017-01-13 22:57:23 -0800544 msg := "fallthrough statement out of place"
Colin Cross846c3162021-05-14 11:11:40 -0700545 code := _MisplacedFallthrough
Dan Willemsenbbdf6642017-01-13 22:57:23 -0800546 if ctxt&finalSwitchCase != 0 {
547 msg = "cannot fallthrough final case in switch"
548 }
Colin Cross846c3162021-05-14 11:11:40 -0700549 check.error(s, code, msg)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700550 }
551 default:
Colin Cross846c3162021-05-14 11:11:40 -0700552 check.invalidAST(s, "branch statement: %s", s.Tok)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700553 }
554
555 case *ast.BlockStmt:
556 check.openScope(s, "block")
557 defer check.closeScope()
558
559 check.stmtList(inner, s.List)
560
561 case *ast.IfStmt:
562 check.openScope(s, "if")
563 defer check.closeScope()
564
565 check.simpleStmt(s.Init)
566 var x operand
567 check.expr(&x, s.Cond)
Dan Willemsen59ee7802021-12-15 01:08:25 -0800568 if x.mode != invalid && !allBoolean(x.typ) {
Colin Cross846c3162021-05-14 11:11:40 -0700569 check.error(s.Cond, _InvalidCond, "non-boolean condition in if statement")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700570 }
571 check.stmt(inner, s.Body)
Dan Willemsen0c157092016-07-08 13:57:52 -0700572 // The parser produces a correct AST but if it was modified
573 // elsewhere the else branch may be invalid. Check again.
574 switch s.Else.(type) {
575 case nil, *ast.BadStmt:
576 // valid or error already reported
577 case *ast.IfStmt, *ast.BlockStmt:
Dan Willemsen6ff23252015-09-15 13:49:18 -0700578 check.stmt(inner, s.Else)
Dan Willemsen0c157092016-07-08 13:57:52 -0700579 default:
Colin Cross846c3162021-05-14 11:11:40 -0700580 check.invalidAST(s.Else, "invalid else branch in if statement")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700581 }
582
583 case *ast.SwitchStmt:
584 inner |= breakOk
585 check.openScope(s, "switch")
586 defer check.closeScope()
587
588 check.simpleStmt(s.Init)
589 var x operand
590 if s.Tag != nil {
591 check.expr(&x, s.Tag)
Dan Willemsen0c157092016-07-08 13:57:52 -0700592 // By checking assignment of x to an invisible temporary
593 // (as a compiler would), we get all the relevant checks.
594 check.assignment(&x, nil, "switch expression")
Colin Cross846c3162021-05-14 11:11:40 -0700595 if x.mode != invalid && !Comparable(x.typ) && !hasNil(x.typ) {
596 check.errorf(&x, _InvalidExprSwitch, "cannot switch on %s (%s is not comparable)", &x, x.typ)
597 x.mode = invalid
598 }
Dan Willemsen6ff23252015-09-15 13:49:18 -0700599 } else {
600 // spec: "A missing switch expression is
601 // equivalent to the boolean value true."
602 x.mode = constant_
603 x.typ = Typ[Bool]
604 x.val = constant.MakeBool(true)
605 x.expr = &ast.Ident{NamePos: s.Body.Lbrace, Name: "true"}
606 }
607
608 check.multipleDefaults(s.Body.List)
609
Dan Willemsen0c157092016-07-08 13:57:52 -0700610 seen := make(valueMap) // map of seen case values to positions and types
Dan Willemsen6ff23252015-09-15 13:49:18 -0700611 for i, c := range s.Body.List {
612 clause, _ := c.(*ast.CaseClause)
613 if clause == nil {
Colin Cross846c3162021-05-14 11:11:40 -0700614 check.invalidAST(c, "incorrect expression switch case")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700615 continue
616 }
Dan Willemsen0c157092016-07-08 13:57:52 -0700617 check.caseValues(&x, clause.List, seen)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700618 check.openScope(clause, "case")
619 inner := inner
620 if i+1 < len(s.Body.List) {
621 inner |= fallthroughOk
Dan Willemsenbbdf6642017-01-13 22:57:23 -0800622 } else {
623 inner |= finalSwitchCase
Dan Willemsen6ff23252015-09-15 13:49:18 -0700624 }
625 check.stmtList(inner, clause.Body)
626 check.closeScope()
627 }
628
629 case *ast.TypeSwitchStmt:
630 inner |= breakOk
631 check.openScope(s, "type switch")
632 defer check.closeScope()
633
634 check.simpleStmt(s.Init)
635
636 // A type switch guard must be of the form:
637 //
638 // TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
639 //
640 // The parser is checking syntactic correctness;
641 // remaining syntactic errors are considered AST errors here.
642 // TODO(gri) better factoring of error handling (invalid ASTs)
643 //
644 var lhs *ast.Ident // lhs identifier or nil
645 var rhs ast.Expr
646 switch guard := s.Assign.(type) {
647 case *ast.ExprStmt:
648 rhs = guard.X
649 case *ast.AssignStmt:
650 if len(guard.Lhs) != 1 || guard.Tok != token.DEFINE || len(guard.Rhs) != 1 {
Colin Cross846c3162021-05-14 11:11:40 -0700651 check.invalidAST(s, "incorrect form of type switch guard")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700652 return
653 }
654
655 lhs, _ = guard.Lhs[0].(*ast.Ident)
656 if lhs == nil {
Colin Cross846c3162021-05-14 11:11:40 -0700657 check.invalidAST(s, "incorrect form of type switch guard")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700658 return
659 }
660
661 if lhs.Name == "_" {
662 // _ := x.(type) is an invalid short variable declaration
Colin Cross846c3162021-05-14 11:11:40 -0700663 check.softErrorf(lhs, _NoNewVar, "no new variable on left side of :=")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700664 lhs = nil // avoid declared but not used error below
665 } else {
666 check.recordDef(lhs, nil) // lhs variable is implicitly declared in each cause clause
667 }
668
669 rhs = guard.Rhs[0]
670
671 default:
Colin Cross846c3162021-05-14 11:11:40 -0700672 check.invalidAST(s, "incorrect form of type switch guard")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700673 return
674 }
675
Dan Willemsen31b9b842021-08-31 12:51:40 -0700676 // rhs must be of the form: expr.(type) and expr must be an ordinary interface
Dan Willemsen6ff23252015-09-15 13:49:18 -0700677 expr, _ := rhs.(*ast.TypeAssertExpr)
678 if expr == nil || expr.Type != nil {
Colin Cross846c3162021-05-14 11:11:40 -0700679 check.invalidAST(s, "incorrect form of type switch guard")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700680 return
681 }
682 var x operand
683 check.expr(&x, expr.X)
684 if x.mode == invalid {
685 return
686 }
Dan Willemsen59ee7802021-12-15 01:08:25 -0800687 // TODO(gri) we may want to permit type switches on type parameter values at some point
Dan Willemsen14b5f992022-03-10 14:27:21 -0800688 var sx *operand // switch expression against which cases are compared against; nil if invalid
Dan Willemsen59ee7802021-12-15 01:08:25 -0800689 if isTypeParam(x.typ) {
690 check.errorf(&x, _InvalidTypeSwitch, "cannot use type switch on type parameter value %s", &x)
Dan Willemsen14b5f992022-03-10 14:27:21 -0800691 } else {
692 if _, ok := under(x.typ).(*Interface); ok {
693 sx = &x
694 } else {
695 check.errorf(&x, _InvalidTypeSwitch, "%s is not an interface", &x)
696 }
Dan Willemsen6ff23252015-09-15 13:49:18 -0700697 }
698
699 check.multipleDefaults(s.Body.List)
700
Colin Cross846c3162021-05-14 11:11:40 -0700701 var lhsVars []*Var // list of implicitly declared lhs variables
702 seen := make(map[Type]ast.Expr) // map of seen types to positions
Dan Willemsen6ff23252015-09-15 13:49:18 -0700703 for _, s := range s.Body.List {
704 clause, _ := s.(*ast.CaseClause)
705 if clause == nil {
Colin Cross846c3162021-05-14 11:11:40 -0700706 check.invalidAST(s, "incorrect type switch case")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700707 continue
708 }
709 // Check each type in this type switch case.
Dan Willemsen14b5f992022-03-10 14:27:21 -0800710 T := check.caseTypes(sx, clause.List, seen)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700711 check.openScope(clause, "case")
712 // If lhs exists, declare a corresponding variable in the case-local scope.
713 if lhs != nil {
714 // spec: "The TypeSwitchGuard may include a short variable declaration.
715 // When that form is used, the variable is declared at the beginning of
716 // the implicit block in each clause. In clauses with a case listing
717 // exactly one type, the variable has that type; otherwise, the variable
718 // has the type of the expression in the TypeSwitchGuard."
719 if len(clause.List) != 1 || T == nil {
720 T = x.typ
721 }
722 obj := NewVar(lhs.Pos(), check.pkg, lhs.Name, T)
Dan Willemsenbbdf6642017-01-13 22:57:23 -0800723 scopePos := clause.Pos() + token.Pos(len("default")) // for default clause (len(List) == 0)
724 if n := len(clause.List); n > 0 {
725 scopePos = clause.List[n-1].End()
Dan Willemsen6ff23252015-09-15 13:49:18 -0700726 }
727 check.declare(check.scope, nil, obj, scopePos)
728 check.recordImplicit(clause, obj)
729 // For the "declared but not used" error, all lhs variables act as
730 // one; i.e., if any one of them is 'used', all of them are 'used'.
731 // Collect them for later analysis.
732 lhsVars = append(lhsVars, obj)
733 }
734 check.stmtList(inner, clause.Body)
735 check.closeScope()
736 }
737
738 // If lhs exists, we must have at least one lhs variable that was used.
739 if lhs != nil {
740 var used bool
741 for _, v := range lhsVars {
742 if v.used {
743 used = true
744 }
745 v.used = true // avoid usage error when checking entire function
746 }
747 if !used {
Colin Cross846c3162021-05-14 11:11:40 -0700748 check.softErrorf(lhs, _UnusedVar, "%s declared but not used", lhs.Name)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700749 }
750 }
751
752 case *ast.SelectStmt:
753 inner |= breakOk
754
755 check.multipleDefaults(s.Body.List)
756
757 for _, s := range s.Body.List {
758 clause, _ := s.(*ast.CommClause)
759 if clause == nil {
760 continue // error reported before
761 }
762
763 // clause.Comm must be a SendStmt, RecvStmt, or default case
764 valid := false
765 var rhs ast.Expr // rhs of RecvStmt, or nil
766 switch s := clause.Comm.(type) {
767 case nil, *ast.SendStmt:
768 valid = true
769 case *ast.AssignStmt:
770 if len(s.Rhs) == 1 {
771 rhs = s.Rhs[0]
772 }
773 case *ast.ExprStmt:
774 rhs = s.X
775 }
776
777 // if present, rhs must be a receive operation
778 if rhs != nil {
779 if x, _ := unparen(rhs).(*ast.UnaryExpr); x != nil && x.Op == token.ARROW {
780 valid = true
781 }
782 }
783
784 if !valid {
Colin Cross846c3162021-05-14 11:11:40 -0700785 check.error(clause.Comm, _InvalidSelectCase, "select case must be send or receive (possibly with assignment)")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700786 continue
787 }
788
789 check.openScope(s, "case")
790 if clause.Comm != nil {
791 check.stmt(inner, clause.Comm)
792 }
793 check.stmtList(inner, clause.Body)
794 check.closeScope()
795 }
796
797 case *ast.ForStmt:
798 inner |= breakOk | continueOk
799 check.openScope(s, "for")
800 defer check.closeScope()
801
802 check.simpleStmt(s.Init)
803 if s.Cond != nil {
804 var x operand
805 check.expr(&x, s.Cond)
Dan Willemsen59ee7802021-12-15 01:08:25 -0800806 if x.mode != invalid && !allBoolean(x.typ) {
Colin Cross846c3162021-05-14 11:11:40 -0700807 check.error(s.Cond, _InvalidCond, "non-boolean condition in for statement")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700808 }
809 }
810 check.simpleStmt(s.Post)
811 // spec: "The init statement may be a short variable
812 // declaration, but the post statement must not."
813 if s, _ := s.Post.(*ast.AssignStmt); s != nil && s.Tok == token.DEFINE {
Colin Cross846c3162021-05-14 11:11:40 -0700814 check.softErrorf(s, _InvalidPostDecl, "cannot declare in post statement")
Dan Willemsene1b3b182018-02-27 19:36:27 -0800815 // Don't call useLHS here because we want to use the lhs in
816 // this erroneous statement so that we don't get errors about
817 // these lhs variables being declared but not used.
Dan Willemsen6ff23252015-09-15 13:49:18 -0700818 check.use(s.Lhs...) // avoid follow-up errors
819 }
820 check.stmt(inner, s.Body)
821
822 case *ast.RangeStmt:
823 inner |= breakOk | continueOk
Dan Willemsen6ff23252015-09-15 13:49:18 -0700824
825 // check expression to iterate over
826 var x operand
827 check.expr(&x, s.X)
828
829 // determine key/value types
830 var key, val Type
831 if x.mode != invalid {
Dan Willemsen14b5f992022-03-10 14:27:21 -0800832 // Ranging over a type parameter is permitted if it has a core type.
Dan Willemsen59ee7802021-12-15 01:08:25 -0800833 var cause string
Dan Willemsen14b5f992022-03-10 14:27:21 -0800834 u := coreType(x.typ)
Dan Willemsen59ee7802021-12-15 01:08:25 -0800835 switch t := u.(type) {
836 case nil:
Dan Willemsen14b5f992022-03-10 14:27:21 -0800837 cause = check.sprintf("%s has no core type", x.typ)
Dan Willemsen59ee7802021-12-15 01:08:25 -0800838 case *Chan:
839 if s.Value != nil {
840 check.softErrorf(s.Value, _InvalidIterVar, "range over %s permits only one iteration variable", &x)
841 // ok to continue
Dan Willemsen31b9b842021-08-31 12:51:40 -0700842 }
Dan Willemsen59ee7802021-12-15 01:08:25 -0800843 if t.dir == SendOnly {
844 cause = "receive from send-only channel"
845 }
846 }
847 key, val = rangeKeyVal(u)
848 if key == nil || cause != "" {
849 if cause == "" {
850 check.softErrorf(&x, _InvalidRangeExpr, "cannot range over %s", &x)
851 } else {
852 check.softErrorf(&x, _InvalidRangeExpr, "cannot range over %s (%s)", &x, cause)
853 }
Dan Willemsen31b9b842021-08-31 12:51:40 -0700854 // ok to continue
855 }
Dan Willemsen6ff23252015-09-15 13:49:18 -0700856 }
857
Dan Willemsen1047e6d2022-03-18 14:43:30 -0700858 // Open the for-statement block scope now, after the range clause.
859 // Iteration variables declared with := need to go in this scope (was issue #51437).
860 check.openScope(s, "range")
861 defer check.closeScope()
862
Dan Willemsen6ff23252015-09-15 13:49:18 -0700863 // check assignment to/declaration of iteration variables
864 // (irregular assignment, cannot easily map to existing assignment checks)
865
866 // lhs expressions and initialization value (rhs) types
867 lhs := [2]ast.Expr{s.Key, s.Value}
868 rhs := [2]Type{key, val} // key, val may be nil
869
870 if s.Tok == token.DEFINE {
Dan Willemsen1047e6d2022-03-18 14:43:30 -0700871 // short variable declaration
Dan Willemsen6ff23252015-09-15 13:49:18 -0700872 var vars []*Var
873 for i, lhs := range lhs {
874 if lhs == nil {
875 continue
876 }
877
878 // determine lhs variable
879 var obj *Var
880 if ident, _ := lhs.(*ast.Ident); ident != nil {
881 // declare new variable
882 name := ident.Name
883 obj = NewVar(ident.Pos(), check.pkg, name, nil)
884 check.recordDef(ident, obj)
885 // _ variables don't count as new variables
886 if name != "_" {
887 vars = append(vars, obj)
888 }
889 } else {
Colin Cross846c3162021-05-14 11:11:40 -0700890 check.invalidAST(lhs, "cannot declare %s", lhs)
Dan Willemsen6ff23252015-09-15 13:49:18 -0700891 obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
892 }
893
894 // initialize lhs variable
895 if typ := rhs[i]; typ != nil {
896 x.mode = value
897 x.expr = lhs // we don't have a better rhs expression to use here
898 x.typ = typ
Dan Willemsen0c157092016-07-08 13:57:52 -0700899 check.initVar(obj, &x, "range clause")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700900 } else {
901 obj.typ = Typ[Invalid]
902 obj.used = true // don't complain about unused variable
903 }
904 }
905
906 // declare variables
907 if len(vars) > 0 {
Dan Willemsen1047e6d2022-03-18 14:43:30 -0700908 scopePos := s.Body.Pos()
Dan Willemsen6ff23252015-09-15 13:49:18 -0700909 for _, obj := range vars {
Dan Willemsen6ff23252015-09-15 13:49:18 -0700910 check.declare(check.scope, nil /* recordDef already called */, obj, scopePos)
911 }
912 } else {
Colin Cross846c3162021-05-14 11:11:40 -0700913 check.error(inNode(s, s.TokPos), _NoNewVar, "no new variables on left side of :=")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700914 }
915 } else {
916 // ordinary assignment
917 for i, lhs := range lhs {
918 if lhs == nil {
919 continue
920 }
921 if typ := rhs[i]; typ != nil {
922 x.mode = value
923 x.expr = lhs // we don't have a better rhs expression to use here
924 x.typ = typ
925 check.assignVar(lhs, &x)
926 }
927 }
928 }
929
930 check.stmt(inner, s.Body)
931
932 default:
Colin Cross846c3162021-05-14 11:11:40 -0700933 check.invalidAST(s, "invalid statement")
Dan Willemsen6ff23252015-09-15 13:49:18 -0700934 }
935}
Dan Willemsen31b9b842021-08-31 12:51:40 -0700936
Dan Willemsen31b9b842021-08-31 12:51:40 -0700937// rangeKeyVal returns the key and value type produced by a range clause
Dan Willemsen59ee7802021-12-15 01:08:25 -0800938// over an expression of type typ. If the range clause is not permitted
939// the results are nil.
940func rangeKeyVal(typ Type) (key, val Type) {
941 switch typ := arrayPtrDeref(typ).(type) {
Dan Willemsen31b9b842021-08-31 12:51:40 -0700942 case *Basic:
943 if isString(typ) {
Dan Willemsen59ee7802021-12-15 01:08:25 -0800944 return Typ[Int], universeRune // use 'rune' name
Dan Willemsen31b9b842021-08-31 12:51:40 -0700945 }
946 case *Array:
Dan Willemsen59ee7802021-12-15 01:08:25 -0800947 return Typ[Int], typ.elem
Dan Willemsen31b9b842021-08-31 12:51:40 -0700948 case *Slice:
Dan Willemsen59ee7802021-12-15 01:08:25 -0800949 return Typ[Int], typ.elem
Dan Willemsen31b9b842021-08-31 12:51:40 -0700950 case *Map:
Dan Willemsen59ee7802021-12-15 01:08:25 -0800951 return typ.key, typ.elem
Dan Willemsen31b9b842021-08-31 12:51:40 -0700952 case *Chan:
Dan Willemsen59ee7802021-12-15 01:08:25 -0800953 return typ.elem, Typ[Invalid]
Dan Willemsen31b9b842021-08-31 12:51:40 -0700954 }
Dan Willemsen59ee7802021-12-15 01:08:25 -0800955 return
Dan Willemsen31b9b842021-08-31 12:51:40 -0700956}