Thread overview | |||||
---|---|---|---|---|---|
|
August 13, 2013 Typeinfo inconsistencies | ||||
---|---|---|---|---|
| ||||
So, I got some free time today and decided to look into issue 6210, and found out that the problem was caused by this: char[] a = "h".dup; const(char)[] b = "h"; string c = "h"; writeln(typeid(a).getHash(&a)); // prints 104 writeln(typeid(b).getHash(&b)); // prints 703014434222502 writeln(typeid(c).getHash(&c)); // prints 104 This is completely b0rken, because it causes the following code to fail: int[char[]] aa; aa["h"] = 1; assert(aa.dup == aa); // fails The reason for this inconsistency is that char[] and immutable(char)[] (aka string) have their getHash functions overridden in druntime's src/rt/typeinfo/ti_Ag.d, but there is no such override for const(char)[]. I tried adding another subclass for const(char)[]'s typeid that inherits the correct version of getHash, but it didn't work because presumably this stuff is hardcoded into the compiler somewhere. So my question is, where in the compiler decides to use the specific typeinfos for char[] and immutable(char)[], but not const(char)[]? T -- That's not a bug; that's a feature! |
August 13, 2013 Re: Typeinfo inconsistencies | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Tuesday, 13 August 2013 at 17:42:31 UTC, H. S. Teoh wrote: > So, I got some free time today and decided to look into issue 6210, and > found out that the problem was caused by this: > > char[] a = "h".dup; > const(char)[] b = "h"; > string c = "h"; > > writeln(typeid(a).getHash(&a)); // prints 104 > writeln(typeid(b).getHash(&b)); // prints 703014434222502 > writeln(typeid(c).getHash(&c)); // prints 104 > > This is completely b0rken, because it causes the following code to fail: > > int[char[]] aa; > aa["h"] = 1; > > assert(aa.dup == aa); // fails > > The reason for this inconsistency is that char[] and immutable(char)[] > (aka string) have their getHash functions overridden in druntime's > src/rt/typeinfo/ti_Ag.d, but there is no such override for > const(char)[]. > > I tried adding another subclass for const(char)[]'s typeid that inherits > the correct version of getHash, but it didn't work because presumably > this stuff is hardcoded into the compiler somewhere. > > So my question is, where in the compiler decides to use the specific > typeinfos for char[] and immutable(char)[], but not const(char)[]? > > > T It seems that important path is taken here: https://github.com/D-Programming-Language/dmd/blob/master/src/typinf.c#L138 And root of the issue maybe here: https://github.com/D-Programming-Language/dmd/blob/master/src/typinf.c#L793 (essentially if(char && immutable)) Based on ad-hoc dmd debug: If type is "AssociativeArray!(const(char)[], int)" Type::builtinTypeInfo returns 0. If type is "char[]" !t->vtinfo is false, so entire branch is skipped. If type is "const(char)[]" then !t->builtinTypeInfo() is true and dmd executes COMDAT generation branch. If type is "const(char)" then !t->builtinTypeInfo() is true and dmd executes COMDAT generation branch (also if (t->isConst()) is also true). If type is "char" then "!t->builtinTypeInfo()" is false. It seems that it is consistent with your observations. |
August 13, 2013 Re: Typeinfo inconsistencies | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Tuesday, 13 August 2013 at 17:42:31 UTC, H. S. Teoh wrote: > So, I got some free time today and decided to look into issue 6210, and > found out that the problem was caused by this: > > char[] a = "h".dup; > const(char)[] b = "h"; > string c = "h"; > > writeln(typeid(a).getHash(&a)); // prints 104 > writeln(typeid(b).getHash(&b)); // prints 703014434222502 > writeln(typeid(c).getHash(&c)); // prints 104 > > This is completely b0rken, because it causes the following code to fail: > > int[char[]] aa; > aa["h"] = 1; > > assert(aa.dup == aa); // fails > > The reason for this inconsistency is that char[] and immutable(char)[] > (aka string) have their getHash functions overridden in druntime's > src/rt/typeinfo/ti_Ag.d, but there is no such override for > const(char)[]. > > I tried adding another subclass for const(char)[]'s typeid that inherits > the correct version of getHash, but it didn't work because presumably > this stuff is hardcoded into the compiler somewhere. > > So my question is, where in the compiler decides to use the specific > typeinfos for char[] and immutable(char)[], but not const(char)[]? > > > T OK --- a/src/typinf.c +++ b/src/typinf.c @@ -790,7 +790,8 @@ int TypeDArray::builtinTypeInfo() #if DMDV2 return !mod && (next->isTypeBasic() != NULL && !next->mod || // strings are so common, make them builtin - next->ty == Tchar && next->mod == MODimmutable); + next->ty == Tchar && next->mod == MODimmutable || + next->ty == Tchar && next->mod == MODconst); #else return next->isTypeBasic() != NULL; #endif --- a/src/rt/typeinfo/ti_Ag.d +++ b/src/rt/typeinfo/ti_Ag.d @@ -186,3 +186,15 @@ class TypeInfo_Aya : TypeInfo_Aa } } +// const(char)[] + +class TypeInfo_Axa : TypeInfo_Aa +{ + override string toString() const { return "const(char)[]"; } + + override @property inout(TypeInfo) next() inout + { + return cast(inout)typeid(const(char)); + } +} + and this program runs fine and prints 104 for three cases import std.stdio; void main() { int[char[]] aa; aa["h"] = 1; assert(aa.dup == aa); // fails, now ok char[] a = "h".dup; const(char)[] b = "h"; string c = "h"; writeln(typeid(a).getHash(&a)); // prints 104 writeln(typeid(b).getHash(&b)); // prints 703014434222502, now 104 writeln(typeid(c).getHash(&c)); // prints 104 } |
Copyright © 1999-2021 by the D Language Foundation