]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: fix re-export of parameters
authorMatthew Dempsky <mdempsky@google.com>
Sun, 3 Jan 2021 22:37:06 +0000 (14:37 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Mon, 4 Jan 2021 10:30:08 +0000 (10:30 +0000)
When exporting signature types, we include the originating package,
because it's exposed via go/types's API. And as a consistency check,
we ensure that the parameter names came from that same package.

However, we were getting this wrong in the case of exported variables
that were initialized with a method value using an imported method. In
this case, when we created the method value wrapper function's
type (which is reused as the variable's type if none is explicitly
provided in the variable declaration), we were reusing the
original (i.e., imported) parameter names, but the newly created
signature type was associated with the current package instead.

The correct fix here is really to preserve the original signature
type's package (along with position and name for its parameters), but
that's awkward to do at the moment because the DeclFunc API requires
an ir representation of the function signature, whereas we only
provide a way to explicitly set packages via the type constructor
APIs.

As an interim fix, we associate the parameters with the current
package, to be consistent with the signature type's package.

Fixes #43479.

Change-Id: Id45a10f8cf64165c9bc7d9598f0a0ee199a5e752
Reviewed-on: https://go-review.googlesource.com/c/go/+/281292
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
src/cmd/compile/internal/typecheck/dcl.go
src/cmd/compile/internal/typecheck/iexport.go
src/cmd/compile/internal/typecheck/iimport.go
src/cmd/compile/internal/typecheck/subr.go
test/fixedbugs/issue43479.dir/a.go [new file with mode: 0644]
test/fixedbugs/issue43479.dir/b.go [new file with mode: 0644]
test/fixedbugs/issue43479.go [new file with mode: 0644]

index daec9848d0fb0808268daf8249ad2a191730bfe4..5eaf100eed06f1ee5309d9bc6a7c411282ee7102 100644 (file)
@@ -486,6 +486,9 @@ func NewMethodType(sig *types.Type, recv *types.Type) *types.Type {
                nrecvs++
        }
 
+       // TODO(mdempsky): Move this function to types.
+       // TODO(mdempsky): Preserve positions, names, and package from sig+recv.
+
        params := make([]*types.Field, nrecvs+sig.Params().Fields().Len())
        if recv != nil {
                params[0] = types.NewField(base.Pos, nil, recv)
index 50acb10a9a9c1aeec526fa6c068c66f462046762..dd515b8ccdd1f54dce0c2dcba021cce87ee7f99d 100644 (file)
@@ -574,6 +574,11 @@ func (w *exportWriter) pos(pos src.XPos) {
 }
 
 func (w *exportWriter) pkg(pkg *types.Pkg) {
+       // TODO(mdempsky): Add flag to types.Pkg to mark pseudo-packages.
+       if pkg == ir.Pkgs.Go {
+               base.Fatalf("export of pseudo-package: %q", pkg.Path)
+       }
+
        // Ensure any referenced packages are declared in the main index.
        w.p.allPkgs[pkg] = true
 
@@ -1529,6 +1534,10 @@ func (w *exportWriter) localName(n *ir.Name) {
 }
 
 func (w *exportWriter) localIdent(s *types.Sym, v int32) {
+       if w.currPkg == nil {
+               base.Fatalf("missing currPkg")
+       }
+
        // Anonymous parameters.
        if s == nil {
                w.string("")
@@ -1553,8 +1562,8 @@ func (w *exportWriter) localIdent(s *types.Sym, v int32) {
                name = fmt.Sprintf("%s·%d", name, v)
        }
 
-       if !types.IsExported(name) && s.Pkg != w.currPkg {
-               base.Fatalf("weird package in name: %v => %v, not %q", s, name, w.currPkg.Path)
+       if s.Pkg != w.currPkg {
+               base.Fatalf("weird package in name: %v => %v from %q, not %q", s, name, s.Pkg.Path, w.currPkg.Path)
        }
 
        w.string(name)
index 0caac362e3a183a8f213d795c887a306cf04e2cd..2dc7e70b650133c30884ad3e89991b02e420599c 100644 (file)
@@ -327,7 +327,7 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name {
                ms := make([]*types.Field, r.uint64())
                for i := range ms {
                        mpos := r.pos()
-                       msym := r.ident()
+                       msym := r.selector()
                        recv := r.param()
                        mtyp := r.signature(recv)
 
@@ -434,18 +434,21 @@ func (p *importReader) float(typ *types.Type) constant.Value {
        return constant.Make(&f)
 }
 
-func (r *importReader) ident() *types.Sym {
+func (r *importReader) ident(selector bool) *types.Sym {
        name := r.string()
        if name == "" {
                return nil
        }
        pkg := r.currPkg
-       if types.IsExported(name) {
+       if selector && types.IsExported(name) {
                pkg = types.LocalPkg
        }
        return pkg.Lookup(name)
 }
 
+func (r *importReader) localIdent() *types.Sym { return r.ident(false) }
+func (r *importReader) selector() *types.Sym   { return r.ident(true) }
+
 func (r *importReader) qualifiedIdent() *ir.Ident {
        name := r.string()
        pkg := r.pkg()
@@ -534,7 +537,7 @@ func (r *importReader) typ1() *types.Type {
                fs := make([]*types.Field, r.uint64())
                for i := range fs {
                        pos := r.pos()
-                       sym := r.ident()
+                       sym := r.selector()
                        typ := r.typ()
                        emb := r.bool()
                        note := r.string()
@@ -563,7 +566,7 @@ func (r *importReader) typ1() *types.Type {
                methods := make([]*types.Field, r.uint64())
                for i := range methods {
                        pos := r.pos()
-                       sym := r.ident()
+                       sym := r.selector()
                        typ := r.signature(fakeRecvField())
 
                        methods[i] = types.NewField(pos, sym, typ)
@@ -599,7 +602,7 @@ func (r *importReader) paramList() []*types.Field {
 }
 
 func (r *importReader) param() *types.Field {
-       return types.NewField(r.pos(), r.ident(), r.typ())
+       return types.NewField(r.pos(), r.localIdent(), r.typ())
 }
 
 func (r *importReader) bool() bool {
@@ -784,7 +787,7 @@ func (r *importReader) caseList(switchExpr ir.Node) []*ir.CaseClause {
                        // Note: per-case variables will have distinct, dotted
                        // names after import. That's okay: swt.go only needs
                        // Sym for diagnostics anyway.
-                       caseVar := ir.NewNameAt(cas.Pos(), r.ident())
+                       caseVar := ir.NewNameAt(cas.Pos(), r.localIdent())
                        Declare(caseVar, DeclContext)
                        cas.Var = caseVar
                        caseVar.Defn = switchExpr
@@ -851,7 +854,7 @@ func (r *importReader) node() ir.Node {
                return r.qualifiedIdent()
 
        case ir.ONAME:
-               return r.ident().Def.(*ir.Name)
+               return r.localIdent().Def.(*ir.Name)
 
        // case OPACK, ONONAME:
        //      unreachable - should have been resolved by typechecking
@@ -862,7 +865,7 @@ func (r *importReader) node() ir.Node {
        case ir.OTYPESW:
                pos := r.pos()
                var tag *ir.Ident
-               if s := r.ident(); s != nil {
+               if s := r.localIdent(); s != nil {
                        tag = ir.NewIdent(pos, s)
                }
                return ir.NewTypeSwitchGuard(pos, tag, r.expr())
@@ -899,7 +902,7 @@ func (r *importReader) node() ir.Node {
 
        case ir.OXDOT:
                // see parser.new_dotname
-               return ir.NewSelectorExpr(r.pos(), ir.OXDOT, r.expr(), r.ident())
+               return ir.NewSelectorExpr(r.pos(), ir.OXDOT, r.expr(), r.selector())
 
        // case ODOTTYPE, ODOTTYPE2:
        //      unreachable - mapped to case ODOTTYPE below by exporter
@@ -989,7 +992,7 @@ func (r *importReader) node() ir.Node {
        // statements
        case ir.ODCL:
                pos := r.pos()
-               lhs := ir.NewDeclNameAt(pos, ir.ONAME, r.ident())
+               lhs := ir.NewDeclNameAt(pos, ir.ONAME, r.localIdent())
                lhs.SetType(r.typ())
 
                Declare(lhs, ir.PAUTO)
@@ -1100,7 +1103,7 @@ func (r *importReader) op() ir.Op {
 func (r *importReader) fieldList() []ir.Node {
        list := make([]ir.Node, r.uint64())
        for i := range list {
-               list[i] = ir.NewStructKeyExpr(r.pos(), r.ident(), r.expr())
+               list[i] = ir.NewStructKeyExpr(r.pos(), r.selector(), r.expr())
        }
        return list
 }
index 447e945d814c9264ade7ea15004909d76466c5d0..569075d684ad3567f3bb3c3b4b3dae2bd78ea66c 100644 (file)
@@ -43,6 +43,9 @@ func NewFuncParams(tl *types.Type, mustname bool) []*ir.Field {
                        // invent a name so that we can refer to it in the trampoline
                        s = LookupNum(".anon", gen)
                        gen++
+               } else if s != nil && s.Pkg != types.LocalPkg {
+                       // TODO(mdempsky): Preserve original position, name, and package.
+                       s = Lookup(s.Name)
                }
                a := ir.NewField(base.Pos, s, nil, t.Type)
                a.Pos = t.Pos
diff --git a/test/fixedbugs/issue43479.dir/a.go b/test/fixedbugs/issue43479.dir/a.go
new file mode 100644 (file)
index 0000000..ed3e6a5
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type Here struct{ stuff int }
+type Info struct{ Dir string }
+
+func New() Here { return Here{} }
+func (h Here) Dir(p string) (Info, error)
+
+type I interface{ M(x string) }
+
+type T = struct {
+       Here
+       I
+}
+
+var X T
+
+var A = (*T).Dir
+var B = T.Dir
+var C = X.Dir
+var D = (*T).M
+var E = T.M
+var F = X.M
diff --git a/test/fixedbugs/issue43479.dir/b.go b/test/fixedbugs/issue43479.dir/b.go
new file mode 100644 (file)
index 0000000..02d1690
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+var Here = a.New()
+var Dir = Here.Dir
+
+type T = struct {
+       a.Here
+       a.I
+}
+
+var X T
+
+// Test exporting the type of method values for anonymous structs with
+// promoted methods.
+var A = a.A
+var B = a.B
+var C = a.C
+var D = a.D
+var E = a.E
+var F = a.F
+var G = (*a.T).Dir
+var H = a.T.Dir
+var I = a.X.Dir
+var J = (*a.T).M
+var K = a.T.M
+var L = a.X.M
+var M = (*T).Dir
+var N = T.Dir
+var O = X.Dir
+var P = (*T).M
+var Q = T.M
+var R = X.M
diff --git a/test/fixedbugs/issue43479.go b/test/fixedbugs/issue43479.go
new file mode 100644 (file)
index 0000000..f21d1d5
--- /dev/null
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored