D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 8545 - defined opCast disables cast(void*)this in classes
Summary: defined opCast disables cast(void*)this in classes
Status: RESOLVED INVALID
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 major
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-08-12 20:33 UTC by Andrej Mitrovic
Modified: 2023-01-02 08:31 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Andrej Mitrovic 2012-08-12 20:33:46 UTC
class Foo
{
    T opCast(T : int)() { return 1; }
    void* test() { return cast(void*)this; }
}

void main() { }

This is problematic, cast(void*)this is the trick used to get the address of 'this' object. &this is the address of the reference and can't be used for the same purpose. So defining opCast for any type ends up disabling 'cast(void*)this'.

I honestly think we should have a druntime function or some kind of compiler intrinsic to get the equivalent of 'cast(void*)this'. That cast itself looks too hacky to begin with.
Comment 1 Andrej Mitrovic 2012-08-12 20:35:06 UTC
Oh and the error message, not that it matters:

Error: template instance opCast!(void*) opCast!(void*) does not match template declaration opCast(T : int)
Comment 2 Walter Bright 2012-08-12 21:50:50 UTC
I don't think this is major, because you can use a union:

{
    static union U { Object o; void* p; }
    U u;
    u.o = this;
    return u.p;
}

In fact, because a union can be used for reinterpret casting, I don't think any new syntax or semantics are needed.
Comment 3 Andrej Mitrovic 2012-08-13 07:57:58 UTC
(In reply to comment #2)
> I don't think this is major, because you can use a union:
> 
> {
>     static union U { Object o; void* p; }
>     U u;
>     u.o = this;
>     return u.p;
> }
> 
> In fact, because a union can be used for reinterpret casting, I don't think any
> new syntax or semantics are needed.

I'm speaking in terms of wrapping C++ libraries (A C++ wrapper class has an inner d_object pointer which it uses to invoke D virtual methods). You're asking me to introduce overhead for every time a new class object is instantiated.
Comment 4 art.08.09 2012-08-14 03:21:53 UTC
(In reply to comment #3)
> (In reply to comment #2)
> > I don't think this is major, because you can use a union:
> > 
> > {
> >     static union U { Object o; void* p; }
> >     U u;
> >     u.o = this;
> >     return u.p;
> > }
> > 
> > In fact, because a union can be used for reinterpret casting, I don't think any
> > new syntax or semantics are needed.
> 
> I'm speaking in terms of wrapping C++ libraries (A C++ wrapper class has an
> inner d_object pointer which it uses to invoke D virtual methods). You're
> asking me to introduce overhead for every time a new class object is
> instantiated.

The compiler /should/ handle it w/o any additional runtime overhead. You could also use

    void* test() { return *cast(void**)&this; }

Which approach will be more efficient probably depends on compiler implementation; ideally both versions should be free.
Comment 5 Andrej Mitrovic 2012-08-14 08:18:35 UTC
> You could also use
> 
>     void* test() { return *cast(void**)&this; }
> 

Thanks! It does seem to create the exact same assembly even with no optimizations.
Comment 6 Richard (Rikki) Andrew Cattermole 2023-01-01 18:18:13 UTC
I'm reopening this bug report for two reasons:

1. Hipreme ran into this when creating a class manually which had opCast defined.
2. With the current work replacing _d_newclass with a template, new will no longer work with a class that isn't ultra-specific with its opCast. In practice this will be a breaking change, so it's time to fix this bug to prevent code breakage.
Comment 7 Richard (Rikki) Andrew Cattermole 2023-01-02 08:31:28 UTC
Closing again, because I did make a mistake.

The new class hook won't need this, and destroy already works. So even if this doesn't make sense why it wasn't fixed, I'll put it back to original state.