diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 2f43940a9dcbb..5a27aaa888256 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -727,7 +727,7 @@ pub struct SyntaxExtension { /// Edition of the crate in which this macro is defined. pub edition: Edition, /// Built-in macros have a couple of special properties like availability - /// in `#[no_implicit_prelude]` modules, so we have to keep this flag. + /// in `#[no_prelude]` modules, so we have to keep this flag. pub builtin_name: Option, } diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 3b54ffbc3f08d..9c7d5712612aa 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -620,6 +620,9 @@ declare_features! ( /// Allows arbitrary expressions in key-value attributes at parse time. (active, extended_key_value_attributes, "1.50.0", Some(78835), None), + /// Allow #![no_prelude] to disable prelude for current module + (active, no_prelude, "1.51.0", Some(20561), None), + /// `:pat2018` and `:pat2021` macro matchers. (active, edition_macro_pats, "1.51.0", Some(54883), None), diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 3ed5320da73b3..3899d0a7c7977 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -253,6 +253,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(path, Normal, template!(NameValueStr: "file")), ungated!(no_std, CrateLevel, template!(Word)), ungated!(no_implicit_prelude, Normal, template!(Word)), + gated!( + no_prelude, Normal, template!(Word), + "experimental feature: replacement for #![no_implicit_prelude] that is not inherited by descendants" + ), ungated!(non_exhaustive, AssumedUsed, template!(Word)), // Runtime diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 4ab14c158d337..bbbdf44a1f041 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -761,10 +761,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ItemKind::Mod(..) => { let module_kind = ModuleKind::Def(DefKind::Mod, def_id, ident.name); + let inheritable_no_prelude = parent.pass_on_no_prelude + || self.r.session.contains_name(&item.attrs, sym::no_implicit_prelude); + let local_no_prelude = inheritable_no_prelude + || self.r.session.contains_name(&item.attrs, sym::no_prelude); let module = self.r.arenas.alloc_module(ModuleData { - no_implicit_prelude: parent.no_implicit_prelude || { - self.r.session.contains_name(&item.attrs, sym::no_implicit_prelude) - }, + pass_on_no_prelude: inheritable_no_prelude, + no_prelude: local_no_prelude, ..ModuleData::new(Some(parent), module_kind, def_id, expansion, item.span) }); self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 3945afb4724a8..25c4ef628516a 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1174,7 +1174,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { // We can see through blocks } else { // Items from the prelude - if !module.no_implicit_prelude { + if !module.no_prelude { let extern_prelude = self.r.extern_prelude.clone(); names.extend(extern_prelude.iter().flat_map(|(ident, _)| { self.r.crate_loader.maybe_process_path_extern(ident.name).and_then( diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index af5341623758a..371168c986960 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -493,7 +493,12 @@ pub struct ModuleData<'a> { unexpanded_invocations: RefCell>, /// Whether `#[no_implicit_prelude]` is active. - no_implicit_prelude: bool, + /// And should therefore be active in decendant modules + pass_on_no_prelude: bool, + + /// Whether `#[no_prelude]` or `#[no_implicit_prelude]` is active. + /// And therefore the current modul should use no prelude + no_prelude: bool, glob_importers: RefCell>>, globs: RefCell>>, @@ -524,7 +529,8 @@ impl<'a> ModuleData<'a> { lazy_resolutions: Default::default(), populate_on_access: Cell::new(!nearest_parent_mod.is_local()), unexpanded_invocations: Default::default(), - no_implicit_prelude: false, + pass_on_no_prelude: false, + no_prelude: false, glob_importers: RefCell::new(Vec::new()), globs: RefCell::new(Vec::new()), traits: RefCell::new(None), @@ -1207,13 +1213,18 @@ impl<'a> Resolver<'a> { let root_local_def_id = LocalDefId { local_def_index: CRATE_DEF_INDEX }; let root_def_id = root_local_def_id.to_def_id(); let root_module_kind = ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty); + let inheritable_no_prelude = session.contains_name(&krate.attrs, sym::no_implicit_prelude); + let local_no_prelude = + inheritable_no_prelude || session.contains_name(&krate.attrs, sym::no_prelude); let graph_root = arenas.alloc_module(ModuleData { - no_implicit_prelude: session.contains_name(&krate.attrs, sym::no_implicit_prelude), + pass_on_no_prelude: inheritable_no_prelude, + no_prelude: local_no_prelude, ..ModuleData::new(None, root_module_kind, root_def_id, ExpnId::root(), krate.span) }); let empty_module_kind = ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty); let empty_module = arenas.alloc_module(ModuleData { - no_implicit_prelude: true, + pass_on_no_prelude: true, + no_prelude: true, ..ModuleData::new( Some(graph_root), empty_module_kind, @@ -1724,7 +1735,7 @@ impl<'a> Resolver<'a> { MacroNS => Scope::DeriveHelpers(parent_scope.expansion), }; let mut ctxt = ctxt.normalize_to_macros_2_0(); - let mut use_prelude = !module.no_implicit_prelude; + let mut use_prelude = !module.no_prelude; loop { let visit = match scope { @@ -1795,7 +1806,7 @@ impl<'a> Resolver<'a> { ValueNS | MacroNS => break, }, Scope::Module(module) => { - use_prelude = !module.no_implicit_prelude; + use_prelude = !module.no_prelude; match self.hygienic_lexical_parent(module, &mut ctxt) { Some(parent_module) => Scope::Module(parent_module), None => { @@ -1967,7 +1978,7 @@ impl<'a> Resolver<'a> { } } - if !module.no_implicit_prelude { + if !module.no_prelude { ident.span.adjust(ExpnId::root()); if ns == TypeNS { if let Some(binding) = self.extern_prelude_get(ident, !record_used) { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 63f95a3908434..34be82198fbf2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -753,6 +753,7 @@ symbols! { no_main, no_mangle, no_niche, + no_prelude, no_sanitize, no_stack_check, no_start, diff --git a/src/test/ui/associated-types/associated-types-impl-redirect.rs b/src/test/ui/associated-types/associated-types-impl-redirect.rs index 8fa20cdf4b7a1..892347175ec38 100644 --- a/src/test/ui/associated-types/associated-types-impl-redirect.rs +++ b/src/test/ui/associated-types/associated-types-impl-redirect.rs @@ -8,8 +8,8 @@ // for `ByRef`. The right answer was to consider the result ambiguous // until more type information was available. -#![feature(lang_items)] -#![no_implicit_prelude] +#![feature(no_prelude, lang_items)] +#![no_prelude] use std::marker::Sized; use std::option::Option::{None, Some, self}; diff --git a/src/test/ui/associated-types/associated-types-issue-20346.rs b/src/test/ui/associated-types/associated-types-issue-20346.rs index 0cce847e1be54..fc7ad509816bb 100644 --- a/src/test/ui/associated-types/associated-types-issue-20346.rs +++ b/src/test/ui/associated-types/associated-types-issue-20346.rs @@ -1,7 +1,8 @@ // Test that we reliably check the value of the associated type. #![crate_type = "lib"] -#![no_implicit_prelude] +#![feature(no_prelude)] +#![no_prelude] use std::option::Option::{self, None, Some}; use std::vec::Vec; diff --git a/src/test/ui/associated-types/associated-types-issue-20346.stderr b/src/test/ui/associated-types/associated-types-issue-20346.stderr index 7193d4163b9ce..5711be43a8095 100644 --- a/src/test/ui/associated-types/associated-types-issue-20346.stderr +++ b/src/test/ui/associated-types/associated-types-issue-20346.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving ` as Iterator>::Item == Option` - --> $DIR/associated-types-issue-20346.rs:34:5 + --> $DIR/associated-types-issue-20346.rs:35:5 | LL | fn is_iterator_of>(_: &I) {} | ------ required by this bound in `is_iterator_of` diff --git a/src/test/ui/associated-types/associated-types-where-clause-impl-ambiguity.rs b/src/test/ui/associated-types/associated-types-where-clause-impl-ambiguity.rs index f2a4c6e42a93f..e5f234ad93961 100644 --- a/src/test/ui/associated-types/associated-types-where-clause-impl-ambiguity.rs +++ b/src/test/ui/associated-types/associated-types-where-clause-impl-ambiguity.rs @@ -7,8 +7,8 @@ // for `ByRef`. The right answer was to consider the result ambiguous // until more type information was available. -#![feature(lang_items)] -#![no_implicit_prelude] +#![feature(no_prelude, lang_items)] +#![no_prelude] use std::marker::Sized; use std::option::Option::{None, Some, self}; diff --git a/src/test/ui/attributes/no-prelude-nested.rs b/src/test/ui/attributes/no-prelude-nested.rs new file mode 100644 index 0000000000000..c90592b2b12c8 --- /dev/null +++ b/src/test/ui/attributes/no-prelude-nested.rs @@ -0,0 +1,63 @@ +#![feature(no_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_prelude` stops working, then the `impl Add` will still +// fail with the same error message). +// +// Unlike `no_implicit_prelude`, `no_prelude` doesn't cascade into nested +// modules, this makes the impl in foo::baz work. + +#[no_prelude] +mod foo { + mod baz { + struct Test; + impl From for Test { + fn from(t: Test) { + Test + } + } + impl Clone for Test { + fn clone(&self) { + Test + } + } + impl Eq for Test {} + + fn foo() { + drop(2) + } + } + + struct Test; + impl From for Test {} //~ ERROR: cannot find trait + impl Clone for Test {} //~ ERROR: expected trait, found derive macro + impl Iterator for Test {} //~ ERROR: cannot find trait + impl ToString for Test {} //~ ERROR: cannot find trait + impl Eq for Test {} //~ ERROR: expected trait, found derive macro + + fn foo() { + drop(2) //~ ERROR: cannot find function `drop` + } +} + +fn qux() { + #[no_prelude] + mod qux_inner { + struct Test; + impl From for Test {} //~ ERROR: cannot find trait + impl Clone for Test {} //~ ERROR: expected trait, found derive macro + impl Iterator for Test {} //~ ERROR: cannot find trait + impl ToString for Test {} //~ ERROR: cannot find trait + impl Eq for Test {} //~ ERROR: expected trait, found derive macro + fn foo() { + drop(2) //~ ERROR: cannot find function `drop` + } + } +} + +fn main() { + // these should work fine + drop(2) +} diff --git a/src/test/ui/attributes/no-prelude-nested.stderr b/src/test/ui/attributes/no-prelude-nested.stderr new file mode 100644 index 0000000000000..a59f9a8168c89 --- /dev/null +++ b/src/test/ui/attributes/no-prelude-nested.stderr @@ -0,0 +1,136 @@ +error[E0405]: cannot find trait `From` in this scope + --> $DIR/no-prelude-nested.rs:34:10 + | +LL | impl From for Test {} + | ^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::convert::From; + | + +error[E0404]: expected trait, found derive macro `Clone` + --> $DIR/no-prelude-nested.rs:35:10 + | +LL | impl Clone for Test {} + | ^^^^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::clone::Clone; + | + +error[E0405]: cannot find trait `Iterator` in this scope + --> $DIR/no-prelude-nested.rs:36:10 + | +LL | impl Iterator for Test {} + | ^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::iter::Iterator; + | + +error[E0405]: cannot find trait `ToString` in this scope + --> $DIR/no-prelude-nested.rs:37:10 + | +LL | impl ToString for Test {} + | ^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::string::ToString; + | + +error[E0404]: expected trait, found derive macro `Eq` + --> $DIR/no-prelude-nested.rs:38:10 + | +LL | impl Eq for Test {} + | ^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::cmp::Eq; + | + +error[E0425]: cannot find function `drop` in this scope + --> $DIR/no-prelude-nested.rs:41:9 + | +LL | drop(2) + | ^^^^ not found in this scope + | +help: consider importing this function + | +LL | use std::mem::drop; + | + +error[E0405]: cannot find trait `From` in this scope + --> $DIR/no-prelude-nested.rs:49:14 + | +LL | impl From for Test {} + | ^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::convert::From; + | + +error[E0404]: expected trait, found derive macro `Clone` + --> $DIR/no-prelude-nested.rs:50:14 + | +LL | impl Clone for Test {} + | ^^^^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::clone::Clone; + | + +error[E0405]: cannot find trait `Iterator` in this scope + --> $DIR/no-prelude-nested.rs:51:14 + | +LL | impl Iterator for Test {} + | ^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::iter::Iterator; + | + +error[E0405]: cannot find trait `ToString` in this scope + --> $DIR/no-prelude-nested.rs:52:14 + | +LL | impl ToString for Test {} + | ^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::string::ToString; + | + +error[E0404]: expected trait, found derive macro `Eq` + --> $DIR/no-prelude-nested.rs:53:14 + | +LL | impl Eq for Test {} + | ^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::cmp::Eq; + | + +error[E0425]: cannot find function `drop` in this scope + --> $DIR/no-prelude-nested.rs:55:13 + | +LL | drop(2) + | ^^^^ not found in this scope + | +help: consider importing this function + | +LL | use std::mem::drop; + | + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0404, E0405, E0425. +For more information about an error, try `rustc --explain E0404`. diff --git a/src/test/ui/attributes/no-prelude.rs b/src/test/ui/attributes/no-prelude.rs new file mode 100644 index 0000000000000..ab39a1d5dbd05 --- /dev/null +++ b/src/test/ui/attributes/no-prelude.rs @@ -0,0 +1,19 @@ +#![feature(no_prelude)] +#![no_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_prelude` stops working, then the `impl Add` will still +// fail with the same error message). + +struct Test; +impl Add for Test {} //~ ERROR: cannot find trait +impl Clone for Test {} //~ ERROR: expected trait, found derive macro +impl Iterator for Test {} //~ ERROR: cannot find trait +impl ToString for Test {} //~ ERROR: cannot find trait +impl Writer for Test {} //~ ERROR: cannot find trait + +fn main() { + drop(2) //~ ERROR: cannot find function `drop` +} diff --git a/src/test/ui/attributes/no-prelude.stderr b/src/test/ui/attributes/no-prelude.stderr new file mode 100644 index 0000000000000..b77dcfbaa5a9b --- /dev/null +++ b/src/test/ui/attributes/no-prelude.stderr @@ -0,0 +1,65 @@ +error[E0405]: cannot find trait `Add` in this scope + --> $DIR/no-prelude.rs:11:6 + | +LL | impl Add for Test {} + | ^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::ops::Add; + | + +error[E0404]: expected trait, found derive macro `Clone` + --> $DIR/no-prelude.rs:12:6 + | +LL | impl Clone for Test {} + | ^^^^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::clone::Clone; + | + +error[E0405]: cannot find trait `Iterator` in this scope + --> $DIR/no-prelude.rs:13:6 + | +LL | impl Iterator for Test {} + | ^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::iter::Iterator; + | + +error[E0405]: cannot find trait `ToString` in this scope + --> $DIR/no-prelude.rs:14:6 + | +LL | impl ToString for Test {} + | ^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::string::ToString; + | + +error[E0405]: cannot find trait `Writer` in this scope + --> $DIR/no-prelude.rs:15:6 + | +LL | impl Writer for Test {} + | ^^^^^^ not found in this scope + +error[E0425]: cannot find function `drop` in this scope + --> $DIR/no-prelude.rs:18:5 + | +LL | drop(2) + | ^^^^ not found in this scope + | +help: consider importing this function + | +LL | use std::mem::drop; + | + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0404, E0405, E0425. +For more information about an error, try `rustc --explain E0404`. diff --git a/src/test/ui/attributes/register-attr-tool-prelude.rs b/src/test/ui/attributes/register-attr-tool-prelude.rs index d217a8146d2ac..3be7804626370 100644 --- a/src/test/ui/attributes/register-attr-tool-prelude.rs +++ b/src/test/ui/attributes/register-attr-tool-prelude.rs @@ -4,7 +4,8 @@ #![register_attr(attr)] #![register_tool(tool)] -#[no_implicit_prelude] +#![feature(no_prelude)] +#[no_prelude] mod m { #[attr] //~ ERROR cannot find attribute `attr` in this scope #[tool::attr] //~ ERROR failed to resolve: use of undeclared crate or module `tool` diff --git a/src/test/ui/attributes/register-attr-tool-prelude.stderr b/src/test/ui/attributes/register-attr-tool-prelude.stderr index 905b661206a6b..6c4d4e3b179fa 100644 --- a/src/test/ui/attributes/register-attr-tool-prelude.stderr +++ b/src/test/ui/attributes/register-attr-tool-prelude.stderr @@ -1,11 +1,11 @@ error[E0433]: failed to resolve: use of undeclared crate or module `tool` - --> $DIR/register-attr-tool-prelude.rs:10:7 + --> $DIR/register-attr-tool-prelude.rs:11:7 | LL | #[tool::attr] | ^^^^ use of undeclared crate or module `tool` error: cannot find attribute `attr` in this scope - --> $DIR/register-attr-tool-prelude.rs:9:7 + --> $DIR/register-attr-tool-prelude.rs:10:7 | LL | #[attr] | ^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-no_prelude.rs b/src/test/ui/feature-gates/feature-gate-no_prelude.rs new file mode 100644 index 0000000000000..fcee4b9458a94 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-no_prelude.rs @@ -0,0 +1,4 @@ +#![no_prelude] //~ ERROR: experimental feature: replacement for #![no_implicit_prelude] + //~^ HELP: feature(no_prelude) + +fn main(){} diff --git a/src/test/ui/feature-gates/feature-gate-no_prelude.stderr b/src/test/ui/feature-gates/feature-gate-no_prelude.stderr new file mode 100644 index 0000000000000..f5dfce5d35e59 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-no_prelude.stderr @@ -0,0 +1,12 @@ +error[E0658]: experimental feature: replacement for #![no_implicit_prelude] that is not inherited by descendants + --> $DIR/feature-gate-no_prelude.rs:1:1 + | +LL | #![no_prelude] + | ^^^^^^^^^^^^^^ + | + = note: see issue #20561 for more information + = help: add `#![feature(no_prelude)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-21363.rs b/src/test/ui/issues/issue-21363.rs index acc28cb430b27..21f69ae9db9bd 100644 --- a/src/test/ui/issues/issue-21363.rs +++ b/src/test/ui/issues/issue-21363.rs @@ -1,7 +1,8 @@ // check-pass // pretty-expanded FIXME #23616 -#![no_implicit_prelude] +#![feature(no_prelude)] +#![no_prelude] trait Iterator { type Item; diff --git a/src/test/ui/macros/issue-78333.rs b/src/test/ui/macros/issue-78333.rs index c376f2067045b..1f18483fd04be 100644 --- a/src/test/ui/macros/issue-78333.rs +++ b/src/test/ui/macros/issue-78333.rs @@ -1,6 +1,7 @@ // build-pass -#![no_implicit_prelude] +#![feature(no_prelude)] +#![no_prelude] fn main() { ::std::panic!(); diff --git a/src/test/ui/unused/unused-no_prelude.rs b/src/test/ui/unused/unused-no_prelude.rs new file mode 100644 index 0000000000000..766cd274d4274 --- /dev/null +++ b/src/test/ui/unused/unused-no_prelude.rs @@ -0,0 +1,12 @@ +#![no_implicit_prelude] +#![feature(no_prelude)] +#![deny(unused_attributes)] +#![no_prelude] +//~^ ERROR: unused attribute + +mod unused { + #![no_prelude] + //~^ ERROR: unused attribute +} + +fn main() {} diff --git a/src/test/ui/unused/unused-no_prelude.stderr b/src/test/ui/unused/unused-no_prelude.stderr new file mode 100644 index 0000000000000..7e1411d651ab7 --- /dev/null +++ b/src/test/ui/unused/unused-no_prelude.stderr @@ -0,0 +1,20 @@ +error: unused attribute + --> $DIR/unused-no_prelude.rs:8:5 + | +LL | #![no_prelude] + | ^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-no_prelude.rs:3:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-no_prelude.rs:4:1 + | +LL | #![no_prelude] + | ^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors +