]> Cypherpunks.ru repositories - gostls13.git/commitdiff
all: merge dev.typealias into master
authorRuss Cox <rsc@golang.org>
Tue, 31 Jan 2017 17:57:12 +0000 (12:57 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 31 Jan 2017 18:01:31 +0000 (13:01 -0500)
For #18130.

f8b4123613 [dev.typealias] spec: use term 'embedded field' rather than 'anonymous field'
9ecc3ee252 [dev.typealias] cmd/compile: avoid false positive cycles from type aliases
49b7af8a30 [dev.typealias] reflect: add test for type aliases
9bbb07ddec [dev.typealias] cmd/compile, reflect: fix struct field names for embedded byte, rune
43c7094386 [dev.typealias] reflect: fix StructOf use of StructField to match StructField docs
9657e0b077 [dev.typealias] cmd/doc: update for type alias
de2e5459ae [dev.typealias] cmd/compile: declare methods after resolving receiver type
9259f3073a [dev.typealias] test: match gccgo error messages on alias2.go
5d92916770 [dev.typealias] cmd/compile: change Func.Shortname to *Sym
a7c884efc1 [dev.typealias] go/internal/gccgoimporter: support for type aliases
5802cfd900 [dev.typealias] cmd/compile: export/import test cases for type aliases
d7cabd40dd [dev.typealias] go/types: clarified doc string
cc2dcce3d7 [dev.typealias] cmd/compile: a few better comments related to alias types
5c160b28ba [dev.typealias] cmd/compile: improved error message for cyles involving type aliases
b2386dffa1 [dev.typealias] cmd/compile: type-check type alias declarations
ac8421f9a5 [dev.typealias] cmd/compile: various minor cleanups
f011e0c6c3 [dev.typealias] cmd/compile, go/types, go/importer: various alias related fixes
49de5f0351 [dev.typealias] cmd/compile, go/importer: define export format and implement importing of type aliases
5ceec42dc0 [dev.typealias] go/types: export TypeName.IsAlias so clients can use it
aa1f0681bc [dev.typealias] go/types: improved Object printing
c80748e389 [dev.typealias] go/types: remove some more vestiges of prior alias implementation
80d8b69e95 [dev.typealias] go/types: implement type aliases
a917097b5e [dev.typealias] go/build: add go1.9 build tag
3e11940437 [dev.typealias] cmd/compile: recognize type aliases but complain for now (not yet supported)
e0a05c274a [dev.typealias] cmd/gofmt: added test cases for alias type declarations
2e5116bd99 [dev.typealias] go/ast, go/parser, go/printer, go/types: initial type alias support

Change-Id: Ia65f2e011fd7195f18e1dce67d4d49b80a261203

1  2 
src/cmd/compile/internal/gc/bimport.go
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/noder.go
src/go/printer/nodes.go
src/reflect/all_test.go
src/reflect/value.go

index 94c1184138fc311349f504450e6487f909e2380a,1ee9e76737e51644514526fadfa7a35be38bc0a1..752f65be425ec55bea71d7513538f7e1e640a348
@@@ -86,10 -86,10 +86,10 @@@ func Import(in *bufio.Reader) 
  
        // read version specific flags - extend as necessary
        switch p.version {
-       // case 4:
+       // case 5:
        //      ...
        //      fallthrough
-       case 3, 2, 1:
+       case 4, 3, 2, 1:
                p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
                p.trackAllTypes = p.bool()
                p.posInfoFormat = p.bool()
        typecheckok = tcok
        resumecheckwidth()
  
 -      testdclstack() // debugging only
 +      if debug_dclstack != 0 {
 +              testdclstack()
 +      }
  }
  
  func formatErrorf(format string, args ...interface{}) {
@@@ -317,6 -315,12 +317,12 @@@ func (p *importer) obj(tag int) 
                val := p.value(typ)
                importconst(sym, idealType(typ), nodlit(val))
  
+       case aliasTag:
+               p.pos()
+               sym := p.qualifiedName()
+               typ := p.typ()
+               importalias(sym, typ)
        case typeTag:
                p.typ()
  
                        }
                }
  
-       case aliasTag:
-               p.pos()
-               alias := importpkg.Lookup(p.string())
-               orig := p.qualifiedName()
-               // Although the protocol allows the alias to precede the original,
-               // this never happens in files produced by gc.
-               alias.Flags |= SymAlias
-               alias.Def = orig.Def
-               importsym(alias, orig.Def.Op)
        default:
                formatErrorf("unexpected object (tag = %d)", tag)
        }
