mirror of
https://github.com/golang/go
synced 2024-09-06 00:19:45 +00:00
go/types: if base type for an alias is known, use it when needed
Because methods are type-checked before the receiver base type is "complete" (i.e., they are checked as part of the receiver base type), situations occur where aliases of those base types are used (in those methods) but the alias types are not known yet (even though their base types are known). This fix is a temporary work-around that looks syntactically for the base types of alias types and uses those base types when we refer to an "incomplete" alias type. The work-around is completely localized and guarded with a flag so it can be disabled at short notice. The correct fix (slated for 1.12) is to decouple type-checking of methods from their receiver base types. See issue #26854. Fixes #26390. Change-Id: I66cc9d834b220c254ac00e671a137cf8a3da59c1 Reviewed-on: https://go-review.googlesource.com/128435 Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
884eea6f0a
commit
e7bce08493
|
@ -91,6 +91,7 @@ var tests = [][]string{
|
||||||
{"testdata/issues.src"},
|
{"testdata/issues.src"},
|
||||||
{"testdata/blank.src"},
|
{"testdata/blank.src"},
|
||||||
{"testdata/issue25008b.src", "testdata/issue25008a.src"}, // order (b before a) is crucial!
|
{"testdata/issue25008b.src", "testdata/issue25008a.src"}, // order (b before a) is crucial!
|
||||||
|
{"testdata/issue26390.src"}, // stand-alone test to ensure case is triggered
|
||||||
}
|
}
|
||||||
|
|
||||||
var fset = token.NewFileSet()
|
var fset = token.NewFileSet()
|
||||||
|
|
|
@ -165,6 +165,31 @@ func (check *Checker) objDecl(obj Object, def *Named, path []*TypeName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case *TypeName:
|
case *TypeName:
|
||||||
|
// fixFor26390 enables a temporary work-around to handle alias type names
|
||||||
|
// that have not been given a type yet even though the underlying type
|
||||||
|
// is already known. See testdata/issue26390.src for a simple example.
|
||||||
|
// Set this flag to false to disable this code quickly (and comment
|
||||||
|
// out the new test in decls4.src that will fail again).
|
||||||
|
// TODO(gri) remove this for Go 1.12 in favor of a more comprehensive fix
|
||||||
|
const fixFor26390 = true
|
||||||
|
if fixFor26390 {
|
||||||
|
// If we have a package-level alias type name that has not been
|
||||||
|
// given a type yet but the underlying type is a type name that
|
||||||
|
// has been given a type already, don't report a cycle but use
|
||||||
|
// the underlying type name's type instead. The cycle shouldn't
|
||||||
|
// exist in the first place in this case and is due to the way
|
||||||
|
// methods are type-checked at the moment. See also the comment
|
||||||
|
// at the end of Checker.typeDecl below.
|
||||||
|
if d := check.objMap[obj]; d != nil && d.alias && obj.typ == Typ[Invalid] {
|
||||||
|
// If we can find the underlying type name syntactically
|
||||||
|
// and it has a type, use that type.
|
||||||
|
if tname := check.resolveBaseTypeName(ast.NewIdent(obj.name)); tname != nil && tname.typ != nil {
|
||||||
|
obj.typ = tname.typ
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if useCycleMarking && check.typeCycle(obj) {
|
if useCycleMarking && check.typeCycle(obj) {
|
||||||
// break cycle
|
// break cycle
|
||||||
// (without this, calling underlying()
|
// (without this, calling underlying()
|
||||||
|
|
11
src/go/types/testdata/issue26390.src
vendored
Normal file
11
src/go/types/testdata/issue26390.src
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2018 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 issue26390
|
||||||
|
|
||||||
|
type A = T
|
||||||
|
|
||||||
|
func (t *T) m() *A { return t }
|
||||||
|
|
||||||
|
type T struct{}
|
Loading…
Reference in a new issue