Skip to content

Commit 5ad9b4e

Browse files
authored
Merge pull request dtolnay#120 from alexcrichton/autodetect
Automatically use rich API on 1.30.0+
2 parents ff8e52f + ce0904d commit 5ad9b4e

File tree

4 files changed

+73
-39
lines changed

4 files changed

+73
-39
lines changed

README.md

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,20 @@
55
[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/proc-macro2)
66

77
A small shim over the `proc_macro` crate in the compiler intended to multiplex
8-
the current stable interface (as of 2017-07-05) and the [upcoming richer
9-
interface][upcoming].
8+
the stable interface as of 1.15.0 and the interface as of 1.30.0.
109

11-
[upcoming]: https://github.com/rust-lang/rust/pull/40939
12-
13-
The upcoming support has features like:
10+
New features added in Rust 1.30.0 include:
1411

1512
* Span information on tokens
1613
* No need to go in/out through strings
1714
* Structured input/output
1815

19-
The hope is that libraries ported to `proc_macro2` will be trivial to port to
20-
the real `proc_macro` crate once the support on nightly is stabilized.
16+
Libraries ported to `proc_macro2` can retain support for older compilers while
17+
continuing to get all the nice benefits of using a 1.30.0+ compiler.
2118

2219
## Usage
2320

24-
This crate by default compiles on the stable version of the compiler. It only
25-
uses the stable surface area of the `proc_macro` crate upstream in the compiler
26-
itself. Usage is done via:
21+
This crate compiles on all 1.15.0+ stable compilers and usage looks like:
2722

2823
```toml
2924
[dependencies]
@@ -48,23 +43,13 @@ pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
4843
}
4944
```
5045

51-
If you'd like you can enable the `nightly` feature in this crate. This will
52-
cause it to compile against the **unstable and nightly-only** features of the
53-
`proc_macro` crate. This in turn requires a nightly compiler. This should help
54-
preserve span information, however, coming in from the compiler itself.
55-
56-
You can enable this feature via:
57-
58-
```toml
59-
[dependencies]
60-
proc-macro2 = { version = "0.4", features = ["nightly"] }
61-
```
62-
46+
The 1.30.0 compiler is automatically detected and its interfaces are used when
47+
available.
6348

6449
## Unstable Features
6550

6651
`proc-macro2` supports exporting some methods from `proc_macro` which are
67-
currently highly unstable, and may not be stabilized in the first pass of
52+
currently highly unstable, and are not stabilized in the first pass of
6853
`proc_macro` stabilizations. These features are not exported by default. Minor
6954
versions of `proc-macro2` may make breaking changes to them at any time.
7055

@@ -79,7 +64,6 @@ Note that this must not only be done for your crate, but for any crate that
7964
depends on your crate. This infectious nature is intentional, as it serves as a
8065
reminder that you are outside of the normal semver guarantees.
8166

82-
8367
# License
8468

8569
This project is licensed under either of

build.rs

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,53 @@
11
use std::env;
2+
use std::process::Command;
3+
use std::str;
24

35
fn main() {
46
println!("cargo:rerun-if-changed=build.rs");
57

68
let target = env::var("TARGET").unwrap();
79

8-
maybe_enable_use_proc_macro(&target);
10+
if !enable_use_proc_macro(&target) {
11+
return
12+
}
13+
println!("cargo:rustc-cfg=use_proc_macro");
14+
15+
let minor = match rustc_minor_version() {
16+
Some(n) => n,
17+
None => return,
18+
};
19+
20+
// Rust 1.30 stabilized the necessary APIs in the `proc_macro` crate
21+
if minor >= 30 || cfg!(feature = "nightly") {
22+
println!("cargo:rustc-cfg=wrap_proc_macro");
23+
24+
if cfg!(procmacro2_semver_exempt) {
25+
println!("cargo:rustc-cfg=super_unstable");
26+
}
27+
} else {
28+
}
929
}
1030

11-
fn maybe_enable_use_proc_macro(target: &str) {
31+
fn enable_use_proc_macro(target: &str) -> bool {
1232
// wasm targets don't have the `proc_macro` crate, disable this feature.
1333
if target.contains("wasm32") {
14-
return;
34+
return false;
1535
}
1636

1737
// Otherwise, only enable it if our feature is actually enabled.
18-
if cfg!(feature = "proc-macro") {
19-
println!("cargo:rustc-cfg=use_proc_macro");
38+
cfg!(feature = "proc-macro")
39+
}
40+
41+
fn rustc_minor_version() -> Option<u32> {
42+
macro_rules! otry {
43+
($e:expr) => (match $e { Some(e) => e, None => return None })
44+
}
45+
let rustc = otry!(env::var_os("RUSTC"));
46+
let output = otry!(Command::new(rustc).arg("--version").output().ok());
47+
let version = otry!(str::from_utf8(&output.stdout).ok());
48+
let mut pieces = version.split('.');
49+
if pieces.next() != Some("rustc 1") {
50+
return None;
2051
}
52+
otry!(pieces.next()).parse().ok()
2153
}

src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
// Proc-macro2 types in rustdoc of other crates get linked to here.
4646
#![doc(html_root_url = "https://docs.rs/proc-macro2/0.4.13")]
4747
#![cfg_attr(
48-
feature = "nightly",
48+
super_unstable,
4949
feature(proc_macro_raw_ident, proc_macro_span)
5050
)]
5151

