New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
deprecatedError + restricted annotation #7790
Conversation
6ad20eb
to
9e87c24
Compare
This is great! Just a point of admin: this isn't backwards-compatible with 2.13.0, so this would have to land in either 2.13.0-RC1 or slip to 2.14. |
There's a WIP of Adriaan's deprescalator. It makes deprecations go up, down, or silent, by use site or deprecatee. I haven't fully digested the feature requests on the ticket for ad-hoc |
Isn't it redundant with |
@nafg |
I've got a PR almost ready for
OK, that started out as a joke. |
b373bcf
to
1e35a49
Compare
I would like to generalize the name to subsume How about we could configure according to label and severity for a myriad ways of telling the user off |
That assumes those all naturally fit in an int axis, which I don't think is true. I think it's plausible to imagine some users wanting to see those What's your driver for trying to unify? |
I don’t want to keep adding annotations for other axes. That’s an order of
magnitude less scalable than the concern with the int for the severity. It
could be an enum. Or a string. In any case, the meaning would be specific to
the project and configurable.
…On Mon, 11 Mar 2019 at 18:15, Dale Wijnand ***@***.***> wrote:
That assumes those all naturally fit in an int axis, which I don't this is
true. I think it's plausible to imagine some users wanting to see those
poorPerformance warnings but others being fine with the apiMayChange
ones, and others wanting the inverse.
What's your driver for trying to unify?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#7790 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAFjyyEighIg7NtZ6WGMP54wGphwwQOsks5vVo9KgaJpZM4bOQAU>
.
|
Would the enum be project-side too, or in the standard library? If it's project-side, then it would lose shared, universal semantic value (such as the |
|
So if we reverse engineer the meaning of
IIUC, the advisory category (
If we imagine |
I'll have to come up with a different name for the |
The annotation and the mechanism to configure whether and how severely to warn should be in the stdlib & compiler, the rest should be configurable. We could have a few default behaviours, like warning on using an internal member from another package. |
I can't extemporaneously come up with a better name, but let's first focus on the semantics. I think we're getting somewhere! |
To avoid the issues caused by adding variants to an enum / sealed hierarchy (around compile-time match exhaustion and runtime matching errors) maybe best have it be unsealed so consumers would have to handle the default case. Optionally with a (scala only) package private constructor, depending on if it should also be user-extendible or not.
Wouldn't it be in the And for that later 👨🎨 naming session:
Perhaps Also, I think it would be good if the in-code names for the categories matched the command-line names. So if it's Finally, for the ultimate 👨🎨: |
I definitely want the category to be user-extensible/definable, which is why I suggest to let it be a String. What good is the type system if we really just want users to be able to come up with sensible names and provide them on the command line -- unless we port the type checker to bash, we won't get much benefit from static checks here. The severity is likely a bit more closed world, so we could do an enum there. I like |
We'd be using the type system in the tools that consume those categories (like MiMa + ApiMayChange), which would provide a little more structure than "please, community, use this string here". So, perhaps: class Category private[annotation]
object Category {
final case object Deprecated extends Category
final case object ApiMayChange extends Category
final case class Custom(identifier: String) extends Category
} |
I see little benefit to that. Some, but not enough to warrant the types.
I think we can get most of the benefit by having a few predefined constants.
…On Tue, 12 Mar 2019 at 10:39, Dale Wijnand ***@***.***> wrote:
I definitely want the category to be user-extensible/definable, which is
why I suggest to let it be a String. What good is the type system if we
really just want users to be able to come up with sensible names and
provide them on the command line -- unless we port the type checker to
bash, we won't get much benefit from static checks here.
We'd be using the type system in the tools that consume those categories
(like MiMa + ApiMayChange), which would provide a little more structure
than "please, community, use this string here". So, perhaps:
class Category private[annotation]
object Category {
final case object Deprecated extends Category
final case object ApiMayChange extends Category
final case class Custom(identifier: String) extends Category {
override def toString = s"Custom($identifier)"
}
}
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#7790 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAFjyw_Tmps1OPvLzfDygSjDYLP3tEUVks5vV3XvgaJpZM4bOQAU>
.
|
String literals being so readily available I fear we'd immediately have both "deprecated" and "deprecation" as categories, because some users didn't see the |
I don't think that's a big deal. This is an optional, cultural thing that will mostly be driven from outside configuration outside the purview of the type checker. I would rather have zero friction to free choice of categories. It's not about correctness/exhaustivity but rather about being helpful. Having a few built-in types and then a If they want the benefits of the few built-in categories we'll eventually support, they'll have to read the docs and fix their spelling. |
OK. And I guess we can attach documentation to those constants, detailing the intended semantics and usage of the category. |
I talked to @szeiger about the removal of the multi-param
|
If we're going to get this annotation into 2.13.0, we need to agree on the design and merge this PR this week. I suggest delaying the multi-param infix errors until later -- we can introduce those in 2.13.x. The reporter configuration part can also come later. For the annotation, I suggest:
In my mind, "lint" could be a label, but the more generic part is that we're restricting usage of a member (as a generalisation of deprecating). All arguments are stringly typed because we're going for flexibility and user-friendliness. There's little for the type checker to enfore here. |
You could encode |
use case 1: library author really wants it to be an errorFor this mode, we need something like use case 2: library author provides some context, and library users decide the severityThis is the use case that generalizes |
1e35a49
to
d580e51
Compare
5d40d26
to
e7ce794
Compare
@adriaanm Implemented |
Wow, excellent! What do you think about also having |
My preference would be to keep |
Implements `deprecatedError` annotation, which is a stronger version of `deprecated` annotation. Instead of continuing to compile the code, `deprecatedError` would fail to compile, displaying the message. The motivation is to display the (hopefully helpful) migration message after the method is gone.
This implements `restricted` annotation as a generic form of `deprecated` annotation. `restricted` takes `label` and `defaultSeverity` parameter. The user can configure how the usages of restricted API are handled by passing in `-Wconfig` config expressions. A warning config expression may be <label>, <label>:<severity>, or <label>:<prefix>:<severity> <label> is a String passed into `restricted` annotation. <severity> must be one of "error", "warning", "info", or "none": default: warning. <prefix> denotes the prefix of the restricted API. For example, "foo.*" will denote that this config would apply only to calls under foo package/object. Note: "*" is simply ignored. The following configuration would escalate apiMayChange restriction to an error: -Wconfig apiMayChange:foo.*:error
e7ce794
to
4019539
Compare
object RestrictedLabel { | ||
final val deprecated = "deprecated" | ||
final val internalOnly = "internalOnly" | ||
final val apiMayChange = "apiMayChange" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a "mistake" label for methods whose use indicates a coding mistake would be nice
in our team meeting, @retronym mentioned JEP 277, which is very much in this space; it was implemented in JDK 9. The Java designers considered encoding the reasons for the deprecation, but in the end, decided only to add a single Among the relevant passages:
|
In the mentioned team meeting I fought pretty hard for this PR, but couldn't convince the others. So, closing, with regret. In summary, the conclusion was that we need to flesh out the design space more and probably submit a SIP. |
Also forRemoval #7714 There is a certain wisdom in leveraging the work already done by the Java community. However, the optional label in the other PR is for convenient suppression, not for explanatory purposes, so kinda orthogonal. |
Implements `deprecatedError` annotation, which is a stronger version of `deprecated` annotation. Instead of continuing to compile the code, `deprecatedError` would fail to compile, displaying the message. This allows libraries to display a helpful migration message after the method is removed. This is a resend of scala#7790 based on the configurable warnings. Ref scala#8373 / https://twitter.com/not_xuwei_k/status/1240354073297268737
This implements `apiStatus ` annotation as a generic form of `deprecated` annotation. `apiStatus` takes `category` and `defaultAction` parameters, corresponding to configurable warning's category and action. One of the usage is to trigger compiler error from the library when a method is invoked to display migration message. Another usage would be to denote bincompat status of the API as warning. This is a resend of scala#7790 based on the configurable warnings. Ref scala#8373 / https://twitter.com/not_xuwei_k/status/1240354073297268737
This implements `apiStatus ` annotation as a generic form of `deprecated` annotation. `apiStatus` takes `category` and `defaultAction` parameters, corresponding to configurable warning's category and action. One of the usage is to trigger compiler error from the library when a method is invoked to display migration message. Another usage would be to denote bincompat status of the API as warning. This is a resend of scala#7790 based on the configurable warnings. Ref scala#8373 / https://twitter.com/not_xuwei_k/status/1240354073297268737
This implements `apiStatus` annotation as a generic form of `deprecated` annotation. While deprecated is only able to discourage someone from using the some API, `apiStatus` can be more nuanced about the state (for instance Category.ApiMayChange), and choose the default compile-time actions (Action.Error, Action.Warning, etc). In other words, this gives library authors the lever to trigger compilation warning or compilation errors! One of the usage is to trigger compiler error from the library when a method is invoked to display migration message. Another usage would be to denote bincompat status of the API as warning. This is a resend of scala#7790 based on the configurable warnings. Ref scala#8373 / https://twitter.com/not_xuwei_k/status/1240354073297268737
This implements
restricted
annotation as a generic form ofdeprecated
annotation.restricted
takeslabel
anddefaultSeverity
parameter.The user can configure how the usages of restricted API are handled by passing in
-Wconfig
config expressions.A warning config expression may be
<label>
,<label>:<severity>
, or<label>:<prefix>:<severity>
<label>
is a String passed into@restricted
.<severity>
must be one of "error", "warning", "info", or "none": default: warning.<prefix>
denotes the prefix of the restricted API. For example,"foo.*"
will denotethat this config would apply only to calls under foo package/object.
Note: "*" is simply ignored.
The following configuration would escalate apiMayChange restriction to an error: