Explain post-1.30 purpose of this crate

This commit is contained in:
David Tolnay 2019-01-19 19:53:10 -08:00
parent fd8cdc8a88
commit 7aa1c9cf0e
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
2 changed files with 105 additions and 50 deletions

View File

@ -4,56 +4,73 @@
[![Latest Version](https://img.shields.io/crates/v/proc-macro2.svg)](https://crates.io/crates/proc-macro2)
[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/proc-macro2)
A small shim over the `proc_macro` crate in the compiler intended to multiplex
the stable interface as of 1.15.0 and the interface as of 1.30.0.
A wrapper around the procedural macro API of the compiler's `proc_macro` crate.
This library serves three purposes:
New features added in Rust 1.30.0 include:
- **Bring proc-macro-like functionality to other contexts like build.rs and
main.rs.** Types from `proc_macro` are entirely specific to procedural macros
and cannot ever exist in code outside of a procedural macro. Meanwhile
`proc_macro2` types may exist anywhere including non-macro code. By developing
foundational libraries like [syn] and [quote] against `proc_macro2` rather
than `proc_macro`, the procedural macro ecosystem becomes easily applicable to
many other use cases and we avoid reimplementing non-macro equivalents of
those libraries.
* Span information on tokens
* No need to go in/out through strings
* Structured input/output
- **Make procedural macros unit testable.** As a consequence of being specific
to procedural macros, nothing that uses `proc_macro` can be executed from a
unit test. In order for helper libraries or components of a macro to be
testable in isolation, they must be implemented using `proc_macro2`.
Libraries ported to `proc_macro2` can retain support for older compilers while
continuing to get all the nice benefits of using a 1.30.0+ compiler.
- **Provide the latest and greatest APIs across all compiler versions.**
Procedural macros were first introduced to Rust in 1.15.0 with an extremely
minimal interface. Since then, many improvements have landed to make macros
more flexible and easier to write. This library tracks the procedural macro
API of the most recent stable compiler but employs a polyfill to provide that
API consistently across any compiler since 1.15.0.
[syn]: https://github.com/dtolnay/syn
[quote]: https://github.com/dtolnay/quote
## Usage
This crate compiles on all 1.15.0+ stable compilers and usage looks like:
```toml
[dependencies]
proc-macro2 = "0.4"
```
followed by
The skeleton of a typical procedural macro typically looks like this:
```rust
extern crate proc_macro;
#[proc_macro_derive(MyDerive)]
pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input: proc_macro2::TokenStream = input.into();
let input = proc_macro2::TokenStream::from(input);
let output: proc_macro2::TokenStream = {
/* transform input */
};
output.into()
proc_macro::TokenStream::from(output)
}
```
The 1.30.0 compiler is automatically detected and its interfaces are used when
available.
If parsing with [Syn], you'll use [`parse_macro_input!`] instead to propagate
parse errors correctly back to the compiler when parsing fails.
## Unstable Features
[`parse_macro_input!`]: https://docs.rs/syn/0.15/syn/macro.parse_macro_input.html
`proc-macro2` supports exporting some methods from `proc_macro` which are
currently highly unstable, and are not stabilized in the first pass of
`proc_macro` stabilizations. These features are not exported by default. Minor
versions of `proc-macro2` may make breaking changes to them at any time.
## Unstable features
To enable these features, the `procmacro2_semver_exempt` config flag must be
passed to rustc.
The default feature set of proc-macro2 tracks the most recent stable compiler
API. Functionality in `proc_macro` that is not yet stable is not exposed by
proc-macro2 by default.
To opt into the additional APIs available in the most recent nightly compiler,
the `procmacro2_semver_exempt` config flag must be passed to rustc. As usual, we
will polyfill those nightly-only APIs all the way back to Rust 1.15.0. As these
are unstable APIs that track the nightly compiler, minor versions of proc-macro2
may make breaking changes to them at any time.
```
RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build
@ -63,6 +80,8 @@ Note that this must not only be done for your crate, but for any crate that
depends on your crate. This infectious nature is intentional, as it serves as a
reminder that you are outside of the normal semver guarantees.
Semver exempt methods are marked as such in the proc-macro2 documentation.
# License
This project is licensed under either of

View File

@ -1,35 +1,72 @@
//! A "shim crate" intended to multiplex the [`proc_macro`] API on to stable
//! Rust.
//! A wrapper around the procedural macro API of the compiler's [`proc_macro`]
//! crate. This library serves three purposes:
//!
//! Procedural macros in Rust operate over the upstream
//! [`proc_macro::TokenStream`][ts] type. This type currently is quite
//! conservative and exposed no internal implementation details. Nightly
//! compilers, however, contain a much richer interface. This richer interface
//! allows fine-grained inspection of the token stream which avoids
//! stringification/re-lexing and also preserves span information.
//! [`proc_macro`]: https://doc.rust-lang.org/proc_macro/
//!
//! The upcoming APIs added to [`proc_macro`] upstream are the foundation for
//! productive procedural macros in the ecosystem. To help prepare the ecosystem
//! for using them this crate serves to both compile on stable and nightly and
//! mirrors the API-to-be. The intention is that procedural macros which switch
//! to use this crate will be trivially able to switch to the upstream
//! `proc_macro` crate once its API stabilizes.
//! - **Bring proc-macro-like functionality to other contexts like build.rs and
//! main.rs.** Types from `proc_macro` are entirely specific to procedural
//! macros and cannot ever exist in code outside of a procedural macro.
//! Meanwhile `proc_macro2` types may exist anywhere including non-macro code.
//! By developing foundational libraries like [syn] and [quote] against
//! `proc_macro2` rather than `proc_macro`, the procedural macro ecosystem
//! becomes easily applicable to many other use cases and we avoid
//! reimplementing non-macro equivalents of those libraries.
//!
//! In the meantime this crate also has a `nightly` Cargo feature which
//! enables it to reimplement itself with the unstable API of [`proc_macro`].
//! This'll allow immediate usage of the beneficial upstream API, particularly
//! around preserving span information.
//! - **Make procedural macros unit testable.** As a consequence of being
//! specific to procedural macros, nothing that uses `proc_macro` can be
//! executed from a unit test. In order for helper libraries or components of
//! a macro to be testable in isolation, they must be implemented using
//! `proc_macro2`.
//!
//! # Unstable Features
//! - **Provide the latest and greatest APIs across all compiler versions.**
//! Procedural macros were first introduced to Rust in 1.15.0 with an
//! extremely minimal interface. Since then, many improvements have landed to
//! make macros more flexible and easier to write. This library tracks the
//! procedural macro API of the most recent stable compiler but employs a
//! polyfill to provide that API consistently across any compiler since
//! 1.15.0.
//!
//! `proc-macro2` supports exporting some methods from `proc_macro` which are
//! currently highly unstable, and may not be stabilized in the first pass of
//! `proc_macro` stabilizations. These features are not exported by default.
//! Minor versions of `proc-macro2` may make breaking changes to them at any
//! time.
//! [syn]: https://github.com/dtolnay/syn
//! [quote]: https://github.com/dtolnay/quote
//!
//! To enable these features, the `procmacro2_semver_exempt` config flag must be
//! passed to rustc.
//! # Usage
//!
//! The skeleton of a typical procedural macro typically looks like this:
//!
//! ```edition2018
//! extern crate proc_macro;
//!
//! # const IGNORE: &str = stringify! {
//! #[proc_macro_derive(MyDerive)]
//! # };
//! pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
//! let input = proc_macro2::TokenStream::from(input);
//!
//! let output: proc_macro2::TokenStream = {
//! /* transform input */
//! # input
//! };
//!
//! proc_macro::TokenStream::from(output)
//! }
//! ```
//!
//! If parsing with [Syn], you'll use [`parse_macro_input!`] instead to
//! propagate parse errors correctly back to the compiler when parsing fails.
//!
//! [`parse_macro_input!`]: https://docs.rs/syn/0.15/syn/macro.parse_macro_input.html
//!
//! # Unstable features
//!
//! The default feature set of proc-macro2 tracks the most recent stable
//! compiler API. Functionality in `proc_macro` that is not yet stable is not
//! exposed by proc-macro2 by default.
//!
//! To opt into the additional APIs available in the most recent nightly
//! compiler, the `procmacro2_semver_exempt` config flag must be passed to
//! rustc. As usual, we will polyfill those nightly-only APIs all the way back
//! to Rust 1.15.0. As these are unstable APIs that track the nightly compiler,
//! minor versions of proc-macro2 may make breaking changes to them at any time.
//!
//! ```sh
//! RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build
@ -39,8 +76,7 @@
//! depends on your crate. This infectious nature is intentional, as it serves
//! as a reminder that you are outside of the normal semver guarantees.
//!
//! [`proc_macro`]: https://doc.rust-lang.org/proc_macro/
//! [ts]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html
//! Semver exempt methods are marked as such in the proc-macro2 documentation.
// Proc-macro2 types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/proc-macro2/0.4.25")]