Explicit implicit conversions
Quirin Schroll
qs.il.paperinik at gmail.com
Thu Feb 6 02:32:54 UTC 2025
Inspired by [this
post](https://forum.dlang.org/post/khqsgbrnorbclxhvtpxy@forum.dlang.org).
The idea is simple: Extend implicit conversions to all types and
values. For built-in types, one can do this: `ushort(myUByte)`
That works because a `ubyte` can be converted to `ushort`. In
some cases, the static type has to be changed by explicitly
requesting a conversion that is intended to be fool-proof. (A
`cast` would allow for narrowing or other unsafe conversions.)
D has many implicit conversions that are “obviously” correct:
- Numeric types when the range of the operand is fully included
in the target type, e.g.:
- `ubyte` → `ushort` → `uint` → `ulong`
- `byte` → `short` → `int` → `long`
- `ubyte` → `short`
- `ushort` → `int`
- `uint` → `long`
- `float` → `double` → `real`
- Adding `const`
- Removing function attributes that make guarantees, e.g. `@safe`
or `pure`.
- Derived to base class or interface
The idea is to allow, e.g. `Type(expression)` evaluate to
`expression` with a static type of `Type`.
Something like this is needed to aid the compiler in figuring out
what you want:
```d
interface I { }
interface J { }
class C : I, J { }
class D : I, J { }
void main()
{
I[] xs = [new C, new D]; // Error: cannot implicitly convert
expression `[new C, new D]` of type `Object[]` to `I[]`
}
```
One solution: Use `cast(I)`, but `cast` is not the right tool: It
results in `null` for a failed cast, but we want to express the
cast shouldn’t fail, and we want an error should we be mistaken.
```d
auto xs = [I(new C), new D]; // proposed: good, typeof(xs) is
`I[]`
```
Another examples is when you want to control what type is
inferred by IFTI:
```d
void f(T)(T x, T y) { pragma(msg, T); }
f(new C, new D); // Error: template `f` is not callable using
argument types `!()(C, D)`
f(I(new C), I(new D)); // proposed: good, prints "I"
```
It could be implemented by lowering to `((Type __result) =>
__result)(expression)`.
Of course, that lowering can be provided by a function template:
```d
auto ref R implicitCast(R, T)(auto ref T x) => x;
```
The main issue with that is that it’s much wordier.
More information about the dip.ideas
mailing list