about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2013-11-24 11:48:46 +1100
committerHuon Wilson <dbau.pp+github@gmail.com>2013-11-25 19:18:44 +1100
commite36cb0d5c1176f8dcb3538e545c86631d5619f00 (patch)
tree7f849e7136a3cf416b5d58cf6d2210543fbdf3ea
parentfb279aa02a7ff2ed069791f60a5159d73c8ed993 (diff)
downloadrust-e36cb0d5c1176f8dcb3538e545c86631d5619f00.tar.gz
rust-e36cb0d5c1176f8dcb3538e545c86631d5619f00.zip
syntax: parse inner attributes on impls.
Fixes #3614.
-rw-r--r--src/libsyntax/parse/parser.rs24
-rw-r--r--src/libsyntax/print/pprust.rs1
-rw-r--r--src/test/run-pass/inner-attrs-on-impl.rs33
3 files changed, 51 insertions, 7 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 486a7a800a0..29ccb235f07 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -3871,9 +3871,14 @@ impl Parser {
          Some(inner_attrs))
     }
 
-    // parse a method in a trait impl
-    fn parse_method(&self) -> @method {
-        let attrs = self.parse_outer_attributes();
+    // parse a method in a trait impl, starting with `attrs` attributes.
+    fn parse_method(&self, already_parsed_attrs: Option<~[Attribute]>) -> @method {
+        let next_attrs = self.parse_outer_attributes();
+        let attrs = match already_parsed_attrs {
+            Some(mut a) => { a.push_all_move(next_attrs); a }
+            None => next_attrs
+        };
+
         let lo = self.span.lo;
 
         let visa = self.parse_visibility();
@@ -3966,16 +3971,21 @@ impl Parser {
         };
 
         let mut meths = ~[];
-        if self.eat(&token::SEMI) {
+        let inner_attrs = if self.eat(&token::SEMI) {
             self.obsolete(*self.last_span, ObsoleteEmptyImpl);
+            None
         } else {
             self.expect(&token::LBRACE);
+            let (inner_attrs, next) = self.parse_inner_attrs_and_next();
+            let mut method_attrs = Some(next);
             while !self.eat(&token::RBRACE) {
-                meths.push(self.parse_method());
+                meths.push(self.parse_method(method_attrs));
+                method_attrs = None;
             }
-        }
+            Some(inner_attrs)
+        };
 
-        (ident, item_impl(generics, opt_trait, ty, meths), None)
+        (ident, item_impl(generics, opt_trait, ty, meths), inner_attrs)
     }
 
     // parse a::B<~str,int>
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index e3e61e50d6b..c41460485da 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -596,6 +596,7 @@ pub fn print_item(s: @ps, item: &ast::item) {
 
         space(s.s);
         bopen(s);
+        print_inner_attributes(s, item.attrs);
         for meth in methods.iter() {
            print_method(s, *meth);
         }
diff --git a/src/test/run-pass/inner-attrs-on-impl.rs b/src/test/run-pass/inner-attrs-on-impl.rs
new file mode 100644
index 00000000000..69ae9d34385
--- /dev/null
+++ b/src/test/run-pass/inner-attrs-on-impl.rs
@@ -0,0 +1,33 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+struct Foo;
+
+impl Foo {
+    #[cfg(cfg_that_surely_doesnt_exist)];
+
+    fn method(&self) -> bool { false }
+}
+
+impl Foo {
+    #[cfg(not(cfg_that_surely_doesnt_exist))];
+
+    // check that we don't eat attributes too eagerly.
+    #[cfg(cfg_that_surely_doesnt_exist)]
+    fn method(&self) -> bool { false }
+
+    fn method(&self) -> bool { true }
+}
+
+
+pub fn main() {
+    assert!(Foo.method());
+}