Skip to content
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

Tracking issue for stmt_expr_attributes: Add attributes to expressions, etc. #15701

Open
brson opened this issue Jul 15, 2014 · 114 comments
Open
Labels
A-grammar Area: The grammar of Rust B-RFC-implemented Feature: Approved by a merged RFC and implemented. B-unstable Feature: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. S-tracking-design-concerns Status: There are blocking ❌ design concerns. S-tracking-needs-summary Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@brson
Copy link
Contributor

brson commented Jul 15, 2014

Tracking RFC 40: rust-lang/rfcs#16

@brson
Copy link
Contributor Author

brson commented Jul 16, 2014

cc @huonw

@liigo
Copy link
Contributor

liigo commented Dec 30, 2014

ping. will this be implemented before 1.0?

@kmcallister
Copy link
Contributor

The RFC suggests

The sort of things one could do with other arbitrary annotations are

#[allowed_unsafe_actions(ffi)]
#[audited="2014-04-22"]
unsafe { ... }

and then have an external tool that checks that that unsafe block's only unsafe actions are FFI, or a tool that lists blocks that have been changed since the last audit or haven't been audited ever.

which inspired me to make a plugin for cryptographically signing unsafe blocks. It would be great to put those signatures on the blocks themselves rather than the enclosing function.

@alexcrichton alexcrichton added the T-lang Relevant to the language team, which will review and decide on the PR/issue. label Aug 11, 2015
@jonas-schievink
Copy link
Contributor

The RFC says:

Attributes bind tighter than any operator, that is #[attr] x op y is always parsed as (#[attr] x) op y.

Does this mean that #[attr] x.f() should be parsed as (#[attr] x).f()? And should #[a] f() be the same as (#[a] f)()?

And what happens if an attribute is applied to a syntax sugar construct that is later expanded, for example #[attr] in <place> { <expr> }? There isn't really an obvious place for the attribute in the desugared form, so not allowing them seems more sensible.

@Kimundi
Copy link
Member

Kimundi commented Nov 5, 2015

Just a heads up that I'm currently in the process of implementing this RFC.

@dgrunwald
Copy link
Contributor

I think the obvious choice is to give attributes the same operator precedence as unary operators.
So #[attr] x.f() would be parsed as #[attr] (x.f()), but #[attr] x + f will be (#[attr] x) + f.

@Kimundi
Copy link
Member

Kimundi commented Nov 6, 2015

Yeah, thats how I'm doing it in my WIP branch right now.

bors added a commit that referenced this issue Dec 4, 2015
…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.
@huonw
Copy link
Member

huonw commented Jan 5, 2016

@Kimundi, is there a reason that #29850 doesn't close this?

@Kimundi
Copy link
Member

Kimundi commented Jan 7, 2016

Not as far as I can rember, probably just forgot about it. :)

@Kimundi Kimundi closed this as completed Jan 7, 2016
@comex
Copy link
Contributor

comex commented Feb 25, 2016

FYI, the stmt_expr_attributes feature gate still mentions this issue number.

@bluss
Copy link
Member

bluss commented Apr 10, 2016

Tracking issues are open until the feature is stable, aren't they?

@msjyoo
Copy link

msjyoo commented Jul 10, 2016

By what Rust version will this feature gate be allowed on the stable channel? I couldn't find any chart / matrix with the list of them.

dgsantana added a commit to dgsantana/leptos that referenced this issue Apr 20, 2023
```error[E0658]: attributes on expressions are experimental
  --> router\src\components\link.rs:84:9
   |
84 |         #[cfg(not(any(feature = "hydrate", feature = "csr")))]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: see issue #15701 <rust-lang/rust#15701> for more information
   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable```
@andreisilviudragnea
Copy link

Hi. Any update on this feature?

@Danvil
Copy link
Contributor

Danvil commented Jul 7, 2023

I encountered this because it would be nice to disable rustfmt for an expression or a scope:

fn awesome(pw: f32, dx: f32, ds: f32) -> [f32; 4] {
    // please help me format this
    let tan_pw = pw.tan();
    let h1 = (dx + ds) * 0.5;

    #[rustfmt::skip]  // but don't touch this block
    {
        [
             dx,        ds,  // I like
            1.0, h1*tan_pw,  //   math
        ]
    }
}

Starson added a commit to Starson/MapRandomizer that referenced this issue Sep 10, 2023
warning: unused import: `std::process::Command` --> src/bin/maprando-web.rs:2:5

