diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index ae7f324627271..855bc1e5852d0 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -12,6 +12,7 @@ #[feature(phase)]; #[allow(non_camel_case_types)]; +#[allow(deprecated_owned_vector)]; // NOTE: remove after stage0 #[deny(warnings)]; extern crate test; diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 2cc41dd7085d9..dbebb8fb2bc68 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -24,6 +24,7 @@ html_root_url = "http://static.rust-lang.org/doc/master")]; #[allow(missing_doc)]; #[feature(managed_boxes)]; +#[allow(deprecated_owned_vector)]; // NOTE: remove after stage0 extern crate collections; diff --git a/src/libgreen/lib.rs b/src/libgreen/lib.rs index a23d2d4f3a57e..b9846c9c3a2a8 100644 --- a/src/libgreen/lib.rs +++ b/src/libgreen/lib.rs @@ -174,6 +174,7 @@ // NB this does *not* include globs, please keep it that way. #[feature(macro_rules, phase)]; #[allow(visible_private_types)]; +#[allow(deprecated_owned_vector)]; // NOTE: remove after stage0 #[cfg(test)] #[phase(syntax, link)] extern crate log; extern crate rand; diff --git a/src/librustuv/lib.rs b/src/librustuv/lib.rs index 890f44faabc0d..ee4f15e7954bd 100644 --- a/src/librustuv/lib.rs +++ b/src/librustuv/lib.rs @@ -42,6 +42,7 @@ via `close` and `delete` methods. #[feature(macro_rules)]; #[deny(unused_result, unused_must_use)]; #[allow(visible_private_types)]; +#[allow(deprecated_owned_vector)]; // NOTE: remove after stage0 #[cfg(test)] extern crate green; diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index c30ab4bda2749..8f7fb5749a1eb 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -38,9 +38,6 @@ impl<'a> ParserAttr for Parser<'a> { attrs.push(self.parse_attribute(false)); } token::POUND => { - if self.look_ahead(1, |t| *t != token::LBRACKET) { - break; - } attrs.push(self.parse_attribute(false)); } token::DOC_COMMENT(s) => { @@ -61,27 +58,40 @@ impl<'a> ParserAttr for Parser<'a> { return attrs; } - // matches attribute = # [ meta_item ] + // matches attribute = # ! [ meta_item ] // - // if permit_inner is true, then a trailing `;` indicates an inner + // if permit_inner is true, then a leading `!` indicates an inner // attribute fn parse_attribute(&mut self, permit_inner: bool) -> ast::Attribute { debug!("parse_attributes: permit_inner={:?} self.token={:?}", permit_inner, self.token); - let (span, value) = match self.token { + let (span, value, mut style) = match self.token { INTERPOLATED(token::NtAttr(attr)) => { assert!(attr.node.style == ast::AttrOuter); self.bump(); - (attr.span, attr.node.value) + (attr.span, attr.node.value, ast::AttrOuter) } token::POUND => { let lo = self.span.lo; self.bump(); + + let style = if self.eat(&token::NOT) { + if !permit_inner { + self.span_err(self.span, + "an inner attribute is not permitted in \ + this context"); + } + ast::AttrInner + } else { + ast::AttrOuter + }; + self.expect(&token::LBRACKET); let meta_item = self.parse_meta_item(); self.expect(&token::RBRACKET); + let hi = self.span.hi; - (mk_sp(lo, hi), meta_item) + (mk_sp(lo, hi), meta_item, style) } _ => { let token_str = self.this_token_to_str(); @@ -89,12 +99,14 @@ impl<'a> ParserAttr for Parser<'a> { token_str)); } }; - let style = if permit_inner && self.token == token::SEMI { - self.bump(); - ast::AttrInner - } else { - ast::AttrOuter - }; + + if permit_inner && self.eat(&token::SEMI) { + // NOTE: uncomment this after a stage0 snap + //self.warn("This uses the old attribute syntax. Semicolons + // are not longer required."); + style = ast::AttrInner; + } + return Spanned { span: span, node: ast::Attribute_ { @@ -125,10 +137,6 @@ impl<'a> ParserAttr for Parser<'a> { self.parse_attribute(true) } token::POUND => { - if self.look_ahead(1, |t| *t != token::LBRACKET) { - // This is an extension - break; - } self.parse_attribute(true) } token::DOC_COMMENT(s) => { diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index 8abc01b6d7545..43ae9b97350df 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -319,7 +319,9 @@ fn read_block_comment(rdr: &StringReader, fn peeking_at_comment(rdr: &StringReader) -> bool { return (rdr.curr_is('/') && nextch_is(rdr, '/')) || (rdr.curr_is('/') && nextch_is(rdr, '*')) || - (rdr.curr_is('#') && nextch_is(rdr, '!')); + // consider shebangs comments, but not inner attributes + (rdr.curr_is('#') && nextch_is(rdr, '!') && + !lexer::nextnextch_is(rdr, '[')); } fn consume_comment(rdr: &StringReader, diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 58ec6acc3ac01..ca2fbd245873f 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -18,9 +18,10 @@ use parse::token::{str_to_ident}; use std::cell::{Cell, RefCell}; use std::char; -use std::rc::Rc; use std::mem::replace; use std::num::from_str_radix; +use std::rc::Rc; +use std::str; pub use ext::tt::transcribe::{TtReader, new_tt_reader}; @@ -271,9 +272,11 @@ pub fn bump(rdr: &StringReader) { rdr.curr.set(None); } } + pub fn is_eof(rdr: &StringReader) -> bool { rdr.curr.get().is_none() } + pub fn nextch(rdr: &StringReader) -> Option { let offset = byte_offset(rdr, rdr.pos.get()).to_uint(); if offset < rdr.filemap.deref().src.len() { @@ -286,6 +289,21 @@ pub fn nextch_is(rdr: &StringReader, c: char) -> bool { nextch(rdr) == Some(c) } +pub fn nextnextch(rdr: &StringReader) -> Option { + let offset = byte_offset(rdr, rdr.pos.get()).to_uint(); + let s = rdr.filemap.deref().src.as_slice(); + if offset >= s.len() { return None } + let str::CharRange { next, .. } = s.char_range_at(offset); + if next < s.len() { + Some(s.char_at(next)) + } else { + None + } +} +pub fn nextnextch_is(rdr: &StringReader, c: char) -> bool { + nextnextch(rdr) == Some(c) +} + fn hex_digit_val(c: Option) -> int { let d = c.unwrap_or('\x00'); @@ -370,6 +388,12 @@ fn consume_any_line_comment(rdr: &StringReader) } } else if rdr.curr_is('#') { if nextch_is(rdr, '!') { + + // Parse an inner attribute. + if nextnextch_is(rdr, '[') { + return None; + } + // I guess this is the only way to figure out if // we're at the beginning of the file... let cmap = CodeMap::new(); diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 3ec80d97d0613..ec7d48cf12bda 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -33,6 +33,7 @@ html_root_url = "http://static.rust-lang.org/doc/master")]; #[feature(asm, macro_rules)]; +#[allow(deprecated_owned_vector)]; // NOTE: remove after stage0 extern crate collections; extern crate getopts; diff --git a/src/test/compile-fail/attr.rs b/src/test/compile-fail/attr.rs new file mode 100644 index 0000000000000..b1f7a791f0958 --- /dev/null +++ b/src/test/compile-fail/attr.rs @@ -0,0 +1,14 @@ +// Copyright 2014 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. + +fn main() {} + +#![lang(foo)] //~ ERROR an inner attribute is not permitted in this context +fn foo() {} diff --git a/src/test/compile-fail/column-offset-1-based.rs b/src/test/compile-fail/column-offset-1-based.rs index 5b38b17ad959d..3a6594f64f36a 100644 --- a/src/test/compile-fail/column-offset-1-based.rs +++ b/src/test/compile-fail/column-offset-1-based.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -# //~ ERROR 11:1: 11:2 error: expected item +# //~ ERROR 11:1: 11:2 error: expected `[` but found `` diff --git a/src/test/compile-fail/issue-1655.rs b/src/test/compile-fail/issue-1655.rs index 37cfc642405dd..e2810b854f795 100644 --- a/src/test/compile-fail/issue-1655.rs +++ b/src/test/compile-fail/issue-1655.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:expected item +// error-pattern:expected `[` but found `~` mod blade_runner { #~[doc( brief = "Blade Runner is probably the best movie ever", diff --git a/src/test/run-pass/attr-mix-new.rs b/src/test/run-pass/attr-mix-new.rs new file mode 100644 index 0000000000000..af615912f2823 --- /dev/null +++ b/src/test/run-pass/attr-mix-new.rs @@ -0,0 +1,16 @@ +// Copyright 2014 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. + +#[foo(bar)] +mod foo { + #![feature(globs)] +} + +pub fn main() {} diff --git a/src/test/run-pass/attr-shebang.rs b/src/test/run-pass/attr-shebang.rs new file mode 100644 index 0000000000000..f4919f768b9cd --- /dev/null +++ b/src/test/run-pass/attr-shebang.rs @@ -0,0 +1,5 @@ +#![allow(unknown_features)] +#![feature(bogus)] +pub fn main() { } +// ignore-license +// ignore-fast diff --git a/src/test/run-pass/attr.rs b/src/test/run-pass/attr.rs new file mode 100644 index 0000000000000..6a19a44e07420 --- /dev/null +++ b/src/test/run-pass/attr.rs @@ -0,0 +1,15 @@ +// Copyright 2014 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. + +// ignore-fast + +#[main] +fn foo() { +}