Skip to content

Commit 62b47c2

Browse files
griesemerandybons
authored andcommitted
[release-branch.go1.11] cmd/compile: reintroduce work-around for cyclic alias declarations
This change re-introduces (temporarily) a work-around for recursive alias type declarations, originally in https://golang.org/cl/35831/ (intended as fix for #18640). The work-around was removed later for a more comprehensive cycle detection check. That check contained a subtle error which made the code appear to work, while in fact creating incorrect types internally. See #25838 for details. By re-introducing the original work-around, we eliminate problems with many simple recursive type declarations involving aliases; specifically cases such as #27232 and #27267. However, the more general problem remains. This CL also fixes the subtle error (incorrect variable use when analyzing a type cycle) mentioned above and now issues a fatal error with a reference to the relevant issue (rather than crashing later during the compilation). While not great, this is better than the current status. The long-term solution will need to address these cycles (see #25838). As a consequence, several old test cases are not accepted anymore by the compiler since they happened to work accidentally only. This CL disables parts or all code of those test cases. The issues are: #18640, #23823, and #24939. One of the new test cases (fixedbugs/issue27232.go) exposed a go/types issue. The test case is excluded from the go/types test suite and an issue was filed (#28576). Updates #18640. Updates #23823. Updates #24939. Updates #25838. Updates #28576. Fixes #27232. Fixes #27267. Fixes #27383. Change-Id: I6c2d10da98bfc6f4f445c755fcaab17fc7b214c5 Reviewed-on: https://go-review.googlesource.com/c/147286 Reviewed-by: Matthew Dempsky <[email protected]> (cherry picked from commit e630538) Reviewed-on: https://go-review.googlesource.com/c/151339 Run-TryBot: Andrew Bonventre <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent 3e6c171 commit 62b47c2

File tree

8 files changed

+68
-10
lines changed

8 files changed

+68
-10
lines changed

src/cmd/compile/internal/gc/main.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -481,13 +481,17 @@ func Main(archInit func(*Arch)) {
481481
// Phase 1: const, type, and names and types of funcs.
482482
// This will gather all the information about types
483483
// and methods but doesn't depend on any of it.
484+
//
485+
// We also defer type alias declarations until phase 2
486+
// to avoid cycles like #18640.
487+
// TODO(gri) Remove this again once we have a fix for #25838.
484488
defercheckwidth()
485489

486490
// Don't use range--typecheck can add closures to xtop.
487491
timings.Start("fe", "typecheck", "top1")
488492
for i := 0; i < len(xtop); i++ {
489493
n := xtop[i]
490-
if op := n.Op; op != ODCL && op != OAS && op != OAS2 {
494+
if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) {
491495
xtop[i] = typecheck(n, Etop)
492496
}
493497
}
@@ -499,7 +503,7 @@ func Main(archInit func(*Arch)) {
499503
timings.Start("fe", "typecheck", "top2")
500504
for i := 0; i < len(xtop); i++ {
501505
n := xtop[i]
502-
if op := n.Op; op == ODCL || op == OAS || op == OAS2 {
506+
if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias {
503507
xtop[i] = typecheck(n, Etop)
504508
}
505509
}

src/cmd/compile/internal/gc/typecheck.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,16 @@ func typecheck(n *Node, top int) *Node {
202202
// since it would expand indefinitely when aliases
203203
// are substituted.
204204
cycle := cycleFor(n)
205-
for _, n := range cycle {
206-
if n.Name != nil && !n.Name.Param.Alias {
205+
for _, n1 := range cycle {
206+
if n1.Name != nil && !n1.Name.Param.Alias {
207+
// Cycle is ok. But if n is an alias type and doesn't
208+
// have a type yet, we have a recursive type declaration
209+
// with aliases that we can't handle properly yet.
210+
// Report an error rather than crashing later.
211+
if n.Name != nil && n.Name.Param.Alias && n.Type == nil {
212+
lineno = n.Pos
213+
Fatalf("cannot handle alias type declaration (issue #25838): %v", n)
214+
}
207215
lineno = lno
208216
return n
209217
}

src/go/types/stdlib_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ func TestStdFixed(t *testing.T) {
176176
"issue22200b.go", // go/types does not have constraints on stack size
177177
"issue25507.go", // go/types does not have constraints on stack size
178178
"issue20780.go", // go/types does not have constraints on stack size
179+
"issue27232.go", // go/types has a bug with alias type (issue #28576)
179180
)
180181
}
181182

test/fixedbugs/issue18640.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ type (
2020
d = c
2121
)
2222

23-
// The compiler reports an incorrect (non-alias related)
24-
// type cycle here (via dowith()). Disabled for now.
23+
// The compiler cannot handle these cases. Disabled for now.
2524
// See issue #25838.
2625
/*
2726
type (
@@ -32,7 +31,6 @@ type (
3231
i = j
3332
j = e
3433
)
35-
*/
3634
3735
type (
3836
a1 struct{ *b1 }
@@ -45,3 +43,4 @@ type (
4543
b2 = c2
4644
c2 struct{ *b2 }
4745
)
46+
*/

test/fixedbugs/issue23823.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
1-
// errorcheck
1+
// compile
22

33
// Copyright 2018 The Go Authors. All rights reserved.
44
// Use of this source code is governed by a BSD-style
55
// license that can be found in the LICENSE file.
66

77
package p
88

9+
// The compiler cannot handle this. Disabled for now.
10+
// See issue #25838.
11+
/*
912
type I1 = interface {
1013
I2
1114
}
1215
13-
type I2 interface { // ERROR "invalid recursive type"
16+
type I2 interface {
1417
I1
1518
}
19+
*/

test/fixedbugs/issue24939.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ type M interface {
1515
}
1616

1717
type P = interface {
18-
I() M
18+
// The compiler cannot handle this case. Disabled for now.
19+
// See issue #25838.
20+
// I() M
1921
}
2022

2123
func main() {}

test/fixedbugs/issue27232.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// compile
2+
3+
// Copyright 2018 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package p
8+
9+
type F = func(T)
10+
11+
type T interface {
12+
m(F)
13+
}
14+
15+
type t struct{}
16+
17+
func (t) m(F) {}
18+
19+
var _ T = &t{}

test/fixedbugs/issue27267.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// compile
2+
3+
// Copyright 2018 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package p
8+
9+
// 1st test case from issue
10+
type F = func(E) // compiles if not type alias or moved below E struct
11+
type E struct {
12+
f F
13+
}
14+
15+
var x = E{func(E) {}}
16+
17+
// 2nd test case from issue
18+
type P = *S
19+
type S struct {
20+
p P
21+
}

0 commit comments

Comments
 (0)