From b766fa887dc0e4b923a38751fe4d570e35a75710 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 6 Dec 2017 20:30:40 -0800 Subject: [PATCH] Add example of making an unhygienic macro hygienic by wrapping it in a declarative macro. --- .../run-pass/hygiene/auxiliary/my_crate.rs | 11 +++++ .../hygiene/auxiliary/unhygienic_example.rs | 37 ++++++++++++++++ .../hygiene/wrap_unhygienic_example.rs | 43 +++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 src/test/run-pass/hygiene/auxiliary/my_crate.rs create mode 100644 src/test/run-pass/hygiene/auxiliary/unhygienic_example.rs create mode 100644 src/test/run-pass/hygiene/wrap_unhygienic_example.rs diff --git a/src/test/run-pass/hygiene/auxiliary/my_crate.rs b/src/test/run-pass/hygiene/auxiliary/my_crate.rs new file mode 100644 index 00000000000..e10d20b6d47 --- /dev/null +++ b/src/test/run-pass/hygiene/auxiliary/my_crate.rs @@ -0,0 +1,11 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn f() {} diff --git a/src/test/run-pass/hygiene/auxiliary/unhygienic_example.rs b/src/test/run-pass/hygiene/auxiliary/unhygienic_example.rs new file mode 100644 index 00000000000..298e0209a09 --- /dev/null +++ b/src/test/run-pass/hygiene/auxiliary/unhygienic_example.rs @@ -0,0 +1,37 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "lib"] + +extern crate my_crate; + +pub fn g() {} // (a) + +#[macro_export] +macro_rules! unhygienic_macro { + () => { + // (1) unhygienic: depends on `my_crate` in the crate root at the invocation site. + ::my_crate::f(); + + // (2) unhygienic: defines `f` at the invocation site (in addition to the above point). + use my_crate::f; + f(); + + g(); // (3) unhygienic: `g` needs to be in scope at use site. + + $crate::g(); // (4) hygienic: this always resolves to (a) + } +} + +#[allow(unused)] +fn test_unhygienic() { + unhygienic_macro!(); + f(); // `f` was defined at the use site +} diff --git a/src/test/run-pass/hygiene/wrap_unhygienic_example.rs b/src/test/run-pass/hygiene/wrap_unhygienic_example.rs new file mode 100644 index 00000000000..55206950214 --- /dev/null +++ b/src/test/run-pass/hygiene/wrap_unhygienic_example.rs @@ -0,0 +1,43 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-pretty pretty-printing is unhygienic + +// aux-build:my_crate.rs +// aux-build:unhygienic_example.rs + +#![feature(decl_macro)] + +extern crate unhygienic_example; +extern crate my_crate; // (b) + +// Hygienic version of `unhygienic_macro`. +pub macro hygienic_macro() { + fn g() {} // (c) + ::unhygienic_example::unhygienic_macro!(); + // ^ Even though we invoke an unhygienic macro, `hygienic_macro` remains hygienic. + // In the above expansion: + // (1) `my_crate` always resolves to (b) regardless of invocation site. + // (2) The defined function `f` is only usable inside this macro definition. + // (3) `g` always resolves to (c) regardless of invocation site. + // (4) `$crate::g` remains hygienic and continues to resolve to (a). + + f(); +} + +#[allow(unused)] +fn test_hygienic_macro() { + hygienic_macro!(); + + fn f() {} // (d) no conflict + f(); // resolves to (d) +} + +fn main() {} -- GitLab