Skip to content

Commit e7bce08

Browse files
committed
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 <[email protected]> Reviewed-by: Alan Donovan <[email protected]>
1 parent 884eea6 commit e7bce08

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

src/go/types/check_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ var tests = [][]string{
9191
{"testdata/issues.src"},
9292
{"testdata/blank.src"},
9393
{"testdata/issue25008b.src", "testdata/issue25008a.src"}, // order (b before a) is crucial!
94+
{"testdata/issue26390.src"}, // stand-alone test to ensure case is triggered
9495
}
9596

9697
var fset = token.NewFileSet()

src/go/types/decl.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,31 @@ func (check *Checker) objDecl(obj Object, def *Named, path []*TypeName) {
165165
}
166166

167167
case *TypeName:
168+
// fixFor26390 enables a temporary work-around to handle alias type names
169+
// that have not been given a type yet even though the underlying type
170+
// is already known. See testdata/issue26390.src for a simple example.
171+
// Set this flag to false to disable this code quickly (and comment
172+
// out the new test in decls4.src that will fail again).
173+
// TODO(gri) remove this for Go 1.12 in favor of a more comprehensive fix
174+
const fixFor26390 = true
175+
if fixFor26390 {
176+
// If we have a package-level alias type name that has not been
177+
// given a type yet but the underlying type is a type name that
178+
// has been given a type already, don't report a cycle but use
179+
// the underlying type name's type instead. The cycle shouldn't
180+
// exist in the first place in this case and is due to the way
181+
// methods are type-checked at the moment. See also the comment
182+
// at the end of Checker.typeDecl below.
183+
if d := check.objMap[obj]; d != nil && d.alias && obj.typ == Typ[Invalid] {
184+
// If we can find the underlying type name syntactically
185+
// and it has a type, use that type.
186+
if tname := check.resolveBaseTypeName(ast.NewIdent(obj.name)); tname != nil && tname.typ != nil {
187+
obj.typ = tname.typ
188+
break
189+
}
190+
}
191+
}
192+
168193
if useCycleMarking && check.typeCycle(obj) {
169194
// break cycle
170195
// (without this, calling underlying()

src/go/types/testdata/issue26390.src

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

0 commit comments

Comments
 (0)