about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorJohn Renner <john@jrenner.net>2018-07-24 17:51:37 -0700
committerJohn Renner <john@jrenner.net>2018-07-30 19:23:24 -0700
commitf76049cd6abd1964999764e5cf596748d29792b4 (patch)
treef249f4bd0ebcccbb5c9322862cf8dc2ee99436be /src
parent487e961c6ae072d969e148def0b0856c2367ae00 (diff)
downloadrust-f76049cd6abd1964999764e5cf596748d29792b4.tar.gz
rust-f76049cd6abd1964999764e5cf596748d29792b4.zip
Reexport tests without polluting namespaces
Diffstat (limited to 'src')
-rw-r--r--src/libsyntax/ext/expand.rs20
-rw-r--r--src/test/run-pass/issue-52557.rs33
2 files changed, 52 insertions, 1 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index b84046d1050..4b17ca87d87 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -15,6 +15,7 @@ use codemap::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan};
 use config::{is_test_or_bench, StripUnconfigured};
 use errors::{Applicability, FatalError};
 use ext::base::*;
+use ext::build::AstBuilder;
 use ext::derive::{add_derived_markers, collect_derives};
 use ext::hygiene::{self, Mark, SyntaxContext};
 use ext::placeholders::{placeholder, PlaceholderExpander};
@@ -1354,12 +1355,29 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
             // Ensure that test functions are accessible from the test harness.
             ast::ItemKind::Fn(..) if self.cx.ecfg.should_test => {
                 if item.attrs.iter().any(|attr| is_test_or_bench(attr)) {
+                    let orig_vis = item.vis.clone();
+
+                    // Publicize the item under gensymed name to avoid pollution
                     item = item.map(|mut item| {
                         item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
+                        item.ident = Ident::from_interned_str(
+                                                item.ident.as_interned_str()).gensym();
                         item
                     });
+
+                    // Use the gensymed name under the item's original visibility
+                    let use_item = self.cx.item_use_simple_(
+                        item.ident.span,
+                        orig_vis,
+                        Some(Ident::from_interned_str(item.ident.as_interned_str())),
+                        self.cx.path(item.ident.span, vec![item.ident]));
+
+                    SmallVector::many(
+                        noop_fold_item(item, self).into_iter()
+                            .chain(noop_fold_item(use_item, self)))
+                } else {
+                    noop_fold_item(item, self)
                 }
-                noop_fold_item(item, self)
             }
             _ => noop_fold_item(item, self),
         }
diff --git a/src/test/run-pass/issue-52557.rs b/src/test/run-pass/issue-52557.rs
new file mode 100644
index 00000000000..d6d272b5fad
--- /dev/null
+++ b/src/test/run-pass/issue-52557.rs
@@ -0,0 +1,33 @@
+// Copyright 2015 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test checks for namespace pollution by private tests.
+// Tests used to marked as public causing name conflicts with normal
+// functions only in test builds.
+
+// compile-flags: --test
+
+mod a {
+    pub fn foo() -> bool {
+        true
+    }
+}
+
+mod b {
+    #[test]
+    fn foo() {}
+}
+
+use a::*;
+use b::*;
+
+fn conflict() {
+    let _: bool = foo();
+}
\ No newline at end of file