From 7517d8bae3f41c96cb511cf241a14fd807a2e103 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 18 Jun 2013 15:34:12 -0700 Subject: [PATCH] go.tools/go/types: catch cycles in function declarations Fixes golang/go#5217. R=adonovan CC=golang-dev https://golang.org/cl/10402044 --- go/types/resolver.go | 7 ++++--- go/types/testdata/decls0.src | 12 ++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/go/types/resolver.go b/go/types/resolver.go index cb9caaa3..ac47ddde 100644 --- a/go/types/resolver.go +++ b/go/types/resolver.go @@ -347,7 +347,7 @@ func (check *checker) declareObject(obj Object, cycleOk bool) { case *TypeName: check.declareType(obj, d.typ, cycleOk) case *Func: - check.declareFunc(obj, cycleOk) + check.declareFunc(obj) default: unreachable() } @@ -525,12 +525,13 @@ func (check *checker) declareType(obj *TypeName, typ ast.Expr, cycleOk bool) { } } -func (check *checker) declareFunc(obj *Func, cycleOk bool) { +func (check *checker) declareFunc(obj *Func) { fdecl := obj.decl // methods are typechecked when their receivers are typechecked // TODO(gri) there is no reason to make this a special case: receivers are simply parameters if fdecl.Recv == nil { - sig := check.typ(fdecl.Type, cycleOk).(*Signature) + obj.typ = Typ[Invalid] // guard against cycles + sig := check.typ(fdecl.Type, false).(*Signature) if obj.name == "init" && (sig.params.Len() > 0 || sig.results.Len() > 0) { check.errorf(fdecl.Pos(), "func init must have no arguments and no return values") // ok to continue diff --git a/go/types/testdata/decls0.src b/go/types/testdata/decls0.src index fe7995b9..f8a50482 100644 --- a/go/types/testdata/decls0.src +++ b/go/types/testdata/decls0.src @@ -186,6 +186,18 @@ type ( Last int ) +// cycles in function/method declarations +// (test cases for issue 5217 and variants) +func f1(x f1 /* ERROR "not a type" */ ) {} +func f2(x *f2 /* ERROR "cannot indirect" */ ) {} +func f3() (x f3 /* ERROR "not a type" */ ) { return } +func f4() (x *f4 /* ERROR "cannot indirect" */ ) { return } + +func (S0) m1(x S0 /* ERROR "field or method" */ .m1) {} +func (S0) m2(x *S0 /* ERROR "field or method" */ .m2) {} +func (S0) m3() (x S0 /* ERROR "field or method" */ .m3) { return } +func (S0) m4() (x *S0 /* ERROR "field or method" */ .m4) { return } + // interfaces may have blank methods type BlankI interface { _()