Skip to content

Commit

Permalink
syntax: Always parse pub ( path_start in tuple structs as visibility
Browse files Browse the repository at this point in the history
  • Loading branch information
petrochenkov committed Apr 19, 2016
1 parent c2aaad4 commit 2169b0c
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 23 deletions.
44 changes: 21 additions & 23 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3587,7 +3587,7 @@ impl<'a> Parser<'a> {
}

fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
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
Expand All @@ -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<Pat>> {
maybe_whole!(self, NtPat);
Expand Down Expand Up @@ -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) &&
Expand Down Expand Up @@ -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()?;
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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 })
}
}
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -6013,7 +6011,7 @@ impl<'a> Parser<'a> {
fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
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
Expand Down
5 changes: 5 additions & 0 deletions src/libsyntax/parse/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<BinOpKind> {
match *self {
Expand Down
16 changes: 16 additions & 0 deletions src/test/parse-fail/visibility-type-conflict.rs
Original file line number Diff line number Diff line change
@@ -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 <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.

// 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 `,`
31 changes: 31 additions & 0 deletions src/test/run-pass/visibility-type-conflict.rs
Original file line number Diff line number Diff line change
@@ -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 <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.

// `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() {}

0 comments on commit 2169b0c

Please sign in to comment.