www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Proposal on improvement to deprecated

reply Jonathan M Davis <jmdavisProg gmx.com> writes:
There has been a fair bit of discussion about improving deprecated in this 
pull request: https://github.com/D-Programming-Language/dmd/pull/345

It's quite clear that we want to add the ability to give a message with 
deprecated. It's also pretty clear, that deprecated needs to be improved in 
other ways, since as soon as you use -d, the deprecation errors go away, and 
you never see them again and end up with no explanation as to how to fix your 
code when a deprecated symbol is actually removed. There has also been some 
discussion on how to work in "scheduled for deprecation." The current method 
of using pragmas only works with templates, and various folks have found the 
messages annoying, since the only way to get rid of them is to cease using the 
symbol which has been scheduled for deprecation and the fact that they're 
pragmas means that they can't really tell you where in your code the symbol 
which has been scheduled for deprecation has been used.

I think that we really need to get this sorted out before the next release, so 
I'd like to make a proposal based on that discussion.

1. deprecated will be changed so that it will be able to have a message with 
it. e.g.

deprecated("message") void func() {}

If you do not include a message, then the message that you get will be 
essentially what you get right now.

2. deprecated will be changed so that it has a second parameter indicating 
whether the deprecation is soft or hard. e.g.

deprecated("message", soft) void func1() {}
deprecated("message", hard) void func2() {}

If no soft or hard is given, then it defaults to soft (which is the closest to 
the current behavior).

3. Regardless of whether the deprecation is soft or hard, code which uses a 
deprecated symbol will not compile unless it uses -d or -di (which would be a 
new flag). This is the same as the current behavior.

4. Soft deprecation means that if you compile with -d or -di, then the code 
will compile even if you use the deprecated symbol. If you use -d, then no 
deprecation messages are printed. If you use -di, then deprecation messages 
are printed, but they have no effect on compilation. They are neither errors 
nor warnings, just messages.

5. Hard deprecation means that the code will not compile at all if the 
deprecated symbol is used. -d and -di will have no effect on hard deprecation. 
The idea is that instead of outright removing the symbol (which then gives no 
indication as to what should be used instead now that the symbol is gone), you 
get a message telling you what to use instead. But the code still won't 
compile, so you'll still be forced change your code.


The way that Phobos will then deal with depreaction is as follows:

1. A symbol which is going to be removed will be scheduled for deprecation. 
This means that its documentation will mark it as scheduled for deprecation, 
and it will be noted in the changelog that it has been scheduled for 
deprecation. But there will be _no_ compiler messages of any kind about the 
change. So, it's up to the programmer to pay attention and notice if anything 
has been scheduled for deprecation.

2. After a period of time, the symbol will be soft deprecated. So, if neither 
-d nor -di is used, then any code using the symbol will fail to compile. If 
the programmer does not want to immediately change their code but still wants 
it to compile, they can then choose to either use -d and get no deprecation 
messages or use -di and get deprecation messages.

3. After a period of time, the symbol will be hard deprecated. So, at that 
point, the programmer _must_ change their code if they want it to continue to 
compile. But unlike right now, they get a decent error message about how to fix 
their code.

4. After a period of time, the symbol is completely removed.


I think that this solution is simple enough to be reasonable. It doesn't stray 
wildly from the current behavior, and it gives programmers the option as to 
whether they really want to see deprecation messages or not before they're 
forced to change their code.

Does this scheme seem acceptable? Are there any reasons why would _shouldn't_ 
go forward with this proposal?

- Jonathan M Davis
Oct 01 2011
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-10-02 07:24, Jonathan M Davis wrote:
 There has been a fair bit of discussion about improving deprecated in this
 pull request: https://github.com/D-Programming-Language/dmd/pull/345

I have not read the discussion on github but an idea would be to have several levels of deprecation. Instead of "soft" and "hard" there could be numbers. Say level 1 could be used for scheduled for deprecation and depending what flags will be used when compiling it could print some kind of message. Level 2 would be soft deprecate and level 3 would be hard deprecate. There could also be more levels in between these levels if we want. The idea is that the user can use a compiler flag to get messages about symbols that are scheduled for deprecation. Don't know if this is too complicated. -- /Jacob Carlborg
Oct 02 2011
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/2/2011 1:16 PM, Jonathan M Davis wrote:
 The feature needs to be simple.

Yes, totally. And it is simple, now. The trouble is coming from the wholesale deprecation of large swaths of Phobos with every recent release. I don't think the solution is to make deprecation more complex (because no matter what you do, the user will still have to re-edit his code, and that's the real problem), but to make deprecation and code breakage a rare event.
Oct 02 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/2/2011 6:48 PM, Jonathan M Davis wrote:
 Regardless of all that though, I think that the issues that we've found in
 using deprecated need to be addressed - preferably with a simple solution, but
 they need to be addressed just the same.

