Skip to content

Commit 795809b

Browse files
committed
go/types: better debugging output for init order computation
Also: Added some test cases for issue #10709. No impact when debugging output is disabled (default). For #10709. Change-Id: I0751befb222c86d46225377a674f6bad2990349e Reviewed-on: https://go-review.googlesource.com/23442 Reviewed-by: Alan Donovan <[email protected]>
1 parent 429bbf3 commit 795809b

File tree

3 files changed

+75
-13
lines changed

3 files changed

+75
-13
lines changed

src/go/types/api_test.go

+41
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,47 @@ func TestInitOrderInfo(t *testing.T) {
572572
`, []string{
573573
"a = next()", "b = next()", "c = next()", "d = next()", "e = next()", "f = next()", "_ = makeOrder()",
574574
}},
575+
// test case for issue 10709
576+
// TODO(gri) enable once the issue is fixed
577+
// {`package p13
578+
579+
// var (
580+
// v = t.m()
581+
// t = makeT(0)
582+
// )
583+
584+
// type T struct{}
585+
586+
// func (T) m() int { return 0 }
587+
588+
// func makeT(n int) T {
589+
// if n > 0 {
590+
// return makeT(n-1)
591+
// }
592+
// return T{}
593+
// }`, []string{
594+
// "t = makeT(0)", "v = t.m()",
595+
// }},
596+
// test case for issue 10709: same as test before, but variable decls swapped
597+
{`package p14
598+
599+
var (
600+
t = makeT(0)
601+
v = t.m()
602+
)
603+
604+
type T struct{}
605+
606+
func (T) m() int { return 0 }
607+
608+
func makeT(n int) T {
609+
if n > 0 {
610+
return makeT(n-1)
611+
}
612+
return T{}
613+
}`, []string{
614+
"t = makeT(0)", "v = t.m()",
615+
}},
575616
}
576617

577618
for _, test := range tests {

src/go/types/initorder.go

+33-12
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,40 @@ func (check *Checker) initOrder() {
1515
// built from several calls to (*Checker).Files. Clear it.
1616
check.Info.InitOrder = check.Info.InitOrder[:0]
1717

18-
// compute the object dependency graph and
19-
// initialize a priority queue with the list
20-
// of graph nodes
18+
// Compute the transposed object dependency graph and initialize
19+
// a priority queue with the list of graph nodes.
2120
pq := nodeQueue(dependencyGraph(check.objMap))
2221
heap.Init(&pq)
2322

2423
const debug = false
2524
if debug {
26-
fmt.Printf("package %s: object dependency graph\n", check.pkg.Name())
25+
fmt.Printf("Computing initialization order for %s\n\n", check.pkg)
26+
fmt.Println("Object dependency graph:")
27+
for obj, d := range check.objMap {
28+
if len(d.deps) > 0 {
29+
fmt.Printf("\t%s depends on\n", obj.Name())
30+
for dep := range d.deps {
31+
fmt.Printf("\t\t%s\n", dep.Name())
32+
}
33+
} else {
34+
fmt.Printf("\t%s has no dependencies\n", obj.Name())
35+
}
36+
}
37+
fmt.Println()
38+
39+
fmt.Println("Transposed object dependency graph:")
2740
for _, n := range pq {
28-
for _, o := range n.out {
29-
fmt.Printf("\t%s -> %s\n", n.obj.Name(), o.obj.Name())
41+
fmt.Printf("\t%s depends on %d nodes\n", n.obj.Name(), n.in)
42+
for _, out := range n.out {
43+
fmt.Printf("\t\t%s is dependent\n", out.obj.Name())
3044
}
3145
}
3246
fmt.Println()
33-
fmt.Printf("package %s: initialization order\n", check.pkg.Name())
47+
48+
fmt.Println("Processing nodes:")
3449
}
3550

36-
// determine initialization order by removing the highest priority node
51+
// Determine initialization order by removing the highest priority node
3752
// (the one with the fewest dependencies) and its edges from the graph,
3853
// repeatedly, until there are no nodes left.
3954
// In a valid Go program, those nodes always have zero dependencies (after
@@ -45,6 +60,11 @@ func (check *Checker) initOrder() {
4560
// get the next node
4661
n := heap.Pop(&pq).(*objNode)
4762

63+
if debug {
64+
fmt.Printf("\t%s (src pos %d) depends on %d nodes now\n",
65+
n.obj.Name(), n.obj.order(), n.in)
66+
}
67+
4868
// if n still depends on other nodes, we have a cycle
4969
if n.in > 0 {
5070
mark++ // mark nodes using a different value each time
@@ -86,14 +106,15 @@ func (check *Checker) initOrder() {
86106
}
87107
init := &Initializer{infoLhs, info.init}
88108
check.Info.InitOrder = append(check.Info.InitOrder, init)
89-
90-
if debug {
91-
fmt.Printf("\t%s\n", init)
92-
}
93109
}
94110

95111
if debug {
96112
fmt.Println()
113+
fmt.Println("Initialization order:")
114+
for _, init := range check.Info.InitOrder {
115+
fmt.Printf("\t%s\n", init)
116+
}
117+
fmt.Println()
97118
}
98119
}
99120

src/go/types/resolver.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (d *declInfo) hasInitializer() bool {
3232
return d.init != nil || d.fdecl != nil && d.fdecl.Body != nil
3333
}
3434

35-
// addDep adds obj as a dependency to d.
35+
// addDep adds obj to the set of objects d's init expression depends on.
3636
func (d *declInfo) addDep(obj Object) {
3737
m := d.deps
3838
if m == nil {

0 commit comments

Comments
 (0)