Skip to content

Commit 09e3989

Browse files
committed
Auto merge of #62086 - petrochenkov:builtout, r=eddyb
Define built-in macros through libcore This PR defines built-in macros through libcore using a scheme similar to lang items (attribute `#[rustc_builtin_macro]`). All the macro properties (stability, visibility, etc.) are taken from the source code in libcore, with exception of the expander function transforming input tokens/AST into output tokens/AST, which is still provided by the compiler. The macros are made available to user code through the standard library prelude (`{core,std}::prelude::v1`), so they are still always in scope. As a result **built-in macros now have stable absolute addresses in the library**, like `core::prelude::v1::line!()`, this is an insta-stable change. Right now `prelude::v1` is the only publicly available absolute address for these macros, but eventually they can be moved into more appropriate locations with library team approval (e.g. `Clone` derive -> `core::clone::Clone`). Now when built-in macros have canonical definitions they can be imported or reexported without issues (#61687). Other changes: - You can now define a derive macro with a name matching one of the built-in derives (#52269). This was an artificial restriction that could be worked around with import renaming anyway. Known regressions: - Empty library crate with a crate-level `#![test]` attribute no longer compiles without `--test`. Previously it didn't compile *with* `--test` or with the bin crate type. Fixes #61687 Fixes #61804 r? @eddyb
2 parents c43753f + 8eaf17b commit 09e3989

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+499
-969
lines changed

src/libcore/macros.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -657,13 +657,13 @@ macro_rules! uninit_array {
657657
);
658658
}
659659

660-
/// Built-in macros to the compiler itself.
660+
/// Definitions of built-in macros.
661661
///
662-
/// These macros do not have any corresponding definition with a `macro_rules!`
663-
/// macro, but are documented here. Their implementations can be found hardcoded
664-
/// into libsyntax itself.
665-
#[cfg(rustdoc)]
666-
mod builtin {
662+
/// Most of the macro properties (stability, visibility, etc.) are taken from the source code here,
663+
/// with exception of expansion functions transforming macro inputs into outputs,
664+
/// those functions are provided by the compiler.
665+
#[cfg(not(bootstrap))]
666+
pub(crate) mod builtin {
667667

668668
/// Causes compilation to fail with the given error message when encountered.
669669
///
@@ -950,7 +950,7 @@ mod builtin {
950950

951951
/// Same as `column`, but less likely to be shadowed.
952952
#[unstable(feature = "__rust_unstable_column", issue = "0",
953-
reason = "internal implementation detail of the `column` macro")]
953+
reason = "internal implementation detail of the `panic` macro")]
954954
#[rustc_builtin_macro]
955955
#[rustc_macro_transparency = "semitransparent"]
956956
pub macro __rust_unstable_column() { /* compiler built-in */ }

src/libcore/prelude/v1.rs

+47
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,50 @@ pub use crate::option::Option::{self, Some, None};
4444
#[stable(feature = "core_prelude", since = "1.4.0")]
4545
#[doc(no_inline)]
4646
pub use crate::result::Result::{self, Ok, Err};
47+
48+
// Re-exported built-in macros
49+
#[cfg(not(bootstrap))]
50+
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
51+
#[allow(deprecated)]
52+
#[doc(no_inline)]
53+
pub use crate::macros::builtin::{
54+
Clone,
55+
Copy,
56+
Debug,
57+
Decodable,
58+
Default,
59+
Encodable,
60+
Eq,
61+
Hash,
62+
Ord,
63+
PartialEq,
64+
PartialOrd,
65+
RustcDecodable,
66+
RustcEncodable,
67+
__rust_unstable_column,
68+
asm,
69+
assert,
70+
bench,
71+
cfg,
72+
column,
73+
compile_error,
74+
concat,
75+
concat_idents,
76+
env,
77+
file,
78+
format_args,
79+
format_args_nl,
80+
global_allocator,
81+
global_asm,
82+
include,
83+
include_bytes,
84+
include_str,
85+
line,
86+
log_syntax,
87+
module_path,
88+
option_env,
89+
stringify,
90+
test,
91+
test_case,
92+
trace_macros,
93+
};

src/libcore/task/wake.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ impl fmt::Debug for Context<'_> {
217217
/// This handle encapsulates a [`RawWaker`] instance, which defines the
218218
/// executor-specific wakeup behavior.
219219
///
220-
/// Implements [`Clone`], [`Send`], and [`Sync`].
220+
/// Implements [`Clone`], [`trait@Send`], and [`trait@Sync`].
221221
///
222222
/// [`RawWaker`]: struct.RawWaker.html
223223
#[repr(transparent)]

