dmd icon indicating copy to clipboard operation
dmd copied to clipboard

Enhancement: `Base(child)` class object upcast

Open ntrel opened this issue 1 year ago • 9 comments

FundamentalType(arg) works, e.g. int(2).

Enum(Enum.foo) works, which does nothing - see compilable/b16346.d below and/or https://issues.dlang.org/show_bug.cgi?id=16346.

Let's allow class instance upcasting without having to use cast - Base(child). cast can be bug-prone, and upcasting is always fine. In generic code it's not always clear what a type resolves to, so avoiding cast makes code reviews easier.

Here upcasting takes precedence over a static opCall, but that could be swapped.

ntrel avatar Apr 29 '24 16:04 ntrel

Thanks for your pull request and interest in making D better, @ntrel! We are looking forward to reviewing it, and you should be hearing from a maintainer soon. Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + dmd#16426"

dlang-bot avatar Apr 29 '24 16:04 dlang-bot

Should I(c) where I is an interface that typeof(c) implements be supported as well?

zopsicle avatar Apr 29 '24 18:04 zopsicle

Base b = child; already works.

atilaneves avatar Apr 30 '24 14:04 atilaneves

@atilaneves The idea is to be able to do conversion as an expression, without a cast. Requiring a declaration breaks the flow of an expression, and pollutes the scope when the declaration is only used once. Uniform scalar type construction was added, yet it could be argued to just use a declaration for that instead.

ntrel avatar May 03 '24 17:05 ntrel

Which expressions would be common enough to warrant the enhancement?

atilaneves avatar May 07 '24 17:05 atilaneves

Which expressions would be common enough to warrant the enhancement?

T(val) in generic code.

PetarKirov avatar May 08 '24 06:05 PetarKirov

Which expressions would be common enough to warrant the enhancement?

T(val) in generic code.

I still don't understand when/why/how this would be used/useful.

atilaneves avatar May 08 '24 23:05 atilaneves

Requiring a declaration breaks the flow of an expression, and pollutes the scope when the declaration is only used once.

This can be a simple library function:

T identity(T)(T value) =>
    value;

Then, use without template argument deduction:

identity!Base(derived)

It is even usable with UFCS:

f.identity!Base.g;

zopsicle avatar May 08 '24 23:05 zopsicle

This can be a simple library function:

T identity(T)(T value) => value;

[…]

f.identity!Base.g;

Over-engineered solution for a problem that shouldn’t exist. Issuing an implicit conversion explicitly should be easy.

Bolpat avatar Aug 07 '24 15:08 Bolpat