Skip to content

Commit 8646c81

Browse files
authored
Rollup merge of rust-lang#64010 - c410-f3r:stabilize-attrs-fn, r=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.
2 parents 5349e69 + 299d696 commit 8646c81

23 files changed

+93
-204
lines changed

src/doc/unstable-book/src/language-features/param-attrs.md

-27
This file was deleted.

src/libsyntax/feature_gate/accepted.rs

+2
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ declare_features! (
243243
(accepted, async_await, "1.39.0", Some(50547), None),
244244
/// Allows mixing bind-by-move in patterns and references to those identifiers in guards.
245245
(accepted, bind_by_move_pattern_guards, "1.39.0", Some(15287), None),
246+
/// Allows attributes in formal function parameters.
247+
(accepted, param_attrs, "1.39.0", Some(60406), None),
246248

247249
// -------------------------------------------------------------------------
248250
// feature-group-end: accepted features

src/libsyntax/feature_gate/active.rs

-3
Original file line numberDiff line numberDiff line change
@@ -489,9 +489,6 @@ declare_features! (
489489
/// Allows the user of associated type bounds.
490490
(active, associated_type_bounds, "1.34.0", Some(52662), None),
491491

492-
/// Attributes on formal function params.
493-
(active, param_attrs, "1.36.0", Some(60406), None),
494-
495492
/// Allows calling constructor functions in `const fn`.
496493
(active, const_constructor, "1.37.0", Some(61456), None),
497494

src/libsyntax/feature_gate/check.rs

-1
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,6 @@ pub fn check_crate(krate: &ast::Crate,
812812
}
813813
}
814814

815-
gate_all!(param_attrs, "attributes on function parameters are unstable");
816815
gate_all!(let_chains, "`let` expressions in this position are experimental");
817816
gate_all!(async_closure, "async closures are unstable");
818817
gate_all!(yields, generators, "yield syntax is experimental");

src/libsyntax/parse/attr.rs

-7
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,6 @@ const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \
1919
permitted in this context";
2020

2121
impl<'a> Parser<'a> {
22-
crate fn parse_param_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
23-
let attrs = self.parse_outer_attributes()?;
24-
self.sess.gated_spans.param_attrs.borrow_mut()
25-
.extend(attrs.iter().map(|a| a.span));
26-
Ok(attrs)
27-
}
28-
2922
/// Parses attributes that appear before an item.
3023
crate fn parse_outer_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
3124
let mut attrs: Vec<ast::Attribute> = Vec::new();

src/libsyntax/parse/mod.rs

-2
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ static_assert_size!(PResult<'_, bool>, 16);
4949
/// used and should be feature gated accordingly in `check_crate`.
5050
#[derive(Default)]
5151
pub struct GatedSpans {
52-
/// Spans collected for gating `param_attrs`, e.g. `fn foo(#[attr] x: u8) {}`.
53-
pub param_attrs: Lock<Vec<Span>>,
5452
/// Spans collected for gating `let_chains`, e.g. `if a && let b = c {}`.
5553
pub let_chains: Lock<Vec<Span>>,
5654
/// Spans collected for gating `async_closure`, e.g. `async || ..`.

src/libsyntax/parse/parser.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ impl<'a> Parser<'a> {
979979
is_name_required: impl Fn(&token::Token) -> bool,
980980
) -> PResult<'a, Param> {
981981
let lo = self.token.span;
982-
let attrs = self.parse_param_attributes()?;
982+
let attrs = self.parse_outer_attributes()?;
983983
if let Some(mut param) = self.parse_self_param()? {
984984
param.attrs = attrs.into();
985985
return self.recover_bad_self_param(param, is_trait_item);
@@ -1362,7 +1362,7 @@ impl<'a> Parser<'a> {
13621362
/// Returns the parsed optional self parameter with attributes and whether a self
13631363
/// shortcut was used.
13641364
fn parse_self_parameter_with_attrs(&mut self) -> PResult<'a, Option<Param>> {
1365-
let attrs = self.parse_param_attributes()?;
1365+
let attrs = self.parse_outer_attributes()?;
13661366
let param_opt = self.parse_self_param()?;
13671367
Ok(param_opt.map(|mut param| {
13681368
param.attrs = attrs.into();

src/libsyntax/parse/parser/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1176,7 +1176,7 @@ impl<'a> Parser<'a> {
11761176
/// Parses a parameter in a closure header (e.g., `|arg, arg|`).
11771177
fn parse_fn_block_param(&mut self) -> PResult<'a, Param> {
11781178
let lo = self.token.span;
1179-
let attrs = self.parse_param_attributes()?;
1179+
let attrs = self.parse_outer_attributes()?;
11801180
let pat = self.parse_pat(PARAM_EXPECTED)?;
11811181
let t = if self.eat(&token::Colon) {
11821182
self.parse_ty()?

src/test/ui/lint/lint-unused-mut-variables.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Exercise the unused_mut attribute in some positive and negative cases
44

55
#![deny(unused_mut)]
6-
#![feature(async_closure, param_attrs)]
6+
#![feature(async_closure)]
77

88
async fn baz_async(
99
mut a: i32,

src/test/ui/lint/lint-unused-variables.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// compile-flags: --cfg something
22
// edition:2018
33

4-
#![feature(async_closure, param_attrs)]
4+
#![feature(async_closure)]
55
#![deny(unused_variables)]
66

77
async fn foo_async(

src/test/ui/parser/fn-arg-doc-comment.rs

-4
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,10 @@ pub fn f(
22
/// Comment
33
//~^ ERROR documentation comments cannot be applied to function parameters
44
//~| NOTE doc comments are not allowed here
5-
//~| ERROR attributes on function parameters are unstable
6-
//~| NOTE https://github.com/rust-lang/rust/issues/60406
75
id: u8,
86
/// Other
97
//~^ ERROR documentation comments cannot be applied to function parameters
108
//~| NOTE doc comments are not allowed here
11-
//~| ERROR attributes on function parameters are unstable
12-
//~| NOTE https://github.com/rust-lang/rust/issues/60406
139
a: u8,
1410
) {}
1511

+7-26
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: attributes cannot be applied to a function parameter's type
2-
--> $DIR/fn-arg-doc-comment.rs:16:12
2+
--> $DIR/fn-arg-doc-comment.rs:12:12
33
|
44
LL | fn bar(id: #[allow(dead_code)] i32) {}
55
| ^^^^^^^^^^^^^^^^^^^ attributes are not allowed here
@@ -11,31 +11,13 @@ LL | /// Comment
1111
| ^^^^^^^^^^^ doc comments are not allowed here
1212

1313
error: documentation comments cannot be applied to function parameters
14-
--> $DIR/fn-arg-doc-comment.rs:8:5
14+
--> $DIR/fn-arg-doc-comment.rs:6:5
1515
|
1616
LL | /// Other
1717
| ^^^^^^^^^ doc comments are not allowed here
1818

19-
error[E0658]: attributes on function parameters are unstable
20-
--> $DIR/fn-arg-doc-comment.rs:2:5
21-
|
22-
LL | /// Comment
23-
| ^^^^^^^^^^^
24-
|
25-
= note: for more information, see https://github.com/rust-lang/rust/issues/60406
26-
= help: add `#![feature(param_attrs)]` to the crate attributes to enable
27-
28-
error[E0658]: attributes on function parameters are unstable
29-
--> $DIR/fn-arg-doc-comment.rs:8:5
30-
|
31-
LL | /// Other
32-
| ^^^^^^^^^
33-
|
34-
= note: for more information, see https://github.com/rust-lang/rust/issues/60406
35-
= help: add `#![feature(param_attrs)]` to the crate attributes to enable
36-
3719
error[E0308]: mismatched types
38-
--> $DIR/fn-arg-doc-comment.rs:22:7
20+
--> $DIR/fn-arg-doc-comment.rs:18:7
3921
|
4022
LL | f("", "");
4123
| ^^ expected u8, found reference
@@ -44,7 +26,7 @@ LL | f("", "");
4426
found type `&'static str`
4527

4628
error[E0308]: mismatched types
47-
--> $DIR/fn-arg-doc-comment.rs:22:11
29+
--> $DIR/fn-arg-doc-comment.rs:18:11
4830
|
4931
LL | f("", "");
5032
| ^^ expected u8, found reference
@@ -53,15 +35,14 @@ LL | f("", "");
5335
found type `&'static str`
5436

5537
error[E0308]: mismatched types
56-
--> $DIR/fn-arg-doc-comment.rs:29:9
38+
--> $DIR/fn-arg-doc-comment.rs:25:9
5739
|
5840
LL | bar("");
5941
| ^^ expected i32, found reference
6042
|
6143
= note: expected type `i32`
6244
found type `&'static str`
6345

64-
error: aborting due to 8 previous errors
46+
error: aborting due to 6 previous errors
6547

66-
Some errors have detailed explanations: E0308, E0658.
67-
For more information about an error, try `rustc --explain E0308`.
48+
For more information about this error, try `rustc --explain E0308`.

src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
// edition:2018
22

3-
#![feature(param_attrs)]
4-
53
trait Trait2015 { fn foo(#[allow(C)] i32); }
64
//~^ ERROR expected one of `:`, `@`, or `|`, found `)`
75

src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: expected one of `:`, `@`, or `|`, found `)`
2-
--> $DIR/param-attrs-2018.rs:5:41
2+
--> $DIR/param-attrs-2018.rs:3:41
33
|
44
LL | trait Trait2015 { fn foo(#[allow(C)] i32); }
55
| ^ expected one of `:`, `@`, or `|` here

src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// compile-flags: --cfg something
33

44
#![deny(unused_mut)]
5-
#![feature(param_attrs)]
65

76
extern "C" {
87
fn ffi(

src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![feature(param_attrs)]
2-
31
extern "C" {
42
fn ffi(
53
/// Foo

0 commit comments

Comments
 (0)