about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2013-07-17 14:23:17 +1000
committerHuon Wilson <dbau.pp+github@gmail.com>2013-07-17 15:01:02 +1000
commit040e470f475944a355101aa89e9ec447c10b0caa (patch)
tree02dee1f1f978752cb83668c3856f52a91e8f5776
parent8a1002fbd93989bbf5c8989ed8002827920b375b (diff)
downloadrust-040e470f475944a355101aa89e9ec447c10b0caa.tar.gz
rust-040e470f475944a355101aa89e9ec447c10b0caa.zip
rustc: implement a `#[no_implicit_prelude]` attribute.
It disables the insertion of `use std::prelude::*;` into the top of
all the modules below the item on which it is placed (including that
item itself).
-rw-r--r--src/librustc/front/std_inject.rs20
-rw-r--r--src/test/compile-fail/no-implicit-prelude-nested.rs68
-rw-r--r--src/test/compile-fail/no-implicit-prelude.rs29
3 files changed, 116 insertions, 1 deletions
diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs
index 45169a2f656..ee0ce32bfec 100644
--- a/src/librustc/front/std_inject.rs
+++ b/src/librustc/front/std_inject.rs
@@ -32,6 +32,9 @@ pub fn maybe_inject_libstd_ref(sess: Session, crate: @ast::crate)
 fn use_std(crate: &ast::crate) -> bool {
     !attr::attrs_contains_name(crate.node.attrs, "no_std")
 }
+fn no_prelude(attrs: &[ast::attribute]) -> bool {
+    attr::attrs_contains_name(attrs, "no_implicit_prelude")
+}
 
 fn inject_libstd_ref(sess: Session, crate: &ast::crate) -> @ast::crate {
     fn spanned<T:Copy>(x: T) -> codemap::spanned<T> {
@@ -63,7 +66,12 @@ fn inject_libstd_ref(sess: Session, crate: &ast::crate) -> @ast::crate {
                 view_items: vis,
                 ../*bad*/copy crate.module
             };
-            new_module = fld.fold_mod(&new_module);
+
+            if !no_prelude(crate.attrs) {
+                // only add `use std::prelude::*;` if there wasn't a
+                // `#[no_implicit_prelude];` at the crate level.
+                new_module = fld.fold_mod(&new_module);
+            }
 
             // FIXME #2543: Bad copy.
             let new_crate = ast::crate_ {
@@ -72,6 +80,16 @@ fn inject_libstd_ref(sess: Session, crate: &ast::crate) -> @ast::crate {
             };
             (new_crate, span)
         },
+        fold_item: |item, fld| {
+            if !no_prelude(item.attrs) {
+                // only recur if there wasn't `#[no_implicit_prelude];`
+                // on this item, i.e. this means that the prelude is not
+                // implicitly imported though the whole subtree
+                fold::noop_fold_item(item, fld)
+            } else {
+                Some(item)
+            }
+        },
         fold_mod: |module, fld| {
             let n2 = sess.next_node_id();
 
diff --git a/src/test/compile-fail/no-implicit-prelude-nested.rs b/src/test/compile-fail/no-implicit-prelude-nested.rs
new file mode 100644
index 00000000000..e215407ec87
--- /dev/null
+++ b/src/test/compile-fail/no-implicit-prelude-nested.rs
@@ -0,0 +1,68 @@
+// Copyright 2013 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.
+
+// Test that things from the prelude aren't in scope. Use many of them
+// so that renaming some things won't magically make this test fail
+// for the wrong reason (e.g. if `Add` changes to `Addition`, and
+// `no_implicit_prelude` stops working, then the `impl Add` will still
+// fail with the same error message).
+
+#[no_implicit_prelude]
+mod foo {
+    mod baz {
+        struct Test;
+        impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
+        impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
+        impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
+        impl ToStr for Test {} //~ ERROR: attempt to implement a nonexistent trait
+        impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
+
+        fn foo() {
+            print("foo"); //~ ERROR: unresolved name
+            println("bar"); //~ ERROR: unresolved name
+        }
+    }
+
+    struct Test;
+    impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
+    impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
+    impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
+    impl ToStr for Test {} //~ ERROR: attempt to implement a nonexistent trait
+    impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
+
+    fn foo() {
+        print("foo"); //~ ERROR: unresolved name
+        println("bar"); //~ ERROR: unresolved name
+    }
+}
+
+fn qux() {
+    #[no_implicit_prelude]
+    mod qux_inner {
+        struct Test;
+        impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
+        impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
+        impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
+        impl ToStr for Test {} //~ ERROR: attempt to implement a nonexistent trait
+        impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
+
+        fn foo() {
+            print("foo"); //~ ERROR: unresolved name
+            println("bar"); //~ ERROR: unresolved name
+        }
+    }
+}
+
+
+fn main() {
+    // these should work fine
+    print("foo");
+    println("bar");
+}
diff --git a/src/test/compile-fail/no-implicit-prelude.rs b/src/test/compile-fail/no-implicit-prelude.rs
new file mode 100644
index 00000000000..ca4533a03c8
--- /dev/null
+++ b/src/test/compile-fail/no-implicit-prelude.rs
@@ -0,0 +1,29 @@
+// Copyright 2013 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.
+
+#[no_implicit_prelude];
+
+// Test that things from the prelude aren't in scope. Use many of them
+// so that renaming some things won't magically make this test fail
+// for the wrong reason (e.g. if `Add` changes to `Addition`, and
+// `no_implicit_prelude` stops working, then the `impl Add` will still
+// fail with the same error message).
+
+struct Test;
+impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
+impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
+impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
+impl ToStr for Test {} //~ ERROR: attempt to implement a nonexistent trait
+impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
+
+fn main() {
+    print("foo"); //~ ERROR: unresolved name
+    println("bar"); //~ ERROR: unresolved name
+}