Skip to content

Commit e5cf370

Browse files
committed
internal/typeparams: factor 2 copies of isParameterized
The typeparams.Free.Has(T) method reports whether type T has free type parameters. It factors two copies of this algorithm, themselves copied from go/types. Change-Id: I285e26ba82b28ca0a3ddbd956fa75e342a0dc22d Reviewed-on: https://go-review.googlesource.com/c/tools/+/573135 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Tim King <[email protected]> Auto-Submit: Alan Donovan <[email protected]> Commit-Queue: Alan Donovan <[email protected]>
1 parent e0a9567 commit e5cf370

File tree

9 files changed

+74
-196
lines changed

9 files changed

+74
-196
lines changed

go/analysis/passes/ifaceassert/ifaceassert.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"golang.org/x/tools/go/analysis/passes/inspect"
1414
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
1515
"golang.org/x/tools/go/ast/inspector"
16+
"golang.org/x/tools/internal/typeparams"
1617
)
1718

1819
//go:embed doc.go
@@ -28,7 +29,7 @@ var Analyzer = &analysis.Analyzer{
2829

2930
// assertableTo checks whether interface v can be asserted into t. It returns
3031
// nil on success, or the first conflicting method on failure.
31-
func assertableTo(v, t types.Type) *types.Func {
32+
func assertableTo(free *typeparams.Free, v, t types.Type) *types.Func {
3233
if t == nil || v == nil {
3334
// not assertable to, but there is no missing method
3435
return nil
@@ -42,7 +43,7 @@ func assertableTo(v, t types.Type) *types.Func {
4243

4344
// Mitigations for interface comparisons and generics.
4445
// TODO(https://github.com/golang/go/issues/50658): Support more precise conclusion.
45-
if isParameterized(V) || isParameterized(T) {
46+
if free.Has(V) || free.Has(T) {
4647
return nil
4748
}
4849
if f, wrongType := types.MissingMethod(V, T, false); wrongType {
@@ -57,6 +58,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
5758
(*ast.TypeAssertExpr)(nil),
5859
(*ast.TypeSwitchStmt)(nil),
5960
}
61+
var free typeparams.Free
6062
inspect.Preorder(nodeFilter, func(n ast.Node) {
6163
var (
6264
assert *ast.TypeAssertExpr // v.(T) expression
@@ -86,7 +88,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
8688
V := pass.TypesInfo.TypeOf(assert.X)
8789
for _, target := range targets {
8890
T := pass.TypesInfo.TypeOf(target)
89-
if f := assertableTo(V, T); f != nil {
91+
if f := assertableTo(&free, V, T); f != nil {
9092
pass.Reportf(
9193
target.Pos(),
9294
"impossible type assertion: no type can implement both %v and %v (conflicting types for %v method)",

go/ssa/create.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,12 @@ import (
3434
// See the Example tests for simple examples.
3535
func NewProgram(fset *token.FileSet, mode BuilderMode) *Program {
3636
return &Program{
37-
Fset: fset,
38-
imported: make(map[string]*Package),
39-
packages: make(map[*types.Package]*Package),
40-
mode: mode,
41-
canon: newCanonizer(),
42-
ctxt: types.NewContext(),
43-
parameterized: tpWalker{seen: make(map[types.Type]bool)},
37+
Fset: fset,
38+
imported: make(map[string]*Package),
39+
packages: make(map[*types.Package]*Package),
40+
mode: mode,
41+
canon: newCanonizer(),
42+
ctxt: types.NewContext(),
4443
}
4544
}
4645

go/ssa/emit.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ func emitConv(f *Function, val Value, typ types.Type) Value {
249249
// Record the types of operands to MakeInterface, if
250250
// non-parameterized, as they are the set of runtime types.
251251
t := val.Type()
252-
if f.typeparams.Len() == 0 || !f.Prog.parameterized.isParameterized(t) {
252+
if f.typeparams.Len() == 0 || !f.Prog.isParameterized(t) {
253253
addRuntimeType(f.Prog, t)
254254
}
255255

go/ssa/instantiate.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func createInstance(fn *Function, targs []types.Type, cr *creator) *Function {
7575
subst *subster
7676
build buildFunc
7777
)
78-
if prog.mode&InstantiateGenerics != 0 && !prog.parameterized.anyParameterized(targs) {
78+
if prog.mode&InstantiateGenerics != 0 && !prog.isParameterized(targs...) {
7979
synthetic = fmt.Sprintf("instance of %s", fn.Name())
8080
if fn.syntax != nil {
8181
scope := obj.Origin().Scope()
@@ -110,3 +110,21 @@ func createInstance(fn *Function, targs []types.Type, cr *creator) *Function {
110110
cr.Add(instance)
111111
return instance
112112
}
113+
114+
// isParameterized reports whether any of the specified types contains
115+
// a free type parameter. It is safe to call concurrently.
116+
func (prog *Program) isParameterized(ts ...types.Type) bool {
117+
prog.hasParamsMu.Lock()
118+
defer prog.hasParamsMu.Unlock()
119+
120+
// TODO(adonovan): profile. If this operation is expensive,
121+
// handle the most common but shallow cases such as T, pkg.T,
122+
// *T without consulting the cache under the lock.
123+
124+
for _, t := range ts {
125+
if prog.hasParams.Has(t) {
126+
return true
127+
}
128+
}
129+
return false
130+
}

go/ssa/methods.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (prog *Program) MethodValue(sel *types.Selection) *Function {
3232
return nil // interface method or type parameter
3333
}
3434

35-
if prog.parameterized.isParameterized(T) {
35+
if prog.isParameterized(T) {
3636
return nil // generic method
3737
}
3838

go/ssa/parameterized.go

Lines changed: 0 additions & 145 deletions
This file was deleted.

go/ssa/ssa.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ type Program struct {
3333
methodsMu sync.Mutex
3434
methodSets typeutil.Map // maps type to its concrete *methodSet
3535

36-
parameterized tpWalker // memoization of whether a type refers to type parameters
36+
// memoization of whether a type refers to type parameters
37+
hasParamsMu sync.Mutex
38+
hasParams typeparams.Free
3739

3840
runtimeTypesMu sync.Mutex
3941
runtimeTypes typeutil.Map // set of runtime types (from MakeInterface)

0 commit comments

Comments
 (0)