Comment #0 by default_357-line — 2021-03-29T07:48:37Z
Consider the following code:
immutable struct S { }
struct Nullable {
S get_() { return S.init; }
deprecated alias get_ this;
}
void foo(immutable Nullable) { }
void foo(immutable S) { }
void main() {
foo(Nullable());
}
So `Nullable()` is implicitly convertible to `immutable Nullable` without hitting the "alias this". And yet, DMD will prefer the deprecated conversion even if `-de` is on, erroring with
Deprecation: `alias get_ this` is deprecated
This despite the fact that removing the `alias get_ this` will allow the code to compile.
Marked as trivial because as you can guess from the struct name, this issue will solve itself "naturally" when 2.097 releases. :)
Comment #1 by moonlightsentinel — 2021-03-29T08:12:00Z
This is actually a regression. Extending your example with appropriate puts("Nullable") / puts("S") yields:
Up to 2.060 : Success with output: Nullable
2.061 to 2.075.1: <Doesn't compile due to overload resolution error>
2.076.1 to 2.087.1: Success with output: S
Since 2.088.1: Success with output:
-----
onlineapp.d(14): Deprecation: `alias get_ this` is deprecated
S
-----
Comment #2 by default_357-line — 2021-03-29T14:01:28Z
That's not really a "regression" - well, it is a regression, but it's an expected regression, because Nullable's alias get this is in the process of being deprecated and has been removed in master. A deprecation is functionally equivalent to a regression, that's why there was a year of warning messages.
Comment #3 by default_357-line — 2021-03-29T14:05:11Z
Oh wait you're right! I thought you were talking about std.typecons.Nullable for a second.
It's still not a regression - it's a bugfix: https://issues.dlang.org/show_bug.cgi?id=20033 , I believe.
Comment #4 by moonlightsentinel — 2021-03-29T14:09:03Z
(In reply to FeepingCreature from comment #2)
> That's not really a "regression" - well, it is a regression, but it's an
This is still a regression. DMD should prefer const-conversions over implicit conversions (e.g. alias this).
This extends example exhibits wrong behaviour since 2.061 :
(Unless i misunderstood the rules for overload matching)
extern(C) void puts(const scope char*);
immutable struct S { }
struct Nullable {
S get_() { return S.init; }
deprecated alias get_ this;
}
void foo(immutable Nullable) { puts("Nullable"); }
void foo(immutable S) { puts("S"); }
void main() {
foo(Nullable()); // prints "S"
}
Comment #5 by moonlightsentinel — 2021-03-29T14:11:38Z
The regression refers to the change which overload is called, not the deprecation message.
Comment #6 by moonlightsentinel — 2021-03-29T14:20:09Z
Even worse when removing the immutable from S and using const parameters:
extern(C) void puts(const scope char*);
struct S { }
struct Nullable {
S get_() { return S.init; }
deprecated alias get_ this;
}
void foo(const Nullable) { puts("Nullable"); }
void foo(const S) { puts("S"); }
void main() {
foo(Nullable()); // fails due to ambiguity
}
Comment #7 by robert.schadek — 2024-12-13T19:15:36Z