Change inner attribute syntax for clarity and consistency

7169e2b
Opened by Brian Anderson at 2014-03-29 01:26:46

As discussed in #2568, the trailing semicolon to differentiate 'inner' from 'outer' attributes is not intuitive. Also, #2498 will add doc comments as a special form of attribute, which will differentiate 'inner' doc comments using doxygen's /**< */ syntax. To make inner attribute syntax more consistent with doc comments and more visually distinct I would like to change the inner attribute syntax to:

#<attribute>

The meaning would still be the same - it's an inner attribute - but in practice you would probably think of them as 'crate attributes' or 'module attributes' since they typically would appear at the top of files and apply to whatever the file represents.

No attribute is followed by a semicolon.


Added clarification for people visiting this bug in the future (e.g. for triage), mostly to explain the "inner" vs "outer" distinction, because that terminology is not used in the Rust manual: Currently attributes in Rust can either be terminated by a semi-colon, or they can leave out the semi-colon; the former denotes an "inner attribute", which applies to the (entire) entity that the attribute is declared within, and the latter denotes an "outer attribute", which must be followed by an entity (and applies solely to that entity).

This bug is discussing a number of alternatives to that syntax. Lets see if we can enumerate the proposals and how much interest they have garnered. (Most of the proposals keep the existing outer attribute syntax unchanged, but there is one exception, so I include it in my examples below.)

  1. (current) semi-colon inner: mod foo { #[outer(attr)] mod bar { #[inner(attr)]; } }
  2. brson's orginal angle-bracketed inner: mod foo { #[outer(attr)] mod bar { #<inner(attr)> } }
  3. bstrie leading exclamation inner: mod foo { #[outer(attr)] mod bar { #![inner(attr)] } }
  4. graydon nested exclamation inner: mod foo { #[outer(attr)] mod bar { #[!inner(attr)] } }
  5. brson bracket-less for both, leading exclamation inner: mod foo { #outer(attr) mod bar { #! inner(attr) } }
  6. bstrie bracketed-inner, bracket-less outer: mod foo { #outer(attr) mod bar { #[inner(attr)] } }
  7. pnkfelix semi-colon terminated bracket-less inner, bracketed outer: mod foo { #[outer(attr)] mod bar { #inner(attr); } }

Note also of course that we have indeed now switched to denoting macros with a trailing ! as discussed in the comments, which paves the way for the bracket-less forms.

  1. This should make attribute parsing significantly simpler since there's a fixed amount of lookahead needed to know if you are parsing an inner attribute.

    Brian Anderson at 2012-06-11 21:09:04

  2. I'm ok with this but as mentioned in the other bug on doc comments, think angle-bracket might not be the most delicious choice. It's not really visually suggestive of what it applies to; the semi rule had that going for it (with the drawback being, I guess, both subtlety and no obvious connection to any doc-comment syntax).

    Maybe something involving exclamation points or vertical bars? :)

    Graydon Hoare at 2012-06-12 01:19:41

  3. (only half joking; we adopted shebang comments already and intend to have those around for tagging language-version. maybe you can dangle this function on a relative of that syntax)

    Graydon Hoare at 2012-06-12 01:20:14

  4. I guess it has much the same issues, but how about ^ instead of < ?

    Gareth Smith at 2012-06-12 20:21:48

  5. @Dretch. I think ^ looks ok in comments but don't see a nice way to wedge it into the attribute syntax - #^[attribute], #^attribute^.

    Brian Anderson at 2012-06-12 21:20:54

  6. I'm surprised that graydon suggested the shebang notation, because I was going to suggest

    #![module_level_attribute]
    // as opposed to
    #[function_level_attribute]
    

    ...but I thought people would think it was too silly. :) I still like it, though!

    bstrie at 2012-06-14 13:25:06

  7. Yeah. I've poked at this long enough in my own emacs buffer now to feel positive about the bang-mark. It goes ok in comments too. Though to ensure we don't confuse any shell interpreters trying to run attributes, I think it should differ in first-two chars from shebang itself. I.e. move the bang inside the attribute. So we wind up with:

    
    // shebang means 'run through this interpreter', like always
    #!/bin/env rustc --run 
    
    // leading sharp-comments in the root source file are scanned for pre-parsing control tags.
    # rust: <compiler-uuid> <low-lang-version> <high-lang-version>
    
    // bang-attrs apply to their containing item.
    // in practice so far these seem to be module-level
    // most of the time, so are "evocative" of shebang and
    // pre-parse control tags, without being ambiguous with them
    #[!warn(no_implicit_copies)]
    
    // normal-attrs apply to the following item.
    #[test]
    fn test_patience() { ... }
    
    // bang-comments are docstrings that apply to their enclosing item.
    
    //! this is a one-liner.
    /*! This is a
     *  multi-line one.
     */
    
    // Common triple-slash and double-star doc-comments
    // apply to the next item.
    
    /// Magic number
    const x = 10;
    
    /** Very enjoyable
     *  function doc
     */
    fn joy() {
    }
    

    Is this too ghastly? It looks ... ok to me. I mean, it's a stretch but we have a bunch of layers of functionality to get to hang together here and it'd be good to have it "work" nice.

    (In theory we could also wedge-in a pre-parse conditional-compilation mode, via the plain-sharp coments, as an escape hatch for conditionally-compiling things that differ at only a lexeme-by-lexeme level. Sometimes the resolution of the #[cfg(...)] attribute is just not fine enough. Might be nice?)

    Graydon Hoare at 2012-06-14 16:23:29

  8. The bang does look good. The main reason I didn't want to use it is because in doxygen /*! and /** mean the same thing, but it is the best looking alternative.

    We should change the attribute grammer to only have one meta item per. This is something I've wanted to do anyway as a simplification, but I really don't want to be able to write #[!inner, outer]. Maybe #![inner] is less confusing.

    The bang does strongly suggest logical negation though. What does #[!cfg(unix)] mean?

    One thing that might impact attribute syntax is that pcwalton wants to change the extension grammer to be fmt! instead of #fmt, which I like. This would open more possibilities in the attribute grammer. Specifically, we can get rid of the brackets:

    # cfg(unix)
    fn foo() {
        #! cfg(unix)
    }
    

    Of course then you have to worry about distinguishing between attributes and a shebang.

    Brian Anderson at 2012-06-14 18:49:32

  9. I'm not sure that we need to resort to #[!. I'm having a hard time imagining any situation where the token #![ could begin a legal shebang (so it would always just throw an error), and since the only time this would ever be encountered would be if someone tried to ./their_rust_program, and since they'd need a valid shebang in that case regardless (and since shebangs can only occur on the first line of a file), I don't know if this could ever be an issue. Worse still, #[! would seem to collide with negation within attributes; does #[!cfg(target_os = "win32")] mean "don't do this on windows"?

    Iff you are swayed by these arguments, I think a clearer rule for the docstrings and attributes would be "docstrings and attributes apply to the following item, unless their opening token is followed by a !". So you'd have:

    #!/bin/env rustc --run
    // for the set of people who like to run their programs directly,
    // and thus will not be at all confused as to what a shebang is
    
    #![module_level_attribute]
    ///! module-level one-line doc comment
    /**! module-level
     *   multiline doc comment
     */
    

    (New personal resolution: submit one unrelated-to-syntax patch for every bikeshedding comment I make.)

    bstrie at 2012-06-14 19:12:59

  10. re: brson's comment (which wasn't here when I started typing the above): I really adore the bracketless notation, and also signifying macros with a trailing !. Once again, I don't think it would be at all hard to disambiguate with shebangs, since people who want to use shebangs will know what a shebang is, and since you can't stick / inside a valid rust identifier (and since shebangs must contain absolute rather than relative paths), and since (on bash at least) shebangs can only appear in the very first line of a file, so it's easy to test for.

    (patch_debt++)

    bstrie at 2012-06-14 19:21:02

  11. I just got assigned this for the triage. I actually feel that the current syntax is more consistent than the suggested alternatives. Does anyone have strong feelings about this still?

    Zack Corr at 2013-04-23 00:17:13

  12. @z0w0 I still have strong feelings that the existing trailing-semicolon-inner-attribute syntax is very bad, I just think there's been no real discussion of what to replace it with. Would be nice to bring this up on the mailing list and fish for comments.

    bstrie at 2013-04-23 00:31:48

  13. I can live with any of the options, including present form. I think @brson still dislikes it though, and people do stumble on it regularly.

    Graydon Hoare at 2013-04-23 00:34:36

  14. My first choice is bracketless, followed by #!.

    Jack Moffitt at 2013-04-23 01:37:58

  15. Perhaps inline could be exclamation mark in front of the statement like !cfg(test) to match rustdocs crate level attributes and outer level macros could look like #cfg(test). The hashbang for inner macros just seems weird to me.

    Zack Corr at 2013-04-23 01:45:58

  16. @metajack bracketless is also my favorite option, and I think brson has expressed some fondness for that form as well. The "lightness" of the bracketless syntax is very refreshing. And maybe we could then use bracketed syntax for inner attributes, as a visual shorthand to represent that those attributes are "enclosed".

    #inline(always)
    fn foo() {
        #[some_inner_thing]
        ...
    }
    

    bstrie at 2013-04-23 02:33:15

  17. @bstrie at first glance +1

    Jack Moffitt at 2013-04-23 02:36:27

  18. If we go with @bstrie's suggestion of bracketless vs brackets then we also need to consider how that relates to doc comments

    # inline(always)
    /// Do a foo
    /** Do a foo */
    fn foo() {
        #[some_inner_thing]
        //! Do a foo
        /*! Do a foo */
        ...
    }
    

    This solution hasn't particularly improved the syntactic relationship between attributes and doc comments. I might feel happiest making inner attributes #! some_inner_thing, but of course that doesn't work because of shebangs.

    Brian Anderson at 2013-04-23 17:40:44

  19. I don't think there's necessarily a need to draw parallels between doc comments and attributes, even if the former happens to be implemented in terms of the latter. Having two forms of doc comments has always just seemed silly. :)

    Inner doc comments can do everything that outer ones can, yeah? At the risk of going out-of-scope, I'd propose getting rid of the bizarre //! and /*! forms, and converting inner doc comments over to the more-standard /// and /**. Python serves as a precedent here.

    More generally speaking, I feel like having two different syntaxes for doc comments is needlessly decadent. Better to pick just one form and enforce it.

    bstrie at 2013-04-23 20:25:50

  20. Inner for modules. We keep revisiting this :)

    Graydon Hoare at 2013-04-23 20:35:08

  21. @bstrie the reasons for needing both doc comment forms are identical to the reason for needing both attribute forms. Doc comments are attributes.

    I am though still open to figuring out a reliable way to make doc comments work with only a single syntax. Even I regularly use the wrong form of comments in places, and emacs still doesn't know how to word wrap //! comments.

    Brian Anderson at 2013-04-23 21:09:29

  22. Nominating.

    Brian Anderson at 2013-04-23 21:10:22

  23. What about two hashes? ## inline(always).

    Zack Corr at 2013-04-24 03:29:32

  24. I prefer the form with the delimiters. I'd like to see them go away altogether or be restricted to module-top-level, but it makes me sad when a perfectly serviceable delimiter notation gets axed.

    John Clements at 2013-04-24 05:26:19

  25. @jbclements "I prefer the form with the delimiters" seems to contradict "I'd like to see them go away altogether"; is there a typo there?

    Update: Okay, I now infer that you meant "I'd like to see inner attributes themselves go away entirely, or be restricted in where they can be used, but if one is going to keep them as a feature, then I'd prefer a bracketed syntax."

    Felix S Klock II at 2013-07-16 08:19:38

  26. If we go with the shebang notation, I would prefer to also keep the trailing semi-colon. I want it to be clear to the human reader that this form is a significant independent entity and does not apply to the item that follows it. For example: mod m { #![inner(attribute)]; fn foo() { ... } #[outer(attribute)] fn bar() { ... } }

    This way, when one is scanning backwards, one can distinguish the two cases without having to look all the way at the beginning of the attribute declaration.

    Felix S Klock II at 2013-07-16 08:30:29

  27. I find it interesting that @bstrie suggested using bracket-less versus bracketed as the way to distinguish the two forms. I want to make a similar suggestion, except that I wanted the bracket-less form with a semi-colon to denote an inner attribute, while a bracketed form without a semi-colon denotes an outer attribute:

    mod m { #inner(attribute); fn foo() { ... } #[outer(attribute)] fn bar() { ... } }

    This preserves the earlier-mentioned property that the semi-colon indicates that the attribute declaration has meaning all on its own; the human reader need not scan the next entity to understand the intent. (The backward scanning argument I provided above does not exactly apply here, since the lack of brackets serves to distinguish the two cases for both forward- and backward scanners. But I still think the semi-colon is a worthwhile terminator to use in this case, in terms of the cognitive hint it supplies.)

    I suspect part of the reason that I want to keep the bracketed form for outer-attributes is that it is trivial to compose a series of inner-attributes, since they each independently apply to the enclosing entity. But for outer-attributes, composition is... well, I suppose it remains pretty trivial, since one can just write them in sequence before the item in question, but I still like the option of putting all the outer-attributes that apply to an entity into one set of [ ... ] square brackets.

    Felix S Klock II at 2013-07-16 08:46:40

  28. The reason why I think significant-semicolons-in-attributes is a bad idea is because we're already asking new users to make a leap of faith wrt significant-semicolons-in-return-position. It simplifies our semicolons story if semicolons are either required or forbidden after all attributes.

    bstrie at 2013-07-16 15:08:56

  29. (shrug); I view the two uses of terminating semi-colons have having synergy with each other, not as in conflict.

    • A semicolon-terminated statement: when it finishes running, it really is done, and the only way that it affects the remainder of the program is via whatever side-effects it had. (This of course has the flip side that those side-effects could actually touch many places.)
    • A semicolon-less final expression: when it finishes running, its value is passed to the caller; one can only understand it via viewing it in tandem with the calling context.

    To me, the situation with semicolon-terminated attributes (semi-global effect) and semicolon-less attributes (local effect on immediately succeeding item) is somewhat analogous. Arguably it could be a false analogy.

    Anyway, I am not going to try very hard to convince you one way or the other, I just wanted to document my viewpoint on the matter. (Note that I do agree that relying on a semicolon's absence/presence alone as the sole determiner for whether an attribute is inner or outer is too subtle; my point is that I want the semi-colon determiner in addition to whatever other distinguishing syntax we select.)

    Felix S Klock II at 2013-07-17 08:12:46

  30. In order to make #! compatible with shebang I propose the following rule: #! followed by either /, ./ or ../ is considered a shebang. This means we don't accept some lines that the OS would, but still allows any program to run via an absolute or relative path, and makes attributes unambiguously parseable.

    We could also say that #! followed by a non-identifier character is a shebang, if we don't use bracketed attribute syntax.

    Brian Anderson at 2013-09-18 23:19:36

  31. I still prefer the non-bracket option, taking away the unused ability to put multiple attributes in a single attribute element. So to me these are the two options:

    # outer(attr)
    # outer(attr)
    mod bar {
        #! inner(attr)
        #! inner(attr)
    }
    
    # outer(attr)
    # outer(attr)
    mod bar {
        #! inner(attr);
        #! inner(attr);
    }
    

    Brian Anderson at 2013-09-18 23:26:02

  32. I think the second suggestion of @brson:

    # outer(attr)
    # outer(attr)
    mod bar {
        #! inner(attr);
        #! inner(attr);
    }
    

    satisfies my most relevant criteria. I.e. It gets my vote in this run-off election. :)

    Felix S Klock II at 2013-09-19 00:44:46

  33. 1+ for getting rid of both the [] and using # and #!.

    Re shebang, how about this: If the first line starts with an #!, then

    • Try to parse as an inner attribute.
    • If successful, optionally emit 'warning: inner attribute on first line, external tools can confuse this with an shebang"' and continue parsing.
    • If unsuccessful, ignore the line as it's most likely an shebang.

    Alternatively, we could always forbid/warn about an possible inner attribute on the first line?

    Marvin Löbel at 2013-09-19 01:14:25

  34. @Kimundi istm that an inner attribute on the first line is a very common use case.

    Brian Anderson at 2013-09-27 01:32:46

  35. @brson Okay, then don't forbid it, and don't emit a warning about it per default. :)

    Marvin Löbel at 2013-09-27 11:12:53

  36. @Kimundi am I right that if we require the semicolon terminator at the end of the inner attribute, that will make it very unlikely that we'd confuse a sh-bang line with an inner attribute ? (Can sh-bang lines even have semicolons?)

    (This is my way of saying: "I think your idea of attempting to parse first line as inner attribute, and then ignoring the first line if we cannot parse as inner attribute, is a good idea.")

    Felix S Klock II at 2013-09-27 11:38:22

  37. I suggested using #^ for inner attributes on IRC and it wasn't met with complete revulsion, so I'm mentioning it here. It solves the shebang issue: #^ ⇒ inner attribute; #! ⇒ shebang on the first line, error elsewhere; other # ⇒ outer attribute or error.

    # outer(attr)
    # outer(attr)
    mod bar {
        #^ inner(attr);
        #^ inner(attr);
    }
    

    (They have the property of pointing to the thing to which they are attached.)

    Huon Wilson at 2013-09-27 12:43:17

  38. These look fine, but when did we start putting spaces between the sigil and the attribute name? It makes attributes appear less visually coherent, especially if you're sticking them all on the same line (as I've seen used in the compiler before):

    # foo # bar fn qux() {
    

    Seems much more wishy-washy than:

    #foo #bar fn qux() {
    

    bstrie at 2013-09-27 12:45:14

  39. AFAIK we already have liberal support for whitespace in the attributes and we might as well keep it that way. I suggest making a lint if you want to guard against # foo cropping up.

    (@huonw mentioned that our lint infrastructure might not support lexical analysis like that. So, okay, it might be a little more work to do it this way.)

    Felix S Klock II at 2013-09-27 12:51:11

  40. @bstrie I'd presume that any whitespace between the # and the identifier would make no difference. The parse just goes "Found a SHEBANG token; expect an attribute next".

    @pnkfelix I think handling of ; would make no difference for the Rust side of parsing it. Once it sees a / or \, rustc knows it's invalid attribute syntax and can skip it, which would probably catch all valid shebangs. Any problem with #! here will stem solely from the fact that the environment might interpret any text file starting with those two bytes specially, irregardless of whether they are followed by a valid file system path or a valid Rust attribute.


    However, if those are reasons enough to not have #!, and we pick #^ as replacement, we could in theory go all the way with it (or at least support the comment form):

    //^ parent item
    //> next item
    //< previous item
    /// sugar/exclusive alternative for next item
    
    #^ parent item
    #> next item
    #< previous item
    # sugar/exclusive alternative for next item
    
    /*^ parent item */
    /*> next item */
    /*< previous item */
    /** sugar/exclusive alternative for next item */
    
    mod example {
        //^ This is an example module 
        //^ Let's see how this looks:
    
        /// This is a struct
        struct Bar {
            field1: uint //< This is the first field
            field2: uint //< This is the second field
        }
    
        mod a; //< stuff
        mod b; //< more stuff
        mod c; //< so much more stuff
    }
    
    

    To be clear, this is not a serious proposal, but I think I saw the //< doccomment form once or twice in the compiler source. :)

    Marvin Löbel at 2013-09-27 21:48:45

  41. My arguments for a terminating ; (in tandem with a leading !) are not for the sake of the rustc parser. They are for the sake of a human being scanning code by eye.

    Felix S Klock II at 2013-09-27 23:36:36

  42. Well, I guess seeing how all existing items items are either terminated by a {} or ;, it could be seen as strange for inner attributes to buckle that trend. #! allow(non_camel_case); Doesn't seem that bad.

    Marvin Löbel at 2013-09-28 09:02:44

  43. My thinking (on why this is not inconsistent with current semicolon usage) was noted in a previous comment.

    Felix S Klock II at 2013-09-28 09:35:27

  44. Some discussion in #rust (starting here) is leading me to wonder if we should actively discuss an alternative character to ! to follow the # to indicate an inner-attribute. (Basically, handling she-bangs is a big mess, especially on windows, and it may be best to either disallow support for them entirely, or stop trying to reuse #! for a different purpose.)

    So far I think I like #^ the best, though Kimundi points out in the IRC chat that the ^ character may be a slight inconvenience on some keyboard layouts.

    Felix S Klock II at 2013-10-11 12:45:24

  45. (The branch I've been hacking on is https://github.com/pnkfelix/rust/tree/fsk-inner-attr-syntax-2569 currently at: pnkfelix@b94add4c2a73ba09374ad96dbf738c4cc326bbd7 )

    Felix S Klock II at 2013-10-11 12:47:54

  46. Just using ## as @z0w0 proposed doesn't look to bad either, I think. A # is at least easier to type than a ^ for me :)

    //# parent item
    /// next item
    
    ## parent item
    # next item
    
    /*# parent item */
    /** next item */
    
    # some_weird_attribute
    mod example {
        //# This is an example module 
        //# Let's see how this looks:
    
        ## another_attribute
    
        /// This is a struct
        struct Bar {
            # volatile
            field1: uint,
            field2: uint
        }
    }
    

    Maybe a bit heavy for the comment ones, but then again you could argue that it makes them more stand out and decreases the possibility to confuse both forms.

    Marvin Löbel at 2013-10-11 13:03:00

  47. Here I'll address just doc comments: I think a single syntax can work just fine; all it takes is the enforcement of certain conventions—which would not be a bad thing (it certainly works for Python).

    /// Module/crate comment. Clearly on the inside 'cos it's got to be.
    ///
    /// This can go on for as long as we like, until we get an end of comment (if
    /// it's a block comment, /** */) or until we get a blank line for per-line
    /// comments.
    
    /// OK, now we must be onto the comment which must clearly apply to the next
    /// thing. As it's coming before something, the thing that comes next *must not*
    /// have an inner. That includes `mod foo;` which has its inner in `mod.rs`. If
    /// it had an inner, we'd complain that it's invalid. Again, I'm not touching
    /// the normal attributes in this proposal, just the doc comments.
    ///
    /// Oh, and there *mustn't* be a blank line between this and the thing it
    /// applies to.
    pub struct FancyInt(int);
    
    pub struct Foo {
        /// This applies to Foo. It would then be easier not to support having no
        /// comment on Foo but having a comment on the field `bar`, as that would
        /// then require the blank line to be significant, which is untenable for
        /// the top of a file. I don't think people will want to document the inner
        /// without the outer in this case, at least, and hopefully generally.
    
        /// This applies to bar. Sure, you might want to put it on the same line,
        /// but does that improve readability? It certainly doesn't encourage
        /// clarity.
        bar: int,
    
        /// This applies to baz. I'm not sure whether the blank line above should be
        /// considered mandatory or not; it may be best so. Just think, if we'd gone
        /// for same-line comments, we might have had something like everyone's
        /// favourite style of automatically generated documentation:
        baz: Option<Foo>,  // baz is an optional Foo [ORLY?]
    }
    

    I think this can apply generally. Not sure precisely how well it will fit in with any other-attributes suggestions. If there are problems that I've neglected to consider, please apprise me of them.

    (It's a good word, that: "apprise". Just don't misspell it "appraise"!)

    Chris Morgan at 2013-10-11 13:22:35

  48. Current leading candidate:

    # foo(bar)
    mod baz {
      #^ foo(bar);
    }
    

    Plus also remove the foo = "bar" form of meta item.

    Brian Anderson at 2013-10-15 22:18:29

  49. Plus also remove the foo = "bar" form of meta item.

    By remove, you mean replace it with foo("bar"), foo(123), etc?

    Huon Wilson at 2013-10-15 22:23:40

  50. @huonw right. We'd have to generalize the attribute syntax slightly to allow e.g. foo("bar") and foo(123) (see https://gist.github.com/pnkfelix/6992779 for some brainstorming results), but I believe that would be the plan.

    Felix S Klock II at 2013-10-16 22:21:28

  51. I knew people wanted to remove the trailing ; on inner attributes, but I had no idea people wanted to remove the brackets. That looks seriously ugly to me. What's the motivation to remove the brackets? #[outer_attr] and #^[inner_attr] looks fine to me (although, personally, I actually like the current trailing semicolon approach).

    Lily Ballard at 2013-10-20 02:29:08

  52. #outer(attr) #! inner(attr)

    +1 for its match to rustdoc-style /// and ///! the [ ] is not needed: #test #cfg(...) fn {}

    Liigo Zhuang at 2013-12-26 04:19:21

  53. How about we take a page from C#'s playbook and use a target specifier:

    • #[attrib(...)] for outer attributes
    • #[outer: attrib(...)] or #[parent: attrib(...)] for inner ones

    Or, possibly, add #[mod: attrib(...)] and remove all other inner ones altogether,- since the only place where inner attributes are actually necessary are the 'whole-file' modules.

    vadimcn at 2014-01-29 07:23:07

  54. I think this proposal makes more sense https://github.com/mozilla/rust/issues/2569#issuecomment-26377517 and it still seems to be the leading one.

    # foo(bar)
    mod baz {
      #^ foo(bar);
    }
    

    Flavio Percoco at 2014-02-08 22:30:03

  55. I really like @vadimcn's suggestion, and it reads much nicer. For example:

    #crate: allow(dead_code)
    #crate: type = dylib,rlib
    #crate: doc = "foo"
    
    #nolink
    mod foo { ... }
    

    emberian at 2014-02-25 02:21:52

  56. @cmr: This feels like it's making newlines significant, which AFAIK is not the case anywhere else except for line comments. I don't like that.

    Lily Ballard at 2014-02-25 02:24:03

  57. @kballard doesn't the proposed "leading" candidate already do that?

    emberian at 2014-02-25 02:31:01

  58. @cmr: Perhaps. I don't like that suggestion either.

    It's also worth noting with your suggestion that you're making it so only crate-level attributes are allowed to be defined inside of the item. I strongly disagree with this, because it's often useful to define attributes inside of functions that apply to the function, e.g. #[inline];.

    Lily Ballard at 2014-02-25 02:33:16

  59. No, not just crate-level. Could also say #parent: foo as well. I was merely elaborating on @vadimcn's suggestion that it reads incredibly clearly for crate attributes. It is more verbose, though.

    On Mon, Feb 24, 2014 at 9:33 PM, Kevin Ballard notifications@github.comwrote:

    @cmr https://github.com/cmr: Perhaps. I don't like that suggestion either.

    It's also worth noting with your suggestion that you're making it so only crate-level attributes are allowed to be defined inside of the item. I strongly disagree with this, because it's often useful to define attributes inside of functions that apply to the function, e.g. #[inline]; .

    — Reply to this email directly or view it on GitHubhttps://github.com/mozilla/rust/issues/2569#issuecomment-35968659 .

    emberian at 2014-02-25 02:34:33

  60. @cmr: I see. But it still feels off to me, and not just because it's overly verbose for inner attributes.

    I really do think that I should be able to strip a source file of all comments, and then remove all newlines, and the end result should still parse the same as the original (minus doc attributes). AFAIK that's true today.

    Lily Ballard at 2014-02-25 02:36:58

  61. Also FWIW the ability to be newline-agnostic is important for the rusti IRC bot.

    Lily Ballard at 2014-02-25 02:37:28

  62. At this point my inclination is to add the bang to the existing syntax, remove the semi, and put this to bed. Existing syntax is mostly fine, we don't need to cause more churn than necessary.

    Brian Anderson at 2014-02-25 03:18:54

  63. @brson :+1: As much as I am in fact partial to the semi, #![foo] is something I'd be perfectly fine with, and is also a relatively tiny change.

    Lily Ballard at 2014-02-25 04:05:13

  64. Currently started working on this. I implemented the previous leading candidate and all tests pass, so changing it to the now leading candidate should be pretty straightforward. So #![foo] is now definitely the new syntax? @brson

    Daniel Fagnan at 2014-02-25 05:23:29

  65. I don't care so much about what the inner attribute syntax ends up being (none of the options seem obviously superior), but I really want to lose the brackets.

    Gábor Lehel at 2014-02-25 07:33:54

  66. @cmr 2014年2月25日 上午10:21于 "Corey Richardson" notifications@github.com写道:

    I really like @vadimcn's suggestion, and it reads much nicer. For example:
    # crate: allow(dead_code)
    # crate: type = dylib,rlib
    # doc = "foo"
    

    +1! Love it!! And maybe put them in one line:

    #crate: allow(), type="rlib", doc="";

    Much better than #![foo]

    Liigo Zhuang at 2014-02-25 08:35:50

  67. cc #12341: RFC: Remove inner attributes and inner doc-comments syntax.

    Liigo Zhuang at 2014-02-25 08:38:07

  68. #![foo] has the least change and is more visible than the semicolon. Moving both inner and outer to a bracket less syntax should be another proposal, it looks nice for handling all the crate attributes but I'm not sure if it is as workable for things like # inline fn foo() {}. It might also have impacts on the parser efficiency.

    Ben Harris at 2014-02-25 23:21:34