Skip to content

Commit 5ebfb07

Browse files
authored
Fix Issues 22149 & 22150 - TypeInfo names aren't unique, leading to botched equality semantics (#12928)
* Fix Issue 22149 - TypeInfo_Struct names aren't unique, leading to botched equality semantics By storing the mangled name, making the TypeInfo_Struct names truly unique and more compact at the same time. Requires dlang/druntime#3527. * Fix Issue 22150 - TypeInfo_Class names aren't unique, leading to botched equality semantics By fully qualifying template arguments. * [temp] Cirrus CI: Use same-named druntime branch * Azure Pipelines: Try to use same-named druntime/Phobos branches for PRs originating from the official dlang repo * Cirrus CI: Try to use same-named druntime/Phobos branches for PRs originating from the official dlang repo
1 parent cdd9063 commit 5ebfb07

File tree

5 files changed

+122
-13
lines changed

5 files changed

+122
-13
lines changed

.azure-pipelines/lib.sh

+5
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,13 @@ install_grep() {
7777

7878
clone_repos() {
7979
if [ -z ${SYSTEM_PULLREQUEST_TARGETBRANCH+x} ]; then
80+
# no PR
8081
local REPO_BRANCH="$BUILD_SOURCEBRANCHNAME"
82+
elif [ ${SYSTEM_PULLREQUEST_ISFORK} == False ]; then
83+
# PR originating from the official dlang repo
84+
local REPO_BRANCH="$SYSTEM_PULLREQUEST_SOURCEBRANCH"
8185
else
86+
# PR from a fork
8287
local REPO_BRANCH="$SYSTEM_PULLREQUEST_TARGETBRANCH"
8388
fi
8489

.cirrus.yml

+16-5
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,24 @@ common_steps_template: &COMMON_STEPS_TEMPLATE
55
set -uexo pipefail
66
ln -s $CIRRUS_WORKING_DIR ../dmd
77
8-
# for PRs - merge with target branch first
9-
if [ ! -z ${CIRRUS_PR+x} ] ; then
10-
git fetch origin "+refs/pull/$CIRRUS_PR/merge:";
11-
git checkout -f FETCH_HEAD;
8+
if [ -z ${CIRRUS_PR+x} ] ; then
9+
# not a PR
10+
REPO_BRANCH="$CIRRUS_BRANCH"
11+
else
12+
# PR - merge with target branch first
13+
git fetch origin "+refs/pull/$CIRRUS_PR/merge:"
14+
git checkout -f FETCH_HEAD
15+
16+
if [[ ! "$CIRRUS_BRANCH" =~ ^pull/ ]]; then
17+
# PR originating from the official dlang repo
18+
REPO_BRANCH="$CIRRUS_BRANCH"
19+
else
20+
# PR from a fork
21+
REPO_BRANCH="$CIRRUS_BASE_BRANCH"
22+
fi
1223
fi
1324
14-
./ci.sh setup_repos "${CIRRUS_BASE_BRANCH:-$CIRRUS_BRANCH}"
25+
./ci.sh setup_repos "$REPO_BRANCH"
1526
build_script: ./ci.sh build
1627

1728
test_dmd_script: |

src/dmd/todt.d

+6-6
Original file line numberDiff line numberDiff line change
@@ -1293,7 +1293,7 @@ private extern (C++) class TypeInfoDtVisitor : Visitor
12931293
}
12941294

12951295
/* Put out:
1296-
* char[] name;
1296+
* char[] mangledName;
12971297
* void[] init;
12981298
* hash_t function(in void*) xtoHash;
12991299
* bool function(in void*, in void*) xopEquals;
@@ -1310,9 +1310,9 @@ private extern (C++) class TypeInfoDtVisitor : Visitor
13101310
* xgetRTInfo
13111311
*/
13121312

1313-
const name = sd.toPrettyChars();
1314-
const namelen = strlen(name);
1315-
dtb.size(namelen);
1313+
const mangledName = tc.deco;
1314+
const mangledNameLen = strlen(mangledName);
1315+
dtb.size(mangledNameLen);
13161316
dtb.xoff(d.csym, Type.typeinfostruct.structsize);
13171317

13181318
// void[] init;
@@ -1410,8 +1410,8 @@ private extern (C++) class TypeInfoDtVisitor : Visitor
14101410
else
14111411
dtb.size(0);
14121412

1413-
// Put out name[] immediately following TypeInfo_Struct
1414-
dtb.nbytes(cast(uint)(namelen + 1), name);
1413+
// Put out mangledName[] immediately following TypeInfo_Struct
1414+
dtb.nbytes(cast(uint)(mangledNameLen + 1), mangledName);
14151415
}
14161416

