Bug 23272 – [REG2.099] CTFE error of typeid comparison ==

Status
NEW
Severity
regression
Priority
P1
Component
druntime
Product
D
Version
D2
Platform
All
OS
All
Creation time
2022-07-27T23:17:05Z
Last change time
2024-12-07T13:42:13Z
Keywords
industry, pull, rejects-valid
Assigned to
No Owner
Creator
johanengelen
Moved to GitHub: dmd#17451 →

Comments

Comment #0 by johanengelen — 2022-07-27T23:17:05Z
Unfortunately a rather large testcase: Testcase: ``` import std.string; import std.conv; import std.traits; import std.typetuple; struct SumType(Ts...) { mixin(() { auto s = "enum Cases : ubyte {"; foreach(i, _; Ts) { s ~= "c" ~ text(i) ~ " = " ~ text(i) ~ ", "; } return s ~= "unset}\n"; }()); Cases which = Cases.unset; union { Ts cases; } auto ref opAssign(U)(auto ref U val) { enum idx = staticIndexOf!(Unqual!U, Ts); cases[idx] = val; which = cast(Cases)idx; return this; } } auto caseOfTemplated(alias func, T)(auto ref T s) { final switch (s.which) foreach(i, CASE; EnumMembers!(T.Cases)) { case CASE: static if (CASE == T.Cases.unset) { assert (false, "not set"); } else { return func(s.cases[i]); } } assert (false); } void foo() { bool validate() { SumType!(string, int) s; s = "hello"; assert (caseOfTemplated!(a => typeid(a))(s) == typeid(string)); return true; } static assert(validate()); } ``` Compilation fails with since dlang2.099 (works for older frontend versions): /opt/compiler-explorer/ldc1.29.0/ldc2-1.29.0-linux-x86_64/bin/../import/object.d(329): Error: cannot convert `&object.TypeInfo` to `Object*` at compile time /opt/compiler-explorer/ldc1.29.0/ldc2-1.29.0-linux-x86_64/bin/../import/object.d(329): called from here: `opEquals(*& lhs, *& rhs)` <source>(47): called from here: `opEquals(caseOfTemplated(s), typeid(string))` <source>(50): called from here: `validate()` <source>(50): while evaluating: `static assert(validate())`
Comment #1 by johanengelen — 2022-07-27T23:19:39Z
Workaround is to use `is` instead of `==`. (`assert (s.caseOfTemplated!(a => typeid(a)) is typeid(string));`)
Comment #2 by ibuclaw — 2022-12-20T19:22:00Z
This is not a compiler regression. Introduced by: https://github.com/dlang/druntime/pull/3665
Comment #3 by ibuclaw — 2022-12-20T19:35:54Z
Possible reduction of the original. --- alias AliasSeq(TList...) = TList; template EnumMembers(E) { alias EnumMembers = AliasSeq; static foreach (M; __traits(allMembers, E)) EnumMembers = AliasSeq!(__traits(getMember, E, M)); } struct SumType(Ts) { mixin(() { auto s = "enum Cases : ubyte {"; return s ~= "unset}\n"; }()); Cases which; union { Ts cases; } } auto caseOfTemplated(alias func, T)(T s) { final switch (s.which) foreach(CASE; EnumMembers!(T.Cases)) { case CASE: return func(s.cases); } } void foo() { bool validate() { SumType!(int) s; caseOfTemplated!(a => typeid(a))(s) == typeid(string); return true; } static assert(validate); }
Comment #4 by destructionator — 2022-12-20T19:49:44Z
The code that does it is: // to bypass any opCast that may be present on the original class. return .opEquals!(Object, Object)(*cast(Object*) &lhs, *cast(Object*) &rhs); And appears plain `cast() lhs, cast() rhs` instead of the pointer cast will also bypass opCast so i think this is a fairly easy fix.
Comment #5 by dlang-bot — 2022-12-20T19:54:10Z
@schveiguy created dlang/dmd pull request #14726 "fix 23272. CTFE comparison of TypeInfo fails" fixing this issue: - fix 23272. CTFE comparison of TypeInfo fails https://github.com/dlang/dmd/pull/14726
Comment #6 by ibuclaw — 2022-12-20T19:55:01Z
(In reply to Iain Buclaw from comment #3) > Possible reduction of the original. Which can be hand simplified further to: --- struct SumType { int cases; } auto caseOfTemplated(alias func, T)(T s) { return func(s.cases); } void foo() { auto validate() { SumType s; auto t = caseOfTemplated!(a => typeid(a))(s) == typeid(string); return true; } static assert(validate); }
Comment #7 by ibuclaw — 2022-12-20T19:58:13Z
(In reply to Iain Buclaw from comment #6) > (In reply to Iain Buclaw from comment #3) > > Possible reduction of the original. > Which can be hand simplified further to: Oh wait, I'm being an idiot. --- void foo() { auto validate() { assert(typeid(int) != typeid(string)); return true; } static assert(validate); }
Comment #8 by robert.schadek — 2024-12-07T13:42:13Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17451 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB