Thread overview
[Issue 18755] std.typecons.Rebindable breaks @safe-ty
Apr 14, 2018
Eduard Staniloiu
Aug 26, 2018
Johannes Loher
Dec 17, 2018
Eduard Staniloiu
Dec 17, 2018
Eduard Staniloiu
Dec 17, 2018
Eduard Staniloiu
April 14, 2018
https://issues.dlang.org/show_bug.cgi?id=18755

Eduard Staniloiu <edi33416@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |bootcamp
                 CC|                            |edi33416@gmail.com

--
August 26, 2018
https://issues.dlang.org/show_bug.cgi?id=18755

Johannes Loher <johannes.loher@fg4f.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |johannes.loher@fg4f.de

--- Comment #1 from Johannes Loher <johannes.loher@fg4f.de> ---
This also applies to std.typecons.UnqualRef because they use the same implementation which is responsible for this:

---
class Foo {
    auto opCast(T)() @system immutable pure nothrow {
        *(cast(uint*)0xdeadbeef) = 0xcafebabe;
        return T.init;
    }
}

void main() @safe {
    import std.typecons;
    auto r = UnqualRef!(immutable Foo)(new Foo); // oops
}
---

The reason for the breakage is that they both implement this opAssign, which gets called by the constructor:

---
void opAssign(T another) @trusted pure nothrow @nogc
{
    stripped = cast(U) another;
}
---

Notice how this performs the cast in an @trusted context.

The problem with this is that we actually need to do this, because casting is not @safe, but in this case we are only casting away immutability etc. which is actually verified manually to be safe in this case.

To get around this, we would need to check, if there is a user defined opCast and if it is provided, check if is safe. If it is not safe, we can either decide to not instanciate Rebindable / UnqualRef, or we can instanciate versions of them, which are not @safe (i.e. we omit the @trusted attributes at the corresponding places).

What do you think would be the correct thing to do in this case?

Here is a basic implementation, which does the necessary checks:

---
template hasElaborateCast(T)
{
    import std.traits : hasMember;
    enum hasElaborateCast = hasMember!(T, "opCast");
}

template hasSafeElaborateCast(T, U)
{
    enum hasSafeElaborateCast = hasElaborateCast!T && __traits(compiles, ()
@safe{ T.init.opCast!U; });
}

private mixin template RebindableCommon(T, U, alias This)
if ((is(T == class) || is(T == interface) || isAssociativeArray!T) &&
    (!hasElaborateCast!T || hasSafeElaborateCast!(T, U)))
/* ... */
---

In this case, I put in as a template constraint, but as mentioned, we could also put it in static ifs to decide whether the implementation should be @trusted or not.

--
December 17, 2018
https://issues.dlang.org/show_bug.cgi?id=18755

Eduard Staniloiu <edi33416@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Assignee|nobody@puremagic.com        |edi33416@gmail.com

--
December 17, 2018
https://issues.dlang.org/show_bug.cgi?id=18755

--- Comment #2 from Eduard Staniloiu <edi33416@gmail.com> ---
PR - https://github.com/dlang/phobos/pull/6808

--
December 17, 2018
https://issues.dlang.org/show_bug.cgi?id=18755

Eduard Staniloiu <edi33416@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |FIXED

--
December 24, 2018
https://issues.dlang.org/show_bug.cgi?id=18755

--- Comment #3 from github-bugzilla@puremagic.com ---
Commits pushed to master at https://github.com/dlang/phobos

https://github.com/dlang/phobos/commit/dbca8521b5164c2ba95401d9bc784ec653e1a157 Fix Issue 18755 - std.typecons.Rebindable breaks @safe-ty

https://github.com/dlang/phobos/commit/4435abf27ebe29bceea3a3666a361b64990f8fb7 Merge pull request #6808 from edi33416/issue_18755

Fix Issue 18755 - std.typecons.Rebindable breaks @safe-ty merged-on-behalf-of: Petar Kirov <ZombineDev@users.noreply.github.com>

--