Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consistent no_prelude attribute #80427

Closed
wants to merge 12 commits into from
2 changes: 1 addition & 1 deletion compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Symbol>,
}

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
25 changes: 18 additions & 7 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,12 @@ pub struct ModuleData<'a> {
unexpanded_invocations: RefCell<FxHashSet<ExpnId>>,

/// 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<Vec<&'a Import<'a>>>,
globs: RefCell<Vec<&'a Import<'a>>>,
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 => {
Expand Down Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ symbols! {
no_main,
no_mangle,
no_niche,
no_prelude,
no_sanitize,
no_stack_check,
no_start,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
3 changes: 2 additions & 1 deletion src/test/ui/associated-types/associated-types-issue-20346.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0271]: type mismatch resolving `<Adapter<I> as Iterator>::Item == Option<T>`
--> $DIR/associated-types-issue-20346.rs:34:5
--> $DIR/associated-types-issue-20346.rs:35:5
|
LL | fn is_iterator_of<A, I: Iterator<Item=A>>(_: &I) {}
| ------ required by this bound in `is_iterator_of`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
63 changes: 63 additions & 0 deletions src/test/ui/attributes/no-prelude-nested.rs
Original file line number Diff line number Diff line change
@@ -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<Test> 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)
}
136 changes: 136 additions & 0 deletions src/test/ui/attributes/no-prelude-nested.stderr
Original file line number Diff line number Diff line change
@@ -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`.
19 changes: 19 additions & 0 deletions src/test/ui/attributes/no-prelude.rs
Original file line number Diff line number Diff line change
@@ -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`
}
Loading