A message is probably justified. The rest, I have serious reservations about.
Oct 02 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/2/2011 8:47 PM, Jonathan M Davis wrote:
 Well, making deprecation print messages but not prevent code compilation and
 then later completely preventing code compilation when you make it "full"
 would better deal with the use case that you're always having problems with of
 code being broken as soon as something is deprecated. It'll make it so that
 programmers get a message (which they may be able to turn off with -d) rather
 than their code breaking, and then when the item would have been removed,
 rather than their code just breaking, it breaks (since the item has been fully
 deprecated and is unusable), but they get a decent message about how to fix it.
 The end result is much less disruptive and not much more complicated than what
 we have now.

I don't see it as less disruptive. I see no point to anything beyond -d to allow deprecations, and no -d to not allow them. The only real point of -d is so the user can defer fixing it until it is convenient; it's not meant as a permanent part of one's build process.
Oct 02 2011
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/2/11 10:57 PM, Walter Bright wrote:
 On 10/2/2011 8:47 PM, Jonathan M Davis wrote:
 Well, making deprecation print messages but not prevent code
 compilation and
 then later completely preventing code compilation when you make it "full"
 would better deal with the use case that you're always having problems
 with of
 code being broken as soon as something is deprecated. It'll make it so
 that
 programmers get a message (which they may be able to turn off with -d)
 rather
 than their code breaking, and then when the item would have been removed,
 rather than their code just breaking, it breaks (since the item has
 been fully
 deprecated and is unusable), but they get a decent message about how
 to fix it.
 The end result is much less disruptive and not much more complicated
 than what
 we have now.

I don't see it as less disruptive. I see no point to anything beyond -d to allow deprecations, and no -d to not allow them. The only real point of -d is so the user can defer fixing it until it is convenient; it's not meant as a permanent part of one's build process.

I agree. Perhaps the best solution is to simply allow a message with deprecated. This will allow library writers to control the "strength" of deprecation by simply adjusting the message from "This will be deprecated on yyy-mm-dd" to "This is now deprecated and unsupported". Andrei
Oct 02 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/2/2011 10:13 PM, Jonathan M Davis wrote:
 I really think that making it so that deprecated doesn't actually stop
 compilation (but rather just prints the message) would improve things

The user has two choices: 1. get deprecation messages and fix the code 2. add -d and ignore it I don't see any point in printing messages and ignoring them. I don't believe it improves the user experience. The user is going to have to eventually fix the code, and that WILL BE ANNOYING to him. Guaranteed. There's no way to deprecate things and not annoy people.
Oct 02 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-10-03 07:59, Walter Bright wrote:
 On 10/2/2011 10:13 PM, Jonathan M Davis wrote:
 I really think that making it so that deprecated doesn't actually stop
 compilation (but rather just prints the message) would improve things

The user has two choices: 1. get deprecation messages and fix the code 2. add -d and ignore it I don't see any point in printing messages and ignoring them. I don't believe it improves the user experience. The user is going to have to eventually fix the code, and that WILL BE ANNOYING to him. Guaranteed. There's no way to deprecate things and not annoy people.

Since we already are using pragma(msg, "scheduled for deprecation") where possible, i.e. in templates, why can't we have a proper language construct for doing it? deprecated("message") {} deprecated {} Behave as it currently does, except that the first form will print a message as well. deprecated("message", scheduled) {} Will behave just as pragma(msg, "") does when a symbol is used that is wrapped in the "deprecated" block. -- /Jacob Carlborg
Oct 03 2011
parent Walter Bright <newshound2 digitalmars.com> writes:
On 10/3/2011 12:21 AM, Jacob Carlborg wrote:
 Since we already are using pragma(msg, "scheduled for deprecation") where
 possible, i.e. in templates, why can't we have a proper language construct for
 doing it?

 deprecated("message") {}
 deprecated {}

 Behave as it currently does, except that the first form will print a message as
 well.

That's a good idea.
 deprecated("message", scheduled) {}

 Will behave just as pragma(msg, "") does when a symbol is used that is wrapped
 in the "deprecated" block.

Too many features.
Oct 03 2011
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 10/2/2011 9:07 PM, Jonathan M Davis wrote:
 If the messages can then be turned off with -d, you get essentially
 the same situation as right now once you compile with -d, except that if there
 is some sort of "full" deprecation beyond that where even -d won't even let
 the code compile, then you get better messages if someone somehow ends up with
 -d in their normal build process (be it by accident or foolishness or
 whatever).

If the user leaves -d in their makefile, then they accept that someday their code will stop compiling.
Oct 02 2011
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-10-02 22:16, Jonathan M Davis wrote:
 On Sunday, October 02, 2011 10:48:53 Jacob Carlborg wrote:
 On 2011-10-02 07:24, Jonathan M Davis wrote:
 There has been a fair bit of discussion about improving deprecated in
 this pull request:
 https://github.com/D-Programming-Language/dmd/pull/345

