Jump to page: 1 2
Thread overview
Annoying deprecation messages when using EnumMembers with enum that has deprecated members
Oct 06, 2019
uranuz
Oct 08, 2019
FeepingCreature
Oct 08, 2019
uranuz
Oct 08, 2019
Jonathan M Davis
Oct 08, 2019
FeepingCreature
Oct 08, 2019
Jonathan M Davis
Oct 09, 2019
FeepingCreature
Oct 09, 2019
Seb
Oct 09, 2019
Jonathan M Davis
Oct 09, 2019
FeepingCreature
Oct 09, 2019
Sönke Ludwig
Oct 09, 2019
H. S. Teoh
Oct 09, 2019
Gregor Mückl
Oct 12, 2019
Jonathan M Davis
October 06, 2019
Hello! I don't no if such behaviour was made by intention or just an accident, but this is very annoying. There is bugzilla issue already for that. So I am not the only person who is concerned about this.
https://issues.dlang.org/show_bug.cgi?id=19864

I try to support my compiler output as clear as possible, so if there is some real errors. So I could find these errors as fast as possible without scrolling several `screens` of text about warnings that I am actulally unable to fix.

This error occurs when I am using std.conv: to with std.json in my code. So I am not the person who actually marked these enum members deprecated. So I can't do something with this.
October 08, 2019
On Sunday, 6 October 2019 at 07:58:41 UTC, uranuz wrote:
> Hello! I don't no if such behaviour was made by intention or just an accident, but this is very annoying. There is bugzilla issue already for that. So I am not the only person who is concerned about this.
> https://issues.dlang.org/show_bug.cgi?id=19864
>
> I try to support my compiler output as clear as possible, so if there is some real errors. So I could find these errors as fast as possible without scrolling several `screens` of text about warnings that I am actulally unable to fix.
>
> This error occurs when I am using std.conv: to with std.json in my code. So I am not the person who actually marked these enum members deprecated. So I can't do something with this.

I also think it would be useful to have some way to suppress deprecations in a block of code. This is going to become important in the next version of D, where deprecated unittests will become basically impossible to use with unit-threaded because there'll be no way for unit-threaded to call a deprecated unittest without incurring a deprecation message. (That I can see.)
October 08, 2019
On Tuesday, 8 October 2019 at 04:31:22 UTC, FeepingCreature wrote:
> On Sunday, 6 October 2019 at 07:58:41 UTC, uranuz wrote:
>> [...]
>
> I also think it would be useful to have some way to suppress deprecations in a block of code. This is going to become important in the next version of D, where deprecated unittests will become basically impossible to use with unit-threaded because there'll be no way for unit-threaded to call a deprecated unittest without incurring a deprecation message. (That I can see.)

It is curious if it needs some language support to suppress deprecation messages or if it is just a library issue?

October 08, 2019
On Tuesday, October 8, 2019 12:39:28 AM MDT uranuz via Digitalmars-d wrote:
> On Tuesday, 8 October 2019 at 04:31:22 UTC, FeepingCreature wrote:
> > On Sunday, 6 October 2019 at 07:58:41 UTC, uranuz wrote:
> >> [...]
> >
> > I also think it would be useful to have some way to suppress deprecations in a block of code. This is going to become important in the next version of D, where deprecated unittests will become basically impossible to use with unit-threaded because there'll be no way for unit-threaded to call a deprecated unittest without incurring a deprecation message. (That I can see.)
>
> It is curious if it needs some language support to suppress deprecation messages or if it is just a library issue?

Any non-deprecated code that uses deprecated symbols will result in a deprecation message when it's compiled. This includes stuff like template constraints and type introspection. So, when you start doing things like using EnumMembers on an enum type which has a deprecated member, then it's definitely going to result in deprecation messages, because the deprecated member is actually used in the code.

This isn't really a new problem, but finally being able to deprecate enum members has certainly made it worse. And there isn't an obvious solution either. After all, just because an enum member was deprecated doesn't mean that it shouldn't be used, and if it is used, there really should be a deprecation message indicating that it was used. The main problem is that you're using it indirectly, so you don't really have any control over it.

A related issue would be what should happen with final switch. A final switch is supposed to have a case for _every_ enum member, and that would include deprecated enum members. If it didn't, then you have an enum member that's perfectly valid (just deprecated) which could be given to the final switch, and it wouldn't be able to handle it, since it wouldn't think that it was a valid value for that enum type. You can't even say that it should do one thing in a function that's deprecated and another thing in a function that's not deprecated, because not only could a deprecated enum value be passed to a non-deprecated function, but code isn't compiled differently based on whether it's in a deprecated context or not. A function's internals are going to compile exactly the same way whether the function is deprecated or not. The only difference is that if the function isn't deprecated, and it uses deprecated symbols, then you're going to get a deprecation message (or an error if -de is used). The generated code is the same.

