From e36cb0d5c1176f8dcb3538e545c86631d5619f00 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sun, 24 Nov 2013 11:48:46 +1100 Subject: [PATCH] syntax: parse inner attributes on impls. Fixes #3614. --- src/libsyntax/parse/parser.rs | 24 ++++++++++++----- src/libsyntax/print/pprust.rs | 1 + src/test/run-pass/inner-attrs-on-impl.rs | 33 ++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 src/test/run-pass/inner-attrs-on-impl.rs 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 or the MIT license +// , 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()); +}