]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.typeparams] all: merge dev.regabi (07569da) into dev.typeparams
authorMatthew Dempsky <mdempsky@google.com>
Mon, 28 Dec 2020 08:39:13 +0000 (00:39 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Mon, 28 Dec 2020 08:39:17 +0000 (00:39 -0800)
Conflicts:

- test/fixedbugs/issue27595.go
- test/fixedbugs/issue30087.go
- test/used.go

Merge List:

+ 2020-12-28 07569dac4e [dev.regabi] all: merge master (1d78139) into dev.regabi
+ 2020-12-28 76136be027 [dev.regabi] cmd/compile: check for recursive import in ImportBody
+ 2020-12-28 fda7ec3a3f [dev.regabi] cmd/compile: remove Name.IsDDD, etc
+ 2020-12-28 098a6490b9 [dev.regabi] cmd/compile: remove Declare in makepartialcall
+ 2020-12-28 137f0d2e06 [dev.regabi] cmd/compile: remove unnecessary Name.Sym call
+ 2020-12-28 3383b5c74a [dev.regabi] cmd/compile: flatten dependency graph [generated]
+ 2020-12-28 f8afb8216a [dev.regabi] cmd/compile: rename CommStmt and CaseStmt [generated]
+ 2020-12-28 5f3bd59a0d [dev.regabi] cmd/compile: remove some unneeded code in package ir
+ 2020-12-28 3bdafb0d82 [dev.regabi] cmd/compile: remove CommStmt.List
+ 2020-12-28 2ecf52b841 [dev.regabi] cmd/compile: separate CommStmt from CaseStmt
+ 2020-12-28 ed9772e130 [dev.regabi] cmd/compile: add explicit file name in types generation
+ 2020-12-28 a59d26603f [dev.regabi] cmd/compile: use []*CaseStmt in {Select,Switch}Stmt
+ 2020-12-28 fbc4458c06 [dev.regabi] cmd/compile: simplify some tree traversal code
+ 2020-12-28 6c67677541 [dev.regabi] cmd/compile: simplify FuncName and PkgFuncName
+ 2020-12-28 676d794b81 [dev.regabi] cmd/compile: remove refersToCommonName
+ 2020-12-28 c98548e110 [dev.regabi] cmd/compile: merge ascompatee, ascompatee1, and reorder3
+ 2020-12-28 4c215c4fa9 [dev.regabi] cmd/compile: simplify and optimize reorder3
+ 2020-12-28 e6c973198d [dev.regabi] cmd/compile: stop mangling SelectorExpr.Sel for ODOTMETH
+ 2020-12-28 135ce1c485 [dev.regabi] cmd/compile: desugar OMETHEXPR into ONAME during walk
+ 2020-12-28 0f732f8c91 [dev.regabi] cmd/compile: minor walkExpr cleanups
+ 2020-12-28 0de8eafd98 [dev.regabi] cmd/compile: remove SelectorExpr.Offset field
+ 2020-12-28 a4f335f420 [dev.regabi] cmd/compile: always use a Field for ODOTPTR expressions
+ 2020-12-26 1d78139128 runtime/cgo: fix Android build with NDK 22
+ 2020-12-25 2018b68a65 net/mail: don't use MDT in test
+ 2020-12-25 e4f293d853 [dev.regabi] cmd/compile: fix OCALLMETH desugaring
+ 2020-12-25 1d9a1f67d5 [dev.regabi] cmd/compile: don't emit reflect data for method types
+ 2020-12-25 396b6c2e7c [dev.regabi] cmd/compile: cleanup assignment typechecking
+ 2020-12-25 e24d2f3d05 [dev.regabi] cmd/compile: remove typ from RangeStmt
+ 2020-12-25 2785c691c2 [dev.regabi] cmd/compile: cleanup devirtualization docs
+ 2020-12-25 4b1d0fe66f [dev.regabi] cmd/compile: new devirtualization pkg [generated]
+ 2020-12-24 082cc8b7d9 [dev.regabi] cmd/compile: change ir.IsAssignable -> ir.IsAddressable
+ 2020-12-24 27b248b307 [dev.regabi] cmd/compile: separate range stmt Vars to Key, Value nodes
+ 2020-12-23 40818038bf [dev.regabi] cmd/compile: change CaseStmt.Vars to Var
+ 2020-12-23 b116404444 runtime: shift timeHistogram buckets and allow negative durations
+ 2020-12-23 8db7e2fecd runtime: fix allocs-by-size and frees-by-size buckets
+ 2020-12-23 fb96f07e1a runtime: fix nStackRoots comment about stack roots
+ 2020-12-23 d1502b3c72 lib/time, time/tzdata: update tzdata to 2020e
+ 2020-12-23 30c99cbb7a cmd/go: add the Retract field to 'go help mod edit' definition of the GoMod struct
+ 2020-12-23 49d0b239cb doc: fix a typo in contribute.html
+ 2020-12-23 9eeed291bc [dev.regabi] cmd/compile: eliminate usage of ir.Node in liveness
+ 2020-12-23 d1d64e4cea [dev.regabi] cmd/compile: split SliceExpr.List into separate fields
+ 2020-12-23 98a73030b0 cmd/go: in 'go get', promote named implicit dependencies to explicit
+ 2020-12-23 d19018e8f1 [dev.regabi] cmd/compile: split SliceHeaderExpr.LenCap into separate fields
+ 2020-12-23 53f082b0ee [dev.regabi] cmd/compile: cleanup export code further
+ 2020-12-23 31267f82e1 [dev.regabi] cmd/compile: simplify function/interface/struct typechecking
+ 2020-12-23 addade2cce [dev.regabi] cmd/compile: prefer types constructors over typecheck
+ 2020-12-23 18ebfb49e9 [dev.regabi] cmd/compile: cleanup noder
+ 2020-12-23 87a592b356 [dev.regabi] cmd/compile: cleanup import/export code
+ 2020-12-23 5898025026 [dev.regabi] cmd/compile: update mkbuiltin.go to use new type constructors
+ 2020-12-23 63c96c2ee7 [dev.regabi] cmd/compile: update mkbuiltin.go and re-enable TestBuiltin
+ 2020-12-23 fd6ba1c8a2 os/signal: fix a deadlock with syscall.AllThreadsSyscall() use
+ 2020-12-23 b0b0d98283 runtime: linux iscgo support for not blocking nptl signals
+ 2020-12-22 223331fc0c cmd/go/internal/modload: add hint for missing implicit dependency

Change-Id: Iecb8a7dfb401b6ab383e97101cd81bfc201683f6

1  2 
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/noder/noder.go
test/fixedbugs/issue27595.go
test/fixedbugs/issue30087.go
test/used.go

index c5870c650a2267048b3e341a2e0960158cd53e69,ba3620e6769fdadd1ad63a9894b0c40a96d0918e..6fc9695d412f00a31a5f991fcffafafc1b334776
@@@ -10,6 -10,7 +10,7 @@@ import 
        "bufio"
        "bytes"
        "cmd/compile/internal/base"
+       "cmd/compile/internal/devirtualize"
        "cmd/compile/internal/dwarfgen"
        "cmd/compile/internal/escape"
        "cmd/compile/internal/inline"
@@@ -214,12 -215,6 +215,12 @@@ func Main(archInit func(*ssagen.ArchInf
        ssagen.CgoSymABIs()
        base.Timer.Stop()
        base.Timer.AddEvent(int64(lines), "lines")
 +      if base.Flag.G != 0 && base.Flag.G < 3 {
 +              // can only parse generic code for now
 +              base.ExitIfErrors()
 +              return
 +      }
 +
        dwarfgen.RecordPackageName()
  
        // Typecheck.
        // Devirtualize.
        for _, n := range typecheck.Target.Decls {
                if n.Op() == ir.ODCLFUNC {
-                       inline.Devirtualize(n.(*ir.Func))
+                       devirtualize.Func(n.(*ir.Func))
                }
        }
        ir.CurFunc = nil
index 1bebb44e6ce11fd747cfe5ee12423b14d760c248,920f4839adfcc3642604496144edd69558078a38..c1356be52f4285f01ba4419bb329a3164c61c880
@@@ -8,7 -8,6 +8,7 @@@ import 
        "fmt"
        "go/constant"
        "go/token"
 +      "io"
        "os"
        "path/filepath"
        "runtime"
        "unicode/utf8"
  
        "cmd/compile/internal/base"
 +      "cmd/compile/internal/importer"
        "cmd/compile/internal/ir"
        "cmd/compile/internal/syntax"
        "cmd/compile/internal/typecheck"
        "cmd/compile/internal/types"
 +      "cmd/compile/internal/types2"
        "cmd/internal/objabi"
        "cmd/internal/src"
  )
@@@ -32,7 -29,7 +32,7 @@@
  // Each declaration in every *syntax.File is converted to a syntax tree
  // and its root represented by *Node is appended to Target.Decls.
  // Returns the total count of parsed lines.
 -func ParseFiles(filenames []string) uint {
 +func ParseFiles(filenames []string) (lines uint) {
        noders := make([]*noder, 0, len(filenames))
        // Limit the number of simultaneously open files.
        sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
@@@ -49,7 -46,7 +49,7 @@@
                        sem <- struct{}{}
                        defer func() { <-sem }()
                        defer close(p.err)
 -                      base := syntax.NewFileBase(filename)
 +                      fbase := syntax.NewFileBase(filename)
  
                        f, err := os.Open(filename)
                        if err != nil {
                        }
                        defer f.Close()
  
 -                      p.file, _ = syntax.Parse(base, f, p.error, p.pragma, syntax.CheckBranches) // errors are tracked via p.error
 +                      mode := syntax.CheckBranches
 +                      if base.Flag.G != 0 {
 +                              mode |= syntax.AllowGenerics
 +                      }
 +                      p.file, _ = syntax.Parse(fbase, f, p.error, p.pragma, mode) // errors are tracked via p.error
                }(filename)
        }
  
 -      var lines uint
 +      // generic noding phase (using new typechecker)
 +      if base.Flag.G != 0 {
 +              // setup and syntax error reporting
 +              nodersmap := make(map[string]*noder)
 +              var files []*syntax.File
 +              for _, p := range noders {
 +                      for e := range p.err {
 +                              p.errorAt(e.Pos, "%s", e.Msg)
 +                      }
 +
 +                      nodersmap[p.file.Pos().RelFilename()] = p
 +                      files = append(files, p.file)
 +                      lines += p.file.EOF.Line()
 +
 +              }
 +              if base.SyntaxErrors() != 0 {
 +                      base.ErrorExit()
 +              }
 +
 +              // typechecking
 +              conf := types2.Config{
 +                      InferFromConstraints:  true,
 +                      IgnoreBranches:        true, // parser already checked via syntax.CheckBranches mode
 +                      CompilerErrorMessages: true, // use error strings matching existing compiler errors
 +                      Error: func(err error) {
 +                              terr := err.(types2.Error)
 +                              if len(terr.Msg) > 0 && terr.Msg[0] == '\t' {
 +                                      // types2 reports error clarifications via separate
 +                                      // error messages which are indented with a tab.
 +                                      // Ignore them to satisfy tools and tests that expect
 +                                      // only one error in such cases.
 +                                      // TODO(gri) Need to adjust error reporting in types2.
 +                                      return
 +                              }
 +                              p := nodersmap[terr.Pos.RelFilename()]
 +                              base.ErrorfAt(p.makeXPos(terr.Pos), "%s", terr.Msg)
 +                      },
 +                      Importer: &gcimports{
 +                              packages: make(map[string]*types2.Package),
 +                              lookup: func(path string) (io.ReadCloser, error) {
 +                                      file, ok := findpkg(path)
 +                                      if !ok {
 +                                              return nil, fmt.Errorf("can't find import: %q", path)
 +                                      }
 +                                      return os.Open(file)
 +                              },
 +                      },
 +              }
 +              info := types2.Info{
 +                      Types:      make(map[syntax.Expr]types2.TypeAndValue),
 +                      Defs:       make(map[*syntax.Name]types2.Object),
 +                      Uses:       make(map[*syntax.Name]types2.Object),
 +                      Selections: make(map[*syntax.SelectorExpr]*types2.Selection),
 +                      // expand as needed
 +              }
 +              conf.Check(base.Ctxt.Pkgpath, files, &info)
 +              base.ExitIfErrors()
 +              if base.Flag.G < 2 {
 +                      return
 +              }
 +
 +              // noding
 +              for _, p := range noders {
 +                      // errors have already been reported
 +
 +                      p.typeInfo = &info
 +                      p.node()
 +                      lines += p.file.EOF.Line()
 +                      p.file = nil // release memory
 +                      base.ExitIfErrors()
 +
 +                      // Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
 +                      types.CheckDclstack()
 +              }
 +
 +              types.LocalPkg.Height = myheight
 +              return
 +      }
 +
 +      // traditional (non-generic) noding phase
        for _, p := range noders {
                for e := range p.err {
                        p.errorAt(e.Pos, "%s", e.Msg)
                }
  
                p.node()
 -              lines += p.file.Lines
 +              lines += p.file.EOF.Line()
                p.file = nil // release memory
 -
                if base.SyntaxErrors() != 0 {
                        base.ErrorExit()
                }
 +
                // Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
                types.CheckDclstack()
        }
        }
  
        types.LocalPkg.Height = myheight
 +      return
 +}
  
 -      return lines
 +// Temporary import helper to get type2-based type-checking going.
 +type gcimports struct {
 +      packages map[string]*types2.Package
 +      lookup   func(path string) (io.ReadCloser, error)
 +}
 +
 +func (m *gcimports) Import(path string) (*types2.Package, error) {
 +      return m.ImportFrom(path, "" /* no vendoring */, 0)
 +}
 +
 +func (m *gcimports) ImportFrom(path, srcDir string, mode types2.ImportMode) (*types2.Package, error) {
 +      if mode != 0 {
 +              panic("mode must be 0")
 +      }
 +      return importer.Import(m.packages, path, srcDir, m.lookup)
  }
  
  // makeSrcPosBase translates from a *syntax.PosBase to a *src.PosBase.
