Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Result type of ternary operator connecting pointers/slices of class handles broken #19533

Open
dlangBugzillaToGithub opened this issue Jan 26, 2019 · 1 comment

Comments

@dlangBugzillaToGithub
Copy link

Bolpat reported this on 2019-01-26T00:52:01Z

Transferred from https://issues.dlang.org/show_bug.cgi?id=19616

CC List

  • ag0aep6g
  • Bolpat

Description

Connecting two pointers/slices of class handles results in weird error messages and behavior.

    @safe:

    // disables constant folding!
    bool condValue;
    bool cond() { return condValue; };

    class Base { }
    class Derived : Base { }

    Base base;
    Derived derived;

    static this()
    {
        base = new Base;
        derived = new Derived;
        condValue = false;
    }

    Base[] baseArr;
    Derived[] derivedArr;

In this setup, the expression
    auto arr = cond() ? baseArr : derivedArr;
gives the error message
    Error: incompatible types for (baseArr) : (derivedArr): Base[] and Derived[]
while clearly const(Base)[] is the best common type. If this is not liked, void*[] is another option.
Explicitly casting `derivedArr` to `const(Base)[]` solves that.
It hinders type inference and usage of `auto`, but fortunately, it won't do actual harm.

Creating pointers is no issue.

    Base* basePtr = &base;
    Derived* derivedPtr = &derived;

Connecting them in a tenery expression gives an undescriptive error message:
    Error: cannot implicitly convert expression [..] of type Base* to Base*
This is useless while the type should be const(Base)*.

Surprisingly, this statement compiles:

    *(cond() ? basePtr : derivedPtr) = new Base();

Note that cond() returns false, i.e. derivedPtr now points to a Base object.
Note that this is @safe code.
@dlangBugzillaToGithub
Copy link
Author

qs.il.paperinik commented on 2019-06-06T21:18:23Z

The same is true for interfaces:

interface I { }
interface A : I { }
bool condValue;
bool cond() { return condValue; }

pragma(msg, typeof(cond() ? &a : cond() ? &b : &i)); // I*
I* iPtr = cond() ? &a : &i; // fails with error message: cannot assign I* to I*
const(I)* iPtr = cond() ? &a : &i; // succeeds
(cond() ? a : i) = i; // succeeds and breaks @safe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant