From 51d8ee0ff8958ff43eebcd5d62fdb1434f26304c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 9 May 2014 13:57:38 -0700 Subject: [PATCH] go.tools/go/types: report init dependencies via method values - one-line fix - comprehensive set of test cases added Fixes golang/go#7963. LGTM=adonovan R=adonovan CC=golang-codereviews https://golang.org/cl/100320043 --- go/types/call.go | 2 + go/types/check_test.go | 1 + go/types/testdata/init0.src | 4 +- go/types/testdata/init1.src | 8 +-- go/types/testdata/init2.src | 139 ++++++++++++++++++++++++++++++++++++ 5 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 go/types/testdata/init2.src diff --git a/go/types/call.go b/go/types/call.go index 74f88872..1bf73a3a 100644 --- a/go/types/call.go +++ b/go/types/call.go @@ -408,6 +408,8 @@ func (check *checker) selector(x *operand, e *ast.SelectorExpr) { sig.recv = nil x.typ = &sig + check.addDeclDep(obj) + default: unreachable() } diff --git a/go/types/check_test.go b/go/types/check_test.go index da21986f..619e1f1e 100644 --- a/go/types/check_test.go +++ b/go/types/check_test.go @@ -57,6 +57,7 @@ var tests = [][]string{ {"testdata/cycles4.src"}, {"testdata/init0.src"}, {"testdata/init1.src"}, + {"testdata/init2.src"}, {"testdata/decls0.src"}, {"testdata/decls1.src"}, {"testdata/decls2a.src", "testdata/decls2b.src"}, diff --git a/go/types/testdata/init0.src b/go/types/testdata/init0.src index 9467daf8..e475f9ad 100644 --- a/go/types/testdata/init0.src +++ b/go/types/testdata/init0.src @@ -96,11 +96,11 @@ func (T1) m() bool { _ = x11; return false } var x11 /* ERROR initialization cycle */ = T1.m(T1{}) -// no cycles via method values +// cycles via method values type T2 struct{} func (T2) m() bool { _ = x12; return false } var t1 T2 -var x12 = t1.m +var x12 /* ERROR initialization cycle */ = t1.m diff --git a/go/types/testdata/init1.src b/go/types/testdata/init1.src index 0a594948..39ca3146 100644 --- a/go/types/testdata/init1.src +++ b/go/types/testdata/init1.src @@ -14,7 +14,7 @@ func (T0) m() int { return y0 } var x0 = T0{} -var y0 = x0.m() // no cycle reported +var y0 /* ERROR initialization cycle */ = x0.m() type T1 struct{} @@ -24,7 +24,7 @@ var x1 interface { m() int } = T1{} -var y1 = x1.m() // no cycle reported +var y1 = x1.m() // no cycle reported, x1 is of interface type // issue 6703 (modified) @@ -50,7 +50,7 @@ func (T3) m() int { return 0 } -var x4 = T4{}.m // <<<< added {} +var x4 /* ERROR initialization cycle */ = T4{}.m // <<<< added {} var y4 = x4 @@ -61,7 +61,7 @@ func (T4) m() int { return 0 } -var x5 = T5{}.m() // <<<< added () +var x5 /* ERROR initialization cycle */ = T5{}.m() // <<<< added () var y5 = x5 diff --git a/go/types/testdata/init2.src b/go/types/testdata/init2.src new file mode 100644 index 00000000..614db6c9 --- /dev/null +++ b/go/types/testdata/init2.src @@ -0,0 +1,139 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// initialization cycles + +package init2 + +// cycles through functions + +func f1() int { _ = x1; return 0 } +var x1 /* ERROR initialization cycle */ = f1 + +func f2() int { _ = x2; return 0 } +var x2 /* ERROR initialization cycle */ = f2() + +// cycles through method expressions + +type T3 int +func (T3) m() int { _ = x3; return 0 } +var x3 /* ERROR initialization cycle */ = T3.m + +type T4 int +func (T4) m() int { _ = x4; return 0 } +var x4 /* ERROR initialization cycle */ = T4.m(0) + +type T3p int +func (*T3p) m() int { _ = x3p; return 0 } +var x3p /* ERROR initialization cycle */ = (*T3p).m + +type T4p int +func (*T4p) m() int { _ = x4p; return 0 } +var x4p /* ERROR initialization cycle */ = (*T4p).m(nil) + +// cycles through method expressions of embedded methods + +type T5 struct { E5 } +type E5 int +func (E5) m() int { _ = x5; return 0 } +var x5 /* ERROR initialization cycle */ = T5.m + +type T6 struct { E6 } +type E6 int +func (E6) m() int { _ = x6; return 0 } +var x6 /* ERROR initialization cycle */ = T6.m(T6{0}) + +type T5p struct { E5p } +type E5p int +func (*E5p) m() int { _ = x5p; return 0 } +var x5p /* ERROR initialization cycle */ = (*T5p).m + +type T6p struct { E6p } +type E6p int +func (*E6p) m() int { _ = x6p; return 0 } +var x6p /* ERROR initialization cycle */ = (*T6p).m(nil) + +// cycles through method values + +type T7 int +func (T7) m() int { _ = x7; return 0 } +var x7 /* ERROR initialization cycle */ = T7(0).m + +type T8 int +func (T8) m() int { _ = x8; return 0 } +var x8 /* ERROR initialization cycle */ = T8(0).m() + +type T7p int +func (*T7p) m() int { _ = x7p; return 0 } +var x7p /* ERROR initialization cycle */ = new(T7p).m + +type T8p int +func (*T8p) m() int { _ = x8p; return 0 } +var x8p /* ERROR initialization cycle */ = new(T8p).m() + +type T7v int +func (T7v) m() int { _ = x7v; return 0 } +var x7var T7v +var x7v /* ERROR initialization cycle */ = x7var.m + +type T8v int +func (T8v) m() int { _ = x8v; return 0 } +var x8var T8v +var x8v /* ERROR initialization cycle */ = x8var.m() + +type T7pv int +func (*T7pv) m() int { _ = x7pv; return 0 } +var x7pvar *T7pv +var x7pv /* ERROR initialization cycle */ = x7pvar.m + +type T8pv int +func (*T8pv) m() int { _ = x8pv; return 0 } +var x8pvar *T8pv +var x8pv /* ERROR initialization cycle */ = x8pvar.m() + +// cycles through method values of embedded methods + +type T9 struct { E9 } +type E9 int +func (E9) m() int { _ = x9; return 0 } +var x9 /* ERROR initialization cycle */ = T9{0}.m + +type T10 struct { E10 } +type E10 int +func (E10) m() int { _ = x10; return 0 } +var x10 /* ERROR initialization cycle */ = T10{0}.m() + +type T9p struct { E9p } +type E9p int +func (*E9p) m() int { _ = x9p; return 0 } +var x9p /* ERROR initialization cycle */ = new(T9p).m + +type T10p struct { E10p } +type E10p int +func (*E10p) m() int { _ = x10p; return 0 } +var x10p /* ERROR initialization cycle */ = new(T10p).m() + +type T9v struct { E9v } +type E9v int +func (E9v) m() int { _ = x9v; return 0 } +var x9var T9v +var x9v /* ERROR initialization cycle */ = x9var.m + +type T10v struct { E10v } +type E10v int +func (E10v) m() int { _ = x10v; return 0 } +var x10var T10v +var x10v /* ERROR initialization cycle */ = x10var.m() + +type T9pv struct { E9pv } +type E9pv int +func (*E9pv) m() int { _ = x9pv; return 0 } +var x9pvar *T9pv +var x9pv /* ERROR initialization cycle */ = x9pvar.m + +type T10pv struct { E10pv } +type E10pv int +func (*E10pv) m() int { _ = x10pv; return 0 } +var x10pvar *T10pv +var x10pv /* ERROR initialization cycle */ = x10pvar.m()