14171417
override void visit(TypeInfoClassDeclaration d)

src/dmd/toobj.d

+2-2
Original file line numberDiff line numberDiff line change
@@ -1259,7 +1259,7 @@ private void genClassInfoForClass(ClassDeclaration cd, Symbol* sinit)
12591259
size_t namelen = strlen(name);
12601260
if (!(namelen > 9 && memcmp(name, "TypeInfo_".ptr, 9) == 0))
12611261
{
1262-
name = cd.toPrettyChars();
1262+
name = cd.toPrettyChars(/*QualifyTypes=*/ true);
12631263
namelen = strlen(name);
12641264
}
12651265
dtb.size(namelen);
@@ -1486,7 +1486,7 @@ private void genClassInfoForInterface(InterfaceDeclaration id)
14861486
dtb.size(0); // initializer
14871487

14881488
// name[]
1489-
const(char) *name = id.toPrettyChars();
1489+
const(char) *name = id.toPrettyChars(/*QualifyTypes=*/ true);
14901490
size_t namelen = strlen(name);
14911491
dtb.size(namelen);
14921492
dt_t *pdtname = dtb.xoffpatch(id.csym, 0, TYnptr);

test/runnable/unique_typeinfo_names.d

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
module unique_typeinfo_names;
2+
3+
// https://issues.dlang.org/show_bug.cgi?id=22149
4+
void structs()
5+
{
6+
static struct Foo(T) {}
7+
8+
auto foo()
9+
{
10+
struct S {}
11+
return Foo!S();
12+
}
13+
14+
auto bar()
15+
{
16+
struct S {}
17+
return Foo!S();
18+
}
19+
20+
auto f = foo();
21+
auto b = bar();
22+
23+
assert(typeid(f) != typeid(b));
24+
assert(typeid(f).name != typeid(b).name);
25+
26+
assert(typeid(f).mangledName == typeof(f).mangleof);
27+
assert(typeid(b).mangledName == typeof(b).mangleof);
28+
assert(typeid(f).name == "unique_typeinfo_names.structs().Foo!(unique_typeinfo_names.structs().foo().S).Foo");
29+
assert(typeid(b).name == "unique_typeinfo_names.structs().Foo!(unique_typeinfo_names.structs().bar().S).Foo");
30+
}
31+
32+
// https://issues.dlang.org/show_bug.cgi?id=22150
33+
void classes()
34+
{
35+
static class Foo(T) {}
36+
37+
static auto foo()
38+
{
39+
struct S {}
40+
return new Foo!S();
41+
}
42+
43+
static auto bar()
44+
{
45+
struct S {}
46+
return new Foo!S();
47+
}
48+
49+
auto f = foo();
50+
auto b = bar();
51+
52+
assert(typeid(f) != typeid(b));
53+
assert(typeid(f).name != typeid(b).name);
54+
55+
assert(typeid(f).name == "unique_typeinfo_names.classes.Foo!(unique_typeinfo_names.classes.foo.S).Foo");
56+
assert(typeid(b).name == "unique_typeinfo_names.classes.Foo!(unique_typeinfo_names.classes.bar.S).Foo");
57+
}
58+
59+
void interfaces()
60+
{
61+
static interface IFoo(T) {}
62+
static class Foo(T) : IFoo!T {}
63+
64+
static auto foo()
65+
{
66+
struct S {}
67+
IFoo!S r = new Foo!S();
68+
return r;
69+
}
70+
71+
static auto bar()
72+
{
73+
struct S {}
74+
IFoo!S r = new Foo!S();
75+
return r;
76+
}
77+
78+
auto f = foo();
79+
auto b = bar();
80+
81+
assert(typeid(f) != typeid(b));
82+
assert(typeid(f).name != typeid(b).name);
83+
84+
assert(typeid(f).name == "unique_typeinfo_names.interfaces.IFoo!(unique_typeinfo_names.interfaces.foo.S).IFoo");
85+
assert(typeid(b).name == "unique_typeinfo_names.interfaces.IFoo!(unique_typeinfo_names.interfaces.bar.S).IFoo");
86+
}
87+
88+
void main()
89+
{
90+
structs();
91+
classes();
92+
interfaces();
93+
}

0 commit comments

Comments
 (0)