]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: better debugging output for init order computation
authorRobert Griesemer <gri@golang.org>
Tue, 24 May 2016 00:43:09 +0000 (17:43 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 27 May 2016 23:39:38 +0000 (23:39 +0000)
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 <adonovan@google.com>
src/go/types/api_test.go
src/go/types/initorder.go
src/go/types/resolver.go

index 8b8ae1bb5d038c9928c6d08f55877fff0876bd0c..035ffd6f39a1735a4e0a47c53e6433891a9792f0 100644 (file)
@@ -572,6 +572,47 @@ func TestInitOrderInfo(t *testing.T) {
                `, []string{
                        "a = next()", "b = next()", "c = next()", "d = next()", "e = next()", "f = next()", "_ = makeOrder()",
                }},
+               // test case for issue 10709
+               // TODO(gri) enable once the issue is fixed
+               // {`package p13
+
+               // var (
+               //     v = t.m()
+               //     t = makeT(0)
+               // )
+
+               // type T struct{}
+
+               // func (T) m() int { return 0 }
+
+               // func makeT(n int) T {
+               //     if n > 0 {
+               //         return makeT(n-1)
+               //     }
+               //     return T{}
+               // }`, []string{
+               //      "t = makeT(0)", "v = t.m()",
+               // }},
+               // test case for issue 10709: same as test before, but variable decls swapped
+               {`package p14
+
+               var (
+                   t = makeT(0)
+                   v = t.m()
+               )
+
+               type T struct{}
+
+               func (T) m() int { return 0 }
+
+               func makeT(n int) T {
+                   if n > 0 {
+                       return makeT(n-1)
+                   }
+                   return T{}
+               }`, []string{
+                       "t = makeT(0)", "v = t.m()",
+               }},
        }
 
        for _, test := range tests {
index ac9016b46ed65f25af8e10af56798968c4e5e841..cf9b8709d8de3f7955a657a996591768b98e41c9 100644 (file)
@@ -15,25 +15,40 @@ func (check *Checker) initOrder() {
        // built from several calls to (*Checker).Files. Clear it.
        check.Info.InitOrder = check.Info.InitOrder[:0]
 
-       // compute the object dependency graph and
-       // initialize a priority queue with the list
-       // of graph nodes
+       // Compute the transposed object dependency graph and initialize
+       // a priority queue with the list of graph nodes.
        pq := nodeQueue(dependencyGraph(check.objMap))
        heap.Init(&pq)
 
        const debug = false
        if debug {
-               fmt.Printf("package %s: object dependency graph\n", check.pkg.Name())
+               fmt.Printf("Computing initialization order for %s\n\n", check.pkg)
+               fmt.Println("Object dependency graph:")
+               for obj, d := range check.objMap {
+                       if len(d.deps) > 0 {
+                               fmt.Printf("\t%s depends on\n", obj.Name())
+                               for dep := range d.deps {
+                                       fmt.Printf("\t\t%s\n", dep.Name())
+                               }
+                       } else {
+                               fmt.Printf("\t%s has no dependencies\n", obj.Name())
+                       }
+               }
+               fmt.Println()
+
+               fmt.Println("Transposed object dependency graph:")
                for _, n := range pq {
-                       for _, o := range n.out {
-                               fmt.Printf("\t%s -> %s\n", n.obj.Name(), o.obj.Name())
+                       fmt.Printf("\t%s depends on %d nodes\n", n.obj.Name(), n.in)
+                       for _, out := range n.out {
+                               fmt.Printf("\t\t%s is dependent\n", out.obj.Name())
                        }
                }
                fmt.Println()
-               fmt.Printf("package %s: initialization order\n", check.pkg.Name())
+
+               fmt.Println("Processing nodes:")
        }
 
-       // determine initialization order by removing the highest priority node
+       // Determine initialization order by removing the highest priority node
        // (the one with the fewest dependencies) and its edges from the graph,
        // repeatedly, until there are no nodes left.
        // In a valid Go program, those nodes always have zero dependencies (after
@@ -45,6 +60,11 @@ func (check *Checker) initOrder() {
                // get the next node
                n := heap.Pop(&pq).(*objNode)
 
+               if debug {
+                       fmt.Printf("\t%s (src pos %d) depends on %d nodes now\n",
+                               n.obj.Name(), n.obj.order(), n.in)
+               }
+
                // if n still depends on other nodes, we have a cycle
                if n.in > 0 {
                        mark++ // mark nodes using a different value each time
@@ -86,14 +106,15 @@ func (check *Checker) initOrder() {
                }
                init := &Initializer{infoLhs, info.init}
                check.Info.InitOrder = append(check.Info.InitOrder, init)
-
-               if debug {
-                       fmt.Printf("\t%s\n", init)
-               }
        }
 
        if debug {
                fmt.Println()
+               fmt.Println("Initialization order:")
+               for _, init := range check.Info.InitOrder {
+                       fmt.Printf("\t%s\n", init)
+               }
+               fmt.Println()
        }
 }
 
index 992188f0ff47b5eaa10385717049ebbe4f2cc2ce..cb8e72e4a6a9a4f38676c4cdc4b8fed72c3ca3c9 100644 (file)
@@ -32,7 +32,7 @@ func (d *declInfo) hasInitializer() bool {
        return d.init != nil || d.fdecl != nil && d.fdecl.Body != nil
 }
 
-// addDep adds obj as a dependency to d.
+// addDep adds obj to the set of objects d's init expression depends on.
 func (d *declInfo) addDep(obj Object) {
        m := d.deps
        if m == nil {