-
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: Attributes in formal function parameter position #2565
Conversation
I think that the underscore prefix convention is well established and that |
Some questions to answer:
|
Thank you for and congratulations on writing your first RFC! |
A use case for this with proptest could be to enable the following: #[proptest]
fn prop_my_property(#[types(T = u8 | u16)] elem: Vec<T>, ...) {
...
) This would replace Also: #[proptest]
fn prop_my_property(#[strat = 0..100] elem: usize, ...) {
...
) Tho I'd probably formulate this instead as: #[proptest]
#[proptest::types(T = u8 | u16)]
fn prop_my_property<T>(elem: Vec<T>, ...) {
...
)
#[proptest]
fn prop_my_property(elem in 0..100usize, ...) { // this unfortunately won't parse
...
) |
You might be right about that. It was just an idea I had. We do not need to have language defined attributes for now. |
Good points! I haven't concretely thought about macro attributes but I think that they should be supported for convenience if that doesn't mean too much extra work. I cannot see the end of the scope for this to be honest. I have no clear answer for the I would postpone the attributes in fn types for another RFC since at least to my understanding this would force having attributes be part of the type system. What do you mean by the future compatibility with attributes on patterns and types? So what shouldn't be compatible with them in the future? I am sorry that I do not understand. |
Thank you for those interesting ideas around the use case. |
Macro attributes are supported only in a relatively small subset of attribute positions, so it's better to start with not supporting them.
It wouldn't have any effect on type system, no more than attributes on function definitions. |
Right now we support attributes on arbitrary expressions, so it's quite possible that we'll eventually support attributes on arbitrary types and patterns as well. In this case what the attribute is attached to in fn f(#[attr] PAT: TYPE) {} , to the pattern, or to the whole parameter? I think we'll be able to reattach the attributes from parameters to patterns if pattern attributes become available, but I'm not entirely sure (macros?). In this sense That's why |
I think that I would prefer the following #[ignore_args]
fn foo( #[ignore] bar: bool); over the following fn foo( #[ignore] bar: bool); The first version is longer, but the scope of the macro is more clear. But then again this distinction is probably out of scope for the RFC. |
Just wanna note that this thing already exists: fn main() {
match 3 {
#[cfg(windows)]
3 => println!("a"),
#[cfg(unix)]
3 => println!("b"),
_ => println!("c"),
}
} and the attribute is applied to the whole arm, not the pattern. |
I'm in favor of allowing attributes on parameters. Please do drop the bits about replacing the |
I believe it's not part of the proposal; rather, it is a hypothetical use case that some person could do in a procedural macro. |
So should we do the same for the parameter attributes so that the attribute is for the |
I should reformulate this to cause no misunderstandings. |
@Robbepop Attributes typically aren't transitive. The attribute is applied to the parameter itself, not the pattern nor the type. |
I am so sorry - saw this just now. Edit: |
This RFC represents an extension to where attributes are permitted in the language. The extension is small, consistently applied, and has notable use cases as per comments in this RFC. I believe that the extension of attributes to other places in the language affords users to encode the EDSLs that they like. As this RFC is an important step on that road, I think we should move ahead with it and so therefore, I propose that we: @rfcbot merge |
Team member @Centril has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
Sounds reasonable to me, though the implementation will need to be careful to avoid adding a bunch of new "we forgot to block that attribute in that particular position" mistakes. @rfcbot reviewed |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
NB: I tagged for @aturon as they are temporarily inactive. |
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. The RFC will be merged soon. |
Huzzah! This RFC has been merged! Tracking issue: rust-lang/rust#60406 |
Stabilize `param_attrs` in Rust 1.39.0 # Stabilization proposal I propose that we stabilize `#![feature(param_attrs)]`. Tracking issue: #60406 Version: 1.39 (2019-09-26 => beta, 2019-11-07 => stable). ## What is stabilized It is now possible to add outer attributes like `#[cfg(..)]` on formal parameters of functions, closures, and function pointer types. For example: ```rust fn len( #[cfg(windows)] slice: &[u16], #[cfg(not(windows))] slice: &[u8], ) -> usize { slice.len() } ``` ## What isn't stabilized * Documentation comments like `/// Doc` on parameters. * Code expansion of a user-defined `#[proc_macro_attribute]` macro used on parameters. * Built-in attributes other than `cfg`, `cfg_attr`, `allow`, `warn`, `deny`, and `forbid`. Currently, only the lints `unused_variables` and `unused_mut` have effect and may be controlled on parameters. ## Motivation The chief motivations for stabilizing `param_attrs` include: * Finer conditional compilation with `#[cfg(..)]` and linting control of variables. * Richer macro DSLs created by users. * External tools and compiler internals can take advantage of the additional information that the parameters provide. For more examples, see the [RFC][rfc motivation]. ## Reference guide In the grammar of function and function pointer, the grammar of variadic tails (`...`) and parameters are changed respectively from: ```rust FnParam = { pat:Pat ":" }? ty:Type; VaradicTail = "..."; ``` into: ```rust FnParam = OuterAttr* { pat:Pat ":" }? ty:Type; VaradicTail = OuterAttr* "..."; ``` The grammar of a closure parameter is changed from: ```rust ClosureParam = pat:Pat { ":" ty:Type }?; ``` into: ```rust ClosureParam = OuterAttr* pat:Pat { ":" ty:Type }?; ``` More generally, where there's a list of formal (value) parameters separated or terminated by `,` and delimited by `(` and `)`. Each parameter in that list may optionally be prefixed by `OuterAttr+`. Note that in all cases, `OuterAttr*` applies to the whole parameter and not just the pattern. This distinction matters in pretty printing and in turn for macros. ## History * On 2018-10-15, @Robbepop proposes [RFC 2565][rfc], "Attributes in formal function parameter position". * On 2019-04-30, [RFC 2565][rfc] is merged and the tracking issue is made. * On 2019-06-12, a partial implementation was completed. The implementation was done in [#60669][60669] by @c410-f3r and the PR was reviewed by @petrochenkov and @Centril. * On 2019-07-29, [#61238][61238] was fixed in [#61856][61856]. The issue fixed was that lint attributes on function args had no effect. The PR was written by @c410-f3r and reviewed by @matthewjasper, @petrochenkov, and @oli-obk. * On 2019-08-02, a bug [#63210][63210] was filed wherein the attributes on formal parameters would not be passed to macros. The issue was about forgetting to call the relevant method in `fn print_arg` in the pretty printer. In [#63212][63212], written by @Centril on 2019-08-02 and reviewed by @davidtwco, the issue aforementioned was fixed. * This PR stabilizes `param_attrs`. ## Tests * [On Rust 2018, attributes aren't permitted on function parameters without a pattern in trait definitions.](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs) * [All attributes that should be allowed. This includes `cfg`, `cfg_attr`, and lints check attributes.](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs) * [Built-in attributes, which should be forbidden, e.g., `#[test]`, are.](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs) * [`cfg` and `cfg_attr` are properly evaluated.](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs) * [`unused_mut`](https://github.com/rust-lang/rust/blob/46f405ec4d7c6bf16fc2eaafe7541019f1da2996/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs) and [`unused_variables`](https://github.com/rust-lang/rust/blob/master/src/test/ui/lint/lint-unused-variables.rs) are correctly applied to parameter patterns. * [Pretty printing takes formal parameter attributes into account.](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs) ## Possible future work * Custom attributes inside function parameters aren't currently supported but it is something being worked on internally. * Since documentation comments are syntactic sugar for `#[doc(...)]`, it is possible to allow literal `/// Foo` comments on function parameters. [rfc motivation]: https://github.com/rust-lang/rfcs/blob/master/text/2565-formal-function-parameter-attributes.md#motivation [rfc]: rust-lang/rfcs#2565 [60669]: #60669 [61856]: #61856 [63210]: #63210 [61238]: #61238 [63212]: #63212 This report is a collaborative work with @Centril.
Stabilize `param_attrs` in Rust 1.39.0 # Stabilization proposal I propose that we stabilize `#![feature(param_attrs)]`. Tracking issue: rust-lang#60406 Version: 1.39 (2019-09-26 => beta, 2019-11-07 => stable). ## What is stabilized It is now possible to add outer attributes like `#[cfg(..)]` on formal parameters of functions, closures, and function pointer types. For example: ```rust fn len( #[cfg(windows)] slice: &[u16], #[cfg(not(windows))] slice: &[u8], ) -> usize { slice.len() } ``` ## What isn't stabilized * Documentation comments like `/// Doc` on parameters. * Code expansion of a user-defined `#[proc_macro_attribute]` macro used on parameters. * Built-in attributes other than `cfg`, `cfg_attr`, `allow`, `warn`, `deny`, and `forbid`. Currently, only the lints `unused_variables` and `unused_mut` have effect and may be controlled on parameters. ## Motivation The chief motivations for stabilizing `param_attrs` include: * Finer conditional compilation with `#[cfg(..)]` and linting control of variables. * Richer macro DSLs created by users. * External tools and compiler internals can take advantage of the additional information that the parameters provide. For more examples, see the [RFC][rfc motivation]. ## Reference guide In the grammar of function and function pointer, the grammar of variadic tails (`...`) and parameters are changed respectively from: ```rust FnParam = { pat:Pat ":" }? ty:Type; VaradicTail = "..."; ``` into: ```rust FnParam = OuterAttr* { pat:Pat ":" }? ty:Type; VaradicTail = OuterAttr* "..."; ``` The grammar of a closure parameter is changed from: ```rust ClosureParam = pat:Pat { ":" ty:Type }?; ``` into: ```rust ClosureParam = OuterAttr* pat:Pat { ":" ty:Type }?; ``` More generally, where there's a list of formal (value) parameters separated or terminated by `,` and delimited by `(` and `)`. Each parameter in that list may optionally be prefixed by `OuterAttr+`. Note that in all cases, `OuterAttr*` applies to the whole parameter and not just the pattern. This distinction matters in pretty printing and in turn for macros. ## History * On 2018-10-15, @Robbepop proposes [RFC 2565][rfc], "Attributes in formal function parameter position". * On 2019-04-30, [RFC 2565][rfc] is merged and the tracking issue is made. * On 2019-06-12, a partial implementation was completed. The implementation was done in [rust-lang#60669][60669] by @c410-f3r and the PR was reviewed by @petrochenkov and @Centril. * On 2019-07-29, [rust-lang#61238][61238] was fixed in [rust-lang#61856][61856]. The issue fixed was that lint attributes on function args had no effect. The PR was written by @c410-f3r and reviewed by @matthewjasper, @petrochenkov, and @oli-obk. * On 2019-08-02, a bug [rust-lang#63210][63210] was filed wherein the attributes on formal parameters would not be passed to macros. The issue was about forgetting to call the relevant method in `fn print_arg` in the pretty printer. In [rust-lang#63212][63212], written by @Centril on 2019-08-02 and reviewed by @davidtwco, the issue aforementioned was fixed. * This PR stabilizes `param_attrs`. ## Tests * [On Rust 2018, attributes aren't permitted on function parameters without a pattern in trait definitions.](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs) * [All attributes that should be allowed. This includes `cfg`, `cfg_attr`, and lints check attributes.](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs) * [Built-in attributes, which should be forbidden, e.g., `#[test]`, are.](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs) * [`cfg` and `cfg_attr` are properly evaluated.](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs) * [`unused_mut`](https://github.com/rust-lang/rust/blob/46f405ec4d7c6bf16fc2eaafe7541019f1da2996/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs) and [`unused_variables`](https://github.com/rust-lang/rust/blob/master/src/test/ui/lint/lint-unused-variables.rs) are correctly applied to parameter patterns. * [Pretty printing takes formal parameter attributes into account.](https://github.com/rust-lang/rust/blob/master/src/test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs) ## Possible future work * Custom attributes inside function parameters aren't currently supported but it is something being worked on internally. * Since documentation comments are syntactic sugar for `#[doc(...)]`, it is possible to allow literal `/// Foo` comments on function parameters. [rfc motivation]: https://github.com/rust-lang/rfcs/blob/master/text/2565-formal-function-parameter-attributes.md#motivation [rfc]: rust-lang/rfcs#2565 [60669]: rust-lang#60669 [61856]: rust-lang#61856 [63210]: rust-lang#63210 [61238]: rust-lang#61238 [63212]: rust-lang#63212 This report is a collaborative work with @Centril.
One thing I've noticed which wasn't obvious to me during RFC discussion. The following is now on the path of the least resistance: fn f(
foo: Foo,
#[cfg(feature = "bar")]
bar: Bar,
) However, it breaks additiveness of the Less obvious, but more maintainable option is to do this: fn f(
foo: Foo,
bar: Bar,
) {
..
}
struct Bar {
#[cfg(feature = "bar")]
imp: RealImpl,
#[cfg(not(feature = "bar"))]
imp: DummyZstImpl,
} |
@matklad would a clippy lint against using |
This RFC proposes to add attributes in formal function parameter position.
Rendered
Tracking issue: rust-lang/rust#60406