Bug 8847 – voldemort + inout confuses "is"

Status
RESOLVED
Resolution
FIXED
Severity
blocker
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-10-18T02:13:00Z
Last change time
2015-06-09T05:14:47Z
Keywords
pull
Assigned to
nobody
Creator
monarchdodra

Comments

Comment #0 by monarchdodra — 2012-10-18T02:13:05Z
I discovered this inside phobos. First reduced test case: //---- import std.stdio; import std.range; import std.conv; void main() { auto a = iota(1, 2); auto b = a[]; alias typeof(a) A; alias typeof(b) B; writeln("Typeof A: ", A.stringof); writeln("Typeof B: ", B.stringof); assert(is(A == B), text(A.stringof, " is different from " , B.stringof)); } //---- Typeof A: Result Typeof B: Result [email protected](13): Result is different from Result //---- Which is very strange. I found the root condition that recreates this: It is having a voldemort function that is qualified with inout: //---- import std.stdio; import std.conv; auto S() { static struct Result { inout(Result) get() inout {return this;} } return Result(); } void main() { auto a = S(); auto b = a.get(); alias typeof(a) A; alias typeof(b) B; writeln("Typeof A: ", A.stringof); writeln("Typeof B: ", B.stringof); assert(is(A == B), text(A.stringof, " is different from " , B.stringof)); } //---- Typeof A: Result Typeof B: Result [email protected](21): Result is different from Result //---- I'm marking this as major, because it is currently showing up in Phobos: I wrote a fix for emplace, to bypass opAssign (which it should *not* be calling), and it turns out there is an emplace that fails to build a zip.opSlice because of this: Pull: https://github.com/D-Programming-Language/phobos/pull/837 D2: http://d.puremagic.com/test-results/pull-history.ghtml?repoid=3&pullid=837
Comment #1 by monarchdodra — 2012-10-18T02:19:29Z
(In reply to comment #0) > Which is very strange. I found the root condition that recreates this: It is > having a voldemort function that is qualified with inout: > > //---- > import std.stdio; > import std.conv; > > auto S() > { > static struct Result > { > inout(Result) get() inout {return this;} > } > return Result(); > } > > void main() > { > auto a = S(); > auto b = a.get(); > alias typeof(a) A; > alias typeof(b) B; > writeln("Typeof A: ", A.stringof); > writeln("Typeof B: ", B.stringof); > assert(is(A == B), text(A.stringof, " is different from " , B.stringof)); > } > //---- > Typeof A: Result > Typeof B: Result > [email protected](21): Result is different from Result > //---- Yeah, I forgot to mention, if you remove the "inout" attribute, or if you make Result a global struct, the problem disappears, so it *really* only ever appears when inout and voldemort are combined.
Comment #2 by code — 2012-10-18T02:29:59Z
This is probably the same issue I hit when merging the 2.060 frontend into LDC a while ago. The issue is that the same type can end up with two different mangled names, which causes two different TypeInfo instances to be emitted. The test case from https://github.com/ldc-developers/ldc/blob/master/gen/tocall.cpp#L677: --- auto iota() { static struct Result { this(int) {} inout(Result) test() inout { return cast(inout)Result(0); } } return Result.init; } void main() { auto r = iota(); } --- I'm not sure what the correct fix is here – Walter? Kenji?
Comment #3 by monarchdodra — 2012-10-28T04:01:55Z
(In reply to comment #2) > This is probably the same issue I hit when merging the 2.060 frontend into LDC > a while ago. The issue is that the same type can end up with two different > mangled names, which causes two different TypeInfo instances to be emitted. > > [SNIP] > > I'm not sure what the correct fix is here – Walter? Kenji? Any news? Do you have any idea about the *cost* of fixing this? If there is a fix possible, then I'll wait for it (No problem waiting whatsoever). But if not, then I'll go for bypass, just want to know which direction I should take this... Thanks.
Comment #4 by monarchdodra — 2012-11-30T02:35:04Z
(In reply to comment #3) > > Any news? I wanted to add that https://github.com/D-Programming-Language/phobos/pull/982 Is also subject to this issue.
Comment #5 by k.hara.pg — 2012-11-30T23:46:35Z
This is a serious problem about the name mangling rule for Voldemort Type. At least there is two rules. 1. Mangled name of a function symbol contains the mangled name of its return type. 2. A nested declaration's mangled name contains its enclosing mangled name. --- module test; pragma(msg, "1f: ", foo.mangleof); // _D4test3fooFZAi // --> _D [ 4test 3foo / [ FZ / Ai ] ] ...#1(Ai == int[]) int[] foo() { struct S { int value; } pragma(msg, "1i: ", S.mangleof); // S4test3fooFZAi1S // --> S [ 4test 3foo / [ FZ / Ai ] ] 1S ...#2 return null; } --- But, Voldemort Types cannot be mangled based on the rules. Because, a nested struct requires enclosing function's mangling, but the function requires return type's mangling. It's circular dependency. In current, that is *accidentally* working. --- auto bar() { struct S { int value; } pragma(msg, "2i: ", S.mangleof); // S4test3bar1S // --> S [ 4test 3bar / [ / ] ] 1S // ...incorrect return S(1); } pragma(msg, "2f: ", bar.mangleof); // _D4test3barFZS4test3bar1S // --> _D [ 4test 3bar / [ FZ / S4test3bar1S ] ] // ...incorrect --- And, inout type deduction on function call shoots the rule inconsistency. --- auto baz(inout int = 0) { struct S { int value; } pragma(msg, "3i: ", S.mangleof); // S inside bar // S4test3baz1S // --> S [ 4test 3baz / [ / ] ] 1S ...(A) return inout(S)(1); } pragma(msg, "3f: ", baz.mangleof); // _D4test3bazFNgiZNgS4test3baz1S // --> _D [ 4test 3baz / [ FNgiZ / Ng S4test3baz1S ] ] pragma(msg, "3o: ", typeof(baz(0)).mangleof); // S outside bar // S4test3bazFNgiZNgS4test3baz1S1S // --> S [ 4test 3baz / [ FNgiZNg / S4test3baz1S ] ] 1S ...(B) --- Compare: A. --> S [ 4test 3baz / [ / ] ] 1S B. --> S [ 4test 3baz / [ FNgiZNg / S4test3baz1S ] ] 1S Mismatching between A and B is the root cause of this issue.
Comment #6 by github-bugzilla — 2012-12-17T21:38:47Z
Commit pushed to master at https://github.com/D-Programming-Language/phobos https://github.com/D-Programming-Language/phobos/commit/6022082b29f670095fb082102420c7b331cb7d14 Further strengthen hasSlicing. The extra requirements are not currently enabled because of bug# 8847, but they're now there, and they're listed as their in the documentation so that no one will think that they're not supposed to apply.
Comment #7 by k.hara.pg — 2012-12-17T22:54:17Z
Comment #8 by github-bugzilla — 2013-02-03T09:40:26Z