-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC for attributes on statements and blocks. #16
Conversation
```rust | ||
fn name(method: SslMethod) -> &'static str { | ||
match method { | ||
Sslv2 => "SSLv2", |
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.
Missing attribute?
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.
This is meant to be a bad example:
i.e. the following is invalid:
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.
Ah, I misread
👍 |
👍 - this would be nice to have 😄 |
Looks unnatural to me if extended to if/else. My random thought is that maybe if/else should look more like a match:
|
I've been thinking about it a little more, and I actually think my second proposed if ... {
...
} else X where |
I think that looks the best too. |
So, what's the process to get a consensus on this? Having this merged would be super useful for me right now. |
@andrew-d, the process is outlined in RFC #1, the relevant part being:
Discussions of RFCs are predominately occurring during weekly meetings right now, but this is not a hard requirement. |
I'm generally in favor. I'm vaguely concerned about parser ambiguities but it should probably be ok. (Oh, my kingdom for a proper grammar.) |
@nikomatsakis I don't see any ambiguities: attributes and only attributes start with |
@chris-morgan I generally agree, I've just learned to be cautious when it comes to annotations that precede blocks etc. |
I'm in favor 👍 🍰 |
👍 |
I don't think its explicitly spelled out in the RFC, so I will ask: Are only outer-attributes allowed to be used in this manner? Or are inner-attributes allowed as well? Supporting inner-attributes could help improve the appearance of e.g. the So, If the intent is that inner-attributes should also be allowed, then we would need to resolve questions of what their scope is (I'm guessing it would be the most tightly enclosing block), and it would probably be good to require all inner-attributes to occur at the start of the block, before any items/declarations/outer-attributes etc). But I would be fine if inner-attributes are not supported, or are not supported in the first iteration of this feature. |
} else { | ||
} | ||
} | ||
``` |
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.
Could this include blocks?
#[attr] {
// ...
}
{
#![attr]
// ...
}
There was a good amount of discussion in today's meeting about this RFC. The general opinion is that it seems a little odd to limit attributes to just statements. One big reason is that many things which look like statements are actually expressions, such as: fn foo() {
if some_condition() { println!("test") } // this is an expression, not a statement
} There are some concerns about how far-reaching it would be to modify the grammar to allow attributes on all expressions (which is the ideal ending point for something like this). In the meantime, how would you feel about paring down the RFC to just attributes on match arms? That seems have a very real and pressing use case, and it pretty much works as expected because it can appear anywhere a match can appear. |
Should I cut it down here? Or open a new RFC, since it will be a rather large simplification (maybe this RFC can be co-opted for the more general statements/expressions attributes). |
I think either way is ok. It sounds like statements/expressions will want to be a separate RFC, so feel free to pick either one to be this one (whichever is easiest) |
I opened #49 since pretty much none of the discussion here is about match arms. (I'll update this to be statement/expression specific at some point.) |
Updated. |
+1 Attributes on all the things! |
A possibly better way to implement this generically would be to add an On Tue, Jun 3, 2014 at 2:09 PM, Eric Reed [email protected] wrote:
|
Some notes from discussion during triage meeting:
@nikomatsakis you had some additional thoughts that seemed a little implementation oriented in terms of what it would be like to parse code that has an arbitrary number of attributes followed by some statment-or-expression, feel free to to to clarify my points above. Anyway, @huonw , we invite you to revise the RFC and then we will try to address it formally at a team meeting. |
As a point of reference, Java 8 significantly expanded the parts of the grammar that can be tagged with annotations: http://java.dzone.com/articles/java-8-type-annotations |
`if` is annoying.
Updated to include expressions more definitely. There are some annoying interactions with |
|
||
This can be addressed by having `#[attr] if cond { ...` be an exterior | ||
attribute (applying to the whole `if`/`else` chain) and `if cond | ||
#[attr] { ... ` be an interior attribute (applying to only the current |
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.
Markdown is interpreting this as a heading :-)
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.
Haha, whoops. Fixed.
Not related to attributes in general, but allowing #[cfg]s everywhere makes it harder to reason about the code, like in C/C++ when you have preprocessor logic all over a function instead of different functions where the platform specific behavior is isolated. That's why I think it might be a bit dangerous to allow this as this might make people move away from separate functions for #[cfg]-dependant behavior. |
- explicitly disallowing attributes on `if`/`else` due to weirdness - provide alternatives for this - add a drawbacks section discussing syntactic lock-down and the antipattern of `#[cfg]` - clarify that this RFC is just for parsing attributes, not requiring that `#[cfg]` stripping be added in all these new places.
general `unsafe` block). | ||
|
||
Only allowing attributes on "statement expressions" that is, | ||
expressions at the top level of a block, |
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.
@huonw oops, missed this earlier: I assume you wanted to finish this sentence with a period, or some expository text explaining why narrowing the scope of the change could be good, or more importantly, why it is not good, i.e. reiterating why it is important to support annotating (most) expressions.
shouldn't this be removed from the active RFC list if it's been accepted/merged? |
The active list contains RFCs that have been accepted but not implemented. |
I'm currently in the process of implementing this, and in accordance with the current RFC text attributes will be initially prohibited on However, thinking about it I wonder if the following scheme could be used: #[covers_remaining_three] if expr #[covers_block] {
// ...
} else #[covers_remaining_two] if expr #[covers_block] {
// ...
} else #[covers_block] {
// ...
} The idea being that an attribute before an Of course, the "disadvantage" here is that for consistency you'd want to support those block-only attributes on anything taking a block, like the loop expressions. And then there would be more than one location per block-taking expression where a attribute might apply, which while not ambiguous could become potentially confusing. |
@Kimundi, that is in fact one of the alternatives. I think nailing down this aspect of the behaviour is probably worth an amendment RFC. |
…kfelix See rust-lang/rfcs#16 and #15701 - Added syntax support for attributes on expressions and all syntax nodes in statement position. - Extended `#[cfg]` folder to allow removal of statements, and of expressions in optional positions like expression lists and trailing block expressions. - Extended lint checker to recognize lint levels on expressions and locals. - As per RFC, attributes are not yet accepted on `if` expressions. Examples: ```rust let x = y; { ... } assert_eq!((1, #[cfg(unset)] 2, 3), (1, 3)); let FOO = 0; ``` Implementation wise, there are a few rough corners and open questions: - The parser work ended up a bit ugly. - The pretty printer change was based mostly on guessing. - Similar to the `if` case, there are some places in the grammar where a new `Expr` node starts, but where it seemed weird to accept attributes and hence the parser doesn't. This includes: - const expressions in patterns - in the middle of an postfix operator chain (that is, after `.`, before indexing, before calls) - on range expressions, since `#[attr] x .. y` parses as `(#[attr] x) .. y`, which is inconsistent with `#[attr] .. y` which would parse as `#[attr] (.. y)` - Attributes are added as additional `Option<Box<Vec<Attribute>>>` fields in expressions and locals. - Memory impact has not been measured yet. - A cfg-away trailing expression in a block does not currently promote the previous `StmtExpr` in a block to a new trailing expr. That is to say, this won't work: ```rust let x = { #[cfg(foo)] Foo { data: x } #[cfg(not(foo))] Foo { data: y } }; ``` - One-element tuples can have their inner expression removed to become Unit, but just Parenthesis can't. Eg, `(#[cfg(unset)] x,) == ()` but `(#[cfg(unset)] x) == error`. This seemed reasonable to me since tuples and unit are type constructors, but could probably be argued either way. - Attributes on macro nodes are currently unconditionally dropped during macro expansion, which seemed fine since macro disappear at that point? - Attributes on `ast::ExprParens` will be prepend-ed to the inner expression in the hir folder. - The work on pretty printer tests for this did trigger, but not fix errors regarding macros: - expression `foo![]` prints as `foo!()` - expression `foo!{}` prints as `foo!()` - statement `foo![];` prints as `foo!();` - statement `foo!{};` prints as `foo!();` - statement `foo!{}` triggers a `None` unwrap ICE.
some README typos
Remove LocalWaker and simplify the RawWakerVTable
Allow attributes on more places inside functions, such as statements and blocks.