diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f3d3bbd9f9905..0b8b9058f7d50 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3587,7 +3587,7 @@ impl<'a> Parser<'a> { } fn parse_pat_range_end(&mut self) -> PResult<'a, P> { - if self.is_path_start() { + if self.token.is_path_start() { let lo = self.span.lo; let (qself, path) = if self.eat_lt() { // Parse a qualified path @@ -3605,12 +3605,6 @@ impl<'a> Parser<'a> { } } - fn is_path_start(&self) -> bool { - (self.token == token::Lt || self.token == token::ModSep - || self.token.is_ident() || self.token.is_path()) - && !self.token.is_keyword(keywords::True) && !self.token.is_keyword(keywords::False) - } - /// Parse a pattern. pub fn parse_pat(&mut self) -> PResult<'a, P> { maybe_whole!(self, NtPat); @@ -3661,7 +3655,7 @@ impl<'a> Parser<'a> { // Parse box pat let subpat = self.parse_pat()?; pat = PatKind::Box(subpat); - } else if self.is_path_start() { + } else if self.token.is_path_start() { // Parse pattern starting with a path if self.token.is_plain_ident() && self.look_ahead(1, |t| *t != token::DotDotDot && *t != token::OpenDelim(token::Brace) && @@ -4930,7 +4924,7 @@ impl<'a> Parser<'a> { let mut attrs = self.parse_outer_attributes()?; let lo = self.span.lo; - let vis = self.parse_visibility(true)?; + let vis = self.parse_visibility()?; let defaultness = self.parse_defaultness()?; let (name, node) = if self.eat_keyword(keywords::Type) { let name = self.parse_ident()?; @@ -5242,7 +5236,7 @@ impl<'a> Parser<'a> { |p| { let attrs = p.parse_outer_attributes()?; let lo = p.span.lo; - let vis = p.parse_visibility(false)?; + let vis = p.parse_visibility()?; let ty = p.parse_ty_sum()?; Ok(StructField { span: mk_sp(lo, p.span.hi), @@ -5283,24 +5277,28 @@ impl<'a> Parser<'a> { /// Parse an element of a struct definition fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> { let attrs = self.parse_outer_attributes()?; - let vis = self.parse_visibility(true)?; + let vis = self.parse_visibility()?; self.parse_single_struct_field(vis, attrs) } - fn parse_visibility(&mut self, allow_restricted: bool) -> PResult<'a, Visibility> { + fn parse_visibility(&mut self) -> PResult<'a, Visibility> { if !self.eat_keyword(keywords::Pub) { Ok(Visibility::Inherited) - } else if !allow_restricted || !self.eat(&token::OpenDelim(token::Paren)) { + } else if !self.check(&token::OpenDelim(token::Paren)) || + !self.look_ahead(1, |t| t.is_path_start()) { Ok(Visibility::Public) - } else if self.eat_keyword(keywords::Crate) { - let span = self.last_span; - self.expect(&token::CloseDelim(token::Paren))?; - Ok(Visibility::Crate(span)) } else { - let path = self.with_res(Restrictions::ALLOW_MODULE_PATHS, - |this| this.parse_path(NoTypesAllowed))?; - self.expect(&token::CloseDelim(token::Paren))?; - Ok(Visibility::Restricted { path: P(path), id: ast::DUMMY_NODE_ID }) + self.bump(); + if self.eat_keyword(keywords::Crate) { + let span = self.last_span; + self.expect(&token::CloseDelim(token::Paren))?; + Ok(Visibility::Crate(span)) + } else { + let path = self.with_res(Restrictions::ALLOW_MODULE_PATHS, + |this| this.parse_path(NoTypesAllowed))?; + self.expect(&token::CloseDelim(token::Paren))?; + Ok(Visibility::Restricted { path: P(path), id: ast::DUMMY_NODE_ID }) + } } } @@ -5763,7 +5761,7 @@ impl<'a> Parser<'a> { let lo = self.span.lo; - let visibility = self.parse_visibility(true)?; + let visibility = self.parse_visibility()?; if self.eat_keyword(keywords::Use) { // USE ITEM @@ -6013,7 +6011,7 @@ impl<'a> Parser<'a> { fn parse_foreign_item(&mut self) -> PResult<'a, Option> { let attrs = self.parse_outer_attributes()?; let lo = self.span.lo; - let visibility = self.parse_visibility(true)?; + let visibility = self.parse_visibility()?; if self.check_keyword(keywords::Static) { // FOREIGN STATIC ITEM diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 16417ac004461..7ac20dae8a0a4 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -263,6 +263,11 @@ impl Token { self.is_keyword(keywords::Const) } + pub fn is_path_start(&self) -> bool { + self == &ModSep || self == &Lt || self.is_path() || self.is_ident() && + !self.is_keyword(keywords::True) && !self.is_keyword(keywords::False) + } + /// Maps a token to its corresponding binary operator. pub fn to_binop(&self) -> Option { match *self { diff --git a/src/test/parse-fail/visibility-type-conflict.rs b/src/test/parse-fail/visibility-type-conflict.rs new file mode 100644 index 0000000000000..cf0a201b965fd --- /dev/null +++ b/src/test/parse-fail/visibility-type-conflict.rs @@ -0,0 +1,16 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only + +// Check that `pub ( path_start` parses as visibility + +struct S(pub (u8, u8)); //~ ERROR expected one of `)` or `::`, found `,` +//~^ ERROR expected one of `::`, `;`, or `where`, found `,` diff --git a/src/test/run-pass/visibility-type-conflict.rs b/src/test/run-pass/visibility-type-conflict.rs new file mode 100644 index 0000000000000..32dd273c3ffd3 --- /dev/null +++ b/src/test/run-pass/visibility-type-conflict.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// `pub ( path_start` parses as visibility, check that it doesn't +// affect macros and workaround with parens works. + +#![feature(type_macros)] + +struct S(pub ((u8, u8))); +struct K(pub ((u8))); +struct U(pub (*const u8, usize)); + +macro_rules! m { + ($t: ty) => ($t) +} + +macro_rules! n { + ($t: ty) => (struct L(pub $t);) +} + +struct Z(pub m!((u8, u8))); +n! { (u8, u8) } + +fn main() {}