Summary

Allow

許可する、可能にする
attributes on more places inside functions, such as statements,
blocks and expressions.

Motivation

One sometimes wishes to annotate things inside functions with, for example, lint #[allow]s, conditional

条件付き、条件的
compilation #[cfg]s, and even extra semantic (or otherwise) annotations for external tools.

For the lints, one can currently only activate lints at the level of the function which is possibly

ことによると、可能性としてあり得ることに
larger than one needs, and so may allow
許可する、可能にする
other "bad" things to sneak through accidentally. E.g.

#![allow(unused)] fn main() { #[allow(uppercase_variable)] let L = List::new(); // lowercase looks like one or capital i }

For the conditional

条件付き、条件的
compilation, the work-around is duplicating the whole containing function with a #[cfg], or breaking the conditional
条件付き、条件的
code into a its own function. This does mean that any variables
変数、ストレージ
need to be explicitly
明示的に
passed as arguments.
引数

The sort of things one could do with other arbitrary

任意の
annotations are

#![allow(unused)] fn main() { #[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.

The minimum

最小の
useful functionality would be supporting attributes on blocks and let statements,
since these are flexible enough to allow
許可する、可能にする
for relatively precise attribute handling.

Detailed design
設計(する)

Normal attribute syntax

文法
on let statements,
blocks and expressions.

#![allow(unused)] fn main() { fn foo() { #[attr1] let x = 1; #[attr2] { // code } #[attr3] unsafe { // code } #[attr4] foo(); let x = #[attr5] 1; qux(3 + #[attr6] 2); foo(x, #[attr7] y, z); } }

Attributes bind tighter than any operator,

演算子
that is #[attr] x op y is always parsed
構文解析する
as (#[attr] x) op y.

cfg

It is definitely an error to place a #[cfg] attribute on a non-statement expressions,

that is, attr1--attr4 can possibly
ことによると、可能性としてあり得ることに
be #[cfg(foo)], but attr5--attr7 cannot, since it makes little sense to strip code down to let x = ;.

However, like #ifdef in C/C++, widespread use of #[cfg] may be an antipattern that makes code harder to read. This RFC is just adding

たす
the ability for attributes to be placed in specific
特定の
places, it is not mandating that #[cfg] actually be stripped in those places (although it should be an error if it is ignored).

Inner
内側の
attributes

Inner

内側の
attributes can be placed at the top of blocks (and other structure incorporating a block) and apply
適用する
to that block.

#![allow(unused)] fn main() { { #![attr11] foo() } match bar { #![attr12] _ => {} } // are the same as #[attr11] { foo() } #[attr12] match bar { _ => {} } }

if

Attributes would be disallowed

許可しない
on if for now, because the interaction with if/else chains are funky, and can be simulated in other ways.

#![allow(unused)] fn main() { #[cfg(not(foo))] if cond1 { } else #[cfg(not(bar))] if cond2 { } else #[cfg(not(baz))] { } }

There is two possible interpretations

解釈
of such a piece of code, depending on if one regards the attributes as attaching to the whole if ... else chain ("exterior") or just to the branch
枝、分岐
on which they are placed ("interior").

  • --cfg foo: could be either removing the whole chain (exterior) or equivalent
    等価
    to if cond2 {} else {} (interior).
  • --cfg bar: could be either if cond1 {} (e) or if cond1 {} else {} (i)
  • --cfg baz: equivalent
    等価
    to if cond1 {} else if cond2 {} (no subtlety).
  • --cfg foo --cfg bar: could be removing the whole chain (e) or the two if branches
    枝、分岐
    (leaving only the else branch) (i).

(This applies

適用する
to any attribute that has some sense of scoping, not just #[cfg], e.g. #[allow] and #[warn] for lints.)

As such, to avoid

避ける、回避する
confusion, attributes would not be supported on if. Alternatives include using blocks:

#![allow(unused)] fn main() { #[attr] if cond { ... } else ... // becomes, for an exterior attribute, #[attr] { if cond { ... } else ... } // and, for an interior attribute, if cond { #[attr] { ... } } else ... }

And, if the attributes are meant to be associated with the actual

実際の
branching (e.g. a hypothetical
仮定の
#[cold] attribute that indicates a branch
枝、分岐
is unlikely), one can annotate match arms:

#![allow(unused)] fn main() { match cond { #[attr] true => { ... } #[attr] false => { ... } } }

Drawbacks

This starts mixing attributes with nearly arbitrary

任意の
code, possibly
ことによると、可能性としてあり得ることに
dramatically restricting
制限する
syntactic changes related to them, for example, there was some consideration
考慮
for using @ for attributes, this change may make this impossible (especially if @ gets reused for something else, e.g. Python is using it for matrix multiplication
乗算
). It may also make it impossible to use # for other things.

As stated above, allowing

許可する、可能にする
#[cfg]s everywhere can make code harder to reason about, but (also stated), this RFC is not for making such #[cfg]s be obeyed, it just opens the language
言語
syntax
文法
to possibly
ことによると、可能性としてあり得ることに
allow
許可する、可能にする
it.

Alternatives

These instances

実例
could possibly
ことによると、可能性としてあり得ることに
be approximated with macros and helper functions, but to a low degree degree (e.g. how would one annotate a general
一般
unsafe block).

Only allowing

許可する、可能にする
attributes on "statement
expressions"
that is, expressions
at the top level of a block, this is slightly limiting; but we can expand to support other contexts backwards compatibly in the future.

The if/else issue may be able to be resolved by introducing explicit

明示的な
"interior" and "exterior" attributes on if: 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 if branch). There is no difference between interior and exterior for an else { branch,
枝、分岐
and so else #[attr] { is sufficient.

Unresolved questions

Are the complications of allowing

許可する、可能にする
attributes on arbitrary
任意の
expressions
worth the benefits?