Skip to content

Commit 671e115

Browse files
committed
go/types, types2: reorder object processing to avoid broken aliases
By processing non-alias type declarations before alias type declaration, and those before everything else we can avoid some of the remaining errors which are due to alias types not being available. For #25838. For #50259. For #50276. For #50729. Change-Id: I233da2899a6d4954c239638624dfa8c08662e6b9 Reviewed-on: https://go-review.googlesource.com/c/go/+/380056 Trust: Robert Griesemer <[email protected]> Run-TryBot: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent fe85c24 commit 671e115

File tree

9 files changed

+102
-38
lines changed

9 files changed

+102
-38
lines changed

src/cmd/compile/internal/types2/resolver.go

+20-14
Original file line numberDiff line numberDiff line change
@@ -656,27 +656,33 @@ func (check *Checker) packageObjects() {
656656
}
657657
}
658658

659-
// We process non-alias declarations first, in order to avoid situations where
660-
// the type of an alias declaration is needed before it is available. In general
661-
// this is still not enough, as it is possible to create sufficiently convoluted
662-
// recursive type definitions that will cause a type alias to be needed before it
663-
// is available (see issue #25838 for examples).
664-
// As an aside, the cmd/compiler suffers from the same problem (#25838).
659+
// We process non-alias type declarations first, followed by alias declarations,
660+
// and then everything else. This appears to avoid most situations where the type
661+
// of an alias is needed before it is available.
662+
// There may still be cases where this is not good enough (see also issue #25838).
663+
// In those cases Checker.ident will report an error ("invalid use of type alias").
665664
var aliasList []*TypeName
666-
// phase 1
665+
var othersList []Object // everything that's not a type
666+
// phase 1: non-alias type declarations
667667
for _, obj := range objList {
668-
// If we have a type alias, collect it for the 2nd phase.
669-
if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].tdecl.Alias {
670-
aliasList = append(aliasList, tname)
671-
continue
668+
if tname, _ := obj.(*TypeName); tname != nil {
669+
if check.objMap[tname].tdecl.Alias {
670+
aliasList = append(aliasList, tname)
671+
} else {
672+
check.objDecl(obj, nil)
673+
}
674+
} else {
675+
othersList = append(othersList, obj)
672676
}
673-
674-
check.objDecl(obj, nil)
675677
}
676-
// phase 2
678+
// phase 2: alias type declarations
677679
for _, obj := range aliasList {
678680
check.objDecl(obj, nil)
679681
}
682+
// phase 3: all other declarations
683+
for _, obj := range othersList {
684+
check.objDecl(obj, nil)
685+
}
680686

681687
// At this point we may have a non-empty check.methods map; this means that not all
682688
// entries were deleted at the end of typeDecl because the respective receiver base
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2022 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 p
6+
7+
// examples from the issue
8+
9+
type (
10+
e = f
11+
f = g
12+
g = []h
13+
h i
14+
i = j
15+
j = e
16+
)
17+
18+
type (
19+
e1 = []h1
20+
h1 e1
21+
)
22+
23+
type (
24+
P = *T
25+
T P
26+
)

src/cmd/compile/internal/types2/testdata/fixedbugs/issue50259.go2

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ package p
77
var x T[B]
88

99
type T[_ any] struct{}
10-
type A T[B /* ERROR invalid use of type alias */ ]
10+
type A T[B]
1111
type B = T[A]
1212

1313
// test case from issue
1414

1515
var v Box[Step]
1616
type Box[T any] struct{}
1717
type Step = Box[StepBox]
18-
type StepBox Box[Step /* ERROR invalid use of type alias */ ]
18+
type StepBox Box[Step]

src/cmd/compile/internal/types2/testdata/fixedbugs/issue50276.go2

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ type pair[S any] struct {}
1111

1212
var _ transform[step]
1313

14-
type box transform[step /* ERROR invalid use of type alias */ ]
14+
type box transform[step]
1515
type step = pair[box]
1616

1717
// test case from issue
@@ -27,7 +27,7 @@ var first Transform[Step]
2727
// This line doesn't use the Step alias, and it compiles fine if you uncomment it.
2828
var second Transform[Pair[Box, interface{}]]
2929

30-
type Box *Transform[Step /* ERROR invalid use of type alias */ ]
30+
type Box *Transform[Step]
3131

