about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2016-07-11 18:29:45 +0200
committerFelix S. Klock II <pnkfelix@pnkfx.org>2016-09-23 17:01:04 +0200
commit3a9b7be10b8e32d014008f9fde276cd032aa4e4a (patch)
treecdb52d948b248d2c070f3c629ef6d9299172b47c /src
parentc242fc3ea3f64f2225e3ba9dd85545bb1d72a578 (diff)
downloadrust-3a9b7be10b8e32d014008f9fde276cd032aa4e4a.tar.gz
rust-3a9b7be10b8e32d014008f9fde276cd032aa4e4a.zip
Added tests and fixed corner case for trailing attributes with no attached binding in generics.
Diffstat (limited to 'src')
-rw-r--r--src/libsyntax/parse/parser.rs17
-rw-r--r--src/test/compile-fail/attrs-with-no-formal-in-generics-1.rs26
-rw-r--r--src/test/compile-fail/attrs-with-no-formal-in-generics-2.rs26
-rw-r--r--src/test/compile-fail/attrs-with-no-formal-in-generics-3.rs26
4 files changed, 94 insertions, 1 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index fe5ff5c47b2..3c561780085 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1958,7 +1958,7 @@ impl<'a> Parser<'a> {
                         assert!(recv.is_empty());
                         *recv = attrs;
                     } else {
-                        let msg = "encountered trailing attributes after lifetime parameters";
+                        let msg = "trailing attribute after lifetime parameters";
                         return Err(self.fatal(msg));
                     }
                     debug!("parse_lifetime_defs ret {:?}", res);
@@ -4294,12 +4294,21 @@ impl<'a> Parser<'a> {
         let span_lo = self.span.lo;
 
         if self.eat(&token::Lt) {
+            // Upon encountering attribute in generics list, we do not
+            // know if it is attached to lifetime or to type param.
+            //
+            // Solution: 1. eagerly parse attributes in tandem with
+            // lifetime defs, 2. store last set of parsed (and unused)
+            // attributes in `attrs`, and 3. pass in those attributes
+            // when parsing formal type param after lifetime defs.
             let mut attrs = vec![];
             let lifetime_defs = self.parse_lifetime_defs(Some(&mut attrs))?;
             let mut seen_default = false;
             let mut post_lifetime_attrs = Some(attrs);
             let ty_params = self.parse_seq_to_gt(Some(token::Comma), |p| {
                 p.forbid_lifetime()?;
+                // Move out of `post_lifetime_attrs` if present. O/w
+                // not first type param: parse attributes anew.
                 let attrs = match post_lifetime_attrs.as_mut() {
                     None => p.parse_outer_attributes()?,
                     Some(attrs) => mem::replace(attrs, vec![]),
@@ -4315,6 +4324,12 @@ impl<'a> Parser<'a> {
                 }
                 Ok(ty_param)
             })?;
+            if let Some(attrs) = post_lifetime_attrs {
+                if !attrs.is_empty() {
+                    self.span_err(attrs[0].span,
+                                  "trailing attribute after lifetime parameters");
+                }
+            }
             Ok(ast::Generics {
                 lifetimes: lifetime_defs,
                 ty_params: ty_params,
diff --git a/src/test/compile-fail/attrs-with-no-formal-in-generics-1.rs b/src/test/compile-fail/attrs-with-no-formal-in-generics-1.rs
new file mode 100644
index 00000000000..53e287cda20
--- /dev/null
+++ b/src/test/compile-fail/attrs-with-no-formal-in-generics-1.rs
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+// This test checks variations on `<#[attr] 'a, #[oops]>`, where
+// `#[oops]` is left dangling (that is, it is unattached, with no
+// formal binding following it).
+
+#![feature(generic_param_attrs, rustc_attrs)]
+#![allow(dead_code)]
+
+struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
+
+impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
+    //~^ ERROR trailing attribute after lifetime parameters
+}
+
+fn main() {
+
+}
diff --git a/src/test/compile-fail/attrs-with-no-formal-in-generics-2.rs b/src/test/compile-fail/attrs-with-no-formal-in-generics-2.rs
new file mode 100644
index 00000000000..a38a7bfb937
--- /dev/null
+++ b/src/test/compile-fail/attrs-with-no-formal-in-generics-2.rs
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+// This test checks variations on `<#[attr] 'a, #[oops]>`, where
+// `#[oops]` is left dangling (that is, it is unattached, with no
+// formal binding following it).
+
+#![feature(generic_param_attrs, rustc_attrs)]
+#![allow(dead_code)]
+
+struct RefAny<'a, T>(&'a T);
+
+impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {
+    //~^ ERROR expected identifier, found `>`
+}
+
+fn main() {
+
+}
diff --git a/src/test/compile-fail/attrs-with-no-formal-in-generics-3.rs b/src/test/compile-fail/attrs-with-no-formal-in-generics-3.rs
new file mode 100644
index 00000000000..e7d5b94d242
--- /dev/null
+++ b/src/test/compile-fail/attrs-with-no-formal-in-generics-3.rs
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+// This test checks variations on `<#[attr] 'a, #[oops]>`, where
+// `#[oops]` is left dangling (that is, it is unattached, with no
+// formal binding following it).
+
+struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
+
+fn hof_lt<Q>(_: Q)
+    where Q: for <#[rustc_1] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
+    //~^ ERROR trailing attribute after lifetime parameters
+{
+
+}
+
+fn main() {
+
+}