PageRenderTime 53ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/third_party/gofrontend/libgo/go/go/types/stmt.go

http://github.com/axw/llgo
Go | 744 lines | 582 code | 76 blank | 86 comment | 228 complexity | ebc8729dbd69ef4058540d9ff1763c17 MD5 | raw file
Possible License(s): BSD-3-Clause, MIT
  1. // 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. // This file implements typechecking of statements.
  5. package types
  6. import (
  7. "fmt"
  8. "go/ast"
  9. "go/constant"
  10. "go/token"
  11. )
  12. func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *ast.BlockStmt) {
  13. if trace {
  14. if name == "" {
  15. name = "<function literal>"
  16. }
  17. fmt.Printf("--- %s: %s {\n", name, sig)
  18. defer fmt.Println("--- <end>")
  19. }
  20. // set function scope extent
  21. sig.scope.pos = body.Pos()
  22. sig.scope.end = body.End()
  23. // save/restore current context and setup function context
  24. // (and use 0 indentation at function start)
  25. defer func(ctxt context, indent int) {
  26. check.context = ctxt
  27. check.indent = indent
  28. }(check.context, check.indent)
  29. check.context = context{
  30. decl: decl,
  31. scope: sig.scope,
  32. sig: sig,
  33. }
  34. check.indent = 0
  35. check.stmtList(0, body.List)
  36. if check.hasLabel {
  37. check.labels(body)
  38. }
  39. if sig.results.Len() > 0 && !check.isTerminating(body, "") {
  40. check.error(body.Rbrace, "missing return")
  41. }
  42. // spec: "Implementation restriction: A compiler may make it illegal to
  43. // declare a variable inside a function body if the variable is never used."
  44. // (One could check each scope after use, but that distributes this check
  45. // over several places because CloseScope is not always called explicitly.)
  46. check.usage(sig.scope)
  47. }
  48. func (check *Checker) usage(scope *Scope) {
  49. for _, obj := range scope.elems {
  50. if v, _ := obj.(*Var); v != nil && !v.used {
  51. check.softErrorf(v.pos, "%s declared but not used", v.name)
  52. }
  53. }
  54. for _, scope := range scope.children {
  55. check.usage(scope)
  56. }
  57. }
  58. // stmtContext is a bitset describing which
  59. // control-flow statements are permissible.
  60. type stmtContext uint
  61. const (
  62. breakOk stmtContext = 1 << iota
  63. continueOk
  64. fallthroughOk
  65. )
  66. func (check *Checker) simpleStmt(s ast.Stmt) {
  67. if s != nil {
  68. check.stmt(0, s)
  69. }
  70. }
  71. func (check *Checker) stmtList(ctxt stmtContext, list []ast.Stmt) {
  72. ok := ctxt&fallthroughOk != 0
  73. inner := ctxt &^ fallthroughOk
  74. for i, s := range list {
  75. inner := inner
  76. if ok && i+1 == len(list) {
  77. inner |= fallthroughOk
  78. }
  79. check.stmt(inner, s)
  80. }
  81. }
  82. func (check *Checker) multipleDefaults(list []ast.Stmt) {
  83. var first ast.Stmt
  84. for _, s := range list {
  85. var d ast.Stmt
  86. switch c := s.(type) {
  87. case *ast.CaseClause:
  88. if len(c.List) == 0 {
  89. d = s
  90. }
  91. case *ast.CommClause:
  92. if c.Comm == nil {
  93. d = s
  94. }
  95. default:
  96. check.invalidAST(s.Pos(), "case/communication clause expected")
  97. }
  98. if d != nil {
  99. if first != nil {
  100. check.errorf(d.Pos(), "multiple defaults (first at %s)", first.Pos())
  101. } else {
  102. first = d
  103. }
  104. }
  105. }
  106. }
  107. func (check *Checker) openScope(s ast.Stmt, comment string) {
  108. scope := NewScope(check.scope, s.Pos(), s.End(), comment)
  109. check.recordScope(s, scope)
  110. check.scope = scope
  111. }
  112. func (check *Checker) closeScope() {
  113. check.scope = check.scope.Parent()
  114. }
  115. func assignOp(op token.Token) token.Token {
  116. // token_test.go verifies the token ordering this function relies on
  117. if token.ADD_ASSIGN <= op && op <= token.AND_NOT_ASSIGN {
  118. return op + (token.ADD - token.ADD_ASSIGN)
  119. }
  120. return token.ILLEGAL
  121. }
  122. func (check *Checker) suspendedCall(keyword string, call *ast.CallExpr) {
  123. var x operand
  124. var msg string
  125. switch check.rawExpr(&x, call, nil) {
  126. case conversion:
  127. msg = "requires function call, not conversion"
  128. case expression:
  129. msg = "discards result of"
  130. case statement:
  131. return
  132. default:
  133. unreachable()
  134. }
  135. check.errorf(x.pos(), "%s %s %s", keyword, msg, &x)
  136. }
  137. func (check *Checker) caseValues(x operand /* copy argument (not *operand!) */, values []ast.Expr) {
  138. // No duplicate checking for now. See issue 4524.
  139. for _, e := range values {
  140. var y operand
  141. check.expr(&y, e)
  142. if y.mode == invalid {
  143. return
  144. }
  145. // TODO(gri) The convertUntyped call pair below appears in other places. Factor!
  146. // Order matters: By comparing y against x, error positions are at the case values.
  147. check.convertUntyped(&y, x.typ)
  148. if y.mode == invalid {
  149. return
  150. }
  151. check.convertUntyped(&x, y.typ)
  152. if x.mode == invalid {
  153. return
  154. }
  155. check.comparison(&y, &x, token.EQL)
  156. }
  157. }
  158. func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[Type]token.Pos) (T Type) {
  159. L:
  160. for _, e := range types {
  161. T = check.typOrNil(e)
  162. if T == Typ[Invalid] {
  163. continue
  164. }
  165. // complain about duplicate types
  166. // TODO(gri) use a type hash to avoid quadratic algorithm
  167. for t, pos := range seen {
  168. if T == nil && t == nil || T != nil && t != nil && Identical(T, t) {
  169. // talk about "case" rather than "type" because of nil case
  170. check.error(e.Pos(), "duplicate case in type switch")
  171. check.errorf(pos, "\tprevious case %s", T) // secondary error, \t indented
  172. continue L
  173. }
  174. }
  175. seen[T] = e.Pos()
  176. if T != nil {
  177. check.typeAssertion(e.Pos(), x, xtyp, T)
  178. }
  179. }
  180. return
  181. }
  182. // stmt typechecks statement s.
  183. func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
  184. // statements cannot use iota in general
  185. // (constant declarations set it explicitly)
  186. assert(check.iota == nil)
  187. // statements must end with the same top scope as they started with
  188. if debug {
  189. defer func(scope *Scope) {
  190. // don't check if code is panicking
  191. if p := recover(); p != nil {
  192. panic(p)
  193. }
  194. assert(scope == check.scope)
  195. }(check.scope)
  196. }
  197. inner := ctxt &^ fallthroughOk
  198. switch s := s.(type) {
  199. case *ast.BadStmt, *ast.EmptyStmt:
  200. // ignore
  201. case *ast.DeclStmt:
  202. check.declStmt(s.Decl)
  203. case *ast.LabeledStmt:
  204. check.hasLabel = true
  205. check.stmt(ctxt, s.Stmt)
  206. case *ast.ExprStmt:
  207. // spec: "With the exception of specific built-in functions,
  208. // function and method calls and receive operations can appear
  209. // in statement context. Such statements may be parenthesized."
  210. var x operand
  211. kind := check.rawExpr(&x, s.X, nil)
  212. var msg string
  213. switch x.mode {
  214. default:
  215. if kind == statement {
  216. return
  217. }
  218. msg = "is not used"
  219. case builtin:
  220. msg = "must be called"
  221. case typexpr:
  222. msg = "is not an expression"
  223. }
  224. check.errorf(x.pos(), "%s %s", &x, msg)
  225. case *ast.SendStmt:
  226. var ch, x operand
  227. check.expr(&ch, s.Chan)
  228. check.expr(&x, s.Value)
  229. if ch.mode == invalid || x.mode == invalid {
  230. return
  231. }
  232. if tch, ok := ch.typ.Underlying().(*Chan); !ok || tch.dir == RecvOnly || !check.assignment(&x, tch.elem) {
  233. if x.mode != invalid {
  234. check.invalidOp(ch.pos(), "cannot send %s to channel %s", &x, &ch)
  235. }
  236. }
  237. case *ast.IncDecStmt:
  238. var op token.Token
  239. switch s.Tok {
  240. case token.INC:
  241. op = token.ADD
  242. case token.DEC:
  243. op = token.SUB
  244. default:
  245. check.invalidAST(s.TokPos, "unknown inc/dec operation %s", s.Tok)
  246. return
  247. }
  248. var x operand
  249. Y := &ast.BasicLit{ValuePos: s.X.Pos(), Kind: token.INT, Value: "1"} // use x's position
  250. check.binary(&x, nil, s.X, Y, op)
  251. if x.mode == invalid {
  252. return
  253. }
  254. check.assignVar(s.X, &x)
  255. case *ast.AssignStmt:
  256. switch s.Tok {
  257. case token.ASSIGN, token.DEFINE:
  258. if len(s.Lhs) == 0 {
  259. check.invalidAST(s.Pos(), "missing lhs in assignment")
  260. return
  261. }
  262. if s.Tok == token.DEFINE {
  263. check.shortVarDecl(s.TokPos, s.Lhs, s.Rhs)
  264. } else {
  265. // regular assignment
  266. check.assignVars(s.Lhs, s.Rhs)
  267. }
  268. default:
  269. // assignment operations
  270. if len(s.Lhs) != 1 || len(s.Rhs) != 1 {
  271. check.errorf(s.TokPos, "assignment operation %s requires single-valued expressions", s.Tok)
  272. return
  273. }
  274. op := assignOp(s.Tok)
  275. if op == token.ILLEGAL {
  276. check.invalidAST(s.TokPos, "unknown assignment operation %s", s.Tok)
  277. return
  278. }
  279. var x operand
  280. check.binary(&x, nil, s.Lhs[0], s.Rhs[0], op)
  281. if x.mode == invalid {
  282. return
  283. }
  284. check.assignVar(s.Lhs[0], &x)
  285. }
  286. case *ast.GoStmt:
  287. check.suspendedCall("go", s.Call)
  288. case *ast.DeferStmt:
  289. check.suspendedCall("defer", s.Call)
  290. case *ast.ReturnStmt:
  291. res := check.sig.results
  292. if res.Len() > 0 {
  293. // function returns results
  294. // (if one, say the first, result parameter is named, all of them are named)
  295. if len(s.Results) == 0 && res.vars[0].name != "" {
  296. // spec: "Implementation restriction: A compiler may disallow an empty expression
  297. // list in a "return" statement if a different entity (constant, type, or variable)
  298. // with the same name as a result parameter is in scope at the place of the return."
  299. for _, obj := range res.vars {
  300. if _, alt := check.scope.LookupParent(obj.name, check.pos); alt != nil && alt != obj {
  301. check.errorf(s.Pos(), "result parameter %s not in scope at return", obj.name)
  302. check.errorf(alt.Pos(), "\tinner declaration of %s", obj)
  303. // ok to continue
  304. }
  305. }
  306. } else {
  307. // return has results or result parameters are unnamed
  308. check.initVars(res.vars, s.Results, s.Return)
  309. }
  310. } else if len(s.Results) > 0 {
  311. check.error(s.Results[0].Pos(), "no result values expected")
  312. check.use(s.Results...)
  313. }
  314. case *ast.BranchStmt:
  315. if s.Label != nil {
  316. check.hasLabel = true
  317. return // checked in 2nd pass (check.labels)
  318. }
  319. switch s.Tok {
  320. case token.BREAK:
  321. if ctxt&breakOk == 0 {
  322. check.error(s.Pos(), "break not in for, switch, or select statement")
  323. }
  324. case token.CONTINUE:
  325. if ctxt&continueOk == 0 {
  326. check.error(s.Pos(), "continue not in for statement")
  327. }
  328. case token.FALLTHROUGH:
  329. if ctxt&fallthroughOk == 0 {
  330. check.error(s.Pos(), "fallthrough statement out of place")
  331. }
  332. default:
  333. check.invalidAST(s.Pos(), "branch statement: %s", s.Tok)
  334. }
  335. case *ast.BlockStmt:
  336. check.openScope(s, "block")
  337. defer check.closeScope()
  338. check.stmtList(inner, s.List)
  339. case *ast.IfStmt:
  340. check.openScope(s, "if")
  341. defer check.closeScope()
  342. check.simpleStmt(s.Init)
  343. var x operand
  344. check.expr(&x, s.Cond)
  345. if x.mode != invalid && !isBoolean(x.typ) {
  346. check.error(s.Cond.Pos(), "non-boolean condition in if statement")
  347. }
  348. check.stmt(inner, s.Body)
  349. if s.Else != nil {
  350. check.stmt(inner, s.Else)
  351. }
  352. case *ast.SwitchStmt:
  353. inner |= breakOk
  354. check.openScope(s, "switch")
  355. defer check.closeScope()
  356. check.simpleStmt(s.Init)
  357. var x operand
  358. if s.Tag != nil {
  359. check.expr(&x, s.Tag)
  360. } else {
  361. // spec: "A missing switch expression is
  362. // equivalent to the boolean value true."
  363. x.mode = constant_
  364. x.typ = Typ[Bool]
  365. x.val = constant.MakeBool(true)
  366. x.expr = &ast.Ident{NamePos: s.Body.Lbrace, Name: "true"}
  367. }
  368. check.multipleDefaults(s.Body.List)
  369. for i, c := range s.Body.List {
  370. clause, _ := c.(*ast.CaseClause)
  371. if clause == nil {
  372. check.invalidAST(c.Pos(), "incorrect expression switch case")
  373. continue
  374. }
  375. if x.mode != invalid {
  376. check.caseValues(x, clause.List)
  377. }
  378. check.openScope(clause, "case")
  379. inner := inner
  380. if i+1 < len(s.Body.List) {
  381. inner |= fallthroughOk
  382. }
  383. check.stmtList(inner, clause.Body)
  384. check.closeScope()
  385. }
  386. case *ast.TypeSwitchStmt:
  387. inner |= breakOk
  388. check.openScope(s, "type switch")
  389. defer check.closeScope()
  390. check.simpleStmt(s.Init)
  391. // A type switch guard must be of the form:
  392. //
  393. // TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
  394. //
  395. // The parser is checking syntactic correctness;
  396. // remaining syntactic errors are considered AST errors here.
  397. // TODO(gri) better factoring of error handling (invalid ASTs)
  398. //
  399. var lhs *ast.Ident // lhs identifier or nil
  400. var rhs ast.Expr
  401. switch guard := s.Assign.(type) {
  402. case *ast.ExprStmt:
  403. rhs = guard.X
  404. case *ast.AssignStmt:
  405. if len(guard.Lhs) != 1 || guard.Tok != token.DEFINE || len(guard.Rhs) != 1 {
  406. check.invalidAST(s.Pos(), "incorrect form of type switch guard")
  407. return
  408. }
  409. lhs, _ = guard.Lhs[0].(*ast.Ident)
  410. if lhs == nil {
  411. check.invalidAST(s.Pos(), "incorrect form of type switch guard")
  412. return
  413. }
  414. if lhs.Name == "_" {
  415. // _ := x.(type) is an invalid short variable declaration
  416. check.softErrorf(lhs.Pos(), "no new variable on left side of :=")
  417. lhs = nil // avoid declared but not used error below
  418. } else {
  419. check.recordDef(lhs, nil) // lhs variable is implicitly declared in each cause clause
  420. }
  421. rhs = guard.Rhs[0]
  422. default:
  423. check.invalidAST(s.Pos(), "incorrect form of type switch guard")
  424. return
  425. }
  426. // rhs must be of the form: expr.(type) and expr must be an interface
  427. expr, _ := rhs.(*ast.TypeAssertExpr)
  428. if expr == nil || expr.Type != nil {
  429. check.invalidAST(s.Pos(), "incorrect form of type switch guard")
  430. return
  431. }
  432. var x operand
  433. check.expr(&x, expr.X)
  434. if x.mode == invalid {
  435. return
  436. }
  437. xtyp, _ := x.typ.Underlying().(*Interface)
  438. if xtyp == nil {
  439. check.errorf(x.pos(), "%s is not an interface", &x)
  440. return
  441. }
  442. check.multipleDefaults(s.Body.List)
  443. var lhsVars []*Var // list of implicitly declared lhs variables
  444. seen := make(map[Type]token.Pos) // map of seen types to positions
  445. for _, s := range s.Body.List {
  446. clause, _ := s.(*ast.CaseClause)
  447. if clause == nil {
  448. check.invalidAST(s.Pos(), "incorrect type switch case")
  449. continue
  450. }
  451. // Check each type in this type switch case.
  452. T := check.caseTypes(&x, xtyp, clause.List, seen)
  453. check.openScope(clause, "case")
  454. // If lhs exists, declare a corresponding variable in the case-local scope.
  455. if lhs != nil {
  456. // spec: "The TypeSwitchGuard may include a short variable declaration.
  457. // When that form is used, the variable is declared at the beginning of
  458. // the implicit block in each clause. In clauses with a case listing
  459. // exactly one type, the variable has that type; otherwise, the variable
  460. // has the type of the expression in the TypeSwitchGuard."
  461. if len(clause.List) != 1 || T == nil {
  462. T = x.typ
  463. }
  464. obj := NewVar(lhs.Pos(), check.pkg, lhs.Name, T)
  465. scopePos := clause.End()
  466. if len(clause.Body) > 0 {
  467. scopePos = clause.Body[0].Pos()
  468. }
  469. check.declare(check.scope, nil, obj, scopePos)
  470. check.recordImplicit(clause, obj)
  471. // For the "declared but not used" error, all lhs variables act as
  472. // one; i.e., if any one of them is 'used', all of them are 'used'.
  473. // Collect them for later analysis.
  474. lhsVars = append(lhsVars, obj)
  475. }
  476. check.stmtList(inner, clause.Body)
  477. check.closeScope()
  478. }
  479. // If lhs exists, we must have at least one lhs variable that was used.
  480. if lhs != nil {
  481. var used bool
  482. for _, v := range lhsVars {
  483. if v.used {
  484. used = true
  485. }
  486. v.used = true // avoid usage error when checking entire function
  487. }
  488. if !used {
  489. check.softErrorf(lhs.Pos(), "%s declared but not used", lhs.Name)
  490. }
  491. }
  492. case *ast.SelectStmt:
  493. inner |= breakOk
  494. check.multipleDefaults(s.Body.List)
  495. for _, s := range s.Body.List {
  496. clause, _ := s.(*ast.CommClause)
  497. if clause == nil {
  498. continue // error reported before
  499. }
  500. // clause.Comm must be a SendStmt, RecvStmt, or default case
  501. valid := false
  502. var rhs ast.Expr // rhs of RecvStmt, or nil
  503. switch s := clause.Comm.(type) {
  504. case nil, *ast.SendStmt:
  505. valid = true
  506. case *ast.AssignStmt:
  507. if len(s.Rhs) == 1 {
  508. rhs = s.Rhs[0]
  509. }
  510. case *ast.ExprStmt:
  511. rhs = s.X
  512. }
  513. // if present, rhs must be a receive operation
  514. if rhs != nil {
  515. if x, _ := unparen(rhs).(*ast.UnaryExpr); x != nil && x.Op == token.ARROW {
  516. valid = true
  517. }
  518. }
  519. if !valid {
  520. check.error(clause.Comm.Pos(), "select case must be send or receive (possibly with assignment)")
  521. continue
  522. }
  523. check.openScope(s, "case")
  524. if clause.Comm != nil {
  525. check.stmt(inner, clause.Comm)
  526. }
  527. check.stmtList(inner, clause.Body)
  528. check.closeScope()
  529. }
  530. case *ast.ForStmt:
  531. inner |= breakOk | continueOk
  532. check.openScope(s, "for")
  533. defer check.closeScope()
  534. check.simpleStmt(s.Init)
  535. if s.Cond != nil {
  536. var x operand
  537. check.expr(&x, s.Cond)
  538. if x.mode != invalid && !isBoolean(x.typ) {
  539. check.error(s.Cond.Pos(), "non-boolean condition in for statement")
  540. }
  541. }
  542. check.simpleStmt(s.Post)
  543. // spec: "The init statement may be a short variable
  544. // declaration, but the post statement must not."
  545. if s, _ := s.Post.(*ast.AssignStmt); s != nil && s.Tok == token.DEFINE {
  546. check.softErrorf(s.Pos(), "cannot declare in post statement")
  547. check.use(s.Lhs...) // avoid follow-up errors
  548. }
  549. check.stmt(inner, s.Body)
  550. case *ast.RangeStmt:
  551. inner |= breakOk | continueOk
  552. check.openScope(s, "for")
  553. defer check.closeScope()
  554. // check expression to iterate over
  555. var x operand
  556. check.expr(&x, s.X)
  557. // determine key/value types
  558. var key, val Type
  559. if x.mode != invalid {
  560. switch typ := x.typ.Underlying().(type) {
  561. case *Basic:
  562. if isString(typ) {
  563. key = Typ[Int]
  564. val = universeRune // use 'rune' name
  565. }
  566. case *Array:
  567. key = Typ[Int]
  568. val = typ.elem
  569. case *Slice:
  570. key = Typ[Int]
  571. val = typ.elem
  572. case *Pointer:
  573. if typ, _ := typ.base.Underlying().(*Array); typ != nil {
  574. key = Typ[Int]
  575. val = typ.elem
  576. }
  577. case *Map:
  578. key = typ.key
  579. val = typ.elem
  580. case *Chan:
  581. key = typ.elem
  582. val = Typ[Invalid]
  583. if typ.dir == SendOnly {
  584. check.errorf(x.pos(), "cannot range over send-only channel %s", &x)
  585. // ok to continue
  586. }
  587. if s.Value != nil {
  588. check.errorf(s.Value.Pos(), "iteration over %s permits only one iteration variable", &x)
  589. // ok to continue
  590. }
  591. }
  592. }
  593. if key == nil {
  594. check.errorf(x.pos(), "cannot range over %s", &x)
  595. // ok to continue
  596. }
  597. // check assignment to/declaration of iteration variables
  598. // (irregular assignment, cannot easily map to existing assignment checks)
  599. // lhs expressions and initialization value (rhs) types
  600. lhs := [2]ast.Expr{s.Key, s.Value}
  601. rhs := [2]Type{key, val} // key, val may be nil
  602. if s.Tok == token.DEFINE {
  603. // short variable declaration; variable scope starts after the range clause
  604. // (the for loop opens a new scope, so variables on the lhs never redeclare
  605. // previously declared variables)
  606. var vars []*Var
  607. for i, lhs := range lhs {
  608. if lhs == nil {
  609. continue
  610. }
  611. // determine lhs variable
  612. var obj *Var
  613. if ident, _ := lhs.(*ast.Ident); ident != nil {
  614. // declare new variable
  615. name := ident.Name
  616. obj = NewVar(ident.Pos(), check.pkg, name, nil)
  617. check.recordDef(ident, obj)
  618. // _ variables don't count as new variables
  619. if name != "_" {
  620. vars = append(vars, obj)
  621. }
  622. } else {
  623. check.errorf(lhs.Pos(), "cannot declare %s", lhs)
  624. obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
  625. }
  626. // initialize lhs variable
  627. if typ := rhs[i]; typ != nil {
  628. x.mode = value
  629. x.expr = lhs // we don't have a better rhs expression to use here
  630. x.typ = typ
  631. check.initVar(obj, &x, false)
  632. } else {
  633. obj.typ = Typ[Invalid]
  634. obj.used = true // don't complain about unused variable
  635. }
  636. }
  637. // declare variables
  638. if len(vars) > 0 {
  639. for _, obj := range vars {
  640. // spec: "The scope of a constant or variable identifier declared inside
  641. // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
  642. // for short variable declarations) and ends at the end of the innermost
  643. // containing block."
  644. scopePos := s.End()
  645. check.declare(check.scope, nil /* recordDef already called */, obj, scopePos)
  646. }
  647. } else {
  648. check.error(s.TokPos, "no new variables on left side of :=")
  649. }
  650. } else {
  651. // ordinary assignment
  652. for i, lhs := range lhs {
  653. if lhs == nil {
  654. continue
  655. }
  656. if typ := rhs[i]; typ != nil {
  657. x.mode = value
  658. x.expr = lhs // we don't have a better rhs expression to use here
  659. x.typ = typ
  660. check.assignVar(lhs, &x)
  661. }
  662. }
  663. }
  664. check.stmt(inner, s.Body)
  665. default:
  666. check.error(s.Pos(), "invalid statement")
  667. }
  668. }