mirror of
https://github.com/golang/go
synced 2024-11-22 08:44:41 -07:00
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 <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>
This commit is contained in:
parent
c3c97ad1bf
commit
31c8150082
@ -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]"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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}
|
||||
}
|
||||
|
@ -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{}
|
||||
|
||||
|
15
test/fixedbugs/issue66873.go
Normal file
15
test/fixedbugs/issue66873.go
Normal file
@ -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() {}
|
Loading…
Reference in New Issue
Block a user