Skip to content

Commit b6aa203

Browse files
committed
compiler: include the scope in the type code name
Fixes #5180
1 parent 707d37a commit b6aa203

File tree

3 files changed

+70
-2
lines changed

3 files changed

+70
-2
lines changed

compiler/interface.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,14 +511,38 @@ var basicTypeNames = [...]string{
511511
types.UnsafePointer: "unsafe.Pointer",
512512
}
513513

514+
// return an integer representing this scope in a package.
515+
func scopeId(pkg *types.Scope, scope *types.Scope) string {
516+
var ids []int
517+
for scope != pkg {
518+
parent := scope.Parent()
519+
for i := range parent.NumChildren() {
520+
if parent.Child(i) == scope {
521+
ids = append(ids, i)
522+
scope = scope.Parent()
523+
break
524+
}
525+
}
526+
}
527+
528+
var buf []byte
529+
for _, v := range ids {
530+
buf = strconv.AppendInt(buf, int64(v), 10)
531+
buf = append(buf, ':')
532+
}
533+
534+
return string(buf)
535+
}
536+
514537
// getTypeCodeName returns a name for this type that can be used in the
515538
// interface lowering pass to assign type codes as expected by the reflect
516539
// package. See getTypeCodeNum.
517540
func getTypeCodeName(t types.Type) (string, bool) {
518541
switch t := types.Unalias(t).(type) {
519542
case *types.Named:
520-
if t.Obj().Parent() != t.Obj().Pkg().Scope() {
521-
return "named:" + t.String() + "$local", true
543+
parent, pkg := t.Obj().Parent(), t.Obj().Pkg().Scope()
544+
if parent != pkg {
545+
return fmt.Sprintf("named:%s$local:%s", t.String(), scopeId(pkg, parent)), true
522546
}
523547
return "named:" + t.String(), false
524548
case *types.Array:

testdata/interface.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ func main() {
119119

120120
// check that type asserts to interfaces with no methods work
121121
emptyintfcrash()
122+
123+
// These are part of a test that checks that `main.Foo` can refer to 2+ different entities without getting them confused.
124+
namedFoo()
125+
namedFoo2Nested()
122126
}
123127

124128
func printItf(val interface{}) {
@@ -343,3 +347,37 @@ func emptyintfcrash() {
343347
println("x is", x.(int))
344348
}
345349
}
350+
351+
func namedFoo() {
352+
type Foo struct {
353+
A int
354+
}
355+
f1 := &Foo{}
356+
fcopy := copyOf(f1)
357+
f2 := fcopy.(*Foo)
358+
println(f2.A)
359+
}
360+
361+
func namedFoo2Nested() {
362+
type Foo struct {
363+
A *int
364+
}
365+
f1 := &Foo{}
366+
fcopy := copyOf(f1)
367+
f2 := fcopy.(*Foo)
368+
println(f2.A == nil)
369+
370+
if f2.A == nil {
371+
type Foo struct {
372+
A *byte
373+
}
374+
nestedf1 := &Foo{}
375+
fcopy := copyOf(nestedf1)
376+
nestedf2 := fcopy.(*Foo)
377+
println(nestedf2.A == nil)
378+
}
379+
}
380+
381+
func copyOf(src interface{}) (dst interface{}) {
382+
return src
383+
}

testdata/interface.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,9 @@ type is int
2828
type is *int
2929
type is **int
3030
x is 5
31+
*main.Foo
32+
0
33+
*main.Foo
34+
true
35+
*main.Foo
36+
true

0 commit comments

Comments
 (0)