warning: unused variable: `notable_strats` --> src/bin/maprando-web.rs:308:5

warning: field `start_addr` is never read --> src/customize/room_palettes.rs:198:5

warning: unused variable: `area_idx` --> src/game_data.rs:2484:14

warning: unused variable: `door` --> src/patch.rs:1642:21
warning: variable does not need to be mutable --> src/patch.rs:1642:17
  NOTE: Line 1641 changed from `for door` to `for _door` as well

warning: variable does not need to be mutable --> src/patch.rs:1013:21
  NOTE: Commented out code below this would require `mut` if reinstated unless folded into initialization ternary-style
  e.g. `let new_song = if room.name != "Landing Site" { area_music[area][subarea] } else { 0x0606 };`

warning: unused import: `Path` --> src/web/logic.rs:1:17

warning: unused variable: `name_no_space` --> /rust/target/release/build/sailfish-compiler-4c1b9b72b1c17739/out/templates/room-eb0b5fdf3a787627:1:10114
  NOTE: Root cause was in `templates/logic/room.stpl`: Removed line 41 `let name_no_space = &difficulty.replace(" ", "");`

NOTE:
There are 6 "unused variable" warnings left in src/web/logic.rs

Most of these are "used" in the sense that they are cloned, however it seems that rust doesn't count that as a "use"

Adding `#[allow(unused_variables)]` before the properties does not work, and from what i can tell they're still working on fully implementing attributes for expressions/structs/etc (rust-lang/rust#15701)

Adding the `#![allow(unused_variables)]` attribute to the top of the file silences these, but it's too broad as it covers the whole file
blkerby added a commit to blkerby/MapRandomizer that referenced this issue Sep 10, 2023
warning: unused import: `std::process::Command` --> src/bin/maprando-web.rs:2:5

warning: unused variable: `notable_strats` --> src/bin/maprando-web.rs:308:5

warning: field `start_addr` is never read --> src/customize/room_palettes.rs:198:5

warning: unused variable: `area_idx` --> src/game_data.rs:2484:14

warning: unused variable: `door` --> src/patch.rs:1642:21
warning: variable does not need to be mutable --> src/patch.rs:1642:17
  NOTE: Line 1641 changed from `for door` to `for _door` as well

warning: variable does not need to be mutable --> src/patch.rs:1013:21
  NOTE: Commented out code below this would require `mut` if reinstated unless folded into initialization ternary-style
  e.g. `let new_song = if room.name != "Landing Site" { area_music[area][subarea] } else { 0x0606 };`

warning: unused import: `Path` --> src/web/logic.rs:1:17

warning: unused variable: `name_no_space` --> /rust/target/release/build/sailfish-compiler-4c1b9b72b1c17739/out/templates/room-eb0b5fdf3a787627:1:10114
  NOTE: Root cause was in `templates/logic/room.stpl`: Removed line 41 `let name_no_space = &difficulty.replace(" ", "");`

NOTE:
There are 6 "unused variable" warnings left in src/web/logic.rs

Most of these are "used" in the sense that they are cloned, however it seems that rust doesn't count that as a "use"

Adding `#[allow(unused_variables)]` before the properties does not work, and from what i can tell they're still working on fully implementing attributes for expressions/structs/etc (rust-lang/rust#15701)

Adding the `#![allow(unused_variables)]` attribute to the top of the file silences these, but it's too broad as it covers the whole file

Co-authored-by: Starson Hochschild <starsonh@gmail.com>
bors added a commit to rust-lang-ci/rust that referenced this issue Nov 13, 2023
@WaffleLapkin
Copy link
Member

WaffleLapkin commented Apr 2, 2024

From what I understand the issue blocking this is ambiguity -- even if the RFC specifies what #[meow] 1 + 1 means, it's still not very readable. I think the path forward is to cut this feature to only allow attributes on things that are unambiguous, such as:

  • All kinds of braces: #[meow] (1 + 1), #[uwu] [1, 2, 3], #[purr] {} (parethesis/grouping expr, tuples, arrays, blocks)
  • Closures: #[kwncjhn] || 2
  • Expressions starting with a keyword: #[meow] if x {}, #[attr] loop { break 'rust; }, #[kva] while false {}, ...
  • etc

Then we can provide a suggestion to add parenthesis around the expression, if it is not supported:

error: meow meow meow ambiguous attribute
 --> src/main.rs:LL:CC
   |
LL |     let x = #[meow] 1 + 1;
   |
