From dff7c5f22f30a24c5eb0df028cdbac05a79a5441 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Tue, 22 Feb 2022 09:47:31 -0500 Subject: [PATCH] go/internal/gcimporter: guard against infinite recursion with recursive type parameters This is a partial port of CL 386335 to x/tools. I have not yet been able to reproduce the crash in a test. For golang/go#51219 Change-Id: I262e6a9dba936b18513ee5f11a2a72d4155d3833 Reviewed-on: https://go-review.googlesource.com/c/tools/+/392475 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Matthew Dempsky gopls-CI: kokoro TryBot-Result: Gopher Robot --- go/internal/gcimporter/iimport.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/go/internal/gcimporter/iimport.go b/go/internal/gcimporter/iimport.go index 1a33cd5c6cd..84cfb807d73 100644 --- a/go/internal/gcimporter/iimport.go +++ b/go/internal/gcimporter/iimport.go @@ -237,6 +237,15 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data pkg.MarkComplete() } + // SetConstraint can't be called if the constraint type is not yet complete. + // When type params are created in the 'P' case of (*importReader).obj(), + // the associated constraint type may not be complete due to recursion. + // Therefore, we defer calling SetConstraint there, and call it here instead + // after all types are complete. + for _, d := range p.later { + typeparams.SetTypeParamConstraint(d.t, d.constraint) + } + for _, typ := range p.interfaceList { typ.Complete() } @@ -244,6 +253,11 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data return pkgs, nil } +type setConstraintArgs struct { + t *typeparams.TypeParam + constraint types.Type +} + type iimporter struct { version int ipath string @@ -260,6 +274,9 @@ type iimporter struct { fake fakeFileSet interfaceList []*types.Interface + // Arguments for calls to SetConstraint that are deferred due to recursive types + later []setConstraintArgs + indent int // for tracing support } @@ -458,7 +475,11 @@ func (r *importReader) obj(name string) { } typeparams.MarkImplicit(iface) } - typeparams.SetTypeParamConstraint(t, constraint) + // The constraint type may not be complete, if we + // are in the middle of a type recursion involving type + // constraints. So, we defer SetConstraint until we have + // completely set up all types in ImportData. + r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint}) case 'V': typ := r.typ()