From 73a35e80c64c5eafa85fc5473bf73e2e3bbc7e37 Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Mon, 17 Nov 2025 18:24:36 +0100 Subject: [PATCH 1/3] Reflect explicit macro import in reference --- src/names/preludes.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/names/preludes.md b/src/names/preludes.md index 3a2c3ff17c..b25b4b8a3e 100644 --- a/src/names/preludes.md +++ b/src/names/preludes.md @@ -81,7 +81,7 @@ r[names.preludes.extern.no_std] ### The `no_std` attribute r[names.preludes.extern.no_std.intro] -The *`no_std` [attribute][attributes]* causes the [`std`] crate to not be linked automatically, the [standard library prelude] to instead use the `core` prelude, and the [`macro_use` prelude] to instead use the macros exported from the `core` crate. +The *`no_std` [attribute][attributes]* causes the [`std`] crate to not be linked automatically and the [standard library prelude] to instead use the `core` prelude. > [!EXAMPLE] > @@ -110,9 +110,6 @@ The `no_std` attribute may be used any number of times on a form. r[names.preludes.extern.no_std.module] The `no_std` attribute changes the [standard library prelude] to use the `core` prelude instead of the `std` prelude. -r[names.preludes.extern.no_std.macro_use] -By default, all macros exported from the `std` crate are added to the [`macro_use` prelude]. If the `no_std` attribute is specified, then all macros exported from the `core` crate are placed into the [`macro_use` prelude] instead. - r[names.preludes.extern.no_std.edition2018] > [!EDITION-2018] > Before the 2018 edition, `std` is injected into the crate root by default. If `no_std` is specified, `core` is injected instead. Starting with the 2018 edition, regardless of `no_std` being specified, neither is injected into the crate root. From b735d675a478b363d25c36cd8d4bf5c5dcf5c5bb Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 14 Jan 2026 00:31:49 +0000 Subject: [PATCH 2/3] Document the `panic!` hack to name resolution In Rust PR 139493, we added a (hopefully temporary) hack to name resolution involving `panic` to avoid breakage. Let's document this in an admonition. --- src/names/name-resolution.md | 33 +++++++++++++++++++++++++++++++++ src/names/preludes.md | 6 ++++++ 2 files changed, 39 insertions(+) diff --git a/src/names/name-resolution.md b/src/names/name-resolution.md index e66a0fec6a..11919287d7 100644 --- a/src/names/name-resolution.md +++ b/src/names/name-resolution.md @@ -229,6 +229,38 @@ const _: () = { r[names.resolution.expansion.imports.ambiguity.glob-vs-outer] Names in imports and macro invocations may not be resolved through glob imports when there is another candidate available in an [outer scope]. +r[names.resolution.expansion.imports.ambiguity.panic-hack] +> [!NOTE] +> When one of [`core::panic!`] or [`std::panic!`] is brought into scope due to the [standard library prelude], and a user-written [glob import] brings the other into scope, `rustc` currently allows use of `panic!`, even though it is ambiguous. The user-written glob import takes precedence to resolve this ambiguity. +> +> In Rust 2021 and later, [`core::panic!`] and [`std::panic!`] operate identically. But in earlier editions, they differ; only [`std::panic!`] accepts a [`String`] as the format argument. +> +> E.g., this is an error: +> +> ```rust,edition2018,compile_fail,E0308 +> extern crate core; +> use ::core::prelude::v1::*; +> fn main() { +> panic!(std::string::String::new()); // ERROR. +> } +> ``` +> +> And this is accepted: +> +> +> ```rust,edition2018,ignore +> #![no_std] +> extern crate std; +> use ::std::prelude::v1::*; +> fn main() { +> panic!(std::string::String::new()); // OK. +> } +> ``` +> +> Don't rely on this behavior; the plan is to remove it. +> +> For details, see [Rust issue #147319](https://github.com/rust-lang/rust/issues/147319). + ```rust,compile_fail,E0659 mod glob { pub mod ambig { @@ -545,6 +577,7 @@ r[names.resolution.type-relative] [`use` declarations]: ../items/use-declarations.md [`use` glob shadowing]: ../items/use-declarations.md#r-items.use.glob.shadowing [derive helper scope]: ../procedural-macros.md#r-macro.proc.derive.attributes.scope +[glob import]: items.use.glob [item definitions]: ../items.md [macro invocations]: ../macros.md#macro-invocation [macro textual scope shadowing]: ../macros-by-example.md#r-macro.decl.scope.textual.shadow diff --git a/src/names/preludes.md b/src/names/preludes.md index b25b4b8a3e..e3f20f4e7c 100644 --- a/src/names/preludes.md +++ b/src/names/preludes.md @@ -40,6 +40,11 @@ Edition | `no_std` not applied | `no_std` applied > > [`core::prelude::rust_2015`] and [`core::prelude::rust_2018`] have the same contents as [`core::prelude::v1`]. +> [!NOTE] +> When one of [`core::panic!`] or [`std::panic!`] is brought into scope due to the [standard library prelude], and a user-written [glob import] brings the other into scope, `rustc` currently allows use of `panic!`, even though it is ambiguous. The user-written glob import takes precedence to resolve this ambiguity. +> +> For details, see [names.resolution.expansion.imports.ambiguity.panic-hack]. + r[names.preludes.extern] ## Extern prelude @@ -203,6 +208,7 @@ r[names.preludes.no_implicit_prelude.edition2018] [Built-in attributes]: ../attributes.md#built-in-attributes-index [extern prelude]: #extern-prelude [floating-point types]: ../types/numeric.md#floating-point-types +[glob import]: items.use.glob [Integer types]: ../types/numeric.md#integer-types [Language prelude]: #language-prelude [Machine-dependent integer types]: ../types/numeric.md#machine-dependent-integer-types From d3b02a9110ba9c470c6f9eb36e7096f314af8653 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 14 Jan 2026 00:33:21 +0000 Subject: [PATCH 3/3] Document built-in macros and `no_implicit_prelude` Macros are part of the standard library prelude. One might expect these to not be in scope when `no_implicit_prelude` is used. But certain macros still are. The history is that these macros were once built in to the language; when this was changed, in Rust PR 62086, a hack was added. Then in Rust PR 139493 this list grew to include `panic!` and `unreachable!`. --- src/names/preludes.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/names/preludes.md b/src/names/preludes.md index e3f20f4e7c..62692966a8 100644 --- a/src/names/preludes.md +++ b/src/names/preludes.md @@ -192,6 +192,41 @@ The `no_implicit_prelude` attribute may be used any number of times on a form. r[names.preludes.no_implicit_prelude.excluded-preludes] The `no_implicit_prelude` attribute prevents the [standard library prelude], [extern prelude], [`macro_use` prelude], and the [tool prelude] from being brought into scope for the module and its descendants. +r[names.preludes.no_implicit_prelude.implicitly-imported-macros] +> [!NOTE] +> Despite `#![no_implicit_prelude]`, `rustc` currently brings certain macros implicitly into scope. Those macros are: +> +> - [`assert!`] +> - [`cfg!`] +> - [`cfg_select!`] +> - [`column!`] +> - [`compile_error!`] +> - [`concat!`] +> - [`concat_bytes!`] +> - [`env!`] +> - [`file!`] +> - [`format_args!`] +> - [`include!`] +> - [`include_bytes!`] +> - [`include_str!`] +> - [`line!`] +> - [`module_path!`] +> - [`option_env!`] +> - [`panic!`] +> - [`stringify!`] +> - [`unreachable!`] +> +> E.g., this works: +> +> ```rust +> #![no_implicit_prelude] +> fn main() { assert!(true); } +> ``` +> +> Don't rely on this behavior; it may be removed in the future. Always bring the items you need into scope explicitly when using `#![no_implicit_prelude]`. +> +> For details, see [Rust PR #62086](https://github.com/rust-lang/rust/pull/62086) and [Rust PR #139493](https://github.com/rust-lang/rust/pull/139493). + r[names.preludes.no_implicit_prelude.lang] The `no_implicit_prelude` attribute does not affect the [language prelude].