help: wrap the expression in parenthesis
   |
LL |     let x = #[meow] (1 + 1);
   |                     +     +
help: wrap the expression in parenthesis (alternative
   |
LL |     let x = (#[meow] 1) + 1;
   |             +         +

(writing this down here because I have no capacity to work on this)

Xiretza added a commit to Xiretza/rust that referenced this issue Apr 11, 2024
The error mentions `///`, when it's actually `//!`:

error[E0658]: attributes on expressions are experimental
 --> test.rs:4:9
  |
4 |         //! wah
  |         ^^^^^^^
  |
  = note: see issue rust-lang#15701 <rust-lang#15701> for more information
  = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
  = help: `///` is for documentation comments. For a plain comment, use `//`.
Xiretza added a commit to Xiretza/rust that referenced this issue Apr 11, 2024
The error mentions `///`, when it's actually `//!`:

error[E0658]: attributes on expressions are experimental
 --> test.rs:4:9
  |
4 |         //! wah
  |         ^^^^^^^
  |
  = note: see issue rust-lang#15701 <rust-lang#15701> for more information
  = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
  = help: `///` is for documentation comments. For a plain comment, use `//`.
Xiretza added a commit to Xiretza/rust that referenced this issue Apr 17, 2024
The error mentions `///`, when it's actually `//!`:

error[E0658]: attributes on expressions are experimental
 --> test.rs:4:9
  |
4 |         //! wah
  |         ^^^^^^^
  |
  = note: see issue rust-lang#15701 <rust-lang#15701> for more information
  = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
  = help: `///` is for documentation comments. For a plain comment, use `//`.
Xiretza added a commit to Xiretza/rust that referenced this issue Apr 21, 2024
The error mentions `///`, when it's actually `//!`:

error[E0658]: attributes on expressions are experimental
 --> test.rs:4:9
  |
4 |         //! wah
  |         ^^^^^^^
  |
  = note: see issue rust-lang#15701 <rust-lang#15701> for more information
  = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
  = help: `///` is for documentation comments. For a plain comment, use `//`.
Xiretza added a commit to Xiretza/rust that referenced this issue Apr 22, 2024
The error mentions `///`, when it's actually `//!`:

error[E0658]: attributes on expressions are experimental
 --> test.rs:4:9
  |
4 |         //! wah
  |         ^^^^^^^
  |
  = note: see issue rust-lang#15701 <rust-lang#15701> for more information
  = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
  = help: `///` is for documentation comments. For a plain comment, use `//`.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Apr 23, 2024
…s, r=davidtwco

Disallow ambiguous attributes on expressions

This implements the suggestion in [rust-lang#15701](rust-lang#15701 (comment)) to disallow ambiguous outer attributes on expressions. This should resolve one of the concerns blocking the stabilization of `stmt_expr_attributes`.
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Apr 23, 2024
Rollup merge of rust-lang#124099 - voidc:disallow-ambiguous-expr-attrs, r=davidtwco

Disallow ambiguous attributes on expressions

This implements the suggestion in [rust-lang#15701](rust-lang#15701 (comment)) to disallow ambiguous outer attributes on expressions. This should resolve one of the concerns blocking the stabilization of `stmt_expr_attributes`.
@nikomatsakis
Copy link
Contributor

I agree with @WaffleLapkin on that path forward

@workingjubilee
Copy link
Contributor

workingjubilee commented Apr 23, 2024

It would be especially good to move forward with making this available for closures, seeing as only one of these closures fires the feature(stmt_expr_attributes) gate, and unless you particularly enjoy this kind of trivia, it's probably not the one you think:

fn main() {
    let _blocked_closure = {
        #[warn(nonsense)]
        || todo!()
    };
    
    let _closure_blocked = #[warn(nonsense)] || { todo!() };
}

Xiretza added a commit to Xiretza/rust that referenced this issue Apr 24, 2024
The error mentions `///`, when it's actually `//!`:

error[E0658]: attributes on expressions are experimental
 --> test.rs:4:9
  |
4 |         //! wah
  |         ^^^^^^^
  |
  = note: see issue rust-lang#15701 <rust-lang#15701> for more information
  = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
  = help: `///` is for documentation comments. For a plain comment, use `//`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-grammar Area: The grammar of Rust B-RFC-implemented Feature: Approved by a merged RFC and implemented. B-unstable Feature: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. S-tracking-design-concerns Status: There are blocking ❌ design concerns. S-tracking-needs-summary Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests