]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: correctly export underlying type of predecl. error type
authorRobert Griesemer <gri@golang.org>
Wed, 1 Jun 2016 20:46:49 +0000 (13:46 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 1 Jun 2016 21:32:46 +0000 (21:32 +0000)
Fixes #15920.

Change-Id: I78cd79b91a58d0f7218b80f9445417f4ee071a6e
Reviewed-on: https://go-review.googlesource.com/23606
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/gc/bexport.go
src/cmd/compile/internal/gc/universe.go
src/go/internal/gcimporter/gcimporter_test.go
src/go/internal/gcimporter/testdata/issue15920.go [new file with mode: 0644]
test/fixedbugs/issue15920.dir/a.go [new file with mode: 0644]
test/fixedbugs/issue15920.dir/b.go [new file with mode: 0644]
test/fixedbugs/issue15920.go [new file with mode: 0644]

index f533053cd74acc2aaf0263c8df26e6336cb26432..c7be2deaa2c37bfcf28bdac6769e446e76496cb5 100644 (file)
@@ -622,6 +622,8 @@ func isInlineable(n *Node) bool {
        return false
 }
 
+var errorInterface *Type // lazily initialized
+
 func (p *exporter) typ(t *Type) {
        if t == nil {
                Fatalf("exporter: nil type")
@@ -673,7 +675,19 @@ func (p *exporter) typ(t *Type) {
                p.qualifiedName(tsym)
 
                // write underlying type
-               p.typ(t.Orig)
+               orig := t.Orig
+               if orig == errortype {
+                       // The error type is the only predeclared type which has
+                       // a composite underlying type. When we encode that type,
+                       // make sure to encode the underlying interface rather than
+                       // the named type again. See also the comment in universe.go
+                       // regarding the errortype and issue #15920.
+                       if errorInterface == nil {
+                               errorInterface = makeErrorInterface()
+                       }
+                       orig = errorInterface
+               }
+               p.typ(orig)
 
                // interfaces don't have associated methods
                if t.Orig.IsInterface() {
index b55af7e25a0a7b4ac8fcdd26d5a1f9c0a3db7c6e..270d4c377088f58945e495110d9ecf8970675a0a 100644 (file)
@@ -358,9 +358,7 @@ func typeinit() {
        itable = typPtr(Types[TUINT8])
 }
 
-func lexinit1() {
-       // t = interface { Error() string }
-
+func makeErrorInterface() *Type {
        rcvr := typ(TSTRUCT)
        rcvr.StructType().Funarg = FunargRcvr
        field := newField()
@@ -387,10 +385,18 @@ func lexinit1() {
        field.Type = f
        t.SetFields([]*Field{field})
 
+       return t
+}
+
+func lexinit1() {
        // error type
        s := Pkglookup("error", builtinpkg)
-       errortype = t
+       errortype = makeErrorInterface()
        errortype.Sym = s
+       // TODO: If we can prove that it's safe to set errortype.Orig here
+       // than we don't need the special errortype/errorInterface case in
+       // bexport.go. See also issue #15920.
+       // errortype.Orig = makeErrorInterface()
        s.Def = typenod(errortype)
 
        // byte alias
index 8de36c713c1453363f7b25aced1ecd35ec1c2682..d8c5bcfb1cad0892360b6a891ea3979c5f52c554 100644 (file)
@@ -400,3 +400,28 @@ func TestIssue15517(t *testing.T) {
                }
        }
 }
+
+func TestIssue15920(t *testing.T) {
+       skipSpecialPlatforms(t)
+
+       // This package only handles gc export data.
+       if runtime.Compiler != "gc" {
+               t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+               return
+       }
+
+       // On windows, we have to set the -D option for the compiler to avoid having a drive
+       // letter and an illegal ':' in the import path - just skip it (see also issue #3483).
+       if runtime.GOOS == "windows" {
+               t.Skip("avoid dealing with relative paths/drive letters on windows")
+       }
+
+       if f := compile(t, "testdata", "issue15920.go"); f != "" {
+               defer os.Remove(f)
+       }
+
+       imports := make(map[string]*types.Package)
+       if _, err := Import(imports, "./testdata/issue15920", "."); err != nil {
+               t.Fatal(err)
+       }
+}
diff --git a/src/go/internal/gcimporter/testdata/issue15920.go b/src/go/internal/gcimporter/testdata/issue15920.go
new file mode 100644 (file)
index 0000000..c70f7d8
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2016 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 p
+
+// The underlying type of Error is the underlying type of error.
+// Make sure we can import this again without problems.
+type Error error
+
+func F() Error { return nil }
diff --git a/test/fixedbugs/issue15920.dir/a.go b/test/fixedbugs/issue15920.dir/a.go
new file mode 100644 (file)
index 0000000..15f9235
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2016 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 Error error
+
+func F() Error { return nil }
diff --git a/test/fixedbugs/issue15920.dir/b.go b/test/fixedbugs/issue15920.dir/b.go
new file mode 100644 (file)
index 0000000..0a36c5c
--- /dev/null
@@ -0,0 +1,7 @@
+// Copyright 2016 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"
diff --git a/test/fixedbugs/issue15920.go b/test/fixedbugs/issue15920.go
new file mode 100644 (file)
index 0000000..4d2844d
--- /dev/null
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2016 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