Skip to content

Commit a248949

Browse files
DanielKeepdurka
authored andcommitted
Implementation of the vis macro matcher.
1 parent ae23e65 commit a248949

File tree

6 files changed

+142
-1
lines changed

6 files changed

+142
-1
lines changed

src/libsyntax/ext/tt/macro_parser.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
529529
token::NtPath(panictry!(p.parse_path(PathStyle::Type)))
530530
},
531531
"meta" => token::NtMeta(panictry!(p.parse_meta_item())),
532+
"vis" => token::NtVis(panictry!(p.parse_visibility(true))),
532533
// this is not supposed to happen, since it has been checked
533534
// when compiling the macro.
534535
_ => p.span_bug(sp, "invalid fragment specifier")

src/libsyntax/ext/tt/macro_rules.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,19 @@ fn is_in_follow(tok: &quoted::TokenTree, frag: &str) -> Result<bool, (String, &'
790790
// harmless
791791
Ok(true)
792792
},
793+
"vis" => {
794+
// Explicitly disallow `priv`, on the off chance it comes back.
795+
match *tok {
796+
Comma => Ok(true),
797+
ModSep => Ok(true),
798+
MatchNt(_, ref frag, _, _) => {
799+
let name = frag.name.as_str();
800+
Ok(name == "ident" || name == "ty")
801+
},
802+
Ident(i, _) if i.name.as_str() != "priv" => Ok(true),
803+
_ => Ok(false)
804+
}
805+
},
793806
"" => Ok(true), // keywords::Invalid
794807
_ => Err((format!("invalid fragment specifier `{}`", frag),
795808
"valid fragment specifiers are `ident`, `block`, \
@@ -813,7 +826,7 @@ fn has_legal_fragment_specifier(tok: &quoted::TokenTree) -> Result<(), String> {
813826
fn is_legal_fragment_specifier(frag: &str) -> bool {
814827
match frag {
815828
"item" | "block" | "stmt" | "expr" | "pat" |
816-
"path" | "ty" | "ident" | "meta" | "tt" | "" => true,
829+
"path" | "ty" | "ident" | "meta" | "tt" | "vis" | "" => true,
817830
_ => false,
818831
}
819832
}

src/libsyntax/fold.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,7 @@ pub fn noop_fold_interpolated<T: Folder>(nt: token::Nonterminal, fld: &mut T)
636636
token::NtWhereClause(where_clause) =>
637637
token::NtWhereClause(fld.fold_where_clause(where_clause)),
638638
token::NtArg(arg) => token::NtArg(fld.fold_arg(arg)),
639+
token::NtVis(vis) => token::NtVis(fld.fold_vis(vis)),
639640
}
640641
}
641642

src/libsyntax/parse/token.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ pub enum Nonterminal {
371371
NtGenerics(ast::Generics),
372372
NtWhereClause(ast::WhereClause),
373373
NtArg(ast::Arg),
374+
NtVis(ast::Visibility),
374375
}
375376

376377
impl fmt::Debug for Nonterminal {
@@ -392,6 +393,7 @@ impl fmt::Debug for Nonterminal {
392393
NtGenerics(..) => f.pad("NtGenerics(..)"),
393394
NtWhereClause(..) => f.pad("NtWhereClause(..)"),
394395
NtArg(..) => f.pad("NtArg(..)"),
396+
NtVis(..) => f.pad("NtVis(..)"),
395397
}
396398
}
397399
}

src/libsyntax/print/pprust.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ pub fn token_to_string(tok: &Token) -> String {
293293
token::NtGenerics(ref e) => generics_to_string(&e),
294294
token::NtWhereClause(ref e) => where_clause_to_string(&e),
295295
token::NtArg(ref e) => arg_to_string(&e),
296+
token::NtVis(ref e) => vis_to_string(&e),
296297
}
297298
}
298299
}
@@ -373,6 +374,10 @@ pub fn ident_to_string(id: ast::Ident) -> String {
373374
to_string(|s| s.print_ident(id))
374375
}
375376

