]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/noder: enable type aliases in type checker
authorMatthew Dempsky <mdempsky@google.com>
Wed, 15 May 2024 05:22:34 +0000 (22:22 -0700)
committerGopher Robot <gobot@golang.org>
Wed, 15 May 2024 15:09:14 +0000 (15:09 +0000)
This CL fixes an initialization loop during IR construction, that
stems from IR lacking first-class support for aliases. As a
workaround, we avoid publishing alias declarations until the RHS type
expression has been constructed.

Thanks to gri@ for investigating while I was out.

Fixes #66873.

Change-Id: I11e0d96ea6c357c295da47f44b6ec408edef89b7
Reviewed-on: https://go-review.googlesource.com/c/go/+/585399
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>

src/cmd/compile/internal/noder/irgen.go
src/cmd/compile/internal/noder/reader.go
src/cmd/compile/internal/noder/writer.go
test/alias2.go
test/fixedbugs/issue66873.go [new file with mode: 0644]

index 34201545b59897d96277346a4f1d9a3ad864ce06..281f619f6fa068e8e7739f4a0b664362cb48a80c 100644 (file)
@@ -49,9 +49,7 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
                IgnoreBranchErrors: true, // parser already checked via syntax.CheckBranches mode
                Importer:           &importer,
                Sizes:              types2.SizesFor("gc", buildcfg.GOARCH),
-               // Currently, the compiler panics when using Alias types.
-               // TODO(gri) set to true once this is fixed (issue #66873)
-               EnableAlias: false,
+               EnableAlias:        true,
        }
        if base.Flag.ErrorURL {
                conf.ErrorURL = " [go.dev/e/%s]"
index abd07ebb623bfbeef484d60f7750ebab5a479447..a7feadaf6e145bea261c3c382b58737a98e28ac3 100644 (file)
@@ -427,7 +427,9 @@ func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict, wrapped bool) *type
        r.dict = dict
 
        typ := r.doTyp()
-       assert(typ != nil)
+       if typ == nil {
+               base.Fatalf("doTyp returned nil for info=%v", info)
+       }
 
        // For recursive type declarations involving interfaces and aliases,
        // above r.doTyp() call may have already set pr.typs[idx], so just
@@ -741,7 +743,26 @@ func (pr *pkgReader) objIdxMayFail(idx pkgbits.Index, implicits, explicits []*ty
 
        case pkgbits.ObjAlias:
                name := do(ir.OTYPE, false)
-               setType(name, r.typ())
+
+               // Clumsy dance: the r.typ() call here might recursively find this
+               // type alias name, before we've set its type (#66873). So we
+               // temporarily clear sym.Def and then restore it later, if still
+               // unset.
+               hack := sym.Def == name
+               if hack {
+                       sym.Def = nil
+               }
+               typ := r.typ()
+               if hack {
+                       if sym.Def != nil {
+                               name = sym.Def.(*ir.Name)
+                               assert(name.Type() == typ)
+                               return name, nil
+                       }
+                       sym.Def = name
+               }
+
+               setType(name, typ)
                name.SetAlias(true)
                return name, nil
 
index 453b08dbf9761ef853a643452c736f4f15860e71..a48e193c5fa69695bff5933e5729db60d96f0db6 100644 (file)
@@ -488,6 +488,18 @@ func (w *writer) typInfo(info typeInfo) {
 // typIdx also reports whether typ is a derived type; that is, whether
 // its identity depends on type parameters.
 func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo {
+       // Strip non-global aliases, because they only appear in inline
+       // bodies anyway. Otherwise, they can cause types.Sym collisions
+       // (e.g., "main.C" for both of the local type aliases in
+       // test/fixedbugs/issue50190.go).
+       for {
+               if alias, ok := typ.(*types2.Alias); ok && !isGlobal(alias.Obj()) {
+                       typ = alias.Rhs()
+               } else {
+                       break
+               }
+       }
+
        if idx, ok := pw.typsIdx[typ]; ok {
                return typeInfo{idx: idx, derived: false}
        }
index 2846e5dc31d21e8e455327eb789f9c202eb20053..95eb25a94b5ae27b83672d14c71961f194c9b457 100644 (file)
@@ -47,7 +47,7 @@ var _ T0 = A0{}
 
 // But aliases and original types cannot be used with new types based on them.
 var _ N0 = T0{} // ERROR "cannot use T0{} \(value of type T0\) as N0 value in variable declaration"
-var _ N0 = A0{} // ERROR "cannot use A0{} \(value of type T0\) as N0 value in variable declaration"
+var _ N0 = A0{} // ERROR "cannot use A0{} \(value of type A0\) as N0 value in variable declaration"
 
 var _ A5 = Value{}
 
@@ -83,7 +83,7 @@ func _() {
        var _ T0 = A0{}
 
        var _ N0 = T0{} // ERROR "cannot use T0{} \(value of type T0\) as N0 value in variable declaration"
-       var _ N0 = A0{} // ERROR "cannot use A0{} \(value of type T0\) as N0 value in variable declaration"
+       var _ N0 = A0{} // ERROR "cannot use A0{} \(value of type A0\) as N0 value in variable declaration"
 
        var _ A5 = Value{} // ERROR "cannot use Value{} \(value of type reflect\.Value\) as A5 value in variable declaration"
 }
@@ -92,10 +92,10 @@ func _() {
 
 type _ = reflect.ValueOf // ERROR "reflect.ValueOf .*is not a type|expected type"
 
-func (A1) m() {} // ERROR "cannot define new methods on non-local type int|may not define methods on non-local type"
+func (A1) m() {} // ERROR "cannot define new methods on non-local type|may not define methods on non-local type"
 func (A2) m() {} // ERROR "invalid receiver type"
-func (A3) m() {} // ERROR "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type"
-func (A4) m() {} // ERROR "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type"
+func (A3) m() {} // ERROR "cannot define new methods on non-local type|may not define methods on non-local type"
+func (A4) m() {} // ERROR "cannot define new methods on non-local type|may not define methods on non-local type"
 
 type B1 = struct{}
 
diff --git a/test/fixedbugs/issue66873.go b/test/fixedbugs/issue66873.go
new file mode 100644 (file)
index 0000000..2f49cc9
--- /dev/null
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2024 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
+
+func f(A) {}
+
+type T int
+
+type A = T
+
+func (A) m() {}