several levels of deprecation. Instead of "soft" and "hard" there could be numbers. Say level 1 could be used for scheduled for deprecation and depending what flags will be used when compiling it could print some kind of message. Level 2 would be soft deprecate and level 3 would be hard deprecate. There could also be more levels in between these levels if we want. The idea is that the user can use a compiler flag to get messages about symbols that are scheduled for deprecation. Don't know if this is too complicated.

And what would each level do? How would it interact with the compiler? The feature needs to be simple. Deprecation is not something that is going to need to be used frequently, so making it particularly complicated is undesirable. It needs to be effective but easy to use. What we have is better than nothing, but it isn't quite good enough. So, it needs to be improved. But we don't need it to be vastly more powerful than it currently is, just iron it out a bit. Your suggestion sounds like it would be getting a bit complicated. - Jonathan M Davis

I was thinking that the levels match to different types of compiler messages. Above one level you get a note, above the next level a warning and above yet another level you get an error. Then it's up to the users to decide what a given level means. -- /Jacob Carlborg
Oct 02 2011
parent Jacob Carlborg <doob me.com> writes:
On 2011-10-03 09:07, Jonathan M Davis wrote:
 On Monday, October 03, 2011 08:54:24 Jacob Carlborg wrote:
 I was thinking that the levels match to different types of compiler
 messages. Above one level you get a note, above the next level a warning
 and above yet another level you get an error. Then it's up to the users
 to decide what a given level means.

I'm sure that someone would find the additional control that your suggestion gives useful, but it really sounds overly complicated to me. Deprecation needs to work smoothly, but it's also a feature that shouldnt' be needed very often, so it's not something that should be particularly complicated. And Walter doesn't seem to like the idea of complicating it more than it currently is _at all_ beyond adding the ability to give a custom message to deprecated. So, if any changes beyond that are going to be made, it looks like they're _really_ going to need to pull their weight and have a very solid argument for their inclusion. - Jonathan M Davis

I guess you're right, I just throw out a suggestion. -- /Jacob Carlborg
Oct 03 2011
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-10-02 22:16, Jonathan M Davis wrote:
 On Sunday, October 02, 2011 10:48:53 Jacob Carlborg wrote:
 On 2011-10-02 07:24, Jonathan M Davis wrote:
 There has been a fair bit of discussion about improving deprecated in
 this pull request:
 https://github.com/D-Programming-Language/dmd/pull/345

several levels of deprecation. Instead of "soft" and "hard" there could be numbers. Say level 1 could be used for scheduled for deprecation and depending what flags will be used when compiling it could print some kind of message. Level 2 would be soft deprecate and level 3 would be hard deprecate. There could also be more levels in between these levels if we want. The idea is that the user can use a compiler flag to get messages about symbols that are scheduled for deprecation. Don't know if this is too complicated.

And what would each level do? How would it interact with the compiler? The feature needs to be simple. Deprecation is not something that is going to need to be used frequently, so making it particularly complicated is undesirable. It needs to be effective but easy to use. What we have is better than nothing, but it isn't quite good enough. So, it needs to be improved. But we don't need it to be vastly more powerful than it currently is, just iron it out a bit. Your suggestion sounds like it would be getting a bit complicated. - Jonathan M Davis

If levels like these are used then there could be a compiler flag that says: "Print out all levels above X as a warning" or "All levels above Y should be a compile error". -- /Jacob Carlborg
Oct 02 2011
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-10-02 05:24:36 +0000, Jonathan M Davis <jmdavisProg gmx.com> said:

 deprecated("message", soft) void func1() {}
 deprecated("message", hard) void func2() {}

This soft/hard thing is a little obscure, no one will understand what it means by looking a it. Why not have separated 'deprecated' and 'unavailable' states? Also, the message part should be part of the Deprecated ddoc section in the documentation. Since the compiler knows about ddoc, wouldn't it be better if it could just write out the Deprecated ddoc section in the error message? This way they can't become out of sync.
 The way that Phobos will then deal with depreaction is as follows:
 
 1. A symbol which is going to be removed will be scheduled for deprecation.
 This means that its documentation will mark it as scheduled for deprecation,
 and it will be noted in the changelog that it has been scheduled for
 deprecation. But there will be _no_ compiler messages of any kind about the
 change. So, it's up to the programmer to pay attention and notice if anything
 has been scheduled for deprecation.