If we had a trait for testing whether a symbol was deprecated or not, and using it on a deprecated symbol did not trigger a deprecation message, then code could choose to test whether something was deprecated and skip it if it were, so we could then have a version of EnumMembers which ignored deprecated members, but again, that would cause problems with final switch, and code like std.conv.to isn't going to use it, because code that worked before that enum member was deprecated needs to continue to work (and work the same way) as long as that enum member still exists. Compiling a piece of code differently based on whether a symbol is deprecated or not could be useful in some circumstances, but it also makes it so that there's a real risk of code breaking simply because a symbol was deprecated, and deprecations result in messages by default rather than errors precisely because we're trying to give people a chance to fix their code before the symbol is removed rather than forcing them to change their code immediately.

If you're looking for something like std.conv.to to not spit out deprecation messages when compiled to convert to or from an enum, you're basically asking it to generate a deprecation message based on whether you use the deprecated enum member or not, which can't std.conv.to can't know until runtime.

A related issue is the -de flag, which arguably is really bad in that it makes it so that is expressions and __traits(compiles, ...) expressions have a different result depending on whether -de is used or not, because -de turns deprecation messages into errors. Meaning that code that compiled just fine before the deprecation may not compile anymore, or it may compile with different behavior.

So, there are a number of subtleties to this whole situation that make it kind of hard to figure out what the best approach is. We don't want deprecation messages being printed when the code isn't really doing anything that needs to be changed, but we also don't want the code's behavior to change just because something was deprecated. And how to tweak what we're doing to fix that in a reasonable way is not obvious.

Regardless, there are really only two ways to shut up deprecation messages when -de isn't used:

1. Change the code so that it doesn't use the deprecated symbol (which we don't really have a way to do when type introspection is involved and whether we would want to not see those messages with type introspection depends on what the type introspection is doing; it's also not always possible or reasonable to change generated code like with std.conv.to).

2. Use -d to shut up all deprecation messages (which means that you won't see them and won't know when you actually need to update your code, so in all likelihood, your code will just end up breaking when the deprecated symbol is finally removed).

If -de is used, then code using deprecated symbols in is expressions or __traits(compiles, ...) expressions shouldn't trigger deprecation messages, because compilation errors are ignored in such expressions beyond determining whether the code compiles or not so that the compiler can give you a boolean result.

- Jonathan M Davis



October 08, 2019
On Tuesday, 8 October 2019 at 10:06:18 UTC, Jonathan M Davis wrote:
> A related issue is the -de flag, which arguably is really bad in that it makes it so that is expressions and __traits(compiles, ...) expressions have a different result depending on whether -de is used or not, because -de turns deprecation messages into errors. Meaning that code that compiled just fine before the deprecation may not compile anymore, or it may compile with different behavior.
>

I'm gonna argue this :) -de makes sense if one interprets it as "generate the code that would result if all deprecated symbols were removed." Of course this doesn't quite work right with stuff like final switch and enums... but it works with pretty much everything else. (?)

Should __traits(allMembers) ignore deprecated enum members with -de? Under this interpretation, it seems that it should.

And regarding expressions having a different result, well, yes, just like they'll have when the deprecated symbol is removed. :)

Separately: the problem with unittest and deprecations is that a "deprecated unittest" results in a deprecated unittest function in __traits(getUnitTests), which there's no way to call without incurring recursive deprecation all the way to deprecated void main. This is arguably wrong - imo deprecated unittest shouldn't mean the *test* is deprecated, just that it tests a deprecated feature. This can be seen by the fact that D's runtime calls deprecated unittests with no warning, -de or otherwise. So you should be able to call them from framework code too.
October 08, 2019
On Tuesday, October 8, 2019 5:50:48 AM MDT FeepingCreature via Digitalmars-d wrote:
> On Tuesday, 8 October 2019 at 10:06:18 UTC, Jonathan M Davis
>
> wrote:
> > A related issue is the -de flag, which arguably is really bad in that it makes it so that is expressions and __traits(compiles, ...) expressions have a different result depending on whether -de is used or not, because -de turns deprecation messages into errors. Meaning that code that compiled just fine before the deprecation may not compile anymore, or it may compile with different behavior.
>
> I'm gonna argue this :) -de makes sense if one interprets it as "generate the code that would result if all deprecated symbols were removed." Of course this doesn't quite work right with stuff like final switch and enums... but it works with pretty much everything else. (?)
>
> Should __traits(allMembers) ignore deprecated enum members with -de? Under this interpretation, it seems that it should.
>
> And regarding expressions having a different result, well, yes, just like they'll have when the deprecated symbol is removed. :)

