Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b2ab7b5

Browse files
Merge branch 'master' of github.com:gopherjs/gopherjs into indexedSel
2 parents 1ff0ea5 + 120c98d commit b2ab7b5

File tree

24 files changed

+1412
-516
lines changed

24 files changed

+1412
-516
lines changed

compiler/compiler_test.go

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,179 @@ func TestDeclSelection_RemoveUnusedTypeConstraint(t *testing.T) {
364364
sel.IsDead(`var:command-line-arguments.ghost`)
365365
}
366366

367+
func TestDeclSelection_RemoveUnusedNestedTypesInFunction(t *testing.T) {
368+
src := `
369+
package main
370+
func Foo[T any](u T) any {
371+
type Bar struct { v T }
372+
return Bar{v: u}
373+
}
374+
func deadCode() {
375+
println(Foo[int](42))
376+
}
377+
func main() {
378+
println(Foo[string]("cat"))
379+
}`
380+
381+
srcFiles := []srctesting.Source{{Name: `main.go`, Contents: []byte(src)}}
382+
sel := declSelection(t, srcFiles, nil)
383+
sel.IsAlive(`func:command-line-arguments.main`)
384+
385+
sel.IsAlive(`funcVar:command-line-arguments.Foo`)
386+
sel.IsAlive(`func:command-line-arguments.Foo<string>`)
387+
sel.IsDead(`func:command-line-arguments.Foo<int>`)
388+
389+
sel.IsAlive(`typeVar:command-line-arguments.Bar`)
390+
sel.IsAlive(`type:command-line-arguments.Bar<string;>`)
391+
sel.IsDead(`type:command-line-arguments.Bar<int;>`)
392+
393+
sel.IsDead(`funcVar:command-line-arguments.deadCode`)
394+
sel.IsDead(`func:command-line-arguments.deadCode`)
395+
}
396+
397+
func TestDeclSelection_RemoveUnusedNestedTypesInMethod(t *testing.T) {
398+
src := `
399+
package main
400+
type Baz[T any] struct{}
401+
func (b *Baz[T]) Foo(u T) any {
402+
type Bar struct { v T }
403+
return Bar{v: u}
404+
}
405+
func deadCode() {
406+
b := Baz[int]{}
407+
println(b.Foo(42))
408+
}
409+
func main() {
410+
b := Baz[string]{}
411+
println(b.Foo("cat"))
412+
}`
413+
414+
srcFiles := []srctesting.Source{{Name: `main.go`, Contents: []byte(src)}}
415+
sel := declSelection(t, srcFiles, nil)
416+
sel.IsAlive(`func:command-line-arguments.main`)
417+
418+
sel.IsAlive(`typeVar:command-line-arguments.Baz`)
419+
sel.IsDead(`type:command-line-arguments.Baz<int>`)
420+
sel.IsAlive(`type:command-line-arguments.Baz<string>`)
421+
422+
sel.IsDead(`func:command-line-arguments.(*Baz).Foo<int>`)
423+
sel.IsAlive(`func:command-line-arguments.(*Baz).Foo<string>`)
424+
425+
sel.IsAlive(`typeVar:command-line-arguments.Bar`)
426+
sel.IsDead(`type:command-line-arguments.Bar<int;>`)
427+
sel.IsAlive(`type:command-line-arguments.Bar<string;>`)
428+
429+
sel.IsDead(`funcVar:command-line-arguments.deadCode`)
430+
sel.IsDead(`func:command-line-arguments.deadCode`)
431+
}
432+
433+
func TestDeclSelection_RemoveAllUnusedNestedTypes(t *testing.T) {
434+
src := `
435+
package main
436+
func Foo[T any](u T) any {
437+
type Bar struct { v T }
438+
return Bar{v: u}
439+
}
440+
func deadCode() {
441+
println(Foo[int](42))
442+
println(Foo[string]("cat"))
443+
}
444+
func main() {}`
445+
446+
srcFiles := []srctesting.Source{{Name: `main.go`, Contents: []byte(src)}}
447+
sel := declSelection(t, srcFiles, nil)
448+
sel.IsAlive(`func:command-line-arguments.main`)
449+
450+
sel.IsDead(`funcVar:command-line-arguments.Foo`)
451+
sel.IsDead(`func:command-line-arguments.Foo<string>`)
452+
sel.IsDead(`func:command-line-arguments.Foo<int>`)
453+
454+
sel.IsDead(`typeVar:command-line-arguments.Bar`)
455+
sel.IsDead(`type:command-line-arguments.Bar<string;>`)
456+
sel.IsDead(`type:command-line-arguments.Bar<int;>`)
457+
458+
sel.IsDead(`funcVar:command-line-arguments.deadCode`)
459+
sel.IsDead(`func:command-line-arguments.deadCode`)
460+
}
461+
462+
func TestDeclSelection_CompletelyRemoveNestedType(t *testing.T) {
463+
src := `
464+
package main
465+
func Foo[T any](u T) any {
466+
type Bar struct { v T }
467+
return Bar{v: u}
468+
}
469+
func deadCode() {
470+
println(Foo[int](42))
471+
}
472+
func main() {}`
473+
474+
srcFiles := []srctesting.Source{{Name: `main.go`, Contents: []byte(src)}}
475+
sel := declSelection(t, srcFiles, nil)
476+
477+
sel.IsAlive(`func:command-line-arguments.main`)
478+
479+
sel.IsDead(`funcVar:command-line-arguments.Foo`)
480+
sel.IsDead(`func:command-line-arguments.Foo<int>`)
481+
482+
sel.IsDead(`typeVar:command-line-arguments.Bar`)
483+
sel.IsDead(`type:command-line-arguments.Bar<int;>`)
484+
485+
sel.IsDead(`funcVar:command-line-arguments.deadCode`)
486+
sel.IsDead(`func:command-line-arguments.deadCode`)
487+
}
488+
489+
func TestDeclSelection_RemoveAnonNestedTypes(t *testing.T) {
490+
// Based on test/fixedbugs/issue53635.go
491+
// This checks that if an anon type (e.g. []T) is used in a function
492+
// that is not used, the type is removed, otherwise it is kept.
493+
494+
src := `
495+
package main
496+
func Foo[T any](u T) any {
497+
return []T(nil)
498+
}
499+
func deadCode() {
500+
println(Foo[string]("cat"))
501+
}
502+
func main() {
503+
println(Foo[int](42))
504+
}`
505+
506+
srcFiles := []srctesting.Source{{Name: `main.go`, Contents: []byte(src)}}
507+
sel := declSelection(t, srcFiles, nil)
508+
sel.IsDead(`anonType:command-line-arguments.sliceType`) // []string
509+
sel.IsAlive(`anonType:command-line-arguments.sliceType$1`) // []int
510+
}
511+
512+
func TestDeclSelection_NoNestAppliedToFuncCallInMethod(t *testing.T) {
513+
// Checks that a function call to a non-local function isn't
514+
// being labeled as a nested function call.
515+
src := `
516+
package main
517+
func foo(a any) {
518+
println(a)
519+
}
520+
type Bar[T any] struct { u T }
521+
func (b *Bar[T]) Baz() {
522+
foo(b.u)
523+
}
524+
func main() {
525+
b := &Bar[int]{u: 42}
526+
b.Baz()
527+
}`
528+
529+
srcFiles := []srctesting.Source{{Name: `main.go`, Contents: []byte(src)}}
530+
sel := declSelection(t, srcFiles, nil)
531+
sel.IsAlive(`init:main`)
532+
533+
sel.IsAlive(`typeVar:command-line-arguments.Bar`)
534+
sel.IsAlive(`type:command-line-arguments.Bar<int>`)
535+
sel.IsAlive(`func:command-line-arguments.(*Bar).Baz<int>`)
536+
537+
sel.IsAlive(`func:command-line-arguments.foo`)
538+
}
539+
367540
func TestLengthParenthesizingIssue841(t *testing.T) {
368541
// See issue https://github.com/gopherjs/gopherjs/issues/841
369542
//

compiler/declNames.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,17 @@ func funcDeclFullName(inst typeparams.Instance) string {
4949
}
5050

5151
// typeVarDeclFullName returns a unique name for a package-level variable
52-
// that is used for a named type declaration.
52+
// that is used for a named type declaration or a named nested type declaration.
5353
// If the type is generic, this declaration name is also for the list
5454
// of instantiations of the type.
5555
func typeVarDeclFullName(o *types.TypeName) string {
5656
return `typeVar:` + symbol.New(o).String()
5757
}
5858

5959
// typeDeclFullName returns a unique name for a package-level type declaration
60-
// for the given instance of a type. Names are only unique per package.
60+
// for the given instance of a type. Names are only unique per scope package
61+
// unless the type is a nested type then the name is only unique per the
62+
// function or method it is declared in.
6163
func typeDeclFullName(inst typeparams.Instance) string {
6264
return `type:` + inst.String()
6365
}

compiler/decls.go

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ func (fc *funcContext) newVarDecl(init *types.Initializer) *Decl {
264264
fc.localVars = nil // Clean up after ourselves.
265265
})
266266

