October 09, 2019
On Tuesday, 8 October 2019 at 10:06:18 UTC, Jonathan M Davis wrote:
> 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.

Would it help to be able to explicitly suppress these warnings in certain regions of code? So e.g. std.conv.to could disable these warnings when iterating over enum members. Other code that is generic and cannot opt out of handling deprecated things could be expected to do the same. This shifts the onus from the compiler to the programmer. But given the complexity of the issue, it might be the right choice.

October 09, 2019
Am 08.10.2019 um 13:50 schrieb FeepingCreature:
> 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.

For the particular issue of filtering out deprecated members, I've written a little workaround some time ago, using the fact that warnings inside of _traits(compiles) are gagged:

https://github.com/s-ludwig/dynamic/blob/79b73a9afe14432da6917fd519563655300092d1/source/dynamic.d#L82-L85

It doesn't help when actual access to these members is desired.
October 09, 2019
On Wed, Oct 09, 2019 at 07:38:34PM +0200, Sönke Ludwig via Digitalmars-d wrote: [...]
> For the particular issue of filtering out deprecated members, I've written a little workaround some time ago, using the fact that warnings inside of _traits(compiles) are gagged:
> 
> https://github.com/s-ludwig/dynamic/blob/79b73a9afe14432da6917fd519563655300092d1/source/dynamic.d#L82-L85
> 
> It doesn't help when actual access to these members is desired.

Interesting idea.

I wonder if it's possible to (ab)use __traits(compiles) to extract information from deprecated members while gagging the deprecation messages. Like, arrange for an expression inside __traits(compiles) to compile or not, based on some desired boolean criteria, then use static if outside to extract this information. This would be a really nasty hack, though, so probably should not be used in production!


T

-- 
First Rule of History: History doesn't repeat itself -- historians merely repeat each other.
October 12, 2019
On Wednesday, October 9, 2019 8:32:36 AM MDT Gregor Mückl via Digitalmars-d wrote:
> On Tuesday, 8 October 2019 at 10:06:18 UTC, Jonathan M Davis
>
> wrote:
> > 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.
>
> Would it help to be able to explicitly suppress these warnings in certain regions of code? So e.g. std.conv.to could disable these warnings when iterating over enum members. Other code that is generic and cannot opt out of handling deprecated things could be expected to do the same. This shifts the onus from the compiler to the programmer. But given the complexity of the issue, it might be the right choice.

AFAIK, it's not currently possible to surpress deprecation messages other than turning them off entirely.

As for whether it would be desirable... I don't know. On the one hand, it's kind of annoying that something like std.conv.to would spit out deprecation messages for things like deprecated enum members. On the other hand, that happens because the code is actually using those deprecated enum members, and it's quite possible that it will be passed an enum value equal to a deprecated enum member. Enum members get a bit weird, because deprecating them doens't necessarily mean that their values are being deprecated, and even if the values are supposed to go away, it's quite easy to have enum values that don't match any members (personally, I wish that our enums were a lot stricter about that than they are, but they aren't).

Normally, deprecation messages indicate that something needs to be updated to no longer use a deprecated symbol, because that symbol is going to be removed later. However, in the case of generated code, it could end up using a deprecated symbol thanks to something like EnumMembers, and yet such code shouldn't actually be changed. It's just going to naturally take care of itself once the deprecated enum member is gone. So, on that basis, the deprecation message is arguably inappropriate, but making it possible to selectively ignore deprecation messages in such code could be problematic as well. For instance, consider the case where opCast is deprecated. That would result in a deprecation message from std.conv.to, but it's one where the caller would almost certainly need to be updated to not use std.conv.to (though that could get a bit murky if the idea was that std.conv.to would switch to using a constructor once the opCast was removed). So, at minimum, it's not the case that std.conv.to should just be eating deprecation messages.

Even if we did decide that we wanted to add a way to selectively ignore deprecation messages, I don't know what that should look like, and depending on what it looked like, it could have other negative consequences.

Honestly, I suspect that in the vast majority of cases, the current situation is not an issue. It's popped up now primarily because of the new ability to deprecate enum members, and while I think that it's great to be able to do so, I also think that deprecating enum members gets a bit iffy once things like EnumMembers come into play anyway. Certainly, generated code like that needs to continue to use deprecated symbols, otherwise it would break existing code, meaning that it can't actually be updated the way that you would normally update code using deprecated symbols, and there's a real risk that once the symbol is actually removed, code will end up breaking due to the symbol then being gone. So, I don't know how much sense it makes to deprecate enum members in practice much as it's desirable in theory.

Personally, the place that I've primarily had issue with needing to use deprecated symbols in code that isn't deprecated is in template constraints that are trying to disallow a deprecated type. In particular, last time I tried to deprecate TickDuration, I ran into problems with a bunch of deprecation messages that I had a hard time figuring out how to get rid of.

It may be that we need to make some kind of change here with regards to when deprecation messages pop up and/or how the programmer can control that, but I'm not sure that we really understand the situation well enough to do a good job with that at the moment. I think that we need to have a good understanding of the situations where deprecation messages are popping up when the code doesn't actually need to be changed - both what's happening and why - before we can really put forward a good solution to the problem.

- Jonathan M Davis




1 2
Next ›   Last »