-de is for those who want to force code in a code base to be updated when a deprecation message pops up instead of letting it be fixed later. It does not do exactly the same thing as having the deprecated symbol removed, since the symbol still exists and still affects stuff like overloading and type introspection. Yes, an expression which tests whether a piece of code compiles or not which uses the deprecated symbol will then fail to compile similar to what it would do once the symbol has been removed, but you could still get subtle differences like a piece of code that doesn't compile because of a conflicting symbol which then compiles fine once the deprecated symbol has actually been removed. So, I'd advise against using -de to see what the code would do once the symbol was removed. The effect will be similar, but it won't be the same, and depending on the code involved, the difference could matter.

All in all though, -de has a lot of the same problems that -w does. Whenever a compiler flag can change what is and isn't an error, there are going to be subtle problems - especially when it's possible to have code which compiles different branches depending on whether a particular piece of code compiles or not. It's not necessarily the case that it's a problem to use -de or -w, but there are risks involved.

> Separately: the problem with unittest and deprecations is that a "deprecated unittest" results in a deprecated unittest function in __traits(getUnitTests), which there's no way to call without incurring recursive deprecation all the way to deprecated void main. This is arguably wrong - imo deprecated unittest shouldn't mean the *test* is deprecated, just that it tests a deprecated feature. This can be seen by the fact that D's runtime calls deprecated unittests with no warning, -de or otherwise. So you should be able to call them from framework code too.

I expect that the problem here has to do with how things get lowered. Underneath the hood, a unittest block is basically a normal function and thus is going to tend to follow the same rules that a normal function would. As such, it would make sense that it would be a problem to have a non-deprecated function calling a unittest function or that a piece of code which is introspecting unit test stuff would get deprecation messages due to deprecated unittest blocks.

I don't know enough of the details about how the unit test stuff works to say how it should be fixed, but I agree that the current behavior isn't great for alternate test runners.

- Jonathan M Davis



October 09, 2019
On Tuesday, 8 October 2019 at 16:03:20 UTC, Jonathan M Davis wrote:
> I don't know enough of the details about how the unit test stuff works to say how it should be fixed, but I agree that the current behavior isn't great for alternate test runners.
>
> - Jonathan M Davis

Maybe just ignore the deprecation if we're calling a function that's a unittest?
October 09, 2019
On Wednesday, 9 October 2019 at 07:24:04 UTC, FeepingCreature wrote:
> On Tuesday, 8 October 2019 at 16:03:20 UTC, Jonathan M Davis wrote:
>> I don't know enough of the details about how the unit test stuff works to say how it should be fixed, but I agree that the current behavior isn't great for alternate test runners.
>>
>> - Jonathan M Davis
>
> Maybe just ignore the deprecation if we're calling a function that's a unittest?

If you want to test deprecated features, you can mark the unittest as deprecated too.


deprecated unittest { ... }

This won't result in deprecations of the unittest's code block triggered.
Example: https://run.dlang.io/is/eRxCtd
October 09, 2019
On Wednesday, October 9, 2019 1:58:56 AM MDT Seb via Digitalmars-d wrote:
> On Wednesday, 9 October 2019 at 07:24:04 UTC, FeepingCreature
>
> wrote:
> > On Tuesday, 8 October 2019 at 16:03:20 UTC, Jonathan M Davis
> >
> > wrote:
> >> I don't know enough of the details about how the unit test stuff works to say how it should be fixed, but I agree that the current behavior isn't great for alternate test runners.
> >>
> >> - Jonathan M Davis
> >
> > Maybe just ignore the deprecation if we're calling a function that's a unittest?
>
> If you want to test deprecated features, you can mark the unittest as deprecated too.
>
>
> deprecated unittest { ... }
>
> This won't result in deprecations of the unittest's code block
> triggered.
> Example: https://run.dlang.io/is/eRxCtd

If I understand his complaint correctly, deprecated unittest blocks result in deprecation messages when you use third party test runners instead of the default one, and if that's what's happening, that should probably be fixed.

- Jonathan M Davis



October 09, 2019
On Wednesday, 9 October 2019 at 08:28:00 UTC, Jonathan M Davis wrote:
> On Wednesday, October 9, 2019 1:58:56 AM MDT Seb via Digitalmars-d wrote:
>> On Wednesday, 9 October 2019 at 07:24:04 UTC, FeepingCreature
>>
>> wrote:
>> > Maybe just ignore the deprecation if we're calling a function that's a unittest?
>>
>> If you want to test deprecated features, you can mark the unittest as deprecated too.
>>
>>
>> deprecated unittest { ... }
>>
>> This won't result in deprecations of the unittest's code block
>> triggered.
>> Example: https://run.dlang.io/is/eRxCtd
>
> If I understand his complaint correctly, deprecated unittest blocks result in deprecation messages when you use third party test runners instead of the default one, and if that's what's happening, that should probably be fixed.
>
> - Jonathan M Davis

That's correct. It's not been a problem in the past since deprecations were ignored in mixins, so unit-threaded worked "by coincidence."
« First   ‹ Prev
1 2