Skip to content

Commit b766fa8

Browse files
committed
Add example of making an unhygienic macro hygienic by wrapping it in a declarative macro.
1 parent d052d28 commit b766fa8

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2017 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.
4+
//
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.
10+
11+
pub fn f() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2017 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.
4+
//
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.
10+
11+
#![crate_type = "lib"]
12+
13+
extern crate my_crate;
14+
15+
pub fn g() {} // (a)
16+
17+
#[macro_export]
18+
macro_rules! unhygienic_macro {
19+
() => {
20+
// (1) unhygienic: depends on `my_crate` in the crate root at the invocation site.
21+
::my_crate::f();
22+
23+
// (2) unhygienic: defines `f` at the invocation site (in addition to the above point).
24+
use my_crate::f;
25+
f();
26+
27+
g(); // (3) unhygienic: `g` needs to be in scope at use site.
28+
29+
$crate::g(); // (4) hygienic: this always resolves to (a)
30+
}
31+
}
32+
33+
#[allow(unused)]
34+
fn test_unhygienic() {
35+
unhygienic_macro!();
36+
f(); // `f` was defined at the use site
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2017 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.
4+
//
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.
10+
11+
// ignore-pretty pretty-printing is unhygienic
12+
13+
// aux-build:my_crate.rs
14+
// aux-build:unhygienic_example.rs
15+
16+
#![feature(decl_macro)]
17+
18+
extern crate unhygienic_example;
19+
extern crate my_crate; // (b)
20+
21+
// Hygienic version of `unhygienic_macro`.
22+
pub macro hygienic_macro() {
23+
fn g() {} // (c)
24+
::unhygienic_example::unhygienic_macro!();
25+
// ^ Even though we invoke an unhygienic macro, `hygienic_macro` remains hygienic.
26+
// In the above expansion:
27+
// (1) `my_crate` always resolves to (b) regardless of invocation site.
28+
// (2) The defined function `f` is only usable inside this macro definition.
29+
// (3) `g` always resolves to (c) regardless of invocation site.
30+
// (4) `$crate::g` remains hygienic and continues to resolve to (a).
31+
32+
f();
33+
}
34+
35+
#[allow(unused)]
36+
fn test_hygienic_macro() {
37+
hygienic_macro!();
38+
39+
fn f() {} // (d) no conflict
40+
f(); // resolves to (d)
41+
}
42+
43+
fn main() {}

0 commit comments

Comments
 (0)