Added tests and fixed corner case for trailing attributes with no attached binding in generics.
This commit is contained in:
parent
c242fc3ea3
commit
3a9b7be10b
@ -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,
|
||||
|
26
src/test/compile-fail/attrs-with-no-formal-in-generics-1.rs
Normal file
26
src/test/compile-fail/attrs-with-no-formal-in-generics-1.rs
Normal file
@ -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() {
|
||||
|
||||
}
|
26
src/test/compile-fail/attrs-with-no-formal-in-generics-2.rs
Normal file
26
src/test/compile-fail/attrs-with-no-formal-in-generics-2.rs
Normal file
@ -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() {
|
||||
|
||||
}
|
26
src/test/compile-fail/attrs-with-no-formal-in-generics-3.rs
Normal file
26
src/test/compile-fail/attrs-with-no-formal-in-generics-3.rs
Normal file
@ -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() {
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user