I'm not against that. But I think many people (including Walter) want to be notified by the compiler before it becomes an error. Passing straight from 'look at documentation' to 'compilation error' is too big of a step. - - - In all this, my opinion is that 'deprecated' should be changed to emit informational messages (not errors) by default. Then you have this: 1. scheduled for deprecation: documentation only 2. deprecated: informational message 3. unavailable: compilation error The scheduled for deprecation step would be mostly for things we know will be deprecated but that have no suitable replacement at the moment. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Oct 02 2011
next sibling parent Paul D Anderson <paul.d.removethis.anderson comcast.andthis.net> writes:
Michel Fortin Wrote:

 
 In all this, my opinion is that 'deprecated' should be changed to emit 
 informational messages (not errors) by default. Then you have this:
 
 1. scheduled for deprecation: documentation only
 2. deprecated: informational message
 3. unavailable: compilation error
 
 The scheduled for deprecation step would be mostly for things we know 
 will be deprecated but that have no suitable replacement at the moment.
 
 -- 
 Michel Fortin
 michel.fortin michelf.com
 http://michelf.com/
 

I like the idea of a deprecation message and the three-level progression. I'm not certain 'unavailable' is the best term but I like this idea better than the hard and soft distinction. 3 levels: documentation, deprecated, and, um, unavailable. A quick look at MS Word thesaurus offers these alternatives: denounced, condemned, censured, denigrated,... hmmm... maybe 'unavailabe' is not so bad. Extinct? Destroyed? Dead? Vanished? Or, that old standby 'depreciated'? Paul
Oct 02 2011
prev sibling next sibling parent Paul D Anderson <paul.d.removethis.anderson comcast.andthis.net> writes:
Michel Fortin Wrote:

 
 In all this, my opinion is that 'deprecated' should be changed to emit 
 informational messages (not errors) by default. Then you have this:
 
 1. scheduled for deprecation: documentation only
 2. deprecated: informational message
 3. unavailable: compilation error
 
 The scheduled for deprecation step would be mostly for things we know 
 will be deprecated but that have no suitable replacement at the moment.
 
 -- 
 Michel Fortin
 michel.fortin michelf.com
 http://michelf.com/
 

I like the idea of a deprecation message and the three-level progression. I'm not certain 'unavailable' is the best term but I like this idea better than the hard and soft distinction. 3 levels: documentation, deprecated, and, um, unavailable. A quick look at MS Word thesaurus offers these alternatives: denounced, condemned, censured, denigrated,... hmmm... maybe 'unavailabe' is not so bad. Extinct? Destroyed? Dead? Vanished? Or, that old standby 'depreciated'? Paul
Oct 02 2011
prev sibling parent travert phare.normalesup.org (Christophe) writes:
Michel Fortin , dans le message (digitalmars.D:145925), a écrit :
 In all this, my opinion is that 'deprecated' should be changed to emit 
 informational messages (not errors) by default. Then you have this:
 
 1. scheduled for deprecation: documentation only
 2. deprecated: informational message
 3. unavailable: compilation error
 
 The scheduled for deprecation step would be mostly for things we know 
 will be deprecated but that have no suitable replacement at the moment.

Could we not use a scheduled for deprecation level of deprecation to display warning if the user specially asks to get the message with a new compiler flag ? That would allow you to check you are not using soon-to-be-replaced functions when you make new code, but will not affect compilation of old code. -- Christophe
Oct 02 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Sunday, October 02, 2011 07:06:36 Michel Fortin wrote:
 On 2011-10-02 05:24:36 +0000, Jonathan M Davis <jmdavisProg gmx.com> said:
 deprecated("message", soft) void func1() {}
 deprecated("message", hard) void func2() {}

This soft/hard thing is a little obscure, no one will understand what it means by looking a it. Why not have separated 'deprecated' and 'unavailable' states?

And make a new keyword? Or do something like deprecated("message"); deprecated("message", unavailable); I'm not exactly married to the idea of using the terms soft and hard. If you have a clearer way of saying the same thing, that's fine with me.
 Also, the message part should be part of the Deprecated ddoc section in
 the documentation. Since the compiler knows about ddoc, wouldn't it be
 better if it could just write out the Deprecated ddoc section in the
 error message? This way they can't become out of sync.

Well, that would be nice in the same way that it would be nice if the examples were taken from a unittest block and put into the documentation. ddoc could be improved at a leter date to automatically include the message that deprecated is given. Not to mention, there's not currently any "deprecated" section in any ddoc in Phobos that I'm aware of. The ones that I've been doing have a note at the beginning of the documentation which is quite similar to what would go in the deprecation message, but it's not its own section with a "Deprecated:" header. We could certainly do that, but we haven't been.
 The way that Phobos will then deal with depreaction is as follows:
 
 1. A symbol which is going to be removed will be scheduled for
 deprecation. This means that its documentation will mark it as
 scheduled for deprecation, and it will be noted in the changelog that
 it has been scheduled for deprecation. But there will be _no_ compiler
 messages of any kind about the change. So, it's up to the programmer to
 pay attention and notice if anything has been scheduled for
 deprecation.

I'm not against that. But I think many people (including Walter) want to be notified by the compiler before it becomes an error. Passing straight from 'look at documentation' to 'compilation error' is too big of a step.

