diff --git a/compiler/interface.go b/compiler/interface.go index bc2cbf33..2d6c4a7f 100644 --- a/compiler/interface.go +++ b/compiler/interface.go @@ -134,12 +134,17 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]), ) case *types.Named: + name := typ.Obj().Name() + var pkgname string + if pkg := typ.Obj().Pkg(); pkg != nil { + pkgname = pkg.Name() + } typeFieldTypes = append(typeFieldTypes, types.NewVar(token.NoPos, nil, "numMethods", types.Typ[types.Uint16]), types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]), types.NewVar(token.NoPos, nil, "underlying", types.Typ[types.UnsafePointer]), types.NewVar(token.NoPos, nil, "pkgpath", types.Typ[types.UnsafePointer]), - types.NewVar(token.NoPos, nil, "name", types.NewArray(types.Typ[types.Int8], 1+int64(len(typ.Obj().Name())))), + types.NewVar(token.NoPos, nil, "name", types.NewArray(types.Typ[types.Int8], int64(len(pkgname)+1+len(name)+1))), ) case *types.Chan, *types.Slice: typeFieldTypes = append(typeFieldTypes, @@ -205,8 +210,10 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { case *types.Named: name := typ.Obj().Name() var pkgpath string + var pkgname string if pkg := typ.Obj().Pkg(); pkg != nil { pkgpath = pkg.Path() + pkgname = pkg.Name() } pkgPathPtr := c.pkgPathPtr(pkgpath) typeFields = []llvm.Value{ @@ -214,7 +221,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { c.getTypeCode(types.NewPointer(typ)), // ptrTo c.getTypeCode(typ.Underlying()), // underlying pkgPathPtr, // pkgpath pointer - c.ctx.ConstString(name+"\x00", false), // name + c.ctx.ConstString(pkgname+"."+name+"\x00", false), // name } metabyte |= 1 << 5 // "named" flag case *types.Chan: diff --git a/compiler/testdata/interface.ll b/compiler/testdata/interface.ll index 4322b554..de37341a 100644 --- a/compiler/testdata/interface.ll +++ b/compiler/testdata/interface.ll @@ -9,7 +9,7 @@ target triple = "wasm32-unknown-wasi" @"reflect/types.type:basic:int" = linkonce_odr constant { i8, ptr } { i8 2, ptr @"reflect/types.type:pointer:basic:int" }, align 4 @"reflect/types.type:pointer:basic:int" = linkonce_odr constant { i8, i16, ptr } { i8 21, i16 0, ptr @"reflect/types.type:basic:int" }, align 4 @"reflect/types.type:pointer:named:error" = linkonce_odr constant { i8, i16, ptr } { i8 21, i16 0, ptr @"reflect/types.type:named:error" }, align 4 -@"reflect/types.type:named:error" = linkonce_odr constant { i8, i16, ptr, ptr, ptr, [6 x i8] } { i8 52, i16 1, ptr @"reflect/types.type:pointer:named:error", ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", ptr @"reflect/types.type.pkgpath.empty", [6 x i8] c"error\00" }, align 4 +@"reflect/types.type:named:error" = linkonce_odr constant { i8, i16, ptr, ptr, ptr, [7 x i8] } { i8 52, i16 1, ptr @"reflect/types.type:pointer:named:error", ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", ptr @"reflect/types.type.pkgpath.empty", [7 x i8] c".error\00" }, align 4 @"reflect/types.type.pkgpath.empty" = linkonce_odr unnamed_addr constant [1 x i8] zeroinitializer, align 1 @"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr } { i8 20, ptr @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" }, align 4 @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, i16, ptr } { i8 21, i16 0, ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}" }, align 4 diff --git a/src/reflect/type.go b/src/reflect/type.go index 79ca6e5f..cc79a709 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -504,13 +504,11 @@ func pointerTo(t *rawType) *rawType { func (t *rawType) String() string { if t.isNamed() { - path := t.PkgPath() - slash := len(path) - 1 - for slash >= 0 && path[slash] != '/' { - slash-- + s := t.name() + if s[0] == '.' { + return s[1:] } - shortened := path[slash+1:] - return shortened + "." + t.Name() + return s } switch t.Kind() { @@ -1037,10 +1035,20 @@ func readStringZ(data unsafe.Pointer) string { })) } +func (t *rawType) name() string { + ntype := (*namedType)(unsafe.Pointer(t)) + return readStringZ(unsafe.Pointer(&ntype.name[0])) +} + func (t *rawType) Name() string { if t.isNamed() { - ntype := (*namedType)(unsafe.Pointer(t)) - return readStringZ(unsafe.Pointer(&ntype.name[0])) + name := t.name() + for i := 0; i < len(name); i++ { + if name[i] == '.' { + return name[i+1:] + } + } + panic("corrupt name data") } if t.Kind() <= UnsafePointer { diff --git a/src/reflect/value_test.go b/src/reflect/value_test.go index 5c36f25d..c915a36d 100644 --- a/src/reflect/value_test.go +++ b/src/reflect/value_test.go @@ -243,6 +243,11 @@ func TestNamedTypes(t *testing.T) { t.Errorf("TypeOf.String()=%v, want %v", got, want) } + errorType := TypeOf((*error)(nil)).Elem() + if s := errorType.String(); s != "error" { + t.Errorf("error type = %v, want error", s) + } + m := make(map[[4]uint16]string) if got, want := TypeOf(m).String(), "map[[4]uint16]string"; got != want {