@@@ -473,14 -466,7 +468,7 @@@ func (p *importer) typ() *Type 
                        result := p.paramList()
                        nointerface := p.bool()
  
-                       base := recv[0].Type
-                       star := false
-                       if base.IsPtr() {
-                               base = base.Elem()
-                               star = true
-                       }
-                       n := methodname0(sym, star, base.Sym)
+                       n := newfuncname(methodname(sym, recv[0].Type))
                        n.Type = functypefield(recv[0], params, result)
                        checkwidth(n.Type)
                        addmethod(sym, n.Type, false, nointerface)
@@@ -583,19 -569,22 +571,22 @@@ func (p *importer) fieldList() (fields 
  
  func (p *importer) field() *Field {
        p.pos()
-       sym := p.fieldName()
+       sym, alias := p.fieldName()
        typ := p.typ()
        note := p.string()
  
        f := newField()
        if sym.Name == "" {
-               // anonymous field - typ must be T or *T and T must be a type name
+               // anonymous field: typ must be T or *T and T must be a type name
                s := typ.Sym
                if s == nil && typ.IsPtr() {
                        s = typ.Elem().Sym // deref
                }
                sym = sym.Pkg.Lookup(s.Name)
                f.Embedded = 1
+       } else if alias {
+               // anonymous field: we have an explicit name because it's a type alias
+               f.Embedded = 1
        }
  
        f.Sym = sym
@@@ -618,7 -607,7 +609,7 @@@ func (p *importer) methodList() (method
  
  func (p *importer) method() *Field {
        p.pos()
-       sym := p.fieldName()
+       sym := p.methodName()
        params := p.paramList()
        result := p.paramList()
  
        return f
  }
  
- func (p *importer) fieldName() *Sym {
+ func (p *importer) fieldName() (*Sym, bool) {
        name := p.string()
        if p.version == 0 && name == "_" {
-               // version 0 didn't export a package for _ fields
+               // version 0 didn't export a package for _ field names
                // but used the builtin package instead
-               return builtinpkg.Lookup(name)
+               return builtinpkg.Lookup(name), false
        }
        pkg := localpkg
-       if name != "" && !exportname(name) {
-               if name == "?" {
-                       name = ""
+       alias := false
+       switch name {
+       case "":
+               // 1) field name matches base type name and is exported: nothing to do
+       case "?":
+               // 2) field name matches base type name and is not exported: need package
+               name = ""
+               pkg = p.pkg()
+       case "@":
+               // 3) field name doesn't match base type name (alias name): need name and possibly package
+               name = p.string()
+               alias = true
+               fallthrough
+       default:
+               if !exportname(name) {
+                       pkg = p.pkg()
                }
+       }
+       return pkg.Lookup(name), alias
+ }
+ func (p *importer) methodName() *Sym {
+       name := p.string()
+       if p.version == 0 && name == "_" {
+               // version 0 didn't export a package for _ method names
+               // but used the builtin package instead
+               return builtinpkg.Lookup(name)
+       }
+       pkg := localpkg
+       if !exportname(name) {
                pkg = p.pkg()
        }
        return pkg.Lookup(name)
index 1690944b3df430c6cdf4f2d0d844f67dfed5ed87,11f0547d5e8082bfa0d0e189d1aad945f6fbf39e..f5fb72bca539c3fa2a12ca017a07a6408aa7550e
@@@ -30,12 -30,11 +30,12 @@@ var 
  )
  
  var (
 -      Debug_append  int
 -      Debug_closure int
 -      Debug_panic   int
 -      Debug_slice   int
 -      Debug_wb      int
 +      Debug_append   int
 +      Debug_closure  int
 +      debug_dclstack int
 +      Debug_panic    int
 +      Debug_slice    int
 +      Debug_wb       int
  )
  
  // Debug arguments.
@@@ -49,7 -48,6 +49,7 @@@ var debugtab = []struct 
        {"append", &Debug_append},         // print information about append compilation
        {"closure", &Debug_closure},       // print information about closure compilation
        {"disablenil", &disable_checknil}, // disable nil checks
 +      {"dclstack", &debug_dclstack},     // run internal dclstack checks
        {"gcprog", &Debug_gcprog},         // print dump of GC programs
        {"nil", &Debug_checknil},          // print information about nil checks
        {"panic", &Debug_panic},           // do not hide any compiler panic
@@@ -327,6 -325,7 +327,6 @@@ func Main() 
        timings.Stop()
        timings.AddEvent(int64(lexlineno-lexlineno0), "lines")
  
 -      testdclstack()
        mkpackage(localpkg.Name) // final import not used checks
        finishUniverse()
  
        // Phase 1: const, type, and names and types of funcs.
        //   This will gather all the information about types
        //   and methods but doesn't depend on any of it.
+       //   We also defer type alias declarations until phase 2
+       //   to avoid cycles like #18640.
        defercheckwidth()
  
        // Don't use range--typecheck can add closures to xtop.
        timings.Start("fe", "typecheck", "top1")
        for i := 0; i < len(xtop); i++ {
-               if xtop[i].Op != ODCL && xtop[i].Op != OAS && xtop[i].Op != OAS2 {
-                       xtop[i] = typecheck(xtop[i], Etop)
+               n := xtop[i]
+               if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) {
+                       xtop[i] = typecheck(n, Etop)
                }
        }
  
        // Don't use range--typecheck can add closures to xtop.
        timings.Start("fe", "typecheck", "top2")
        for i := 0; i < len(xtop); i++ {
-               if xtop[i].Op == ODCL || xtop[i].Op == OAS || xtop[i].Op == OAS2 {
-                       xtop[i] = typecheck(xtop[i], Etop)
+               n := xtop[i]
+               if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias {
+                       xtop[i] = typecheck(n, Etop)
                }
        }
        resumecheckwidth()
        timings.Start("fe", "typecheck", "func")
        var fcount int64
        for i := 0; i < len(xtop); i++ {
-               if xtop[i].Op == ODCLFUNC || xtop[i].Op == OCLOSURE {
-                       Curfn = xtop[i]
+               n := xtop[i]
+               if op := n.Op; op == ODCLFUNC || op == OCLOSURE {
+                       Curfn = n
                        decldepth = 1
                        saveerrors()
                        typecheckslice(Curfn.Nbody.Slice(), Etop)
        timings.Start("be", "compilefuncs")
        fcount = 0
        for i := 0; i < len(xtop); i++ {
-               if xtop[i].Op == ODCLFUNC {
-                       funccompile(xtop[i])
+               n := xtop[i]
+               if n.Op == ODCLFUNC {
+                       funccompile(n)
                        fcount++
                }
        }
@@@ -924,7 -929,7 +930,7 @@@ func mkpackage(pkgname string) 
                                continue
                        }
  
-                       if s.Def.Sym != s && s.Flags&SymAlias == 0 {
+                       if s.isAlias() {
                                // throw away top-level name left over
                                // from previous import . "x"
                                if s.Def.Name != nil && s.Def.Name.Pack != nil && !s.Def.Name.Pack.Used && nsyntaxerrors == 0 {
index ce18297ac3d31006ca50a85589a8bb8064aec832,1d69151cc41dd2be51a70c01b9cf37820353774f..9dbe769fa7c8e370982501c0be6fd10778c1a840
@@@ -34,7 -34,6 +34,7 @@@ func parseFile(filename string) 
        }
  
        if nsyntaxerrors == 0 {
 +              // Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
                testdclstack()
        }
  }
@@@ -154,11 -153,7 +154,7 @@@ func (p *noder) importDecl(imp *syntax.
  
  func (p *noder) varDecl(decl *syntax.VarDecl) []*Node {
        names := p.declNames(decl.NameList)
-       var typ *Node
-       if decl.Type != nil {
-               typ = p.typeExpr(decl.Type)
-       }
+       typ := p.typeExprOrNil(decl.Type)
  
        var exprs []*Node
        if decl.Values != nil {
  
  func (p *noder) constDecl(decl *syntax.ConstDecl) []*Node {
        names := p.declNames(decl.NameList)
-       var typ *Node
-       if decl.Type != nil {
-               typ = p.typeExpr(decl.Type)
-       }
+       typ := p.typeExprOrNil(decl.Type)
  
        var exprs []*Node
        if decl.Values != nil {
  
  func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
        name := typedcl0(p.name(decl.Name))
-       name.Name.Param.Pragma = Pragma(decl.Pragma)
  
-       var typ *Node
-       if decl.Type != nil {
-               typ = p.typeExpr(decl.Type)
-       }
+       // decl.Type may be nil but in that case we got a syntax error during parsing
+       typ := p.typeExprOrNil(decl.Type)
  
-       return typedcl1(name, typ, true)
+       return typedcl1(name, typ, Pragma(decl.Pragma), decl.Alias)
  }
  
  func (p *noder) declNames(names []*syntax.Name) []*Node {
@@@ -259,19 -247,19 +248,19 @@@ func (p *noder) funcHeader(fun *syntax.
                                yyerror("func main must have no arguments and no return values")
                        }
                }
-               f.Func.Nname = newfuncname(name)
        } else {
-               // Receiver MethodName Signature
-               f.Func.Shortname = newfuncname(name)
-               f.Func.Nname = methodname(f.Func.Shortname, t.Left.Right)
+               f.Func.Shortname = name
+               name = nblank.Sym // filled in by typecheckfunc
        }
  
+       f.Func.Nname = newfuncname(name)
        f.Func.Nname.Name.Defn = f
        f.Func.Nname.Name.Param.Ntype = t // TODO: check if nname already has an ntype
  
-       declare(f.Func.Nname, PFUNC)
+       if fun.Recv == nil {
+               declare(f.Func.Nname, PFUNC)
+       }
        funchdr(f)
        return f
  }
@@@ -467,6 -455,13 +456,13 @@@ func (p *noder) typeExpr(typ syntax.Exp
        return p.expr(typ)
  }
  
+ func (p *noder) typeExprOrNil(typ syntax.Expr) *Node {
+       if typ != nil {
+               return p.expr(typ)
+       }
+       return nil
+ }
  func (p *noder) chanDir(dir syntax.ChanDir) ChanDir {
        switch dir {
        case 0:
@@@ -1056,7 -1051,6 +1052,7 @@@ func (p *noder) pragma(pos, line int, t
                lookup(f[1]).Linkname = f[2]
  
        case strings.HasPrefix(text, "go:cgo_"):
 +              lineno = p.baseline + int32(line) - 1 // pragcgo may call yyerror
                pragcgobuf += pragcgo(text)
                fallthrough // because of //go:cgo_unsafe_args
        default:
                if i := strings.Index(text, " "); i >= 0 {
                        verb = verb[:i]
                }
 +              lineno = p.baseline + int32(line) - 1 // pragmaValue may call yyerror
                return syntax.Pragma(pragmaValue(verb))
        }
  
diff --combined src/go/printer/nodes.go
index ea432860a8e5ac2b159b48fbb8941182108fec00,5a408cd5710e580419569776f9043e9d0ea1bd93..08b8711c2d67c7cd8a599430ed58c49adf67fd97
@@@ -733,7 -733,7 +733,7 @@@ func (p *printer) expr1(expr ast.Expr, 
  
        case *ast.FuncLit:
                p.expr(x.Type)
 -              p.adjBlock(p.distanceFrom(x.Type.Pos()), blank, x.Body)
 +              p.funcBody(p.distanceFrom(x.Type.Pos()), blank, x.Body)
  
        case *ast.ParenExpr:
                if _, hasParens := x.X.(*ast.ParenExpr); hasParens {
                if x.Type != nil {
                        p.expr1(x.Type, token.HighestPrec, depth)
                }
 +              p.level++
                p.print(x.Lbrace, token.LBRACE)
                p.exprList(x.Lbrace, x.Elts, 1, commaTerm, x.Rbrace)
                // do not insert extra line break following a /*-style comment
                        mode |= noExtraBlank
                }
                p.print(mode, x.Rbrace, token.RBRACE, mode)
 +              p.level--
  
        case *ast.Ellipsis:
                p.print(token.ELLIPSIS)
@@@ -1447,6 -1445,9 +1447,9 @@@ func (p *printer) spec(spec ast.Spec, 
                } else {
                        p.print(vtab)
                }
+               if s.Assign.IsValid() {
+                       p.print(token.ASSIGN, blank)
+               }
                p.expr(s.Type)
                p.setComment(s.Comment)
  
@@@ -1559,23 -1560,18 +1562,23 @@@ func (p *printer) bodySize(b *ast.Block
        return bodySize
  }
  
 -// adjBlock prints an "adjacent" block (e.g., a for-loop or function body) following
 -// a header (e.g., a for-loop control clause or function signature) of given headerSize.
 +// funcBody prints a function body following a function header of given headerSize.
  // If the header's and block's size are "small enough" and the block is "simple enough",
  // the block is printed on the current line, without line breaks, spaced from the header
  // by sep. Otherwise the block's opening "{" is printed on the current line, followed by
  // lines for the block's statements and its closing "}".
  //
 -func (p *printer) adjBlock(headerSize int, sep whiteSpace, b *ast.BlockStmt) {
 +func (p *printer) funcBody(headerSize int, sep whiteSpace, b *ast.BlockStmt) {
        if b == nil {
                return
        }
  
 +      // save/restore composite literal nesting level
 +      defer func(level int) {
 +              p.level = level
 +      }(p.level)
 +      p.level = 0
 +
        const maxSize = 100
        if headerSize+p.bodySize(b, maxSize) <= maxSize {
                p.print(sep, b.Lbrace, token.LBRACE)
@@@ -1620,7 -1616,7 +1623,7 @@@ func (p *printer) funcDecl(d *ast.FuncD
        }
        p.expr(d.Name)
        p.signature(d.Type.Params, d.Type.Results)
 -      p.adjBlock(p.distanceFrom(d.Pos()), vtab, d.Body)
 +      p.funcBody(p.distanceFrom(d.Pos()), vtab, d.Body)
  }
  
  func (p *printer) decl(decl ast.Decl) {
diff --combined src/reflect/all_test.go
index 022350b322f9910f30514b5df973203c8ebaaf59,1fed972eeafcd72c57a5544cfcedd72ab9bd5bff..0be306dc5418e52ff65c57d8fbf072a43210654d
@@@ -26,8 -26,6 +26,8 @@@ import 
        "unsafe"
  )
  
 +var sink interface{}
 +
  func TestBool(t *testing.T) {
        v := ValueOf(true)
        if v.Bool() != true {
@@@ -3691,7 -3689,7 +3691,7 @@@ func checkSameType(t *testing.T, x, y i
  
  func TestArrayOf(t *testing.T) {
        // check construction and use of type not in binary
-       for _, table := range []struct {
+       tests := []struct {
                n          int
                value      func(i int) interface{}
                comparable bool
                        comparable: true,
                        want:       "[{0 0} {1 1} {2 2} {3 3} {4 4} {5 5} {6 6} {7 7} {8 8} {9 9}]",
                },
-       } {
+       }
+       for _, table := range tests {
                at := ArrayOf(table.n, TypeOf(table.value(0)))
                v := New(at).Elem()
                vok := New(at).Elem()
@@@ -4135,50 -4135,58 +4137,58 @@@ func TestStructOfExportRules(t *testing
                f()
        }
  
-       for i, test := range []struct {
+       tests := []struct {
                field     StructField
                mustPanic bool
                exported  bool
        }{
                {
-                       field:     StructField{Name: "", Type: TypeOf(S1{})},
-                       mustPanic: false,
-                       exported:  true,
+                       field:    StructField{Name: "S1", Anonymous: true, Type: TypeOf(S1{})},
+                       exported: true,
                },
                {
-                       field:     StructField{Name: "", Type: TypeOf((*S1)(nil))},
-                       mustPanic: false,
-                       exported:  true,
+                       field:    StructField{Name: "S1", Anonymous: true, Type: TypeOf((*S1)(nil))},
+                       exported: true,
                },
                {
-                       field:     StructField{Name: "", Type: TypeOf(s2{})},
-                       mustPanic: false,
-                       exported:  false,
+                       field:     StructField{Name: "s2", Anonymous: true, Type: TypeOf(s2{})},
+                       mustPanic: true,
                },
                {
-                       field:     StructField{Name: "", Type: TypeOf((*s2)(nil))},
-                       mustPanic: false,
-                       exported:  false,
+                       field:     StructField{Name: "s2", Anonymous: true, Type: TypeOf((*s2)(nil))},
+                       mustPanic: true,
                },
                {
-                       field:     StructField{Name: "", Type: TypeOf(S1{}), PkgPath: "other/pkg"},
+                       field:     StructField{Name: "Name", Type: nil, PkgPath: ""},
                        mustPanic: true,
-                       exported:  true,
                },
                {
-                       field:     StructField{Name: "", Type: TypeOf((*S1)(nil)), PkgPath: "other/pkg"},
+                       field:     StructField{Name: "", Type: TypeOf(S1{}), PkgPath: ""},
+                       mustPanic: true,
+               },
+               {
+                       field:     StructField{Name: "S1", Anonymous: true, Type: TypeOf(S1{}), PkgPath: "other/pkg"},
+                       mustPanic: true,
+               },
+               {
+                       field:     StructField{Name: "S1", Anonymous: true, Type: TypeOf((*S1)(nil)), PkgPath: "other/pkg"},
+                       mustPanic: true,
+               },
+               {
+                       field:     StructField{Name: "s2", Anonymous: true, Type: TypeOf(s2{}), PkgPath: "other/pkg"},
+                       mustPanic: true,
+               },
+               {
+                       field:     StructField{Name: "s2", Anonymous: true, Type: TypeOf((*s2)(nil)), PkgPath: "other/pkg"},
                        mustPanic: true,
-                       exported:  true,
                },
                {
-                       field:     StructField{Name: "", Type: TypeOf(s2{}), PkgPath: "other/pkg"},
+                       field:     StructField{Name: "s2", Type: TypeOf(int(0)), PkgPath: "other/pkg"},
                        mustPanic: true,
-                       exported:  false,
                },
                {
-                       field:     StructField{Name: "", Type: TypeOf((*s2)(nil)), PkgPath: "other/pkg"},
+                       field:     StructField{Name: "s2", Type: TypeOf(int(0)), PkgPath: "other/pkg"},
                        mustPanic: true,
-                       exported:  false,
                },
                {
                        field:     StructField{Name: "S", Type: TypeOf(S1{})},
                        exported:  true,
                },
                {
-                       field:     StructField{Name: "S", Type: TypeOf((*S1)(nil))},
-                       mustPanic: false,
-                       exported:  true,
+                       field:    StructField{Name: "S", Type: TypeOf((*S1)(nil))},
+                       exported: true,
                },
                {
-                       field:     StructField{Name: "S", Type: TypeOf(s2{})},
-                       mustPanic: false,
-                       exported:  true,
+                       field:    StructField{Name: "S", Type: TypeOf(s2{})},
+                       exported: true,
                },
                {
-                       field:     StructField{Name: "S", Type: TypeOf((*s2)(nil))},
-                       mustPanic: false,
-                       exported:  true,
+                       field:    StructField{Name: "S", Type: TypeOf((*s2)(nil))},
+                       exported: true,
                },
                {
                        field:     StructField{Name: "s", Type: TypeOf(S1{})},
                        mustPanic: true,
-                       exported:  false,
                },
                {
                        field:     StructField{Name: "s", Type: TypeOf((*S1)(nil))},
                        mustPanic: true,
-                       exported:  false,
                },
                {
                        field:     StructField{Name: "s", Type: TypeOf(s2{})},
                        mustPanic: true,
-                       exported:  false,
                },
                {
                        field:     StructField{Name: "s", Type: TypeOf((*s2)(nil))},
                        mustPanic: true,
-                       exported:  false,
                },
                {
                        field:     StructField{Name: "s", Type: TypeOf(S1{}), PkgPath: "other/pkg"},
                        mustPanic: true, // TODO(sbinet): creating a name with a package path
-                       exported:  false,
                },
                {
                        field:     StructField{Name: "s", Type: TypeOf((*S1)(nil)), PkgPath: "other/pkg"},
                        mustPanic: true, // TODO(sbinet): creating a name with a package path
-                       exported:  false,
                },
                {
                        field:     StructField{Name: "s", Type: TypeOf(s2{}), PkgPath: "other/pkg"},
                        mustPanic: true, // TODO(sbinet): creating a name with a package path
-                       exported:  false,
                },
                {
                        field:     StructField{Name: "s", Type: TypeOf((*s2)(nil)), PkgPath: "other/pkg"},
                        mustPanic: true, // TODO(sbinet): creating a name with a package path
-                       exported:  false,
                },
                {
                        field:     StructField{Name: "", Type: TypeOf(ΦType{})},
-                       mustPanic: false,
-                       exported:  true,
+                       mustPanic: true,
                },
                {
                        field:     StructField{Name: "", Type: TypeOf(φType{})},
-                       mustPanic: false,
-                       exported:  false,
+                       mustPanic: true,
                },
                {
-                       field:     StructField{Name: "Φ", Type: TypeOf(0)},
-                       mustPanic: false,
-                       exported:  true,
+                       field:    StructField{Name: "Φ", Type: TypeOf(0)},
+                       exported: true,
                },
                {
-                       field:     StructField{Name: "φ", Type: TypeOf(0)},
-                       mustPanic: false,
-                       exported:  false,
+                       field:    StructField{Name: "φ", Type: TypeOf(0)},
+                       exported: false,
                },
-       } {
+       }
+       for i, test := range tests {
                testPanic(i, test.mustPanic, func() {
                        typ := StructOf([]StructField{test.field})
                        if typ == nil {
                        field := typ.Field(0)
                        n := field.Name
                        if n == "" {
-                               n = field.Type.Name()
+                               panic("field.Name must not be empty")
                        }
                        exported := isExported(n)
                        if exported != test.exported {
@@@ -4348,7 -4343,7 +4345,7 @@@ func TestStructOfGenericAlg(t *testing.
                {Name: "S1", Type: st1},
        })
  
-       for _, table := range []struct {
+       tests := []struct {
                rt  Type
                idx []int
        }{
                        ),
                        idx: []int{2},
                },
-       } {
+       }
+       for _, table := range tests {
                v1 := New(table.rt).Elem()
                v2 := New(table.rt).Elem()
  
@@@ -4531,18 -4528,21 +4530,21 @@@ func TestStructOfWithInterface(t *testi
        type Iface interface {
                Get() int
        }
-       for i, table := range []struct {
+       tests := []struct {
+               name string
                typ  Type
                val  Value
                impl bool
        }{
                {
+                       name: "StructI",
                        typ:  TypeOf(StructI(want)),
                        val:  ValueOf(StructI(want)),
                        impl: true,
                },
                {
-                       typ: PtrTo(TypeOf(StructI(want))),
+                       name: "StructI",
+                       typ:  PtrTo(TypeOf(StructI(want))),
                        val: ValueOf(func() interface{} {
                                v := StructI(want)
                                return &v
                        impl: true,
                },
                {
-                       typ: PtrTo(TypeOf(StructIPtr(want))),
+                       name: "StructIPtr",
+                       typ:  PtrTo(TypeOf(StructIPtr(want))),
                        val: ValueOf(func() interface{} {
                                v := StructIPtr(want)
                                return &v
                        impl: true,
                },
                {
+                       name: "StructIPtr",
                        typ:  TypeOf(StructIPtr(want)),
                        val:  ValueOf(StructIPtr(want)),
                        impl: false,
                //      val:  ValueOf(StructI(want)),
                //      impl: true,
                // },
-       } {
+       }
+       for i, table := range tests {
                rt := StructOf(
                        []StructField{
                                {
-                                       Name:    "",
-                                       PkgPath: "",
-                                       Type:    table.typ,
+                                       Name:      table.name,
+                                       Anonymous: true,
+                                       PkgPath:   "",
+                                       Type:      table.typ,
                                },
                        },
                )
@@@ -5333,72 -5338,6 +5340,72 @@@ func TestCallGC(t *testing.T) 
        f2("four", "five5", "six666", "seven77", "eight888")
  }
  
 +// Issue 18635 (function version).
 +func TestKeepFuncLive(t *testing.T) {
 +      // Test that we keep makeFuncImpl live as long as it is
 +      // referenced on the stack.
 +      typ := TypeOf(func(i int) {})
 +      var f, g func(in []Value) []Value
 +      f = func(in []Value) []Value {
 +              clobber()
 +              i := int(in[0].Int())
 +              if i > 0 {
 +                      // We can't use Value.Call here because
 +                      // runtime.call* will keep the makeFuncImpl
 +                      // alive. However, by converting it to an
 +                      // interface value and calling that,
 +                      // reflect.callReflect is the only thing that
 +                      // can keep the makeFuncImpl live.
 +                      //
 +                      // Alternate between f and g so that if we do
 +                      // reuse the memory prematurely it's more
 +                      // likely to get obviously corrupted.
 +                      MakeFunc(typ, g).Interface().(func(i int))(i - 1)
 +              }
 +              return nil
 +      }
 +      g = func(in []Value) []Value {
 +              clobber()
 +              i := int(in[0].Int())
 +              MakeFunc(typ, f).Interface().(func(i int))(i)
 +              return nil
 +      }
 +      MakeFunc(typ, f).Call([]Value{ValueOf(10)})
 +}
 +
 +// Issue 18635 (method version).
 +type KeepMethodLive struct{}
 +
 +func (k KeepMethodLive) Method1(i int) {
 +      clobber()
 +      if i > 0 {
 +              ValueOf(k).MethodByName("Method2").Interface().(func(i int))(i - 1)
 +      }
 +}
 +
 +func (k KeepMethodLive) Method2(i int) {
 +      clobber()
 +      ValueOf(k).MethodByName("Method1").Interface().(func(i int))(i)
 +}
 +
 +func TestKeepMethodLive(t *testing.T) {
 +      // Test that we keep methodValue live as long as it is
 +      // referenced on the stack.
 +      KeepMethodLive{}.Method1(10)
 +}
 +
 +// clobber tries to clobber unreachable memory.
 +func clobber() {
 +      runtime.GC()
 +      for i := 1; i < 32; i++ {
 +              for j := 0; j < 10; j++ {
 +                      obj := make([]*byte, i)
 +                      sink = obj
 +              }
 +      }
 +      runtime.GC()
 +}
 +
  type funcLayoutTest struct {
        rcvr, t                  Type
        size, argsize, retOffset uintptr
@@@ -6019,6 -5958,7 +6026,7 @@@ func TestSwapper(t *testing.T) 
                        want: []pairPtr{{5, 6, &c}, {3, 4, &b}, {1, 2, &a}},
                },
        }
        for i, tt := range tests {
                inStr := fmt.Sprint(tt.in)
                Swapper(tt.in)(tt.i, tt.j)
@@@ -6044,3 -5984,38 +6052,38 @@@ func TestUnaddressableField(t *testing.
                lv.Set(rv)
        })
  }
+ type Tint int
+ type Tint2 = Tint
+ type Talias1 struct {
+       byte
+       uint8
+       int
+       int32
+       rune
+ }
+ type Talias2 struct {
+       Tint
+       Tint2
+ }
+ func TestAliasNames(t *testing.T) {
+       t1 := Talias1{byte: 1, uint8: 2, int: 3, int32: 4, rune: 5}
+       out := fmt.Sprintf("%#v", t1)
+       want := "reflect_test.Talias1{byte:0x1, uint8:0x2, int:3, int32:4, rune:5}"
+       if out != want {
+               t.Errorf("Talias1 print:\nhave: %s\nwant: %s", out, want)
+       }
+       t2 := Talias2{Tint: 1, Tint2: 2}
+       out = fmt.Sprintf("%#v", t2)
+       want = "reflect_test.Talias2{Tint:1, Tint2:2}"
+       if out != want {
+               t.Errorf("Talias2 print:\nhave: %s\nwant: %s", out, want)
+       }
+ }
diff --combined src/reflect/value.go
index 699ba69408671db979b0037af4d7fc6629ac89ef,a1bfb6d489976c1505cc283e8012741576c5104b..1abfbe6f65029d2f83b2498579213a3b6b7d156c
@@@ -538,11 -538,6 +538,11 @@@ func callReflect(ctxt *makeFuncImpl, fr
                        off += typ.size
                }
        }
 +
 +      // runtime.getArgInfo expects to be able to find ctxt on the
 +      // stack when it finds our caller, makeFuncStub. Make sure it
 +      // doesn't get garbage collected.
 +      runtime.KeepAlive(ctxt)
  }
  
  // methodReceiver returns information about the receiver
@@@ -655,9 -650,6 +655,9 @@@ func callMethod(ctxt *methodValue, fram
        // though it's a heap object.
        memclrNoHeapPointers(args, frametype.size)
        framePool.Put(args)
 +
 +      // See the comment in callReflect.
 +      runtime.KeepAlive(ctxt)
  }
  
  // funcName returns the name of f, for use in error messages.
@@@ -763,7 -755,7 +763,7 @@@ func (v Value) Field(i int) Value 
        fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind())
        // Using an unexported field forces flagRO.
        if !field.name.isExported() {
-               if field.name.name() == "" {
+               if field.anon() {
                        fl |= flagEmbedRO
                } else {
                        fl |= flagStickyRO
        // In the former case, we want v.ptr + offset.
        // In the latter case, we must have field.offset = 0,
        // so v.ptr + field.offset is still okay.
-       ptr := unsafe.Pointer(uintptr(v.ptr) + field.offset)
+       ptr := unsafe.Pointer(uintptr(v.ptr) + field.offset())
        return Value{typ, ptr, fl}
  }