The problem is that a number of people have been complaining about the pragma messages. They don't _want_ messages. So, it's very hard to please everyone here. My proposal makes it possible to choose as to whether you want messages or not via the choice of -di vs -d in an attempt to placate both sides of that debate.
 - - -
 
 In all this, my opinion is that 'deprecated' should be changed to emit
 informational messages (not errors) by default. Then you have this:
 
 1. scheduled for deprecation: documentation only
 2. deprecated: informational message
 3. unavailable: compilation error

Well, in my proposal, that's what would happen when compiling with -di. We _could_ make it so that that's what always happens and make it so that -d turns off the informational messages. That's not necessarily a bad idea and is simpler, which is a good thing.
 The scheduled for deprecation step would be mostly for things we know
 will be deprecated but that have no suitable replacement at the moment.

Well, that's not how Walter has wanted it used nor how we've been using it. But the main reason for Walter wanting to have essentially _everything_ that's deprecated to be "scheduled for deprecation" first is to avoid breaking anyone's code without warning if they don't compile with -d, and your suggestion would make it so that that doesn't happen, since deprecating something doesn't immediately break code. So, your proposal has the downside of being a larger change with regards to the default behavior, but it's simpler and gives essentially the same benefits. Not to mention, it doesn't involve adding a new compiler flag, so it's probably simpler to implement too. - Jonathan M Davis
Oct 02 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Sunday, October 02, 2011 10:48:53 Jacob Carlborg wrote:
 On 2011-10-02 07:24, Jonathan M Davis wrote:
 There has been a fair bit of discussion about improving deprecated in
 this pull request:
 https://github.com/D-Programming-Language/dmd/pull/345

several levels of deprecation. Instead of "soft" and "hard" there could be numbers. Say level 1 could be used for scheduled for deprecation and depending what flags will be used when compiling it could print some kind of message. Level 2 would be soft deprecate and level 3 would be hard deprecate. There could also be more levels in between these levels if we want. The idea is that the user can use a compiler flag to get messages about symbols that are scheduled for deprecation. Don't know if this is too complicated.

And what would each level do? How would it interact with the compiler? The feature needs to be simple. Deprecation is not something that is going to need to be used frequently, so making it particularly complicated is undesirable. It needs to be effective but easy to use. What we have is better than nothing, but it isn't quite good enough. So, it needs to be improved. But we don't need it to be vastly more powerful than it currently is, just iron it out a bit. Your suggestion sounds like it would be getting a bit complicated. - Jonathan M Davis
Oct 02 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, October 02, 2011 17:10:58 Walter Bright wrote:
 On 10/2/2011 1:16 PM, Jonathan M Davis wrote:
 The feature needs to be simple.

Yes, totally. And it is simple, now. The trouble is coming from the wholesale deprecation of large swaths of Phobos with every recent release. I don't think the solution is to make deprecation more complex (because no matter what you do, the user will still have to re-edit his code, and that's the real problem), but to make deprecation and code breakage a rare event.

I think that that's a separate (albeit related) issue. If anything, the fact that we've been using the deprecated feature and found there to be issues with using it shows that it needs to be improved. I don't think that it needs drastic improvements (aside from adding a message to it), but it does need some improvement. I think that my suggestion does that, though Michel Fortin's suggestion in his response probably does it better because the result is even simpler than my proposal. I completely agree that deprecation should be a rare event. However, a number of us feel that Phobos needs to be made more consistent and have been making changes in line with that (such as fixing the names to match the naming scheme of the rest of Phobos and to make stuff follow current D programming idioms, such as ranges). I fully expect that that will taper off and that Phobos' APIs will become more stable. But we either fix it now or leave it as inconsistent in the long run (thereby reducing its quality), since the longer that we wait to change it, the more code will break when we do. For what it's worth, I think that most of the major changes are done aside from a few major module redesigns which have been in the works for some time (such as the redesign of std.stream and std.xml). The only major set of functions that I can think of at the moment that need to be looked at are the functions in std.string which take patterns, since they don't follow the correct naming scheme yet and there has been discussion of making them use regexes instead. So, I think that we're approaching the point when the APIs will stabilize. Regardless of all that though, I think that the issues that we've found in using deprecated need to be addressed - preferably with a simple solution, but they need to be addressed just the same. - Jonathan M Davis
Oct 02 2011
prev sibling next sibling parent "Marco Leise" <Marco.Leise gmx.de> writes:
Am 03.10.2011, 02:10 Uhr, schrieb Walter Bright  
<newshound2 digitalmars.com>:

 On 10/2/2011 1:16 PM, Jonathan M Davis wrote:
 The feature needs to be simple.

Yes, totally. And it is simple, now. The trouble is coming from the wholesale deprecation of large swaths of Phobos with every recent release. I don't think the solution is to make deprecation more complex (because no matter what you do, the user will still have to re-edit his code, and that's the real problem), but to make deprecation and code breakage a rare event.