@@@ -257,40 -155,9 +257,40 @@@ type noder struct 
        trackScopes bool
        scopeVars   []int
  
 +      // typeInfo provides access to the type information computed by the new
 +      // typechecker. It is only present if -G is set, and all noders point to
 +      // the same types.Info. For now this is a local field, if need be we can
 +      // make it global.
 +      typeInfo *types2.Info
 +
        lastCloseScopePos syntax.Pos
  }
  
 +// For now we provide these basic accessors to get to type and object
 +// information of expression nodes during noding. Eventually we will
 +// attach this information directly to the syntax tree which should
 +// simplify access and make it more efficient as well.
 +
 +// typ returns the type and value information for the given expression.
 +func (p *noder) typ(x syntax.Expr) types2.TypeAndValue {
 +      return p.typeInfo.Types[x]
 +}
 +
 +// def returns the object for the given name in its declaration.
 +func (p *noder) def(x *syntax.Name) types2.Object {
 +      return p.typeInfo.Defs[x]
 +}
 +
 +// use returns the object for the given name outside its declaration.
 +func (p *noder) use(x *syntax.Name) types2.Object {
 +      return p.typeInfo.Uses[x]
 +}
 +
 +// sel returns the selection information for the given selector expression.
 +func (p *noder) sel(x *syntax.SelectorExpr) *types2.Selection {
 +      return p.typeInfo.Selections[x]
 +}
 +
  func (p *noder) funcBody(fn *ir.Func, block *syntax.BlockStmt) {
        oldScope := p.scope
        p.scope = 0
@@@ -452,7 -319,7 +452,7 @@@ func (p *noder) decls(decls []syntax.De
  }
  
  func (p *noder) importDecl(imp *syntax.ImportDecl) {
 -      if imp.Path.Bad {
 +      if imp.Path == nil || imp.Path.Bad {
                return // avoid follow-on errors if there was a syntax error
        }
  
  func (p *noder) varDecl(decl *syntax.VarDecl) []ir.Node {
        names := p.declNames(ir.ONAME, decl.NameList)
        typ := p.typeExprOrNil(decl.Type)
-       var exprs []ir.Node
-       if decl.Values != nil {
-               exprs = p.exprList(decl.Values)
-       }
+       exprs := p.exprList(decl.Values)
  
        if pragma, ok := decl.Pragma.(*pragmas); ok {
                if len(pragma.Embeds) > 0 {
@@@ -753,10 -616,14 +749,14 @@@ func (p *noder) param(param *syntax.Fie
  }
  
  func (p *noder) exprList(expr syntax.Expr) []ir.Node {
-       if list, ok := expr.(*syntax.ListExpr); ok {
-               return p.exprs(list.ElemList)
+       switch expr := expr.(type) {
+       case nil:
+               return nil
+       case *syntax.ListExpr:
+               return p.exprs(expr.ElemList)
+       default:
+               return []ir.Node{p.expr(expr)}
        }
-       return []ir.Node{p.expr(expr)}
  }
  
  func (p *noder) exprs(exprs []syntax.Expr) []ir.Node {
@@@ -775,17 -642,14 +775,14 @@@ func (p *noder) expr(expr syntax.Expr) 
        case *syntax.Name:
                return p.mkname(expr)
        case *syntax.BasicLit:
-               n := ir.NewLiteral(p.basicLit(expr))
+               n := ir.NewBasicLit(p.pos(expr), p.basicLit(expr))
                if expr.Kind == syntax.RuneLit {
                        n.SetType(types.UntypedRune)
                }
                n.SetDiag(expr.Bad) // avoid follow-on errors if there was a syntax error
                return n
        case *syntax.CompositeLit:
-               n := ir.NewCompLitExpr(p.pos(expr), ir.OCOMPLIT, nil, nil)
-               if expr.Type != nil {
-                       n.Ntype = ir.Node(p.expr(expr.Type)).(ir.Ntype)
-               }
+               n := ir.NewCompLitExpr(p.pos(expr), ir.OCOMPLIT, p.typeExpr(expr.Type), nil)
                l := p.exprs(expr.ElemList)
                for i, e := range l {
                        l[i] = p.wrapname(expr.ElemList[i], e)
                if expr.Full {
                        op = ir.OSLICE3
                }
-               n := ir.NewSliceExpr(p.pos(expr), op, p.expr(expr.X))
+               x := p.expr(expr.X)
                var index [3]ir.Node
-               for i, x := range &expr.Index {
-                       if x != nil {
-                               index[i] = p.expr(x)
+               for i, n := range &expr.Index {
+                       if n != nil {
+                               index[i] = p.expr(n)
                        }
                }
-               n.SetSliceBounds(index[0], index[1], index[2])
-               return n
+               return ir.NewSliceExpr(p.pos(expr), op, x, index[0], index[1], index[2])
        case *syntax.AssertExpr:
-               return ir.NewTypeAssertExpr(p.pos(expr), p.expr(expr.X), p.typeExpr(expr.Type).(ir.Ntype))
+               return ir.NewTypeAssertExpr(p.pos(expr), p.expr(expr.X), p.typeExpr(expr.Type))
        case *syntax.Operation:
                if expr.Op == syntax.Add && expr.Y != nil {
                        return p.sum(expr)
                }
                return ir.NewBinaryExpr(pos, op, x, y)
        case *syntax.CallExpr:
-               n := ir.NewCallExpr(p.pos(expr), ir.OCALL, p.expr(expr.Fun), nil)
-               n.Args.Set(p.exprs(expr.ArgList))
+               n := ir.NewCallExpr(p.pos(expr), ir.OCALL, p.expr(expr.Fun), p.exprs(expr.ArgList))
                n.IsDDD = expr.HasDots
                return n
  
@@@ -1120,7 -982,7 +1115,7 @@@ func (p *noder) stmt(stmt syntax.Stmt) 
  func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
        p.setlineno(stmt)
        switch stmt := stmt.(type) {
-       case *syntax.EmptyStmt:
+       case nil, *syntax.EmptyStmt:
                return nil
        case *syntax.LabeledStmt:
                return p.labeledStmt(stmt, fallOK)
                }
                return ir.NewGoDeferStmt(p.pos(stmt), op, p.expr(stmt.Call))
        case *syntax.ReturnStmt:
-               var results []ir.Node
-               if stmt.Results != nil {
-                       results = p.exprList(stmt.Results)
-               }
-               n := ir.NewReturnStmt(p.pos(stmt), nil)
-               n.Results.Set(results)
+               n := ir.NewReturnStmt(p.pos(stmt), p.exprList(stmt.Results))
                if len(n.Results) == 0 && ir.CurFunc != nil {
                        for _, ln := range ir.CurFunc.Dcl {
                                if ln.Class_ == ir.PPARAM {
@@@ -1292,14 -1149,11 +1282,11 @@@ func (p *noder) blockStmt(stmt *syntax.
  
  func (p *noder) ifStmt(stmt *syntax.IfStmt) ir.Node {
        p.openScope(stmt.Pos())
-       n := ir.NewIfStmt(p.pos(stmt), nil, nil, nil)
-       if stmt.Init != nil {
-               *n.PtrInit() = []ir.Node{p.stmt(stmt.Init)}
+       init := p.stmt(stmt.Init)
+       n := ir.NewIfStmt(p.pos(stmt), p.expr(stmt.Cond), p.blockStmt(stmt.Then), nil)
+       if init != nil {
+               *n.PtrInit() = []ir.Node{init}
        }
-       if stmt.Cond != nil {
-               n.Cond = p.expr(stmt.Cond)
-       }
-       n.Body.Set(p.blockStmt(stmt.Then))
        if stmt.Else != nil {
                e := p.stmt(stmt.Else)
                if e.Op() == ir.OBLOCK {
@@@ -1320,53 -1174,46 +1307,46 @@@ func (p *noder) forStmt(stmt *syntax.Fo
                        panic("unexpected RangeClause")
                }
  
-               n := ir.NewRangeStmt(p.pos(r), nil, p.expr(r.X), nil)
+               n := ir.NewRangeStmt(p.pos(r), nil, nil, p.expr(r.X), nil)
                if r.Lhs != nil {
                        n.Def = r.Def
-                       n.Vars.Set(p.assignList(r.Lhs, n, n.Def))
+                       lhs := p.assignList(r.Lhs, n, n.Def)
+                       n.Key = lhs[0]
+                       if len(lhs) > 1 {
+                               n.Value = lhs[1]
+                       }
                }
                n.Body.Set(p.blockStmt(stmt.Body))
                p.closeAnotherScope()
                return n
        }
  
-       n := ir.NewForStmt(p.pos(stmt), nil, nil, nil, nil)
-       if stmt.Init != nil {
-               *n.PtrInit() = []ir.Node{p.stmt(stmt.Init)}
-       }
-       if stmt.Cond != nil {
-               n.Cond = p.expr(stmt.Cond)
-       }
-       if stmt.Post != nil {
-               n.Post = p.stmt(stmt.Post)
-       }
-       n.Body.Set(p.blockStmt(stmt.Body))
+       n := ir.NewForStmt(p.pos(stmt), p.stmt(stmt.Init), p.expr(stmt.Cond), p.stmt(stmt.Post), p.blockStmt(stmt.Body))
        p.closeAnotherScope()
        return n
  }
  
  func (p *noder) switchStmt(stmt *syntax.SwitchStmt) ir.Node {
        p.openScope(stmt.Pos())
-       n := ir.NewSwitchStmt(p.pos(stmt), nil, nil)
-       if stmt.Init != nil {
-               *n.PtrInit() = []ir.Node{p.stmt(stmt.Init)}
-       }
-       if stmt.Tag != nil {
-               n.Tag = p.expr(stmt.Tag)
+       init := p.stmt(stmt.Init)
+       n := ir.NewSwitchStmt(p.pos(stmt), p.expr(stmt.Tag), nil)
+       if init != nil {
+               *n.PtrInit() = []ir.Node{init}
        }
  
        var tswitch *ir.TypeSwitchGuard
        if l := n.Tag; l != nil && l.Op() == ir.OTYPESW {
                tswitch = l.(*ir.TypeSwitchGuard)
        }
-       n.Cases.Set(p.caseClauses(stmt.Body, tswitch, stmt.Rbrace))
+       n.Cases = p.caseClauses(stmt.Body, tswitch, stmt.Rbrace)
  
        p.closeScope(stmt.Rbrace)
        return n
  }
  
- func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []ir.Node {
-       nodes := make([]ir.Node, 0, len(clauses))
+ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []*ir.CaseClause {
+       nodes := make([]*ir.CaseClause, 0, len(clauses))
        for i, clause := range clauses {
                p.setlineno(clause)
                if i > 0 {
                }
                p.openScope(clause.Pos())
  
-               n := ir.NewCaseStmt(p.pos(clause), nil, nil)
-               if clause.Cases != nil {
-                       n.List.Set(p.exprList(clause.Cases))
-               }
+               n := ir.NewCaseStmt(p.pos(clause), p.exprList(clause.Cases), nil)
                if tswitch != nil && tswitch.Tag != nil {
                        nn := typecheck.NewName(tswitch.Tag.Sym())
                        typecheck.Declare(nn, typecheck.DeclContext)
-                       n.Vars = []ir.Node{nn}
+                       n.Var = nn
                        // keep track of the instances for reporting unused
                        nn.Defn = tswitch
                }
  }
  
  func (p *noder) selectStmt(stmt *syntax.SelectStmt) ir.Node {
-       n := ir.NewSelectStmt(p.pos(stmt), nil)
-       n.Cases.Set(p.commClauses(stmt.Body, stmt.Rbrace))
-       return n
+       return ir.NewSelectStmt(p.pos(stmt), p.commClauses(stmt.Body, stmt.Rbrace))
  }
  
- func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []ir.Node {
-       nodes := make([]ir.Node, 0, len(clauses))
+ func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*ir.CommClause {
+       nodes := make([]*ir.CommClause, len(clauses))
        for i, clause := range clauses {
                p.setlineno(clause)
                if i > 0 {
                }
                p.openScope(clause.Pos())
  
-               n := ir.NewCaseStmt(p.pos(clause), nil, nil)
-               if clause.Comm != nil {
-                       n.List = []ir.Node{p.stmt(clause.Comm)}
-               }
-               n.Body.Set(p.stmts(clause.Body))
-               nodes = append(nodes, n)
+               nodes[i] = ir.NewCommStmt(p.pos(clause), p.stmt(clause.Comm), p.stmts(clause.Body))
        }
        if len(clauses) > 0 {
                p.closeScope(rbrace)
@@@ -2001,7 -1838,6 +1971,6 @@@ func oldname(s *types.Sym) ir.Node 
                        c = typecheck.NewName(s)
                        c.Class_ = ir.PAUTOHEAP
                        c.SetIsClosureVar(true)
-                       c.SetIsDDD(n.IsDDD())
                        c.Defn = n
  
                        // Link into list of active closure variables.
index 82771457698599474aafb55fff97fa0e8d22a870,b9328a68132a132d6a9abcea51f798e365ac8dc9..2fc0eb2a58ea17a7987ee0bf478c8097ab735731
@@@ -6,9 -6,9 +6,9 @@@
  
  package main
  
 -var a = twoResults()       // ERROR "assignment mismatch: 1 variable but twoResults returns 2 values"
 -var b, c, d = twoResults() // ERROR "assignment mismatch: 3 variables but twoResults returns 2 values"
 -var e, f = oneResult()     // ERROR "assignment mismatch: 2 variables but oneResult returns 1 value"
 +var a = twoResults()       // ERROR "assignment mismatch: 1 variable but twoResults returns 2 values|2\-valued"
 +var b, c, d = twoResults() // ERROR "assignment mismatch: 3 variables but twoResults returns 2 values|cannot initialize"
- var e, f = oneResult()     // ERROR "assignment mismatch: 2 variables but oneResult returns 1 values|cannot initialize"
++var e, f = oneResult()     // ERROR "assignment mismatch: 2 variables but oneResult returns 1 value|cannot initialize"
  
  func twoResults() (int, int) {
        return 1, 2
index e2aec63a52931debc54d70618b52687f83f61d41,a8f6202329e860fdd5a32544016a8407d04794ba..3e4b0324a3765404a0dfd9daf10020829dee669d
@@@ -7,9 -7,8 +7,9 @@@
  package main
  
  func main() {
-       var a, b = 1    // ERROR "assignment mismatch: 2 variables but 1 values|wrong number of initializations|cannot initialize"
-       _ = 1, 2        // ERROR "assignment mismatch: 1 variables but 2 values|number of variables does not match|cannot assign"
-       c, d := 1       // ERROR "assignment mismatch: 2 variables but 1 values|wrong number of initializations|cannot initialize"
 -      var a, b = 1    // ERROR "assignment mismatch: 2 variables but 1 value|wrong number of initializations"
 -      _ = 1, 2        // ERROR "assignment mismatch: 1 variable but 2 values|number of variables does not match"
 -      c, d := 1       // ERROR "assignment mismatch: 2 variables but 1 value|wrong number of initializations"
 -      e, f := 1, 2, 3 // ERROR "assignment mismatch: 2 variables but 3 values|wrong number of initializations"
++      var a, b = 1    // ERROR "assignment mismatch: 2 variables but 1 value|wrong number of initializations|cannot initialize"
++      _ = 1, 2        // ERROR "assignment mismatch: 1 variable but 2 values|number of variables does not match|cannot assign"
++      c, d := 1       // ERROR "assignment mismatch: 2 variables but 1 value|wrong number of initializations|cannot initialize"
 +      e, f := 1, 2, 3 // ERROR "assignment mismatch: 2 variables but 3 values|wrong number of initializations|cannot initialize"
 +      _, _, _, _ = c, d, e, f
  }
diff --combined test/used.go
index a3f0e1270befedfe73ce5bfdd78f52ea5ba50bde,76f3fc91cccd2490fd512831dc31eb620e742c13..5bdc5a731886913c393b42177ffc17964fbc4579
@@@ -42,103 -42,103 +42,104 @@@ var m map[int]in
  
  func _() {
        // Note: if the next line changes to x, the error silences the x+x etc below!
 -      x1 // ERROR "x1 evaluated but not used"
 +      x1 // ERROR "x1 .* not used"
  
 -      nil                    // ERROR "nil evaluated but not used"
 -      C                      // ERROR  "C evaluated but not used"
 -      1                      // ERROR "1 evaluated but not used"
 -      x + x                  // ERROR "x \+ x evaluated but not used"
 -      x - x                  // ERROR "x - x evaluated but not used"
 -      x | x                  // ERROR "x \| x evaluated but not used"
 -      "a" + s                // ERROR ".a. \+ s evaluated but not used"
 -      &x                     // ERROR "&x evaluated but not used"
 -      b && b                 // ERROR "b && b evaluated but not used"
 -      append(slice, 1)       // ERROR "append\(slice, 1\) evaluated but not used"
 -      string(bytes)          // ERROR "string\(bytes\) evaluated but not used"
 -      string(runes)          // ERROR "string\(runes\) evaluated but not used"
 +      nil                    // ERROR "nil .* not used"
 +      C                      // ERROR  "C .* not used"
 +      1                      // ERROR "1 .* not used"
 +      x + x                  // ERROR "x \+ x .* not used"
 +      x - x                  // ERROR "x - x .* not used"
 +      x | x                  // ERROR "x \| x .* not used"
 +      "a" + s                // ERROR ".a. \+ s .* not used"
 +      &x                     // ERROR "&x .* not used"
 +      b && b                 // ERROR "b && b .* not used"
 +      append(slice, 1)       // ERROR "append\(slice, 1\) .* not used"
 +      string(bytes)          // ERROR "string\(bytes\) .* not used"
 +      string(runes)          // ERROR "string\(runes\) .* not used"
        f0()                   // ok
        f1()                   // ok
        f2()                   // ok
 -      _ = f0()               // ERROR "f0\(\) used as value"
 +      _ = f0()               // ERROR "f0\(\) .*used as value"
        _ = f1()               // ok
        _, _ = f2()            // ok
 -      _ = f2()               // ERROR "assignment mismatch: 1 variable but f2 returns 2 values"
 -      _ = f1(), 0            // ERROR "assignment mismatch: 1 variable but 2 values"
 -      T.M0                   // ERROR "T.M0 evaluated but not used"
 -      t.M0                   // ERROR "t.M0 evaluated but not used"
 -      cap                    // ERROR "use of builtin cap not in function call"
 -      cap(slice)             // ERROR "cap\(slice\) evaluated but not used"
 +      _ = f2()               // ERROR "assignment mismatch: 1 variable but f2 returns 2 values|cannot assign"
++      _ = f1(), 0            // ERROR "assignment mismatch: 1 variable but 2 values|cannot assign"
 +      T.M0                   // ERROR "T.M0 .* not used"
 +      t.M0                   // ERROR "t.M0 .* not used"
 +      cap                    // ERROR "use of builtin cap not in function call|must be called"
 +      cap(slice)             // ERROR "cap\(slice\) .* not used"
        close(c)               // ok
 -      _ = close(c)           // ERROR "close\(c\) used as value"
 -      func() {}              // ERROR "func literal evaluated but not used"
 +      _ = close(c)           // ERROR "close\(c\) .*used as value"
 +      func() {}              // ERROR "func literal .* not used|is not used"
        X{}                    // ERROR "undefined: X"
 -      map[string]int{}       // ERROR "map\[string\]int{} evaluated but not used"
 -      struct{}{}             // ERROR "struct ?{}{} evaluated but not used"
 -      [1]int{}               // ERROR "\[1\]int{} evaluated but not used"
 -      []int{}                // ERROR "\[\]int{} evaluated but not used"
 -      &struct{}{}            // ERROR "&struct ?{}{} evaluated but not used"
 -      float32(x)             // ERROR "float32\(x\) evaluated but not used"
 -      I(t)                   // ERROR "I\(t\) evaluated but not used"
 -      int(x)                 // ERROR "int\(x\) evaluated but not used"
 +      map[string]int{}       // ERROR "map\[string\]int{} .* not used"
 +      struct{}{}             // ERROR "struct ?{}{} .* not used"
 +      [1]int{}               // ERROR "\[1\]int{} .* not used"
 +      []int{}                // ERROR "\[\]int{} .* not used"
 +      &struct{}{}            // ERROR "&struct ?{}{} .* not used"
 +      float32(x)             // ERROR "float32\(x\) .* not used"
 +      I(t)                   // ERROR "I\(t\) .* not used"
 +      int(x)                 // ERROR "int\(x\) .* not used"
        copy(slice, slice)     // ok
        _ = copy(slice, slice) // ok
        delete(m, 1)           // ok
 -      _ = delete(m, 1)       // ERROR "delete\(m, 1\) used as value"
 -      t.X                    // ERROR "t.X evaluated but not used"
 -      tp.X                   // ERROR "tp.X evaluated but not used"
 -      t.M                    // ERROR "t.M evaluated but not used"
 -      I.M                    // ERROR "I.M evaluated but not used"
 -      i.(T)                  // ERROR "i.\(T\) evaluated but not used"
 -      x == x                 // ERROR "x == x evaluated but not used"
 -      x != x                 // ERROR "x != x evaluated but not used"
 -      x != x                 // ERROR "x != x evaluated but not used"
 -      x < x                  // ERROR "x < x evaluated but not used"
 -      x >= x                 // ERROR "x >= x evaluated but not used"
 -      x > x                  // ERROR "x > x evaluated but not used"
 -      *tp                    // ERROR "\*tp evaluated but not used"
 -      slice[0]               // ERROR "slice\[0\] evaluated but not used"
 -      m[1]                   // ERROR "m\[1\] evaluated but not used"
 -      len(slice)             // ERROR "len\(slice\) evaluated but not used"
 -      make(chan int)         // ERROR "make\(chan int\) evaluated but not used"
 -      make(map[int]int)      // ERROR "make\(map\[int\]int\) evaluated but not used"
 -      make([]int, 1)         // ERROR "make\(\[\]int, 1\) evaluated but not used"
 -      x * x                  // ERROR "x \* x evaluated but not used"
 -      x / x                  // ERROR "x / x evaluated but not used"
 -      x % x                  // ERROR "x % x evaluated but not used"
 -      x << x                 // ERROR "x << x evaluated but not used"
 -      x >> x                 // ERROR "x >> x evaluated but not used"
 -      x & x                  // ERROR "x & x evaluated but not used"
 -      x &^ x                 // ERROR "x &\^ x evaluated but not used"
 -      new(int)               // ERROR "new\(int\) evaluated but not used"
 -      !b                     // ERROR "!b evaluated but not used"
 -      ^x                     // ERROR "\^x evaluated but not used"
 -      +x                     // ERROR "\+x evaluated but not used"
 -      -x                     // ERROR "-x evaluated but not used"
 -      b || b                 // ERROR "b \|\| b evaluated but not used"
 +      _ = delete(m, 1)       // ERROR "delete\(m, 1\) .*used as value"
 +      t.X                    // ERROR "t.X .* not used"
 +      tp.X                   // ERROR "tp.X .* not used"
 +      t.M                    // ERROR "t.M .* not used"
 +      I.M                    // ERROR "I.M .* not used"
 +      i.(T)                  // ERROR "i.\(T\) .* not used"
 +      x == x                 // ERROR "x == x .* not used"
 +      x != x                 // ERROR "x != x .* not used"
 +      x != x                 // ERROR "x != x .* not used"
 +      x < x                  // ERROR "x < x .* not used"
 +      x >= x                 // ERROR "x >= x .* not used"
 +      x > x                  // ERROR "x > x .* not used"
 +      *tp                    // ERROR "\*tp .* not used"
 +      slice[0]               // ERROR "slice\[0\] .* not used"
 +      m[1]                   // ERROR "m\[1\] .* not used"
 +      len(slice)             // ERROR "len\(slice\) .* not used"
 +      make(chan int)         // ERROR "make\(chan int\) .* not used"
 +      make(map[int]int)      // ERROR "make\(map\[int\]int\) .* not used"
 +      make([]int, 1)         // ERROR "make\(\[\]int, 1\) .* not used"
 +      x * x                  // ERROR "x \* x .* not used"
 +      x / x                  // ERROR "x / x .* not used"
 +      x % x                  // ERROR "x % x .* not used"
 +      x << x                 // ERROR "x << x .* not used"
 +      x >> x                 // ERROR "x >> x .* not used"
 +      x & x                  // ERROR "x & x .* not used"
 +      x &^ x                 // ERROR "x &\^ x .* not used"
 +      new(int)               // ERROR "new\(int\) .* not used"
 +      !b                     // ERROR "!b .* not used"
 +      ^x                     // ERROR "\^x .* not used"
 +      +x                     // ERROR "\+x .* not used"
 +      -x                     // ERROR "-x .* not used"
 +      b || b                 // ERROR "b \|\| b .* not used"
        panic(1)               // ok
 -      _ = panic(1)           // ERROR "panic\(1\) used as value"
 +      _ = panic(1)           // ERROR "panic\(1\) .*used as value"
        print(1)               // ok
 -      _ = print(1)           // ERROR "print\(1\) used as value"
 +      _ = print(1)           // ERROR "print\(1\) .*used as value"
        println(1)             // ok
 -      _ = println(1)         // ERROR "println\(1\) used as value"
 +      _ = println(1)         // ERROR "println\(1\) .*used as value"
        c <- 1                 // ok
 -      slice[1:1]             // ERROR "slice\[1:1\] evaluated but not used"
 -      array[1:1]             // ERROR "array\[1:1\] evaluated but not used"
 -      s[1:1]                 // ERROR "s\[1:1\] evaluated but not used"
 -      slice[1:1:1]           // ERROR "slice\[1:1:1\] evaluated but not used"
 -      array[1:1:1]           // ERROR "array\[1:1:1\] evaluated but not used"
 +      slice[1:1]             // ERROR "slice\[1:1\] .* not used"
 +      array[1:1]             // ERROR "array\[1:1\] .* not used"
 +      s[1:1]                 // ERROR "s\[1:1\] .* not used"
 +      slice[1:1:1]           // ERROR "slice\[1:1:1\] .* not used"
 +      array[1:1:1]           // ERROR "array\[1:1:1\] .* not used"
        recover()              // ok
        <-c                    // ok
 -      string(r)              // ERROR "string\(r\) evaluated but not used"
 -      iota                   // ERROR "undefined: iota"
 -      real(cp)               // ERROR "real\(cp\) evaluated but not used"
 -      imag(cp)               // ERROR "imag\(cp\) evaluated but not used"
 -      complex(1, 2)          // ERROR "complex\(1, 2\) evaluated but not used"
 -      unsafe.Alignof(t.X)    // ERROR "unsafe.Alignof\(t.X\) evaluated but not used"
 -      unsafe.Offsetof(t.X)   // ERROR "unsafe.Offsetof\(t.X\) evaluated but not used"
 -      unsafe.Sizeof(t)       // ERROR "unsafe.Sizeof\(t\) evaluated but not used"
 -      _ = int                // ERROR "type int is not an expression"
 -      (x)                    // ERROR "x evaluated but not used"
 -      _ = new(x2)            // ERROR "x2 is not a type"
 -      _ = new(1 + 1)         // ERROR "1 \+ 1 is not a type"
 +      string(r)              // ERROR "string\(r\) .* not used"
 +      iota                   // ERROR "undefined: iota|cannot use iota"
 +      real(cp)               // ERROR "real\(cp\) .* not used"
 +      imag(cp)               // ERROR "imag\(cp\) .* not used"
 +      complex(1, 2)          // ERROR "complex\(1, 2\) .* not used"
 +      unsafe.Alignof(t.X)    // ERROR "unsafe.Alignof\(t.X\) .* not used"
 +      unsafe.Offsetof(t.X)   // ERROR "unsafe.Offsetof\(t.X\) .* not used"
 +      unsafe.Sizeof(t)       // ERROR "unsafe.Sizeof\(t\) .* not used"
 +      _ = int                // ERROR "type int is not an expression|not an expression"
 +      (x)                    // ERROR "x .* not used|not used"
 +      _ = new(x2)            // ERROR "x2 is not a type|not a type"
 +      // Disabled due to issue #43125.
 +      // _ = new(1 + 1)         // DISABLED "1 \+ 1 is not a type"
  }