-
Notifications
You must be signed in to change notification settings - Fork 107
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
Add Deprecated
and Unimplemented
attributes
#785
Conversation
092a967
to
51c4514
Compare
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.
Left some comments. Code looks good but I have reservations about the design and the feature in general.
/// Indicates that an item has been deprecated and may eventually be removed. | ||
Deprecated(Option<Span>), | ||
/// Indicates that an item does not have an implementation available for use. | ||
Unimplemented, |
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'm not really sold on having two separate attributes. Is Unimplemented
like a more severe Deprecated
? Or is it for things that we literally can't implement, where the implementation would just have a fail
statement or something? In either case, I feel like we could just reuse the Deprecated
attribute, perhaps with an additional flag or comment.
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.
Deprecated is typically something implemented but doomed to be removed soon.
/// Indicates that a callable is an entry point to a program. | ||
EntryPoint, | ||
/// Indicates that an item has been deprecated and may eventually be removed. | ||
Deprecated(Option<Span>), |
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 it would be nice if this could take a user provided message (which would then be displayed in the warning).
@@ -1126,8 +1155,28 @@ impl Display for Ident { | |||
/// An attribute. | |||
#[derive(Clone, Debug, PartialEq)] | |||
pub enum Attr { | |||
/// Provide pre-processing information about when an item should be included in compilation. | |||
Config, |
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.
Just a thought, not sure if I love it or not: Could we overload the @Config
attribute for the purposes of deprecation? Like put some items behind a configuration that will never exist in practice (like None
or literally Deprecated
). The error message could then provide a little more context based on the configuration, or the attribute could take a user-provided message.
@@ -175,6 +176,16 @@ impl Checker { | |||
)); | |||
} | |||
|
|||
fn check_attr_expr(&mut self, names: &Names, expr: &Expr) { |
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.
Honestly it feels weird to allow an expression here. Can we just allow a Path
to a global if the intention is "use this alternative API"? Why would we allow lambdas? If we're allowing expressions, why not statements too? I don't think I get the use case you have in mind.
))] | ||
#[diagnostic(severity(Warning))] | ||
#[diagnostic(code("Qsc.Resolve.Deprecated"))] | ||
Deprecated(String, #[label] Span), |
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 feel iffy about having this baked into the resolver, I feel like it could be a separate pass, both for future-facing reasons (such as the ability to disable and order checks, as we talked about), but also because it feels like scope creep for the core parts of the compiler.
@minestarks is asking some great questions, and even pointed out that the current approach doesn't fully update for the existence of a new warning type. For example, the playground and QCOM disable the run button if any errors are present, but check that by just looking at whether the length of VSDiagnostics returned from compilation is greater than zero. We can improve this via filtering (and should) but it might be worth a more holistic look at what a warning means and how it should be surfaced. I'm changing this to draft to give us the chance to work through these questions and decide if a separate, "prepare for warnings" PR is needed in the infrastructure. I think it might be worth reviewing that on it's own separate from the feature being introduced here. |
Ok, after thinking about it some more, I have an approach I'd like to try. I'm going to split this up into two PRs. The first PR will introduce the Unimplemented attribute and include the refactoring of attribute handling to be enum-based as well as the error reporting for the new Unimplemented attribute. There, we can focus on deciding whether that error makes sense in name resolution or should be pulled out to a pass and make sure the infrastructure for annotating references with relevant attribute info is acceptable. Then the second, follow-up PR can introduce the Deprecated attribute, which will be the first warning in the new stack. That PR discussion can focus on making sure we agree on how warnings are handled throughout the stack and tools, as well as making sure Deprecated itself is handled in a consistent way to give a good use experience. |
part 1 is now up as #826. Closing this in favor of that approach. |
This change adds support for two new attributes:
Deprecated
which will produce a warning if the attributed callable is used and can accept either unit/()
or a callable expression as the alternative. If an expression is provided, it will be name resolved and type checked.Unimplemented
which produces an error if the attributed callalbe is used and only accepts unit/()
.The idea is to be able to use these to indicate parts of the standard library are either getting ready to be removed or entirely not present. The expectationsi that they could be used like this (using two old Bitwise utilities):
And here is how that would show up if user code called these functions:
