1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! A support library for macro authors when defining new macros.
13 //! This library, provided by the standard distribution, provides the types
14 //! consumed in the interfaces of procedurally defined macro definitions.
15 //! Currently the primary use of this crate is to provide the ability to define
16 //! new custom derive modes through `#[proc_macro_derive]`.
18 //! Note that this crate is intentionally very bare-bones currently. The main
19 //! type, `TokenStream`, only supports `fmt::Display` and `FromStr`
20 //! implementations, indicating that it can only go to and come from a string.
21 //! This functionality is intended to be expanded over time as more surface
22 //! area for macro authors is stabilized.
24 //! See [the book](../book/procedural-macros.html) for more.
26 #![crate_name = "proc_macro"]
27 #![stable(feature = "proc_macro_lib", since = "1.15.0")]
28 #![crate_type = "rlib"]
29 #![crate_type = "dylib"]
31 #![deny(missing_docs)]
32 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
33 html_favicon_url
= "https://doc.rust-lang.org/favicon.ico",
34 html_root_url
= "https://doc.rust-lang.org/nightly/",
35 html_playground_url
= "https://play.rust-lang.org/",
36 issue_tracker_base_url
= "https://github.com/rust-lang/rust/issues/",
37 test(no_crate_inject
, attr(deny(warnings
))),
38 test(attr(allow(dead_code
, deprecated
, unused_variables
, unused_mut
))))]
40 #![feature(rustc_private)]
41 #![feature(staged_api)]
42 #![feature(lang_items)]
47 use std
::str::FromStr
;
49 use syntax
::errors
::DiagnosticBuilder
;
51 use syntax
::tokenstream
::TokenStream
as TokenStream_
;
53 /// The main type provided by this crate, representing an abstract stream of
56 /// This is both the input and output of `#[proc_macro_derive]` definitions.
57 /// Currently it's required to be a list of valid Rust items, but this
58 /// restriction may be lifted in the future.
60 /// The API of this type is intentionally bare-bones, but it'll be expanded over
62 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
63 pub struct TokenStream
{
67 /// Error returned from `TokenStream::from_str`.
69 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
74 /// Permanently unstable internal implementation details of this crate. This
75 /// should not be used.
77 /// These methods are used by the rest of the compiler to generate instances of
78 /// `TokenStream` to hand to macro definitions, as well as consume the output.
80 /// Note that this module is also intentionally separate from the rest of the
81 /// crate. This allows the `#[unstable]` directive below to naturally apply to
82 /// all of the contents.
83 #[unstable(feature = "proc_macro_internals", issue = "27812")]
91 use syntax
::parse
::{self, token, ParseSess}
;
92 use syntax
::tokenstream
::{TokenTree, TokenStream as TokenStream_}
;
94 use super::{TokenStream, LexError}
;
96 pub fn new_token_stream(item
: P
<ast
::Item
>) -> TokenStream
{
98 inner
: TokenTree
::Token(item
.span
, token
::Interpolated(Rc
::new(token
::NtItem(item
))))
103 pub fn token_stream_wrap(inner
: TokenStream_
) -> TokenStream
{
109 pub fn token_stream_parse_items(stream
: TokenStream
) -> Result
<Vec
<P
<ast
::Item
>>, LexError
> {
110 with_parse_sess(move |sess
| {
111 let mut parser
= parse
::stream_to_parser(sess
, stream
.inner
);
112 let mut items
= Vec
::new();
114 while let Some(item
) = try
!(parser
.parse_item().map_err(super::parse_to_lex_err
)) {
122 pub fn token_stream_inner(stream
: TokenStream
) -> TokenStream_
{
127 fn register_custom_derive(&mut self,
129 expand
: fn(TokenStream
) -> TokenStream
,
130 attributes
: &[&'
static str]);
132 fn register_attr_proc_macro(&mut self,
134 expand
: fn(TokenStream
, TokenStream
) -> TokenStream
);
136 fn register_bang_proc_macro(&mut self,
138 expand
: fn(TokenStream
) -> TokenStream
);
141 // Emulate scoped_thread_local!() here essentially
143 static CURRENT_SESS
: Cell
<*const ParseSess
> = Cell
::new(0 as *const _
);
146 pub fn set_parse_sess
<F
, R
>(sess
: &ParseSess
, f
: F
) -> R
147 where F
: FnOnce() -> R
149 struct Reset { prev: *const ParseSess }
151 impl Drop
for Reset
{
153 CURRENT_SESS
.with(|p
| p
.set(self.prev
));
157 CURRENT_SESS
.with(|p
| {
158 let _reset
= Reset { prev: p.get() }
;
164 pub fn with_parse_sess
<F
, R
>(f
: F
) -> R
165 where F
: FnOnce(&ParseSess
) -> R
167 let p
= CURRENT_SESS
.with(|p
| p
.get());
168 assert
!(!p
.is_null(), "proc_macro::__internal::with_parse_sess() called \
169 before set_parse_sess()!");
174 fn parse_to_lex_err(mut err
: DiagnosticBuilder
) -> LexError
{
176 LexError { _inner: () }
179 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
180 impl FromStr
for TokenStream
{
183 fn from_str(src
: &str) -> Result
<TokenStream
, LexError
> {
184 __internal
::with_parse_sess(|sess
| {
185 let src
= src
.to_string();
186 let name
= "<proc-macro source code>".to_string();
187 let stream
= parse
::parse_stream_from_source_str(name
, src
, sess
);
188 Ok(__internal
::token_stream_wrap(stream
))
193 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
194 impl fmt
::Display
for TokenStream
{
195 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{