267-
d.Dce().SetName(init.Lhs[0])
267+
d.Dce().SetName(init.Lhs[0], nil, nil)
268268
if len(init.Lhs) != 1 || analysis.HasSideEffect(init.Rhs, fc.pkgCtx.Info.Info) {
269269
d.Dce().SetAsAlive()
270270
}
@@ -297,7 +297,7 @@ func (fc *funcContext) funcDecls(functions []*ast.FuncDecl) ([]*Decl, error) {
297297
FullName: funcVarDeclFullName(o),
298298
Vars: []string{objName},
299299
}
300-
varDecl.Dce().SetName(o)
300+
varDecl.Dce().SetName(o, nil, nil)
301301
if len(instances) > 1 || !instances[0].IsTrivial() {
302302
varDecl.DeclCode = fc.CatchOutput(0, func() {
303303
fc.Printf("%s = {};", objName)
@@ -340,7 +340,7 @@ func (fc *funcContext) newFuncDecl(fun *ast.FuncDecl, inst typeparams.Instance)
340340
Blocking: fc.pkgCtx.IsBlocking(inst),
341341
LinkingName: symbol.New(o),
342342
}
343-
d.Dce().SetName(o, inst.TArgs...)
343+
d.Dce().SetName(o, inst.TNest, inst.TArgs)
344344

345345
if typesutil.IsMethod(o) {
346346
recv := typesutil.RecvType(o.Type().(*types.Signature)).Obj()
@@ -442,6 +442,7 @@ func (fc *funcContext) newNamedTypeVarDecl(obj *types.TypeName) *Decl {
442442
FullName: typeVarDeclFullName(obj),
443443
Vars: []string{name},
444444
}
445+
varDecl.Dce().SetName(obj, nil, nil)
445446
if fc.pkgCtx.instanceSet.Pkg(obj.Pkg()).ObjHasInstances(obj) {
446447
varDecl.DeclCode = fc.CatchOutput(0, func() {
447448
fc.Printf("%s = {};", name)
@@ -460,13 +461,7 @@ func (fc *funcContext) newNamedTypeVarDecl(obj *types.TypeName) *Decl {
460461
func (fc *funcContext) newNamedTypeInstDecl(inst typeparams.Instance) (*Decl, error) {
461462
originType := inst.Object.Type().(*types.Named)
462463

463-
var nestResolver *typeparams.Resolver
464-
if len(inst.TNest) > 0 {
465-
fn := typeparams.FindNestingFunc(inst.Object)
466-
tp := typeparams.SignatureTypeParams(fn.Type().(*types.Signature))
467-
nestResolver = typeparams.NewResolver(fc.pkgCtx.typesCtx, tp, inst.TNest, nil)
468-
}
469-
fc.typeResolver = typeparams.NewResolver(fc.pkgCtx.typesCtx, originType.TypeParams(), inst.TArgs, nestResolver)
464+
fc.typeResolver = typeparams.NewResolver(fc.pkgCtx.typesCtx, inst)
470465
defer func() { fc.typeResolver = nil }()
471466

472467
instanceType := originType
@@ -478,17 +473,14 @@ func (fc *funcContext) newNamedTypeInstDecl(inst typeparams.Instance) (*Decl, er
478473
}
479474
instanceType = instantiated.(*types.Named)
480475
}
481-
if len(inst.TNest) > 0 {
482-
instantiated := nestResolver.Substitute(instanceType)
483-
instanceType = instantiated.(*types.Named)
484-
}
476+
instanceType = fc.typeResolver.Substitute(instanceType).(*types.Named)
485477
}
486478

487479
underlying := instanceType.Underlying()
488480
d := &Decl{
489481
FullName: typeDeclFullName(inst),
490482
}
491-
d.Dce().SetName(inst.Object, inst.TArgs...)
483+
d.Dce().SetName(inst.Object, inst.TNest, inst.TArgs)
492484
fc.pkgCtx.CollectDCEDeps(d, func() {
493485
// Code that declares a JS type (i.e. prototype) for each Go type.
494486
d.DeclCode = fc.CatchOutput(0, func() {
@@ -613,7 +605,7 @@ func (fc *funcContext) anonTypeDecls(anonTypes []*types.TypeName) []*Decl {
613605
FullName: anonTypeDeclFullName(t),
614606
Vars: []string{t.Name()},
615607
}
616-
d.Dce().SetName(t)
608+
d.Dce().SetName(t, nil, nil)
617609
fc.pkgCtx.CollectDCEDeps(d, func() {
618610
d.DeclCode = []byte(fmt.Sprintf("\t%s = $%sType(%s);\n", t.Name(), strings.ToLower(typeKind(t.Type())[5:]), fc.initArgs(t.Type())))
619611
})

compiler/expressions.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ func (fc *funcContext) translateExpr(expr ast.Expr) *expression {
538538
panic(fmt.Errorf("unhandled IndexExpr of a Signature: %T in %T", u, fc.typeOf(e.X)))
539539
}
540540
default:
541-
panic(fmt.Errorf(`unhandled IndexExpr: %T`, t))
541+
panic(fmt.Errorf(`unhandled IndexExpr: %T in %T`, t, fc.typeOf(e.X)))
542542
}
543543
case *ast.IndexListExpr:
544544
switch t := fc.typeOf(e.X).Underlying().(type) {
@@ -605,7 +605,7 @@ func (fc *funcContext) translateExpr(expr ast.Expr) *expression {
605605
case types.MethodVal:
606606
return fc.formatExpr(`$methodVal(%s, "%s")`, fc.makeReceiver(e), sel.Obj().(*types.Func).Name())
607607
case types.MethodExpr:
608-
fc.pkgCtx.DeclareDCEDep(sel.Obj(), inst.TArgs...)
608+
fc.pkgCtx.DeclareDCEDep(sel.Obj(), inst.TNest, inst.TArgs)
609609
if _, ok := sel.Recv().Underlying().(*types.Interface); ok {
610610
return fc.formatExpr(`$ifaceMethodExpr("%s")`, sel.Obj().(*types.Func).Name())
611611
}
@@ -920,7 +920,7 @@ func (fc *funcContext) delegatedCall(expr *ast.CallExpr) (callable *expression,
920920
func (fc *funcContext) makeReceiver(e *ast.SelectorExpr) *expression {
921921
sel, _ := fc.selectionOf(e)
922922
if !sel.Obj().Exported() {
923-
fc.pkgCtx.DeclareDCEDep(sel.Obj())
923+
fc.pkgCtx.DeclareDCEDep(sel.Obj(), nil, nil)
924924
}
925925

926926
x := e.X

compiler/functions.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,9 @@ func (fc *funcContext) nestedFunctionContext(info *analysis.FuncInfo, inst typep
4848
c.allVars[k] = v
4949
}
5050

51-
if sig.TypeParams().Len() > 0 {
52-
c.typeResolver = typeparams.NewResolver(c.pkgCtx.typesCtx, sig.TypeParams(), inst.TArgs, nil)
53-
} else if sig.RecvTypeParams().Len() > 0 {
54-
c.typeResolver = typeparams.NewResolver(c.pkgCtx.typesCtx, sig.RecvTypeParams(), inst.TArgs, nil)
55-
}
56-
if c.objectNames == nil {
57-
c.objectNames = map[types.Object]string{}
51+
// Use the parent function's resolver unless the function has it's own type arguments.
52+
if !inst.IsTrivial() {
53+
c.typeResolver = typeparams.NewResolver(fc.pkgCtx.typesCtx, inst)
5854
}
5955

6056
// Synthesize an identifier by which the function may reference itself. Since

compiler/internal/analysis/info.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,7 @@ func (info *Info) newFuncInfoInstances(fd *ast.FuncDecl) []*FuncInfo {
124124

125125
funcInfos := make([]*FuncInfo, 0, len(instances))
126126
for _, inst := range instances {
127-
var resolver *typeparams.Resolver
128-
if sig, ok := obj.Type().(*types.Signature); ok {
129-
tp := typeparams.SignatureTypeParams(sig)
130-
resolver = typeparams.NewResolver(info.typeCtx, tp, inst.TArgs, nil)
131-
}
127+
resolver := typeparams.NewResolver(info.typeCtx, inst)
132128
fi := info.newFuncInfo(fd, inst.Object, inst.TArgs, resolver)
133129
funcInfos = append(funcInfos, fi)
134130
}

compiler/internal/dce/README.md

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -265,17 +265,32 @@ of either will indicate a use of both. This will cause slightly more unexported
265265
methods to be alive while reducing the complication of type checking which object
266266
or type of object is performing the call.
267267

268-
| Declaration | exported | unexported | non-generic | generic | object name | method name |
269-
|:------------|:--------:|:----------:|:-----------:|:-------:|:------------|:------------|
270-
| variables |||| n/a | `<package>.<var name>` | |
271-
| functions |||| | `<package>.<func name>` | |
272-
| functions ||| || `<package>.<func name>[<type args>]` | |
273-
| named type |||| | `<package>.<type name>` | |
274-
| named type ||| || `<package>.<type name>[<type args>]` | |
275-
| method || || | `<package>.<receiver name>` | |
276-
| method || | || `<package>.<receiver name>[<type args>]` | |
277-
| method | ||| | `<package>.<receiver name>` | `<package>.<method name>(<parameter types>)(<result types>)` |
278-
| method | || || `<package>.<receiver name>[<type args>]` | `<package>.<method name>(<parameter types>)(<result types>)` |
268+
| Declaration | exported | unexported | generic | object name | method name |
269+
|:------------|:--------:|:----------:|:-------:|:------------|:------------|
270+
| variables ||| | `<package>.<var name>` | |
271+
| functions ||| | `<package>.<func name>` | |
272+
| functions |||| `<package>.<func name>[<type args>]` | |
273+
| named type ||| | `<package>.<type name>` | |
274+
| named type |||| `<package>.<type name>[<type args>]` | |
275+
| method || | | `<package>.<receiver name>` | |
276+
| method || || `<package>.<receiver name>[<type args>]` | |
277+
| method | || | `<package>.<receiver name>` | `<package>.<method name>(<parameter types>)(<result types>)` |
278+
| method | ||| `<package>.<receiver name>[<type args>]` | `<package>.<method name>(<parameter types>)(<result types>)` |
279+
280+
For nested types, the nest (the function or method in which the type is
281+
declared) needs to be taken into consideration to differentiate types with
282+
the same name but different nests.
283+
284+
| Nest type | generic nest | generic object | object name |
285+
|:----------|:------------:|:--------------:|:------------|
286+
| function | | | `<package>.<func name>:<type name>` |
287+
| function || | `<package>.<func name>:<type name>[<nest args>;]` |
288+
| function | || `<package>.<func name>:<type name>[<type args>]` |
289+
| function ||| `<package>.<func name>:<type name>[<nest args>;<type args>]` |
290+
| method | | | `<package>.<receiver name>:<method name>:<type name>` |
291+
| method || | `<package>.<receiver name>:<method name>:<type name>[<nest args>;]` |
292+
| method | || `<package>.<receiver name>:<method name>:<type name>[<type args>]` |
293+
| method ||| `<package>.<receiver name>:<method name>:<type name>[<nest args>;<type args>]` |
279294

280295
#### Name Specifics
281296

compiler/internal/dce/collector.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ func (c *Collector) CollectDCEDeps(decl Decl, f func()) {
3939
// The given optional type arguments are used to when the object is a
4040
// function with type parameters or anytime the object doesn't carry them.
4141
// If not given, this attempts to get the type arguments from the object.
42-
func (c *Collector) DeclareDCEDep(o types.Object, tArgs ...types.Type) {
42+
func (c *Collector) DeclareDCEDep(o types.Object, tNest, tArgs []types.Type) {
4343
if c.dce != nil {
44-
c.dce.addDep(o, tArgs)
44+
c.dce.addDep(o, tNest, tArgs)
4545
}
4646
}

0 commit comments

Comments
 (0)