mirror of
https://github.com/golang/go
synced 2024-11-22 18:54:44 -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
|
IgnoreBranchErrors: true, // parser already checked via syntax.CheckBranches mode
|
||||||
Importer: &importer,
|
Importer: &importer,
|
||||||
Sizes: types2.SizesFor("gc", buildcfg.GOARCH),
|
Sizes: types2.SizesFor("gc", buildcfg.GOARCH),
|
||||||
// Currently, the compiler panics when using Alias types.
|
EnableAlias: true,
|
||||||
// TODO(gri) set to true once this is fixed (issue #66873)
|
|
||||||
EnableAlias: false,
|
|
||||||
}
|
}
|
||||||
if base.Flag.ErrorURL {
|
if base.Flag.ErrorURL {
|
||||||
conf.ErrorURL = " [go.dev/e/%s]"
|
conf.ErrorURL = " [go.dev/e/%s]"
|
||||||
|
@ -427,7 +427,9 @@ func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict, wrapped bool) *type
|
|||||||
r.dict = dict
|
r.dict = dict
|
||||||
|
|
||||||
typ := r.doTyp()
|
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,
|
// For recursive type declarations involving interfaces and aliases,
|
||||||
// above r.doTyp() call may have already set pr.typs[idx], so just
|
// 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:
|
case pkgbits.ObjAlias:
|
||||||
name := do(ir.OTYPE, false)
|
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)
|
name.SetAlias(true)
|
||||||
return name, nil
|
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
|
// typIdx also reports whether typ is a derived type; that is, whether
|
||||||
// its identity depends on type parameters.
|
// its identity depends on type parameters.
|
||||||
func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo {
|
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 {
|
if idx, ok := pw.typsIdx[typ]; ok {
|
||||||
return typeInfo{idx: idx, derived: false}
|
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.
|
// 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 = 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{}
|
var _ A5 = Value{}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ func _() {
|
|||||||
var _ T0 = A0{}
|
var _ T0 = A0{}
|
||||||
|
|
||||||
var _ N0 = T0{} // ERROR "cannot use T0{} \(value of type T0\) as N0 value in variable declaration"
|
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"
|
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"
|
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 (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 (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 reflect.Value|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{}
|
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