src/librustc/hir/def_id.rs

-6
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@ newtype_index! {
1212

1313
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1414
pub enum CrateNum {
15-
/// Virtual crate for builtin macros
16-
// FIXME(jseyfried): this is also used for custom derives until proc-macro crates get
17-
// `CrateNum`s.
18-
BuiltinMacros,
1915
/// A special CrateNum that we use for the tcx.rcache when decoding from
2016
/// the incr. comp. cache.
2117
ReservedForIncrCompCache,
@@ -26,7 +22,6 @@ impl ::std::fmt::Debug for CrateNum {
2622
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
2723
match self {
2824
CrateNum::Index(id) => write!(fmt, "crate{}", id.private),
29-
CrateNum::BuiltinMacros => write!(fmt, "builtin macros crate"),
3025
CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"),
3126
}
3227
}
@@ -86,7 +81,6 @@ impl fmt::Display for CrateNum {
8681
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8782
match self {
8883
CrateNum::Index(id) => fmt::Display::fmt(&id.private, f),
89-
CrateNum::BuiltinMacros => write!(f, "builtin macros crate"),
9084
CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"),
9185
}
9286
}

src/librustc/hir/lowering.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -4009,8 +4009,7 @@ impl<'a> LoweringContext<'a> {
40094009
let mut vis = self.lower_visibility(&i.vis, None);
40104010
let attrs = self.lower_attrs(&i.attrs);
40114011
if let ItemKind::MacroDef(ref def) = i.node {
4012-
if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) ||
4013-
attr::contains_name(&i.attrs, sym::rustc_builtin_macro) {
4012+
if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) {
40144013
let body = self.lower_token_stream(def.stream());
40154014
let hir_id = self.lower_node_id(i.id);
40164015
self.exported_macros.push(hir::MacroDef {

src/librustc_interface/passes.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,10 @@ fn configure_and_expand_inner<'a>(
372372
crate_loader,
373373
&resolver_arenas,
374374
);
375-
syntax_ext::register_builtins(&mut resolver, plugin_info.syntax_exts, sess.edition());
375+
syntax_ext::register_builtin_macros(&mut resolver, sess.edition());
376+
syntax_ext::plugin_macro_defs::inject(
377+
&mut krate, &mut resolver, plugin_info.syntax_exts, sess.edition()
378+
);
376379

377380
// Expand all macros
378381
sess.profiler(|p| p.start_activity("macro expansion"));

src/librustc_resolve/build_reduced_graph.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::{resolve_error, resolve_struct_error, ResolutionError, Determinacy};
1313

1414
use rustc::bug;
1515
use rustc::hir::def::{self, *};
16-
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
16+
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
1717
use rustc::ty;
1818
use rustc::middle::cstore::CrateStore;
1919
use rustc_metadata::cstore::LoadedMacro;
@@ -31,7 +31,6 @@ use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, Nod
3131
use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant};
3232
use syntax::ext::base::SyntaxExtension;
3333
use syntax::ext::hygiene::ExpnId;
34-
use syntax::ext::tt::macro_rules;
3534
use syntax::feature_gate::is_builtin_attr;
3635
use syntax::parse::token::{self, Token};
3736
use syntax::span_err;
@@ -748,21 +747,24 @@ impl<'a> Resolver<'a> {
748747
};
749748
if let Some(id) = self.definitions.as_local_node_id(def_id) {
750749
self.local_macro_def_scopes[&id]
751-
} else if def_id.krate == CrateNum::BuiltinMacros {
750+
} else if self.is_builtin_macro(Some(def_id)) {
752751
self.injected_crate.unwrap_or(self.graph_root)
753752
} else {
754753
let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
755754
self.get_module(module_def_id)
756755
}
757756
}
758757

759-
pub fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
760-
let def_id = match res {
761-
Res::Def(DefKind::Macro(..), def_id) => def_id,
758+
crate fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
759+
match res {
760+
Res::Def(DefKind::Macro(..), def_id) => self.get_macro_by_def_id(def_id),
762761
Res::NonMacroAttr(attr_kind) =>
763-
return Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
764-
_ => return None,
765-
};
762+
Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
763+
_ => None,
764+
}
765+
}
766+
767+
crate fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option<Lrc<SyntaxExtension>> {
766768
if let Some(ext) = self.macro_map.get(&def_id) {
767769
return Some(ext.clone());
768770
}
@@ -772,10 +774,7 @@ impl<'a> Resolver<'a> {
772774
LoadedMacro::ProcMacro(ext) => return Some(ext),
773775
};
774776

775-
let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
776-
&self.session.features_untracked(),
777-
&macro_def,
778-
self.cstore.crate_edition_untracked(def_id.krate)));
777+
let ext = self.compile_macro(&macro_def, self.cstore.crate_edition_untracked(def_id.krate));
779778
self.macro_map.insert(def_id, ext.clone());
780779
Some(ext)
781780
}