3232
// This line is the same as the `first` line, but it comes after the Box declaration and
3333
// does not break the compile.

src/go/types/resolver.go

+20-14
Original file line numberDiff line numberDiff line change
@@ -629,27 +629,33 @@ func (check *Checker) packageObjects() {
629629
}
630630
}
631631

632-
// We process non-alias declarations first, in order to avoid situations where
633-
// the type of an alias declaration is needed before it is available. In general
634-
// this is still not enough, as it is possible to create sufficiently convoluted
635-
// recursive type definitions that will cause a type alias to be needed before it
636-
// is available (see issue #25838 for examples).
637-
// As an aside, the cmd/compiler suffers from the same problem (#25838).
632+
// We process non-alias type declarations first, followed by alias declarations,
633+
// and then everything else. This appears to avoid most situations where the type
634+
// of an alias is needed before it is available.
635+
// There may still be cases where this is not good enough (see also issue #25838).
636+
// In those cases Checker.ident will report an error ("invalid use of type alias").
638637
var aliasList []*TypeName
639-
// phase 1
638+
var othersList []Object // everything that's not a type
639+
// phase 1: non-alias type declarations
640640
for _, obj := range objList {
641-
// If we have a type alias, collect it for the 2nd phase.
642-
if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].tdecl.Assign.IsValid() {
643-
aliasList = append(aliasList, tname)
644-
continue
641+
if tname, _ := obj.(*TypeName); tname != nil {
642+
if check.objMap[tname].tdecl.Assign.IsValid() {
643+
aliasList = append(aliasList, tname)
644+
} else {
645+
check.objDecl(obj, nil)
646+
}
647+
} else {
648+
othersList = append(othersList, obj)
645649
}
646-
647-
check.objDecl(obj, nil)
648650
}
649-
// phase 2
651+
// phase 2: alias type declarations
650652
for _, obj := range aliasList {
651653
check.objDecl(obj, nil)
652654
}
655+
// phase 3: all other declarations
656+
for _, obj := range othersList {
657+
check.objDecl(obj, nil)
658+
}
653659

654660
// At this point we may have a non-empty check.methods map; this means that not all
655661
// entries were deleted at the end of typeDecl because the respective receiver base
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2022 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 p
6+
7+
// examples from the issue
8+
9+
type (
10+
e = f
11+
f = g
12+
g = []h
13+
h i
14+
i = j
15+
j = e
16+
)
17+
18+
type (
19+
e1 = []h1
20+
h1 e1
21+
)
22+
23+
type (
24+
P = *T
25+
T P
26+
)

src/go/types/testdata/fixedbugs/issue50259.go2

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ package p
77
var x T[B]
88

99
type T[_ any] struct{}
10-
type A T[B /* ERROR invalid use of type alias */ ]
10+
type A T[B]
1111
type B = T[A]
1212

1313
// test case from issue
1414

1515
var v Box[Step]
1616
type Box[T any] struct{}
1717
type Step = Box[StepBox]
18-
type StepBox Box[Step /* ERROR invalid use of type alias */ ]
18+
type StepBox Box[Step]

src/go/types/testdata/fixedbugs/issue50276.go2

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ type pair[S any] struct {}
1111

1212
var _ transform[step]
1313

14-
type box transform[step /* ERROR invalid use of type alias */ ]
14+
type box transform[step]
1515
type step = pair[box]
1616

1717
// test case from issue
@@ -27,7 +27,7 @@ var first Transform[Step]
2727
// This line doesn't use the Step alias, and it compiles fine if you uncomment it.
2828
var second Transform[Pair[Box, interface{}]]
2929

30-
type Box *Transform[Step /* ERROR invalid use of type alias */ ]
30+
type Box *Transform[Step]
3131

3232
// This line is the same as the `first` line, but it comes after the Box declaration and
3333
// does not break the compile.

test/typeparam/issue50259.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// errorcheck -G=3
1+
// compile -G=3
22

33
// Copyright 2022 The Go Authors. All rights reserved.
44
// Use of this source code is governed by a BSD-style
@@ -9,5 +9,5 @@ package p
99
var x T[B]
1010

1111
type T[_ any] struct{}
12-
type A T[B] // ERROR "invalid use of type alias B in recursive type"
12+
type A T[B]
1313
type B = T[A]

0 commit comments

Comments
 (0)