Skip to content

Commit 31c8150

Browse files
mdempskygopherbot
authored andcommitted
cmd/compile/internal/noder: enable type aliases in type checker
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 <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Reviewed-by: Cuong Manh Le <[email protected]> Auto-Submit: Matthew Dempsky <[email protected]>
1 parent c3c97ad commit 31c8150

File tree

5 files changed

+56
-10
lines changed

5 files changed

+56
-10
lines changed

src/cmd/compile/internal/noder/irgen.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,7 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
4949
IgnoreBranchErrors: true, // parser already checked via syntax.CheckBranches mode
5050
Importer: &importer,
5151
Sizes: types2.SizesFor("gc", buildcfg.GOARCH),
52-
// Currently, the compiler panics when using Alias types.
53-
// TODO(gri) set to true once this is fixed (issue #66873)
54-
EnableAlias: false,
52+
EnableAlias: true,
5553
}
5654
if base.Flag.ErrorURL {
5755
conf.ErrorURL = " [go.dev/e/%s]"

src/cmd/compile/internal/noder/reader.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,9 @@ func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict, wrapped bool) *type
427427
r.dict = dict
428428

429429
typ := r.doTyp()
430-
assert(typ != nil)
430+
if typ == nil {
431+
base.Fatalf("doTyp returned nil for info=%v", info)
432+
}
431433

432434
// For recursive type declarations involving interfaces and aliases,
433435
// 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
741743

742744
case pkgbits.ObjAlias:
743745
name := do(ir.OTYPE, false)
744-
setType(name, r.typ())
746+
747+
// Clumsy dance: the r.typ() call here might recursively find this
748+
// type alias name, before we've set its type (#66873). So we
749+
// temporarily clear sym.Def and then restore it later, if still
750+
// unset.
751+
hack := sym.Def == name
752+
if hack {
753+
sym.Def = nil
754+
}
755+
typ := r.typ()
756+
if hack {
757+
if sym.Def != nil {
758+
name = sym.Def.(*ir.Name)
759+
assert(name.Type() == typ)
760+
return name, nil
761+
}
762+
sym.Def = name
763+
}
764+
765+
setType(name, typ)
745766
name.SetAlias(true)
746767
return name, nil
747768

src/cmd/compile/internal/noder/writer.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,18 @@ func (w *writer) typInfo(info typeInfo) {
488488
// typIdx also reports whether typ is a derived type; that is, whether
489489
// its identity depends on type parameters.
490490
func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo {
491+
// Strip non-global aliases, because they only appear in inline
492+
// bodies anyway. Otherwise, they can cause types.Sym collisions
493+
// (e.g., "main.C" for both of the local type aliases in
494+
// test/fixedbugs/issue50190.go).
495+
for {
496+
if alias, ok := typ.(*types2.Alias); ok && !isGlobal(alias.Obj()) {
497+
typ = alias.Rhs()
498+
} else {
499+
break
500+
}
501+
}
502+
491503
if idx, ok := pw.typsIdx[typ]; ok {
492504
return typeInfo{idx: idx, derived: false}
493505
}

test/alias2.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ var _ T0 = A0{}
4747

4848
// But aliases and original types cannot be used with new types based on them.
4949
var _ N0 = T0{} // ERROR "cannot use T0{} \(value of type T0\) as N0 value in variable declaration"
50-
var _ N0 = A0{} // ERROR "cannot use A0{} \(value of type T0\) as N0 value in variable declaration"
50+
var _ N0 = A0{} // ERROR "cannot use A0{} \(value of type A0\) as N0 value in variable declaration"
5151

5252
var _ A5 = Value{}
5353

@@ -83,7 +83,7 @@ func _() {
8383
var _ T0 = A0{}
8484

8585
var _ N0 = T0{} // ERROR "cannot use T0{} \(value of type T0\) as N0 value in variable declaration"
86-
var _ N0 = A0{} // ERROR "cannot use A0{} \(value of type T0\) as N0 value in variable declaration"
86+
var _ N0 = A0{} // ERROR "cannot use A0{} \(value of type A0\) as N0 value in variable declaration"
8787

8888
var _ A5 = Value{} // ERROR "cannot use Value{} \(value of type reflect\.Value\) as A5 value in variable declaration"
8989
}
@@ -92,10 +92,10 @@ func _() {
9292

9393
type _ = reflect.ValueOf // ERROR "reflect.ValueOf .*is not a type|expected type"
9494

95-
func (A1) m() {} // ERROR "cannot define new methods on non-local type int|may not define methods on non-local type"
95+
func (A1) m() {} // ERROR "cannot define new methods on non-local type|may not define methods on non-local type"
9696
func (A2) m() {} // ERROR "invalid receiver type"
97-
func (A3) m() {} // ERROR "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type"
98-
func (A4) m() {} // ERROR "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type"
97+
func (A3) m() {} // ERROR "cannot define new methods on non-local type|may not define methods on non-local type"
98+
func (A4) m() {} // ERROR "cannot define new methods on non-local type|may not define methods on non-local type"
9999

100100
type B1 = struct{}
101101

test/fixedbugs/issue66873.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// compile
2+
3+
// Copyright 2024 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package p
8+
9+
func f(A) {}
10+
11+
type T int
12+
13+
type A = T
14+
15+
func (A) m() {}

0 commit comments

Comments
 (0)