src/librustc_resolve/diagnostics.rs

+12-25
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,12 @@ enum AssocSuggestion {
3535

3636
struct TypoSuggestion {
3737
candidate: Symbol,
38-
39-
/// The kind of the binding ("crate", "module", etc.)
40-
kind: &'static str,
41-
42-
/// An appropriate article to refer to the binding ("a", "an", etc.)
43-
article: &'static str,
38+
res: Res,
4439
}
4540

4641
impl TypoSuggestion {
4742
fn from_res(candidate: Symbol, res: Res) -> TypoSuggestion {
48-
TypoSuggestion { candidate, kind: res.descr(), article: res.article() }
43+
TypoSuggestion { candidate, res }
4944
}
5045
}
5146

@@ -59,7 +54,9 @@ fn add_typo_suggestion(
5954
err: &mut DiagnosticBuilder<'_>, suggestion: Option<TypoSuggestion>, span: Span
6055
) -> bool {
6156
if let Some(suggestion) = suggestion {
62-
let msg = format!("{} {} with a similar name exists", suggestion.article, suggestion.kind);
57+
let msg = format!(
58+
"{} {} with a similar name exists", suggestion.res.article(), suggestion.res.descr()
59+
);
6360
err.span_suggestion(
6461
span, &msg, suggestion.candidate.to_string(), Applicability::MaybeIncorrect
6562
);
@@ -566,7 +563,7 @@ impl<'a> Resolver<'a> {
566563
filter_fn: &impl Fn(Res) -> bool,
567564
) -> Option<TypoSuggestion> {
568565
let mut suggestions = Vec::new();
569-
self.visit_scopes(scope_set, parent_scope, ident, |this, scope, _| {
566+
self.visit_scopes(scope_set, parent_scope, ident, |this, scope, use_prelude, _| {
570567
match scope {
571568
Scope::DeriveHelpers => {
572569
let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
@@ -611,16 +608,6 @@ impl<'a> Resolver<'a> {
611608
}
612609
}));
613610
}
614-
Scope::BuiltinMacros => {
615-
suggestions.extend(this.builtin_macros.iter().filter_map(|(name, binding)| {
616-
let res = binding.res();
617-
if filter_fn(res) {
618-
Some(TypoSuggestion::from_res(*name, res))
619-
} else {
620-
None
621-
}
622-
}));
623-
}
624611
Scope::BuiltinAttrs => {
625612
let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin);
626613
if filter_fn(res) {
@@ -656,7 +643,11 @@ impl<'a> Resolver<'a> {
656643
}
657644
Scope::StdLibPrelude => {
658645
if let Some(prelude) = this.prelude {
659-
add_module_candidates(prelude, &mut suggestions, filter_fn);
646+
let mut tmp_suggestions = Vec::new();
647+
add_module_candidates(prelude, &mut tmp_suggestions, filter_fn);
648+
suggestions.extend(tmp_suggestions.into_iter().filter(|s| {
649+
use_prelude || this.is_builtin_macro(s.res.opt_def_id())
650+
}));
660651
}
661652
}
662653
Scope::BuiltinTypes => {
@@ -733,11 +724,7 @@ impl<'a> Resolver<'a> {
733724
);
734725

735726
if filter_fn(crate_mod) {
736-
Some(TypoSuggestion {
737-
candidate: ident.name,
738-
article: "a",
739-
kind: "crate",
740-
})
727+
Some(TypoSuggestion::from_res(ident.name, crate_mod))
741728
} else {
742729
None
743730
}

src/librustc_resolve/lib.rs

+13-11
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ enum Scope<'a> {
114114
CrateRoot,
115115
Module(Module<'a>),
116116
MacroUsePrelude,
117-
BuiltinMacros,
118117
BuiltinAttrs,
119118
LegacyPluginHelpers,
120119
ExternPrelude,
@@ -1679,7 +1678,7 @@ pub struct Resolver<'a> {
16791678

16801679
crate_loader: &'a mut CrateLoader<'a>,
16811680
macro_names: FxHashSet<Ident>,
1682-
builtin_macros: FxHashMap<Name, &'a NameBinding<'a>>,
1681+
builtin_macros: FxHashMap<Name, SyntaxExtension>,
16831682
macro_use_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
16841683
pub all_macros: FxHashMap<Name, Res>,
16851684
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
@@ -2021,7 +2020,7 @@ impl<'a> Resolver<'a> {
20212020

20222021
crate_loader,
20232022
macro_names: FxHashSet::default(),
2024-
builtin_macros: FxHashMap::default(),
2023+
builtin_macros: Default::default(),
20252024
macro_use_prelude: FxHashMap::default(),
20262025
all_macros: FxHashMap::default(),
20272026
macro_map: FxHashMap::default(),
@@ -2068,6 +2067,11 @@ impl<'a> Resolver<'a> {
20682067
f(self, MacroNS);
20692068
}
20702069

2070+
fn is_builtin_macro(&mut self, def_id: Option<DefId>) -> bool {
2071+
def_id.and_then(|def_id| self.get_macro_by_def_id(def_id))
2072+
.map_or(false, |ext| ext.is_builtin)
2073+
}
2074+
20712075
fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
20722076
loop {
20732077
match self.macro_defs.get(&ctxt.outer_expn()) {
@@ -2146,7 +2150,7 @@ impl<'a> Resolver<'a> {
21462150
scope_set: ScopeSet,
21472151
parent_scope: &ParentScope<'a>,
21482152
ident: Ident,
2149-
mut visitor: impl FnMut(&mut Self, Scope<'a>, Ident) -> Option<T>,
2153+
mut visitor: impl FnMut(&mut Self, Scope<'a>, /*use_prelude*/ bool, Ident) -> Option<T>,
21502154
) -> Option<T> {
21512155
// General principles:
21522156
// 1. Not controlled (user-defined) names should have higher priority than controlled names
@@ -2185,8 +2189,8 @@ impl<'a> Resolver<'a> {
21852189
// 4. `macro_use` prelude (open, the open part is from macro expansions, not controlled).
21862190
// 4a. User-defined prelude from macro-use
21872191
// (open, the open part is from macro expansions, not controlled).
2188-
// 4b. Standard library prelude is currently implemented as `macro-use` (closed, controlled)
2189-
// 5. Language prelude: builtin macros (closed, controlled, except for legacy plugins).
2192+
// 4b. "Standard library prelude" part implemented through `macro-use` (closed, controlled).
2193+
// 4c. Standard library prelude (de-facto closed, controlled).
21902194
// 6. Language prelude: builtin attributes (closed, controlled).
21912195
// 4-6. Legacy plugin helpers (open, not controlled). Similar to derive helpers,
21922196
// but introduced by legacy plugins using `register_attribute`. Priority is somewhere
@@ -2214,17 +2218,16 @@ impl<'a> Resolver<'a> {
22142218
Scope::CrateRoot => true,
22152219
Scope::Module(..) => true,
22162220
Scope::MacroUsePrelude => use_prelude || rust_2015,
2217-
Scope::BuiltinMacros => true,
22182221
Scope::BuiltinAttrs => true,
22192222
Scope::LegacyPluginHelpers => use_prelude || rust_2015,
22202223
Scope::ExternPrelude => use_prelude || is_absolute_path,
22212224
Scope::ToolPrelude => use_prelude,
2222-
Scope::StdLibPrelude => use_prelude,
2225+
Scope::StdLibPrelude => use_prelude || ns == MacroNS,
22232226
Scope::BuiltinTypes => true,
22242227
};
22252228

22262229
if visit {
2227-
if let break_result @ Some(..) = visitor(self, scope, ident) {
2230+
if let break_result @ Some(..) = visitor(self, scope, use_prelude, ident) {
22282231
return break_result;
22292232
}
22302233
}
@@ -2263,7 +2266,6 @@ impl<'a> Resolver<'a> {
22632266
}
22642267
}
22652268
Scope::MacroUsePrelude => Scope::StdLibPrelude,
2266-
Scope::BuiltinMacros => Scope::BuiltinAttrs,
22672269
Scope::BuiltinAttrs => Scope::LegacyPluginHelpers,
22682270
Scope::LegacyPluginHelpers => break, // nowhere else to search
22692271
Scope::ExternPrelude if is_absolute_path => break,
@@ -2272,7 +2274,7 @@ impl<'a> Resolver<'a> {
22722274
Scope::StdLibPrelude => match ns {
22732275
TypeNS => Scope::BuiltinTypes,
22742276
ValueNS => break, // nowhere else to search
2275-
MacroNS => Scope::BuiltinMacros,
2277+
MacroNS => Scope::BuiltinAttrs,
22762278
}
22772279
Scope::BuiltinTypes => break, // nowhere else to search
22782280
};

0 commit comments

Comments
 (0)