377+
pub fn vis_to_string(v: &ast::Visibility) -> String {
378+
to_string(|s| s.print_visibility(v))
379+
}
380+
376381
pub fn fun_to_string(decl: &ast::FnDecl,
377382
unsafety: ast::Unsafety,
378383
constness: ast::Constness,
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#![allow(dead_code, unused_imports)]
2+
#![feature(pub_restricted)]
3+
4+
/**
5+
Ensure that `:vis` matches can be captured in existing positions, and passed
6+
through without the need for reparse tricks.
7+
*/
8+
macro_rules! vis_passthru {
9+
($vis:vis const $name:ident: $ty:ty = $e:expr;) => { $vis const $name: $ty = $e; };
10+
($vis:vis enum $name:ident {}) => { $vis struct $name {} };
11+
($vis:vis extern "C" fn $name:ident() {}) => { $vis extern "C" fn $name() {} };
12+
($vis:vis fn $name:ident() {}) => { $vis fn $name() {} };
13+
($vis:vis mod $name:ident {}) => { $vis mod $name {} };
14+
($vis:vis static $name:ident: $ty:ty = $e:expr;) => { $vis static $name: $ty = $e; };
15+
($vis:vis struct $name:ident;) => { $vis struct $name; };
16+
($vis:vis trait $name:ident {}) => { $vis trait $name {} };
17+
($vis:vis type $name:ident = $ty:ty;) => { $vis type $name = $ty; };
18+
($vis:vis use $path:ident as $name:ident;) => { $vis use self::$path as $name; };
19+
}
20+
21+
mod with_pub {
22+
vis_passthru! { pub const A: i32 = 0; }
23+
vis_passthru! { pub enum B {} }
24+
vis_passthru! { pub extern "C" fn c() {} }
25+
vis_passthru! { pub mod d {} }
26+
vis_passthru! { pub static E: i32 = 0; }
27+
vis_passthru! { pub struct F; }
28+
vis_passthru! { pub trait G {} }
29+
vis_passthru! { pub type H = i32; }
30+
vis_passthru! { pub use A as I; }
31+
}
32+
33+
mod without_pub {
34+
vis_passthru! { const A: i32 = 0; }
35+
vis_passthru! { enum B {} }
36+
vis_passthru! { extern "C" fn c() {} }
37+
vis_passthru! { mod d {} }
38+
vis_passthru! { static E: i32 = 0; }
39+
vis_passthru! { struct F; }
40+
vis_passthru! { trait G {} }
41+
vis_passthru! { type H = i32; }
42+
vis_passthru! { use A as I; }
43+
}
44+
45+
mod with_pub_restricted {
46+
vis_passthru! { pub(crate) const A: i32 = 0; }
47+
vis_passthru! { pub(crate) enum B {} }
48+
vis_passthru! { pub(crate) extern "C" fn c() {} }
49+
vis_passthru! { pub(crate) mod d {} }
50+
vis_passthru! { pub(crate) static E: i32 = 0; }
51+
vis_passthru! { pub(crate) struct F; }
52+
vis_passthru! { pub(crate) trait G {} }
53+
vis_passthru! { pub(crate) type H = i32; }
54+
vis_passthru! { pub(crate) use A as I; }
55+
}
56+
57+
mod garden {
58+
mod with_pub_restricted_path {
59+
vis_passthru! { pub(::garden) const A: i32 = 0; }
60+
vis_passthru! { pub(::garden) enum B {} }
61+
vis_passthru! { pub(::garden) extern "C" fn c() {} }
62+
vis_passthru! { pub(::garden) mod d {} }
63+
vis_passthru! { pub(::garden) static E: i32 = 0; }
64+
vis_passthru! { pub(::garden) struct F; }
65+
vis_passthru! { pub(::garden) trait G {} }
66+
vis_passthru! { pub(::garden) type H = i32; }
67+
vis_passthru! { pub(::garden) use A as I; }
68+
}
69+
}
70+
71+
/*
72+
Ensure that the `:vis` matcher works in a more complex situation: parsing a
73+
struct definition.
74+
*/
75+
macro_rules! vis_parse_struct {
76+
/*
77+
The rule duplication is currently unavoidable due to the leading attribute
78+
matching.
79+
*/
80+
($(#[$($attrs:tt)*])* pub($($vis:tt)*) struct $name:ident {$($body:tt)*}) => {
81+
vis_parse_struct! { @parse_fields $(#[$($attrs)*])*, pub($($vis)*), $name, $($body)* }
82+
};
83+
($(#[$($attrs:tt)*])* pub struct $name:ident {$($body:tt)*}) => {
84+
vis_parse_struct! { @parse_fields $(#[$($attrs)*])*, pub, $name, $($body)* }
85+
};
86+
($(#[$($attrs:tt)*])* struct $name:ident {$($body:tt)*}) => {
87+
vis_parse_struct! { @parse_fields $(#[$($attrs)*])*, , $name, $($body)* }
88+
};
89+
90+
($(#[$($attrs:tt)*])* pub($($vis:tt)*) struct $name:ident ($($body:tt)*);) => {
91+
vis_parse_struct! { @parse_tuple $(#[$($attrs)*])*, pub($($vis)*), $name, $($body)* }
92+
};
93+
($(#[$($attrs:tt)*])* pub struct $name:ident ($($body:tt)*);) => {
94+
vis_parse_struct! { @parse_tuple $(#[$($attrs)*])*, pub, $name, $($body)* }
95+
};
96+
($(#[$($attrs:tt)*])* struct $name:ident ($($body:tt)*);) => {
97+
vis_parse_struct! { @parse_tuple $(#[$($attrs)*])*, , $name, $($body)* }
98+
};
99+
100+
(@parse_fields $(#[$attrs:meta])*, $vis:vis, $name:ident, $($fvis:vis $fname:ident: $fty:ty),* $(,)*) => {
101+
$(#[$attrs])* $vis struct $name { $($fvis $fname: $fty,)* }
102+
};
103+
104+
(@parse_tuple $(#[$attrs:meta])*, $vis:vis, $name:ident, $($fvis:vis $fty:ty),* $(,)*) => {
105+
$(#[$attrs])* $vis struct $name ( $($fvis $fty,)* );
106+
};
107+
}
108+
109+
mod test_struct {
110+
vis_parse_struct! { pub(crate) struct A { pub a: i32, b: i32, pub(crate) c: i32 } }
111+
vis_parse_struct! { pub struct B { a: i32, pub(crate) b: i32, pub c: i32 } }
112+
vis_parse_struct! { struct C { pub(crate) a: i32, pub b: i32, c: i32 } }
113+
114+
vis_parse_struct! { pub(crate) struct D (pub i32, i32, pub(crate) i32); }
115+
vis_parse_struct! { pub struct E (i32, pub(crate) i32, pub i32); }
116+
vis_parse_struct! { struct F (pub(crate) i32, pub i32, i32); }
117+
}
118+
119+
fn main() {}

0 commit comments

Comments
 (0)