@@ -65,10 +65,10 @@ use std::str::FromStr;
6565
mod strnom;
6666
mod stable;
6767

68-
#[cfg(not(feature = "nightly"))]
68+
#[cfg(not(wrap_proc_macro))]
6969
use stable as imp;
7070
#[path = "unstable.rs"]
71-
#[cfg(feature = "nightly")]
71+
#[cfg(wrap_proc_macro)]
7272
mod imp;
7373

7474
/// An abstract stream of tokens, or more concretely a sequence of token trees.
@@ -328,7 +328,7 @@ impl Span {
328328
}
329329

330330
/// This method is only available when the `"nightly"` feature is enabled.
331-
#[cfg(all(feature = "nightly", use_proc_macro))]
331+
#[cfg(super_unstable)]
332332
pub fn unstable(self) -> proc_macro::Span {
333333
self.inner.unstable()
334334
}

src/unstable.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![cfg_attr(not(procmacro2_semver_exempt), allow(dead_code))]
1+
#![cfg_attr(not(super_unstable), allow(dead_code))]
22

33
use std::fmt;
44
use std::iter;
@@ -292,11 +292,13 @@ pub use stable::FileName;
292292
// NOTE: We have to generate our own filename object here because we can't wrap
293293
// the one provided by proc_macro.
294294
#[derive(Clone, PartialEq, Eq)]
295+
#[cfg(super_unstable)]
295296
pub enum SourceFile {
296297
Nightly(proc_macro::SourceFile, FileName),
297298
Stable(stable::SourceFile),
298299
}
299300

301+
#[cfg(super_unstable)]
300302
impl SourceFile {
301303
fn nightly(sf: proc_macro::SourceFile) -> Self {
302304
let filename = stable::file_name(sf.path().display().to_string());
@@ -319,12 +321,14 @@ impl SourceFile {
319321
}
320322
}
321323

324+
#[cfg(super_unstable)]
322325
impl AsRef<FileName> for SourceFile {
323326
fn as_ref(&self) -> &FileName {
324327
self.path()
325328
}
326329
}
327330

331+
#[cfg(super_unstable)]
328332
impl fmt::Debug for SourceFile {
329333
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
330334
match self {
@@ -354,6 +358,7 @@ impl Span {
354358
}
355359
}
356360

361+
#[cfg(super_unstable)]
357362
pub fn def_site() -> Span {
358363
if nightly_works() {
359364
Span::Nightly(proc_macro::Span::def_site())
@@ -362,6 +367,7 @@ impl Span {
362367
}
363368
}
364369

370+
#[cfg(super_unstable)]
365371
pub fn resolved_at(&self, other: Span) -> Span {
366372
match (self, other) {
367373
(Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.resolved_at(b)),
@@ -370,6 +376,7 @@ impl Span {
370376
}
371377
}
372378

379+
#[cfg(super_unstable)]
373380
pub fn located_at(&self, other: Span) -> Span {
374381
match (self, other) {
375382
(Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.located_at(b)),
@@ -385,15 +392,15 @@ impl Span {
385392
}
386393
}
387394

388-
#[cfg(procmacro2_semver_exempt)]
395+
#[cfg(super_unstable)]
389396
pub fn source_file(&self) -> SourceFile {
390397
match self {
391398
Span::Nightly(s) => SourceFile::nightly(s.source_file()),
392399
Span::Stable(s) => SourceFile::Stable(s.source_file()),
393400
}
394401
}
395402

396-
#[cfg(procmacro2_semver_exempt)]
403+
#[cfg(super_unstable)]
397404
pub fn start(&self) -> LineColumn {
398405
match self {
399406
Span::Nightly(s) => {
@@ -407,7 +414,7 @@ impl Span {
407414
}
408415
}
409416

410-
#[cfg(procmacro2_semver_exempt)]
417+
#[cfg(super_unstable)]
411418
pub fn end(&self) -> LineColumn {
412419
match self {
413420
Span::Nightly(s) => {
@@ -421,7 +428,7 @@ impl Span {
421428
}
422429
}
423430

424-
#[cfg(procmacro2_semver_exempt)]
431+
#[cfg(super_unstable)]
425432
pub fn join(&self, other: Span) -> Option<Span> {
426433
let ret = match (self, other) {
427434
(Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.join(b)?),
@@ -431,6 +438,7 @@ impl Span {
431438
Some(ret)
432439
}
433440

441+
#[cfg(super_unstable)]
434442
pub fn eq(&self, other: &Span) -> bool {
435443
match (self, other) {
436444
(Span::Nightly(a), Span::Nightly(b)) => a.eq(b),
@@ -484,7 +492,17 @@ impl Ident {
484492

485493
pub fn new_raw(string: &str, span: Span) -> Ident {
486494
match span {
487-
Span::Nightly(s) => Ident::Nightly(proc_macro::Ident::new_raw(string, s)),
495+
Span::Nightly(s) => {
496+
let p: proc_macro::TokenStream = string.parse().unwrap();
497+
let ident = match p.into_iter().next() {
498+
Some(proc_macro::TokenTree::Ident(mut i)) => {
499+
i.set_span(s);
500+
i
501+
}
502+
_ => panic!(),
503+
};
504+
Ident::Nightly(ident)
505+
}
488506
Span::Stable(s) => Ident::Stable(stable::Ident::new_raw(string, s)),
489507
}
490508
}

0 commit comments

Comments
 (0)