Skip to content

Commit

Permalink
go/internal/gcimporter: guard against infinite recursion with recursive
Browse files Browse the repository at this point in the history
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 <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
  • Loading branch information
findleyr committed Mar 14, 2022
1 parent 49d48a0 commit dff7c5f
Showing 1 changed file with 22 additions and 1 deletion.
23 changes: 22 additions & 1 deletion go/internal/gcimporter/iimport.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,13 +237,27 @@ 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()
}

return pkgs, nil
}

type setConstraintArgs struct {
t *typeparams.TypeParam
constraint types.Type
}

type iimporter struct {
version int
ipath string
Expand All @@ -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
}

Expand Down Expand Up @@ -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()
Expand Down

0 comments on commit dff7c5f

Please sign in to comment.