I totally agree, yet I wouldn't mind to know the line of code where I am using a deprecated feature and a custom message. Unless of course, you like deprecation messages to be annoying so that it doesn't become a habit to deprecate stuff. ;)
Oct 02 2011
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, October 02, 2011 07:06:36 Michel Fortin wrote:
 On 2011-10-02 05:24:36 +0000, Jonathan M Davis <jmdavisProg gmx.com> said:
 deprecated("message", soft) void func1() {}
 deprecated("message", hard) void func2() {}

This soft/hard thing is a little obscure, no one will understand what it means by looking a it. Why not have separated 'deprecated' and 'unavailable' states?

We could just do deprecated("message"); deprecated("message", full); "Full" deprecation should be clear enough, I would think. And for simplicity, you just don't have any argument for partial deprecation. - Jonathan M Davis
Oct 02 2011
parent reply =?utf-8?Q?Aleksandar_Ru=C5=BEi=C4=8Di=C4=87?= <ruzicic.aleksandar gmail.com> writes:
What about using an attribute for that?

deprecated("foo() is deprecated use bar()") void foo() {...}
 schedule deprecated("foo() is going to be deprecated as of YYYY-MM-DD, use 
bar() instead") void foo() {...}

First form will behave like just it does now, with optional message 
argument.
Second form would produce informational message instead of compile error 
(with line number where that symbol is accessed from).

Both forms would print nothing when using -d switch.

In case "unavailable" is required, another attribute could be used for that:

 removed deprecated("foo() was removed as of YYYY-MM-DD, use bar() 
instead.") void foo();

When  removed deprecated symbol is used compiler will abort with detailed 
error message (line number where symbol is accessed from) even if -d switch 
is used. This would be more convenient than just bailing out with message 
"undefined symbol foo()" because we can  use message parameter of deprecated 
to direct user where to look for replacement.

Of course  schedule and  removed names are just an example..


"Jonathan M Davis"  wrote in message 
news:mailman.29.1317612078.22016.digitalmars-d puremagic.com...

On Sunday, October 02, 2011 07:06:36 Michel Fortin wrote:
 On 2011-10-02 05:24:36 +0000, Jonathan M Davis <jmdavisProg gmx.com> said:
 deprecated("message", soft) void func1() {}
 deprecated("message", hard) void func2() {}

This soft/hard thing is a little obscure, no one will understand what it means by looking a it. Why not have separated 'deprecated' and 'unavailable' states?

We could just do deprecated("message"); deprecated("message", full); "Full" deprecation should be clear enough, I would think. And for simplicity, you just don't have any argument for partial deprecation. - Jonathan M Davis
Oct 03 2011
parent reply Piotr Szturmaj <bncrbme jadamspam.pl> writes:
Aleksandar Ružičić wrote:
 What about using an attribute for that?

Looks like a good use case for user defined attributes (I need to write DIP on that). struct Deprecated { string message; // instantiated on every symbol marked with this attribute template applyAttribute(Symbol) { static assert(0, Symbol.stringof ~ "is deprecated: " ~ message); } } std.attributes.Deprecated("test"); class A { } This is just enough for deprecation. For other cases __traits should be extended with hasAttribute and getAttributes: static assert(__traits(hasAttribute, A, Deprecated)); static assert(is(__traits(getAttributes, A) == TypeTuple!(Deprecated))); // struct Deprecated available at compile time static assert(__traits(getAttribute, A, 0).message != ""); ---- Serialization example: ---- std.xml.XmlElement("address") struct Address { string street; string city; string country; } std.xml.XmlElement("person") struct Person { XmlAttribute("age") int ageInYears; string fullName; XmlElement("addr") // override element name Address address; } // with Uniform Function Call Syntax: void save(T)(T serializable, string fileName) if (__traits(hasAttribute, T, std.xml.XmlElement)) { auto elemAttr = __traits(getAttribute, T, std.xml.XmlElement); // serialization code } auto person = Person(30, "John Doe"); person.address = Address("Some street address", "London", "UK"); person.save("person.xml"); // should produce this content: <?xml version="1.0" encoding="UTF-8" ?> <person age="30"> <fullName>John Doe</fullName> <addr> <street>Some street address</street> <city>London</city> <country>UK</country> </addr> </person> ---- Other example with UFCS (flag handling) ---- struct Flags { template applyAttribute(Symbol) { // 1. test if Symbol is an enum // 2. test if there is only one Flags attribute for this enum // 3. test if flags don't overlap } } Flags enum A { Flag1 = 1, Flag2 = 2, Flag3 = 4 } bool hasFlag(T, V)(T t, V v) if (__traits(hasAttribute, T, Flags)) { return t & v == v; } void f(A a) { if (a.hasFlag(A.Flag1)) { // } } There are of course many other possible use cases like Object/Relational Mapping, RPC/Remoting, debugger visualization overrides, hints for the GC, etc. User defined attributes provide a powerful way to extend language without constantly upgrading the compiler (and avoiding "too many features" in it). I would love to hear any opinions about general idea of user defined attributes in D, not necessarily this particular syntax as it is only my loud thinking, though it should show what the whole thing is about.
Oct 03 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Piotr Szturmaj:

 for user defined attributes (I need to write DIP on that).

Please write that DIP :-) Even if it will be refused, it will be a starting point to build on successive better ideas for user defined attributes.
 There are of course many other possible use cases like Object/Relational
 Mapping, RPC/Remoting, debugger visualization overrides, hints for the
 GC, etc.

I see user defined attributes also as ways to extend the type system with in library/user code, a bit like dehydra/treehydra (but with no need to use another language to specify them). But I think more static introspection will be needed for that. I mean things like a __trait that given a function name, returns an array of the names of all its local variables, a __trait that tells if a variable used in a function is locally defined, globally defined, if it is static, etc. Some of such info is already present in the JSON documentation about modules. So a way to perform searches on such JSON at compile time will be useful. Eventually maybe even linear types or uniqueness types become implementable with annotations. Bye, bearophile
Oct 03 2011
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-10-03 20:22, Piotr Szturmaj wrote:
 Aleksandar Ružičić wrote:
 What about using an attribute for that?

Looks like a good use case for user defined attributes (I need to write DIP on that).

 There are of course many other possible use cases like Object/Relational
 Mapping, RPC/Remoting, debugger visualization overrides, hints for the
 GC, etc.

 User defined attributes provide a powerful way to extend language
 without constantly upgrading the compiler (and avoiding "too many
 features" in it).

 I would love to hear any opinions about general idea of user defined
 attributes in D, not necessarily this particular syntax as it is only
 my loud thinking, though it should show what the whole thing is about.

I would love this see this as well. I think it needs to be accessible at runtime too. It should be possible to get the attributes of a class through a base class reference and it should return the attributes of the runtime type. I would like to have something similar as this possible as well: class Foo { get_set int x; } Would insert a getter and setter for "x" like this: class Foo { int x_; int x () { return x_; } int x (int x) { return x_ = x; } } An attribute should be able to insert something else instead of the symbol it applies to, or nothing at all. -- /Jacob Carlborg
Oct 03 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Jacob Carlborg:

 I would like to have something similar as this possible as well:
 
 class Foo
 {
       get_set int x;
 }
 
 Would insert a getter and setter for "x" like this:
 
 class Foo
 {
      int x_;
 
      int x () { return x_; }
      int x (int x) { return x_ = x; }
 }

I think a template mixin is already able to do this. Bye, bearophile
Oct 03 2011
parent Jacob Carlborg <doob me.com> writes:
On 2011-10-03 21:54, bearophile wrote:
 Jacob Carlborg:

 I would like to have something similar as this possible as well:

 class Foo
 {
        get_set int x;
 }

 Would insert a getter and setter for "x" like this:

 class Foo
 {
       int x_;

       int x () { return x_; }
       int x (int x) { return x_ = x; }
 }

I think a template mixin is already able to do this. Bye, bearophile

Template mixins can do (most of) the other things suggested in this thread as well, except for your suggestion. But it's not pretty. -- /Jacob Carlborg
Oct 03 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, October 02, 2011 20:36:58 Walter Bright wrote:
 On 10/2/2011 6:48 PM, Jonathan M Davis wrote:
 Regardless of all that though, I think that the issues that we've found
 in using deprecated need to be addressed - preferably with a simple
 solution, but they need to be addressed just the same.

A message is probably justified. The rest, I have serious reservations about.

Well, making deprecation print messages but not prevent code compilation and then later completely preventing code compilation when you make it "full" would better deal with the use case that you're always having problems with of code being broken as soon as something is deprecated. It'll make it so that programmers get a message (which they may be able to turn off with -d) rather than their code breaking, and then when the item would have been removed, rather than their code just breaking, it breaks (since the item has been fully deprecated and is unusable), but they get a decent message about how to fix it. The end result is much less disruptive and not much more complicated than what we have now. - Jonathan M Davis
Oct 02 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, October 02, 2011 20:57:37 Walter Bright wrote:
 On 10/2/2011 8:47 PM, Jonathan M Davis wrote:
 Well, making deprecation print messages but not prevent code compilation
 and then later completely preventing code compilation when you make it
 "full" would better deal with the use case that you're always having
 problems with of code being broken as soon as something is deprecated.
 It'll make it so that programmers get a message (which they may be able
 to turn off with -d) rather than their code breaking, and then when the
 item would have been removed, rather than their code just breaking, it
 breaks (since the item has been fully deprecated and is unusable), but
 they get a decent message about how to fix it. The end result is much
 less disruptive and not much more complicated than what we have now.

I don't see it as less disruptive. I see no point to anything beyond -d to allow deprecations, and no -d to not allow them. The only real point of -d is so the user can defer fixing it until it is convenient; it's not meant as a permanent part of one's build process.

It's less disruptive, because code doesn't immediately break when something is deprecated (particularly since -d _shouldn't_ be part of on's normal build process). If the messages can then be turned off with -d, you get essentially the same situation as right now once you compile with -d, except that if there is some sort of "full" deprecation beyond that where even -d won't even let the code compile, then you get better messages if someone somehow ends up with -d in their normal build process (be it by accident or foolishness or whatever). But simply changing deprecation so that it prints a message instead of causing compilation failure makes deprecation less disruptive. Obviously, it's ultimately disruptive regardless, since the code has to be changed eventually, but at least in that case, it doesn't break immediately. As I recall, the main reason that you wanted stuff to be "scheduled for deprecation" first was because deprecated breaks code immediately, and you wanted people to have a chance to change their code before they'd _have_ to change either their code or their build scripts for their code to compile. Making it so that deprecated produces a message rather than stopping compilation does that. - Jonathan M Davis
Oct 02 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, October 02, 2011 23:36:13 Andrei Alexandrescu wrote:
 On 10/2/11 10:57 PM, Walter Bright wrote:
 On 10/2/2011 8:47 PM, Jonathan M Davis wrote:
 Well, making deprecation print messages but not prevent code
 compilation and
 then later completely preventing code compilation when you make it
 "full" would better deal with the use case that you're always having
 problems with of
 code being broken as soon as something is deprecated. It'll make it so
 that
 programmers get a message (which they may be able to turn off with -d)
 rather
 than their code breaking, and then when the item would have been
 removed, rather than their code just breaking, it breaks (since the
 item has been fully
 deprecated and is unusable), but they get a decent message about how
 to fix it.
 The end result is much less disruptive and not much more complicated
 than what
 we have now.

I don't see it as less disruptive. I see no point to anything beyond -d to allow deprecations, and no -d to not allow them. The only real point of -d is so the user can defer fixing it until it is convenient; it's not meant as a permanent part of one's build process.

I agree. Perhaps the best solution is to simply allow a message with deprecated. This will allow library writers to control the "strength" of deprecation by simply adjusting the message from "This will be deprecated on yyy-mm-dd" to "This is now deprecated and unsupported".

Except that the code won't compile regardless of whether the message says that the symbol is going to be deprecated or that it has been deprecated. In either case, the symbol has been deprecated as far as the compiler is concerned, regardless of what the message says. So, the strength of the deprecation is identical in either case. The only difference is whether the library writers will fix any bugs found in such a deprecated function. In both cases, the programmer is either going to have to immediately change their code or add -d to their bulid process. I really think that making it so that deprecated doesn't actually stop compilation (but rather just prints the message) would improve things even if we didn't add any kind of level to deprecated that would always stop compilation prior to the symbol actually being removed. - Jonathan M Davis
Oct 02 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, October 03, 2011 08:54:24 Jacob Carlborg wrote:
 I was thinking that the levels match to different types of compiler
 messages. Above one level you get a note, above the next level a warning
 and above yet another level you get an error. Then it's up to the users
 to decide what a given level means.

I'm sure that someone would find the additional control that your suggestion gives useful, but it really sounds overly complicated to me. Deprecation needs to work smoothly, but it's also a feature that shouldnt' be needed very often, so it's not something that should be particularly complicated. And Walter doesn't seem to like the idea of complicating it more than it currently is _at all_ beyond adding the ability to give a custom message to deprecated. So, if any changes beyond that are going to be made, it looks like they're _really_ going to need to pull their weight and have a very solid argument for their inclusion. - Jonathan M Davis
Oct 03 2011
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
We've already got informational warnings, warnings and errors.. why not  
just expand pragma to allow programmers to emit them on a case by case  
basis, i.e.

pragma(info, "foo is scheduled for deprecation")
pragma(warning, "foo will be deprecated on dd/mm/yy, replace with bar")
pragma(error, "foo has been deprecated, replace with bar")

R
Oct 03 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, October 03, 2011 15:01:13 Regan Heath wrote:
 We've already got informational warnings, warnings and errors.. why not
 just expand pragma to allow programmers to emit them on a case by case
 basis, i.e.
 
 pragma(info, "foo is scheduled for deprecation")
 pragma(warning, "foo will be deprecated on dd/mm/yy, replace with bar")
 pragma(error, "foo has been deprecated, replace with bar")

A key problem with using pragmas for deprecation messages is the fact that pragma is run once when that code is compiled. So, if you want it to affect only people who use the deprecated function, the function has to be templated. So, anything which isn't templated, can't have a message. Also, it'll print once per template instantion, not once per use, and it won't give any line numbers (if it did, it would give the line number of the pragma, not where the function is called). The pragma messages are somewhat useful, but they're too general to work very well as deprecation messages. - Jonathan M Davis
Oct 03 2011