This patch does two related things. First, it fixes the hash code in the type descript for a named type so that it matches the hash code the compiler will use internally. Second, it fixes the hash code in the new type structure created by reflect.PtrTo to match the hash code which the compiler will generate for that type. Also it changes PtrTo to canonicalize the type. A change to the reflect test is included; I've already committed that change in the upstream sources. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r a935765ae010 go/types.cc --- a/go/types.cc Thu Feb 02 17:05:05 2012 -0800 +++ b/go/types.cc Fri Feb 03 17:18:52 2012 -0800 @@ -1658,7 +1658,12 @@ ++p; go_assert(p->is_field_name("hash")); - mpz_set_ui(iv, this->hash_for_method(gogo)); + unsigned int h; + if (name != NULL) + h = name->hash_for_method(gogo); + else + h = this->hash_for_method(gogo); + mpz_set_ui(iv, h); vals->push_back(Expression::make_integer(&iv, p->type(), bloc)); ++p; diff -r a935765ae010 libgo/go/reflect/all_test.go --- a/libgo/go/reflect/all_test.go Thu Feb 02 17:05:05 2012 -0800 +++ b/libgo/go/reflect/all_test.go Fri Feb 03 17:18:52 2012 -0800 @@ -1528,6 +1528,18 @@ if p.X != 4 { t.Errorf("Addr.Elem.Set valued to set value in top value") } + + // Verify that taking the address of a type gives us a pointer + // which we can convert back using the usual interface + // notation. + var s struct { + B *bool + } + ps := ValueOf(&s).Elem().Field(0).Addr().Interface() + *(ps.(**bool)) = new(bool) + if s.B == nil { + t.Errorf("Addr.Interface direct assignment failed") + } } /* gccgo does do allocations here. diff -r a935765ae010 libgo/go/reflect/type.go --- a/libgo/go/reflect/type.go Thu Feb 02 17:05:05 2012 -0800 +++ b/libgo/go/reflect/type.go Fri Feb 03 17:18:52 2012 -0800 @@ -999,6 +999,17 @@ return &p.commonType } + s := "*" + *ct.string + + canonicalTypeLock.RLock() + r, ok := canonicalType[s] + canonicalTypeLock.RUnlock() + if ok { + ptrMap.m[ct] = (*ptrType)(unsafe.Pointer(r.(*commonType))) + ptrMap.Unlock() + return r.(*commonType) + } + rp := new(runtime.PtrType) // initialize p using *byte's ptrType as a prototype. @@ -1008,7 +1019,6 @@ bp := (*ptrType)(unsafe.Pointer(unsafe.Typeof((*byte)(nil)).(*runtime.PtrType))) *p = *bp - s := "*" + *ct.string p.string = &s // For the type structures linked into the binary, the @@ -1016,12 +1026,16 @@ // Create a good hash for the new string by using // the FNV-1 hash's mixing function to combine the // old hash and the new "*". - p.hash = ct.hash*16777619 ^ '*' + // p.hash = ct.hash*16777619 ^ '*' + // This is the gccgo version. + p.hash = (ct.hash << 4) + 9 p.uncommonType = nil p.ptrToThis = nil p.elem = (*runtime.Type)(unsafe.Pointer(ct)) + p = canonicalize(p).(*ptrType) + ptrMap.m[ct] = p ptrMap.Unlock() return &p.commonType