From 8eaf17bca2674293eba0ea10056d5c77b6352086 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 20 Jun 2019 11:52:31 +0300 Subject: [PATCH] Introduce built-in macros through libcore --- src/libcore/macros.rs | 14 +- src/libcore/prelude/v1.rs | 47 ++ src/libcore/task/wake.rs | 2 +- src/librustc/hir/def_id.rs | 6 - src/librustc/hir/lowering.rs | 3 +- src/librustc_interface/passes.rs | 5 +- src/librustc_resolve/build_reduced_graph.rs | 25 +- src/librustc_resolve/diagnostics.rs | 37 +- src/librustc_resolve/lib.rs | 24 +- src/librustc_resolve/macros.rs | 70 ++- src/librustc_resolve/resolve_imports.rs | 18 +- src/libstd/error.rs | 10 +- src/libstd/lib.rs | 40 +- src/libstd/macros.rs | 531 ------------------ src/libstd/prelude/v1.rs | 63 ++- src/libsyntax/ext/base.rs | 6 +- src/libsyntax/ext/tt/macro_rules.rs | 1 + src/libsyntax_ext/deriving/mod.rs | 86 +-- src/libsyntax_ext/lib.rs | 194 ++----- src/libsyntax_ext/plugin_macro_defs.rs | 64 +++ src/libsyntax_ext/proc_macro_decls.rs | 6 - src/test/run-make-fulldeps/simd-ffi/simd.rs | 6 +- src/test/rustdoc/intra-link-builtin-macros.rs | 3 + .../ui-fulldeps/auxiliary/attr-plugin-test.rs | 15 +- src/test/ui-fulldeps/deprecated-derive.stderr | 2 +- src/test/ui-fulldeps/plugin-reexport.rs | 10 + src/test/ui-fulldeps/plugin-reexport.stderr | 15 + .../issue-43106-gating-of-bench.rs | 13 +- .../issue-43106-gating-of-bench.stderr | 15 +- .../issue-43106-gating-of-test.rs | 12 +- .../issue-43106-gating-of-test.stderr | 15 +- .../feature-gate-cfg-target-has-atomic.rs | 6 +- src/test/ui/imports/glob-shadowing.stderr | 4 +- .../local-modularized-tricky-fail-1.stderr | 2 +- src/test/ui/issues/issue-28134.rs | 2 +- src/test/ui/issues/issue-28134.stderr | 8 +- src/test/ui/macros/unknown-builtin.rs | 14 + src/test/ui/macros/unknown-builtin.stderr | 14 + src/test/ui/proc-macro/attribute.rs | 3 +- src/test/ui/proc-macro/attribute.stderr | 24 +- .../not-whitelisted.rs | 2 +- .../not-whitelisted.stderr | 8 +- .../rust-2018/uniform-paths/prelude-fail.rs | 7 +- .../uniform-paths/prelude-fail.stderr | 10 +- .../ui/rust-2018/uniform-paths/prelude.rs | 4 + src/test/ui/rust-unstable-column-gated.stderr | 2 +- 46 files changed, 499 insertions(+), 969 deletions(-) create mode 100644 src/libsyntax_ext/plugin_macro_defs.rs create mode 100644 src/test/rustdoc/intra-link-builtin-macros.rs create mode 100644 src/test/ui-fulldeps/plugin-reexport.rs create mode 100644 src/test/ui-fulldeps/plugin-reexport.stderr create mode 100644 src/test/ui/macros/unknown-builtin.rs create mode 100644 src/test/ui/macros/unknown-builtin.stderr diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 17781798946ed..218c164a7dc35 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -657,13 +657,13 @@ macro_rules! uninit_array { ); } -/// Built-in macros to the compiler itself. +/// Definitions of built-in macros. /// -/// These macros do not have any corresponding definition with a `macro_rules!` -/// macro, but are documented here. Their implementations can be found hardcoded -/// into libsyntax itself. -#[cfg(rustdoc)] -mod builtin { +/// Most of the macro properties (stability, visibility, etc.) are taken from the source code here, +/// with exception of expansion functions transforming macro inputs into outputs, +/// those functions are provided by the compiler. +#[cfg(not(bootstrap))] +pub(crate) mod builtin { /// Causes compilation to fail with the given error message when encountered. /// @@ -950,7 +950,7 @@ mod builtin { /// Same as `column`, but less likely to be shadowed. #[unstable(feature = "__rust_unstable_column", issue = "0", - reason = "internal implementation detail of the `column` macro")] + reason = "internal implementation detail of the `panic` macro")] #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] pub macro __rust_unstable_column() { /* compiler built-in */ } diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index 501a41d0d1c76..de79e2fa260ce 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -44,3 +44,50 @@ pub use crate::option::Option::{self, Some, None}; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] pub use crate::result::Result::{self, Ok, Err}; + +// Re-exported built-in macros +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow(deprecated)] +#[doc(no_inline)] +pub use crate::macros::builtin::{ + Clone, + Copy, + Debug, + Decodable, + Default, + Encodable, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, + RustcDecodable, + RustcEncodable, + __rust_unstable_column, + asm, + assert, + bench, + cfg, + column, + compile_error, + concat, + concat_idents, + env, + file, + format_args, + format_args_nl, + global_allocator, + global_asm, + include, + include_bytes, + include_str, + line, + log_syntax, + module_path, + option_env, + stringify, + test, + test_case, + trace_macros, +}; diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index 6f841bd2adf41..65e293642874c 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -217,7 +217,7 @@ impl fmt::Debug for Context<'_> { /// This handle encapsulates a [`RawWaker`] instance, which defines the /// executor-specific wakeup behavior. /// -/// Implements [`Clone`], [`Send`], and [`Sync`]. +/// Implements [`Clone`], [`trait@Send`], and [`trait@Sync`]. /// /// [`RawWaker`]: struct.RawWaker.html #[repr(transparent)] diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index f3edb5f862117..c0a661908a654 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -12,10 +12,6 @@ newtype_index! { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum CrateNum { - /// Virtual crate for builtin macros - // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get - // `CrateNum`s. - BuiltinMacros, /// A special CrateNum that we use for the tcx.rcache when decoding from /// the incr. comp. cache. ReservedForIncrCompCache, @@ -26,7 +22,6 @@ impl ::std::fmt::Debug for CrateNum { fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { match self { CrateNum::Index(id) => write!(fmt, "crate{}", id.private), - CrateNum::BuiltinMacros => write!(fmt, "builtin macros crate"), CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"), } } @@ -86,7 +81,6 @@ impl fmt::Display for CrateNum { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { CrateNum::Index(id) => fmt::Display::fmt(&id.private, f), - CrateNum::BuiltinMacros => write!(f, "builtin macros crate"), CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"), } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 288fd2714e251..2d1835514d425 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -4009,8 +4009,7 @@ impl<'a> LoweringContext<'a> { let mut vis = self.lower_visibility(&i.vis, None); let attrs = self.lower_attrs(&i.attrs); if let ItemKind::MacroDef(ref def) = i.node { - if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) || - attr::contains_name(&i.attrs, sym::rustc_builtin_macro) { + if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) { let body = self.lower_token_stream(def.stream()); let hir_id = self.lower_node_id(i.id); self.exported_macros.push(hir::MacroDef { diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 1cc7cfda0120a..2754c55ea0685 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -372,7 +372,10 @@ fn configure_and_expand_inner<'a>( crate_loader, &resolver_arenas, ); - syntax_ext::register_builtins(&mut resolver, plugin_info.syntax_exts, sess.edition()); + syntax_ext::register_builtin_macros(&mut resolver, sess.edition()); + syntax_ext::plugin_macro_defs::inject( + &mut krate, &mut resolver, plugin_info.syntax_exts, sess.edition() + ); // Expand all macros sess.profiler(|p| p.start_activity("macro expansion")); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index cfba42580fcef..f52f7d9cfb3c3 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -13,7 +13,7 @@ use crate::{resolve_error, resolve_struct_error, ResolutionError, Determinacy}; use rustc::bug; use rustc::hir::def::{self, *}; -use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; +use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::ty; use rustc::middle::cstore::CrateStore; use rustc_metadata::cstore::LoadedMacro; @@ -31,7 +31,6 @@ use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, Nod use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant}; use syntax::ext::base::SyntaxExtension; use syntax::ext::hygiene::ExpnId; -use syntax::ext::tt::macro_rules; use syntax::feature_gate::is_builtin_attr; use syntax::parse::token::{self, Token}; use syntax::span_err; @@ -748,7 +747,7 @@ impl<'a> Resolver<'a> { }; if let Some(id) = self.definitions.as_local_node_id(def_id) { self.local_macro_def_scopes[&id] - } else if def_id.krate == CrateNum::BuiltinMacros { + } else if self.is_builtin_macro(Some(def_id)) { self.injected_crate.unwrap_or(self.graph_root) } else { let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap(); @@ -756,13 +755,16 @@ impl<'a> Resolver<'a> { } } - pub fn get_macro(&mut self, res: Res) -> Option> { - let def_id = match res { - Res::Def(DefKind::Macro(..), def_id) => def_id, + crate fn get_macro(&mut self, res: Res) -> Option> { + match res { + Res::Def(DefKind::Macro(..), def_id) => self.get_macro_by_def_id(def_id), Res::NonMacroAttr(attr_kind) => - return Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)), - _ => return None, - }; + Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)), + _ => None, + } + } + + crate fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option> { if let Some(ext) = self.macro_map.get(&def_id) { return Some(ext.clone()); } @@ -772,10 +774,7 @@ impl<'a> Resolver<'a> { LoadedMacro::ProcMacro(ext) => return Some(ext), }; - let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess, - &self.session.features_untracked(), - ¯o_def, - self.cstore.crate_edition_untracked(def_id.krate))); + let ext = self.compile_macro(¯o_def, self.cstore.crate_edition_untracked(def_id.krate)); self.macro_map.insert(def_id, ext.clone()); Some(ext) } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 90a4107f773e1..aeb6f23da5aa6 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -35,17 +35,12 @@ enum AssocSuggestion { struct TypoSuggestion { candidate: Symbol, - - /// The kind of the binding ("crate", "module", etc.) - kind: &'static str, - - /// An appropriate article to refer to the binding ("a", "an", etc.) - article: &'static str, + res: Res, } impl TypoSuggestion { fn from_res(candidate: Symbol, res: Res) -> TypoSuggestion { - TypoSuggestion { candidate, kind: res.descr(), article: res.article() } + TypoSuggestion { candidate, res } } } @@ -59,7 +54,9 @@ fn add_typo_suggestion( err: &mut DiagnosticBuilder<'_>, suggestion: Option, span: Span ) -> bool { if let Some(suggestion) = suggestion { - let msg = format!("{} {} with a similar name exists", suggestion.article, suggestion.kind); + let msg = format!( + "{} {} with a similar name exists", suggestion.res.article(), suggestion.res.descr() + ); err.span_suggestion( span, &msg, suggestion.candidate.to_string(), Applicability::MaybeIncorrect ); @@ -566,7 +563,7 @@ impl<'a> Resolver<'a> { filter_fn: &impl Fn(Res) -> bool, ) -> Option { let mut suggestions = Vec::new(); - self.visit_scopes(scope_set, parent_scope, ident, |this, scope, _| { + self.visit_scopes(scope_set, parent_scope, ident, |this, scope, use_prelude, _| { match scope { Scope::DeriveHelpers => { let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); @@ -611,16 +608,6 @@ impl<'a> Resolver<'a> { } })); } - Scope::BuiltinMacros => { - suggestions.extend(this.builtin_macros.iter().filter_map(|(name, binding)| { - let res = binding.res(); - if filter_fn(res) { - Some(TypoSuggestion::from_res(*name, res)) - } else { - None - } - })); - } Scope::BuiltinAttrs => { let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin); if filter_fn(res) { @@ -656,7 +643,11 @@ impl<'a> Resolver<'a> { } Scope::StdLibPrelude => { if let Some(prelude) = this.prelude { - add_module_candidates(prelude, &mut suggestions, filter_fn); + let mut tmp_suggestions = Vec::new(); + add_module_candidates(prelude, &mut tmp_suggestions, filter_fn); + suggestions.extend(tmp_suggestions.into_iter().filter(|s| { + use_prelude || this.is_builtin_macro(s.res.opt_def_id()) + })); } } Scope::BuiltinTypes => { @@ -733,11 +724,7 @@ impl<'a> Resolver<'a> { ); if filter_fn(crate_mod) { - Some(TypoSuggestion { - candidate: ident.name, - article: "a", - kind: "crate", - }) + Some(TypoSuggestion::from_res(ident.name, crate_mod)) } else { None } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d718d3f78f4e2..a5e498fa75643 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -114,7 +114,6 @@ enum Scope<'a> { CrateRoot, Module(Module<'a>), MacroUsePrelude, - BuiltinMacros, BuiltinAttrs, LegacyPluginHelpers, ExternPrelude, @@ -1679,7 +1678,7 @@ pub struct Resolver<'a> { crate_loader: &'a mut CrateLoader<'a>, macro_names: FxHashSet, - builtin_macros: FxHashMap>, + builtin_macros: FxHashMap, macro_use_prelude: FxHashMap>, pub all_macros: FxHashMap, macro_map: FxHashMap>, @@ -2021,7 +2020,7 @@ impl<'a> Resolver<'a> { crate_loader, macro_names: FxHashSet::default(), - builtin_macros: FxHashMap::default(), + builtin_macros: Default::default(), macro_use_prelude: FxHashMap::default(), all_macros: FxHashMap::default(), macro_map: FxHashMap::default(), @@ -2068,6 +2067,11 @@ impl<'a> Resolver<'a> { f(self, MacroNS); } + fn is_builtin_macro(&mut self, def_id: Option) -> bool { + def_id.and_then(|def_id| self.get_macro_by_def_id(def_id)) + .map_or(false, |ext| ext.is_builtin) + } + fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId { loop { match self.macro_defs.get(&ctxt.outer_expn()) { @@ -2146,7 +2150,7 @@ impl<'a> Resolver<'a> { scope_set: ScopeSet, parent_scope: &ParentScope<'a>, ident: Ident, - mut visitor: impl FnMut(&mut Self, Scope<'a>, Ident) -> Option, + mut visitor: impl FnMut(&mut Self, Scope<'a>, /*use_prelude*/ bool, Ident) -> Option, ) -> Option { // General principles: // 1. Not controlled (user-defined) names should have higher priority than controlled names @@ -2185,8 +2189,8 @@ impl<'a> Resolver<'a> { // 4. `macro_use` prelude (open, the open part is from macro expansions, not controlled). // 4a. User-defined prelude from macro-use // (open, the open part is from macro expansions, not controlled). - // 4b. Standard library prelude is currently implemented as `macro-use` (closed, controlled) - // 5. Language prelude: builtin macros (closed, controlled, except for legacy plugins). + // 4b. "Standard library prelude" part implemented through `macro-use` (closed, controlled). + // 4c. Standard library prelude (de-facto closed, controlled). // 6. Language prelude: builtin attributes (closed, controlled). // 4-6. Legacy plugin helpers (open, not controlled). Similar to derive helpers, // but introduced by legacy plugins using `register_attribute`. Priority is somewhere @@ -2214,17 +2218,16 @@ impl<'a> Resolver<'a> { Scope::CrateRoot => true, Scope::Module(..) => true, Scope::MacroUsePrelude => use_prelude || rust_2015, - Scope::BuiltinMacros => true, Scope::BuiltinAttrs => true, Scope::LegacyPluginHelpers => use_prelude || rust_2015, Scope::ExternPrelude => use_prelude || is_absolute_path, Scope::ToolPrelude => use_prelude, - Scope::StdLibPrelude => use_prelude, + Scope::StdLibPrelude => use_prelude || ns == MacroNS, Scope::BuiltinTypes => true, }; if visit { - if let break_result @ Some(..) = visitor(self, scope, ident) { + if let break_result @ Some(..) = visitor(self, scope, use_prelude, ident) { return break_result; } } @@ -2263,7 +2266,6 @@ impl<'a> Resolver<'a> { } } Scope::MacroUsePrelude => Scope::StdLibPrelude, - Scope::BuiltinMacros => Scope::BuiltinAttrs, Scope::BuiltinAttrs => Scope::LegacyPluginHelpers, Scope::LegacyPluginHelpers => break, // nowhere else to search Scope::ExternPrelude if is_absolute_path => break, @@ -2272,7 +2274,7 @@ impl<'a> Resolver<'a> { Scope::StdLibPrelude => match ns { TypeNS => Scope::BuiltinTypes, ValueNS => break, // nowhere else to search - MacroNS => Scope::BuiltinMacros, + MacroNS => Scope::BuiltinAttrs, } Scope::BuiltinTypes => break, // nowhere else to search }; diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 3760cabcd898a..88850c5988b7b 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -1,18 +1,19 @@ use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc, Determinacy}; use crate::{CrateLint, Resolver, ResolutionError, Scope, ScopeSet, ParentScope, Weak}; -use crate::{Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding}; +use crate::{Module, ModuleKind, NameBinding, PathResult, Segment, ToNameBinding}; use crate::{resolve_error, KNOWN_TOOLS}; use crate::ModuleOrUniformRoot; use crate::Namespace::*; use crate::build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport}; use crate::resolve_imports::ImportResolver; -use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; +use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc::hir::def::{self, DefKind, NonMacroAttrKind}; use rustc::hir::map::DefCollector; use rustc::middle::stability; use rustc::{ty, lint, span_bug}; use syntax::ast::{self, Ident, ItemKind}; use syntax::attr::{self, StabilityLevel}; +use syntax::edition::Edition; use syntax::ext::base::{self, Indeterminate}; use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; @@ -182,21 +183,8 @@ impl<'a> base::Resolver for Resolver<'a> { invocation.output_legacy_scope.set(Some(visitor.current_legacy_scope)); } - fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc) { - let def_id = DefId { - krate: CrateNum::BuiltinMacros, - index: DefIndex::from(self.macro_map.len()), - }; - let kind = ext.macro_kind(); - self.macro_map.insert(def_id, ext); - let binding = self.arenas.alloc_name_binding(NameBinding { - kind: NameBindingKind::Res(Res::Def(DefKind::Macro(kind), def_id), false), - ambiguity: None, - span: DUMMY_SP, - vis: ty::Visibility::Public, - expansion: ExpnId::root(), - }); - if self.builtin_macros.insert(ident.name, binding).is_some() { + fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension) { + if self.builtin_macros.insert(ident.name, ext).is_some() { self.session.span_err(ident.span, &format!("built-in macro `{}` was already defined", ident)); } @@ -449,8 +437,8 @@ impl<'a> Resolver<'a> { let mut determinacy = Determinacy::Determined; // Go through all the scopes and try to resolve the name. - let break_result = - self.visit_scopes(scope_set, parent_scope, orig_ident, |this, scope, ident| { + let break_result = self.visit_scopes(scope_set, parent_scope, orig_ident, + |this, scope, use_prelude, ident| { let result = match scope { Scope::DeriveHelpers => { let mut result = Err(Determinacy::Determined); @@ -535,10 +523,6 @@ impl<'a> Resolver<'a> { this.graph_root.unresolved_invocations.borrow().is_empty() )) } - Scope::BuiltinMacros => match this.builtin_macros.get(&ident.name).cloned() { - Some(binding) => Ok((binding, Flags::PRELUDE)), - None => Err(Determinacy::Determined), - } Scope::BuiltinAttrs => if is_builtin_attr_name(ident.name) { let binding = (Res::NonMacroAttr(NonMacroAttrKind::Builtin), ty::Visibility::Public, DUMMY_SP, ExpnId::root()) @@ -579,7 +563,9 @@ impl<'a> Resolver<'a> { false, path_span, ) { - result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)); + if use_prelude || this.is_builtin_macro(binding.res().opt_def_id()) { + result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)); + } } } result @@ -844,18 +830,42 @@ impl<'a> Resolver<'a> { } } + /// Compile the macro into a `SyntaxExtension` and possibly replace it with a pre-defined + /// extension partially or entirely for built-in macros and legacy plugin macros. + crate fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> Lrc { + let mut result = macro_rules::compile( + &self.session.parse_sess, self.session.features_untracked(), item, edition + ); + + if result.is_builtin { + // The macro was marked with `#[rustc_builtin_macro]`. + if let Some(ext) = self.builtin_macros.remove(&item.ident.name) { + if ext.is_builtin { + // The macro is a built-in, replace only the expander function. + result.kind = ext.kind; + // Also reset its edition to the global one for compatibility. + result.edition = self.session.edition(); + } else { + // The macro is from a plugin, the in-source definition is dummy, + // take all the data from the resolver. + result = ext; + } + } else { + let msg = format!("cannot find a built-in macro with name `{}`", item.ident); + self.session.span_err(item.span, &msg); + } + } + + Lrc::new(result) + } + pub fn define_macro(&mut self, item: &ast::Item, expansion: ExpnId, current_legacy_scope: &mut LegacyScope<'a>) { let (ext, ident, span, is_legacy) = match &item.node { ItemKind::MacroDef(def) => { - let ext = Lrc::new(macro_rules::compile( - &self.session.parse_sess, - &self.session.features_untracked(), - item, - self.session.edition(), - )); + let ext = self.compile_macro(item, self.session.edition()); (ext, item.ident, item.span, def.legacy) } ItemKind::Fn(..) => match proc_macro_stub(item) { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 1960c06e86e4c..59438883d60bc 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -21,8 +21,8 @@ use rustc::lint::builtin::{ PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS, }; -use rustc::hir::def_id::{CrateNum, DefId}; -use rustc::hir::def::{self, DefKind, PartialRes, Export}; +use rustc::hir::def_id::DefId; +use rustc::hir::def::{self, PartialRes, Export}; use rustc::session::DiagnosticMessageId; use rustc::util::nodemap::FxHashSet; use rustc::{bug, span_bug}; @@ -1214,17 +1214,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // this may resolve to either a value or a type, but for documentation // purposes it's good enough to just favor one over the other. self.per_ns(|this, ns| if let Some(binding) = source_bindings[ns].get().ok() { - let mut res = binding.res(); - if let Res::Def(DefKind::Macro(_), def_id) = res { - // `DefId`s from the "built-in macro crate" should not leak from resolve because - // later stages are not ready to deal with them and produce lots of ICEs. Replace - // them with `Res::Err` until some saner scheme is implemented for built-in macros. - if def_id.krate == CrateNum::BuiltinMacros { - this.session.span_err(directive.span, "cannot import a built-in macro"); - res = Res::Err; - } - } - this.import_res_map.entry(directive.id).or_default()[ns] = Some(res); + this.import_res_map.entry(directive.id).or_default()[ns] = Some(binding.res()); }); self.check_for_redundant_imports( @@ -1388,7 +1378,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let res = binding.res(); if res != Res::Err { if let Some(def_id) = res.opt_def_id() { - if !def_id.is_local() && def_id.krate != CrateNum::BuiltinMacros { + if !def_id.is_local() { self.cstore.export_macros_untracked(def_id.krate); } } diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 5b1e78a113917..117a430eec6b9 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -254,8 +254,8 @@ impl<'a, E: Error + 'a> From for Box { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + Send + Sync + 'a> From for Box { - /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of dyn [`Error`] + - /// [`Send`] + [`Sync`]. + /// Converts a type of [`Error`] + [`trait@Send`] + [`trait@Sync`] into a box of + /// dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// @@ -298,7 +298,7 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box for Box { - /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// Converts a [`String`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// @@ -362,7 +362,7 @@ impl From for Box { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> From<&str> for Box { - /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// Converts a [`str`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// @@ -405,7 +405,7 @@ impl From<&str> for Box { #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a, 'b> From> for Box { - /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// Converts a [`Cow`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. /// /// [`Cow`]: ../borrow/enum.Cow.html /// [`Error`]: ../error/trait.Error.html diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index fbc68c610ee39..722c08a22a6b6 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -221,14 +221,15 @@ #![cfg_attr(test, feature(print_internals, set_stdio, test, update_panic_count))] #![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"), - feature(global_asm, slice_index_methods, - decl_macro, coerce_unsized, sgx_platform, ptr_wrapping_offset_from))] + feature(slice_index_methods, decl_macro, coerce_unsized, + sgx_platform, ptr_wrapping_offset_from))] #![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"), feature(fixed_size_array, maybe_uninit_extra))] // std is implemented with unstable features, many of which are internal // compiler details that will never be stable // NB: the following list is sorted to minimize merge conflicts. +#![cfg_attr(not(bootstrap), feature(__rust_unstable_column))] #![feature(alloc_error_handler)] #![feature(alloc_layout_extra)] #![feature(allocator_api)] @@ -251,6 +252,7 @@ #![feature(const_cstr_unchecked)] #![feature(const_raw_ptr_deref)] #![feature(core_intrinsics)] +#![feature(custom_test_frameworks)] #![feature(doc_alias)] #![feature(doc_cfg)] #![feature(doc_keyword)] @@ -262,7 +264,9 @@ #![feature(exhaustive_patterns)] #![feature(external_doc)] #![feature(fn_traits)] +#![feature(format_args_nl)] #![feature(generator_trait)] +#![feature(global_asm)] #![feature(hash_raw_entry)] #![feature(hashmap_internals)] #![feature(int_error_internals)] @@ -272,6 +276,7 @@ #![feature(libc)] #![feature(link_args)] #![feature(linkage)] +#![feature(log_syntax)] #![feature(maybe_uninit_ref)] #![feature(maybe_uninit_slice)] #![feature(mem_take)] @@ -303,6 +308,7 @@ #![feature(thread_local)] #![feature(todo_macro)] #![feature(toowned_clone_into)] +#![feature(trace_macros)] #![feature(try_reserve)] #![feature(unboxed_closures)] #![feature(untagged_unions)] @@ -510,6 +516,36 @@ mod std_detect; #[cfg(not(test))] pub use std_detect::detect; +// Document built-in macros in the crate root for consistency with libcore and existing tradition. +// FIXME: Attribute and derive macros are not reexported because rustdoc renders them +// as reexports rather than as macros, and that's not what we want. +#[cfg(rustdoc)] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +pub use crate::prelude::v1::{ + __rust_unstable_column, + asm, + assert, + cfg, + column, + compile_error, + concat, + concat_idents, + env, + file, + format_args, + format_args_nl, + global_asm, + include, + include_bytes, + include_str, + line, + log_syntax, + module_path, + option_env, + stringify, + trace_macros, +}; + // Include a number of private modules that exist solely to provide // the rustdoc documentation for primitive types. Using `include!` // because rustdoc only looks for these modules at the crate level. diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index b3e09d6974229..839b4c5656a09 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -365,534 +365,3 @@ macro_rules! assert_approx_eq { "{} is not approximately equal to {}", *a, *b); }) } - -/// Built-in macros to the compiler itself. -/// -/// These macros do not have any corresponding definition with a `macro_rules!` -/// macro, but are documented here. Their implementations can be found hardcoded -/// into libsyntax itself. -#[cfg(rustdoc)] -mod builtin { - - /// Causes compilation to fail with the given error message when encountered. - /// - /// This macro should be used when a crate uses a conditional compilation strategy to provide - /// better error messages for erroneous conditions. It's the compiler-level form of [`panic!`], - /// which emits an error at *runtime*, rather than during compilation. - /// - /// # Examples - /// - /// Two such examples are macros and `#[cfg]` environments. - /// - /// Emit better compiler error if a macro is passed invalid values. Without the final branch, - /// the compiler would still emit an error, but the error's message would not mention the two - /// valid values. - /// - /// ```compile_fail - /// macro_rules! give_me_foo_or_bar { - /// (foo) => {}; - /// (bar) => {}; - /// ($x:ident) => { - /// compile_error!("This macro only accepts `foo` or `bar`"); - /// } - /// } - /// - /// give_me_foo_or_bar!(neither); - /// // ^ will fail at compile time with message "This macro only accepts `foo` or `bar`" - /// ``` - /// - /// Emit compiler error if one of a number of features isn't available. - /// - /// ```compile_fail - /// #[cfg(not(any(feature = "foo", feature = "bar")))] - /// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate."); - /// ``` - /// - /// [`panic!`]: ../std/macro.panic.html - #[stable(feature = "compile_error_macro", since = "1.20.0")] - #[rustc_builtin_macro] - macro_rules! compile_error { - ($msg:expr) => ({ /* compiler built-in */ }); - ($msg:expr,) => ({ /* compiler built-in */ }); - } - - /// Constructs parameters for the other string-formatting macros. - /// - /// This macro functions by taking a formatting string literal containing - /// `{}` for each additional argument passed. `format_args!` prepares the - /// additional parameters to ensure the output can be interpreted as a string - /// and canonicalizes the arguments into a single type. Any value that implements - /// the [`Display`] trait can be passed to `format_args!`, as can any - /// [`Debug`] implementation be passed to a `{:?}` within the formatting string. - /// - /// This macro produces a value of type [`fmt::Arguments`]. This value can be - /// passed to the macros within [`std::fmt`] for performing useful redirection. - /// All other formatting macros ([`format!`], [`write!`], [`println!`], etc) are - /// proxied through this one. `format_args!`, unlike its derived macros, avoids - /// heap allocations. - /// - /// You can use the [`fmt::Arguments`] value that `format_args!` returns - /// in `Debug` and `Display` contexts as seen below. The example also shows - /// that `Debug` and `Display` format to the same thing: the interpolated - /// format string in `format_args!`. - /// - /// ```rust - /// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); - /// let display = format!("{}", format_args!("{} foo {:?}", 1, 2)); - /// assert_eq!("1 foo 2", display); - /// assert_eq!(display, debug); - /// ``` - /// - /// For more information, see the documentation in [`std::fmt`]. - /// - /// [`Display`]: ../std/fmt/trait.Display.html - /// [`Debug`]: ../std/fmt/trait.Debug.html - /// [`fmt::Arguments`]: ../std/fmt/struct.Arguments.html - /// [`std::fmt`]: ../std/fmt/index.html - /// [`format!`]: ../std/macro.format.html - /// [`write!`]: ../std/macro.write.html - /// [`println!`]: ../std/macro.println.html - /// - /// # Examples - /// - /// ``` - /// use std::fmt; - /// - /// let s = fmt::format(format_args!("hello {}", "world")); - /// assert_eq!(s, format!("hello {}", "world")); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! format_args { - ($fmt:expr) => ({ /* compiler built-in */ }); - ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }); - } - - /// Inspects an environment variable at compile time. - /// - /// This macro will expand to the value of the named environment variable at - /// compile time, yielding an expression of type `&'static str`. - /// - /// If the environment variable is not defined, then a compilation error - /// will be emitted. To not emit a compile error, use the [`option_env!`] - /// macro instead. - /// - /// [`option_env!`]: ../std/macro.option_env.html - /// - /// # Examples - /// - /// ``` - /// let path: &'static str = env!("PATH"); - /// println!("the $PATH variable at the time of compiling was: {}", path); - /// ``` - /// - /// You can customize the error message by passing a string as the second - /// parameter: - /// - /// ```compile_fail - /// let doc: &'static str = env!("documentation", "what's that?!"); - /// ``` - /// - /// If the `documentation` environment variable is not defined, you'll get - /// the following error: - /// - /// ```text - /// error: what's that?! - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! env { - ($name:expr) => ({ /* compiler built-in */ }); - ($name:expr,) => ({ /* compiler built-in */ }); - } - - /// Optionally inspects an environment variable at compile time. - /// - /// If the named environment variable is present at compile time, this will - /// expand into an expression of type `Option<&'static str>` whose value is - /// `Some` of the value of the environment variable. If the environment - /// variable is not present, then this will expand to `None`. See - /// [`Option`][option] for more information on this type. - /// - /// A compile time error is never emitted when using this macro regardless - /// of whether the environment variable is present or not. - /// - /// [option]: ../std/option/enum.Option.html - /// - /// # Examples - /// - /// ``` - /// let key: Option<&'static str> = option_env!("SECRET_KEY"); - /// println!("the secret key might be: {:?}", key); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! option_env { - ($name:expr) => ({ /* compiler built-in */ }); - ($name:expr,) => ({ /* compiler built-in */ }); - } - - /// Concatenates identifiers into one identifier. - /// - /// This macro takes any number of comma-separated identifiers, and - /// concatenates them all into one, yielding an expression which is a new - /// identifier. Note that hygiene makes it such that this macro cannot - /// capture local variables. Also, as a general rule, macros are only - /// allowed in item, statement or expression position. That means while - /// you may use this macro for referring to existing variables, functions or - /// modules etc, you cannot define a new one with it. - /// - /// # Examples - /// - /// ``` - /// #![feature(concat_idents)] - /// - /// # fn main() { - /// fn foobar() -> u32 { 23 } - /// - /// let f = concat_idents!(foo, bar); - /// println!("{}", f()); - /// - /// // fn concat_idents!(new, fun, name) { } // not usable in this way! - /// # } - /// ``` - #[unstable(feature = "concat_idents_macro", issue = "29599")] - #[rustc_builtin_macro] - macro_rules! concat_idents { - ($($e:ident),+) => ({ /* compiler built-in */ }); - ($($e:ident,)+) => ({ /* compiler built-in */ }); - } - - /// Concatenates literals into a static string slice. - /// - /// This macro takes any number of comma-separated literals, yielding an - /// expression of type `&'static str` which represents all of the literals - /// concatenated left-to-right. - /// - /// Integer and floating point literals are stringified in order to be - /// concatenated. - /// - /// # Examples - /// - /// ``` - /// let s = concat!("test", 10, 'b', true); - /// assert_eq!(s, "test10btrue"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! concat { - ($($e:expr),*) => ({ /* compiler built-in */ }); - ($($e:expr,)*) => ({ /* compiler built-in */ }); - } - - /// Expands to the line number on which it was invoked. - /// - /// With [`column!`] and [`file!`], these macros provide debugging information for - /// developers about the location within the source. - /// - /// The expanded expression has type `u32` and is 1-based, so the first line - /// in each file evaluates to 1, the second to 2, etc. This is consistent - /// with error messages by common compilers or popular editors. - /// The returned line is *not necessarily* the line of the `line!` invocation itself, - /// but rather the first macro invocation leading up to the invocation - /// of the `line!` macro. - /// - /// [`column!`]: macro.column.html - /// [`file!`]: macro.file.html - /// - /// # Examples - /// - /// ``` - /// let current_line = line!(); - /// println!("defined on line: {}", current_line); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! line { () => ({ /* compiler built-in */ }) } - - /// Expands to the column number at which it was invoked. - /// - /// With [`line!`] and [`file!`], these macros provide debugging information for - /// developers about the location within the source. - /// - /// The expanded expression has type `u32` and is 1-based, so the first column - /// in each line evaluates to 1, the second to 2, etc. This is consistent - /// with error messages by common compilers or popular editors. - /// The returned column is *not necessarily* the line of the `column!` invocation itself, - /// but rather the first macro invocation leading up to the invocation - /// of the `column!` macro. - /// - /// [`line!`]: macro.line.html - /// [`file!`]: macro.file.html - /// - /// # Examples - /// - /// ``` - /// let current_col = column!(); - /// println!("defined on column: {}", current_col); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! column { () => ({ /* compiler built-in */ }) } - - /// Expands to the file name in which it was invoked. - /// - /// With [`line!`] and [`column!`], these macros provide debugging information for - /// developers about the location within the source. - /// - /// - /// The expanded expression has type `&'static str`, and the returned file - /// is not the invocation of the `file!` macro itself, but rather the - /// first macro invocation leading up to the invocation of the `file!` - /// macro. - /// - /// [`line!`]: macro.line.html - /// [`column!`]: macro.column.html - /// - /// # Examples - /// - /// ``` - /// let this_file = file!(); - /// println!("defined in file: {}", this_file); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! file { () => ({ /* compiler built-in */ }) } - - /// Stringifies its arguments. - /// - /// This macro will yield an expression of type `&'static str` which is the - /// stringification of all the tokens passed to the macro. No restrictions - /// are placed on the syntax of the macro invocation itself. - /// - /// Note that the expanded results of the input tokens may change in the - /// future. You should be careful if you rely on the output. - /// - /// # Examples - /// - /// ``` - /// let one_plus_one = stringify!(1 + 1); - /// assert_eq!(one_plus_one, "1 + 1"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! stringify { ($($t:tt)*) => ({ /* compiler built-in */ }) } - - /// Includes a utf8-encoded file as a string. - /// - /// The file is located relative to the current file. (similarly to how - /// modules are found) - /// - /// This macro will yield an expression of type `&'static str` which is the - /// contents of the file. - /// - /// # Examples - /// - /// Assume there are two files in the same directory with the following - /// contents: - /// - /// File 'spanish.in': - /// - /// ```text - /// adiós - /// ``` - /// - /// File 'main.rs': - /// - /// ```ignore (cannot-doctest-external-file-dependency) - /// fn main() { - /// let my_str = include_str!("spanish.in"); - /// assert_eq!(my_str, "adiós\n"); - /// print!("{}", my_str); - /// } - /// ``` - /// - /// Compiling 'main.rs' and running the resulting binary will print "adiós". - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! include_str { - ($file:expr) => ({ /* compiler built-in */ }); - ($file:expr,) => ({ /* compiler built-in */ }); - } - - /// Includes a file as a reference to a byte array. - /// - /// The file is located relative to the current file. (similarly to how - /// modules are found) - /// - /// This macro will yield an expression of type `&'static [u8; N]` which is - /// the contents of the file. - /// - /// # Examples - /// - /// Assume there are two files in the same directory with the following - /// contents: - /// - /// File 'spanish.in': - /// - /// ```text - /// adiós - /// ``` - /// - /// File 'main.rs': - /// - /// ```ignore (cannot-doctest-external-file-dependency) - /// fn main() { - /// let bytes = include_bytes!("spanish.in"); - /// assert_eq!(bytes, b"adi\xc3\xb3s\n"); - /// print!("{}", String::from_utf8_lossy(bytes)); - /// } - /// ``` - /// - /// Compiling 'main.rs' and running the resulting binary will print "adiós". - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! include_bytes { - ($file:expr) => ({ /* compiler built-in */ }); - ($file:expr,) => ({ /* compiler built-in */ }); - } - - /// Expands to a string that represents the current module path. - /// - /// The current module path can be thought of as the hierarchy of modules - /// leading back up to the crate root. The first component of the path - /// returned is the name of the crate currently being compiled. - /// - /// # Examples - /// - /// ``` - /// mod test { - /// pub fn foo() { - /// assert!(module_path!().ends_with("test")); - /// } - /// } - /// - /// test::foo(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! module_path { () => ({ /* compiler built-in */ }) } - - /// Evaluates boolean combinations of configuration flags at compile-time. - /// - /// In addition to the `#[cfg]` attribute, this macro is provided to allow - /// boolean expression evaluation of configuration flags. This frequently - /// leads to less duplicated code. - /// - /// The syntax given to this macro is the same syntax as the [`cfg`] - /// attribute. - /// - /// [`cfg`]: ../reference/conditional-compilation.html#the-cfg-attribute - /// - /// # Examples - /// - /// ``` - /// let my_directory = if cfg!(windows) { - /// "windows-specific-directory" - /// } else { - /// "unix-directory" - /// }; - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) } - - /// Parses a file as an expression or an item according to the context. - /// - /// The file is located relative to the current file (similarly to how - /// modules are found). - /// - /// Using this macro is often a bad idea, because if the file is - /// parsed as an expression, it is going to be placed in the - /// surrounding code unhygienically. This could result in variables - /// or functions being different from what the file expected if - /// there are variables or functions that have the same name in - /// the current file. - /// - /// # Examples - /// - /// Assume there are two files in the same directory with the following - /// contents: - /// - /// File 'monkeys.in': - /// - /// ```ignore (only-for-syntax-highlight) - /// ['🙈', '🙊', '🙉'] - /// .iter() - /// .cycle() - /// .take(6) - /// .collect::() - /// ``` - /// - /// File 'main.rs': - /// - /// ```ignore (cannot-doctest-external-file-dependency) - /// fn main() { - /// let my_string = include!("monkeys.in"); - /// assert_eq!("🙈🙊🙉🙈🙊🙉", my_string); - /// println!("{}", my_string); - /// } - /// ``` - /// - /// Compiling 'main.rs' and running the resulting binary will print - /// "🙈🙊🙉🙈🙊🙉". - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! include { - ($file:expr) => ({ /* compiler built-in */ }); - ($file:expr,) => ({ /* compiler built-in */ }); - } - - /// Asserts that a boolean expression is `true` at runtime. - /// - /// This will invoke the [`panic!`] macro if the provided expression cannot be - /// evaluated to `true` at runtime. - /// - /// # Uses - /// - /// Assertions are always checked in both debug and release builds, and cannot - /// be disabled. See [`debug_assert!`] for assertions that are not enabled in - /// release builds by default. - /// - /// Unsafe code relies on `assert!` to enforce run-time invariants that, if - /// violated could lead to unsafety. - /// - /// Other use-cases of `assert!` include testing and enforcing run-time - /// invariants in safe code (whose violation cannot result in unsafety). - /// - /// # Custom Messages - /// - /// This macro has a second form, where a custom panic message can - /// be provided with or without arguments for formatting. See [`std::fmt`] - /// for syntax for this form. - /// - /// [`panic!`]: macro.panic.html - /// [`debug_assert!`]: macro.debug_assert.html - /// [`std::fmt`]: ../std/fmt/index.html - /// - /// # Examples - /// - /// ``` - /// // the panic message for these assertions is the stringified value of the - /// // expression given. - /// assert!(true); - /// - /// fn some_computation() -> bool { true } // a very simple function - /// - /// assert!(some_computation()); - /// - /// // assert with a custom message - /// let x = true; - /// assert!(x, "x wasn't true!"); - /// - /// let a = 3; let b = 27; - /// assert!(a + b == 30, "a = {}, b = {}", a, b); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! assert { - ($cond:expr) => ({ /* compiler built-in */ }); - ($cond:expr,) => ({ /* compiler built-in */ }); - ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ }); - } -} diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index a863bebf4a264..7b12d2ee6f081 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -7,9 +7,13 @@ #![stable(feature = "rust1", since = "1.0.0")] // Re-exported core operators +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] -pub use crate::marker::{Copy, Send, Sized, Sync, Unpin}; +pub use crate::marker::Copy; +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] +pub use crate::marker::{Send, Sized, Sync, Unpin}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::ops::{Drop, Fn, FnMut, FnOnce}; @@ -20,15 +24,18 @@ pub use crate::ops::{Drop, Fn, FnMut, FnOnce}; pub use crate::mem::drop; // Re-exported types and traits +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::clone::Clone; +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::cmp::{PartialEq, PartialOrd, Eq, Ord}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::convert::{AsRef, AsMut, Into, From}; +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::default::Default; @@ -45,6 +52,60 @@ pub use crate::option::Option::{self, Some, None}; #[doc(no_inline)] pub use crate::result::Result::{self, Ok, Err}; +// Re-exported built-in macros +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(no_inline)] +pub use core::prelude::v1::{ + __rust_unstable_column, + asm, + assert, + cfg, + column, + compile_error, + concat, + concat_idents, + env, + file, + format_args, + format_args_nl, + global_asm, + include, + include_bytes, + include_str, + line, + log_syntax, + module_path, + option_env, + stringify, + trace_macros, +}; + +// FIXME: Attribute and derive macros are not documented because for them rustdoc generates +// dead links which fail link checker testing. +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow(deprecated)] +#[doc(hidden)] +pub use core::prelude::v1::{ + Clone, + Copy, + Debug, + Decodable, + Default, + Encodable, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, + RustcDecodable, + RustcEncodable, + bench, + global_allocator, + test, + test_case, +}; // The file so far is equivalent to src/libcore/prelude/v1.rs, // and below to src/liballoc/prelude.rs. diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 11b7a984aaa00..0ab14bee160da 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -592,6 +592,9 @@ pub struct SyntaxExtension { pub helper_attrs: Vec, /// Edition of the crate in which this macro is defined. pub edition: Edition, + /// Built-in macros have a couple of special properties (meaning of `$crate`, + /// availability in `#[no_implicit_prelude]` modules), so we have to keep this flag. + pub is_builtin: bool, } impl SyntaxExtensionKind { @@ -636,6 +639,7 @@ impl SyntaxExtension { deprecation: None, helper_attrs: Vec::new(), edition, + is_builtin: false, kind, } } @@ -687,7 +691,7 @@ pub trait Resolver { fn resolve_dollar_crates(&mut self); fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment, derives: &[ExpnId]); - fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc); + fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension); fn resolve_imports(&mut self); diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 4503cea0f10c8..c76e964b5e7d7 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -437,6 +437,7 @@ pub fn compile( deprecation: attr::find_deprecation(&sess, &def.attrs, def.span), helper_attrs: Vec::new(), edition, + is_builtin: attr::contains_name(&def.attrs, sym::rustc_builtin_macro), } } diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index e491e93256d1c..1a86509928841 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -1,11 +1,7 @@ //! The compiler code necessary to implement the `#[derive]` extensions. -use rustc_data_structures::sync::Lrc; use syntax::ast::{self, MetaItem}; -use syntax::attr::Deprecation; -use syntax::edition::Edition; -use syntax::ext::base::{Annotatable, ExtCtxt, Resolver, MultiItemModifier}; -use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; +use syntax::ext::base::{Annotatable, ExtCtxt, MultiItemModifier}; use syntax::ext::build::AstBuilder; use syntax::ptr::P; use syntax::symbol::{Symbol, sym}; @@ -43,8 +39,8 @@ pub mod ord; pub mod generic; -struct BuiltinDerive( - fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable)) +crate struct BuiltinDerive( + crate fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable)) ); impl MultiItemModifier for BuiltinDerive { @@ -60,82 +56,6 @@ impl MultiItemModifier for BuiltinDerive { } } -macro_rules! derive_traits { - ($( [$deprecation:expr] $name:ident => $func:path, )+) => { - pub fn is_builtin_trait(name: ast::Name) -> bool { - match name { - $( sym::$name )|+ => true, - _ => false, - } - } - - pub fn register_builtin_derives(resolver: &mut dyn Resolver, edition: Edition) { - let allow_internal_unstable = Some([ - sym::core_intrinsics, - sym::rustc_attrs, - Symbol::intern("derive_clone_copy"), - Symbol::intern("derive_eq"), - Symbol::intern("libstd_sys_internals"), // RustcDeserialize and RustcSerialize - ][..].into()); - - $( - resolver.add_builtin( - ast::Ident::with_empty_ctxt(sym::$name), - Lrc::new(SyntaxExtension { - deprecation: $deprecation.map(|msg| Deprecation { - since: Some(Symbol::intern("1.0.0")), - note: Some(Symbol::intern(msg)), - }), - allow_internal_unstable: allow_internal_unstable.clone(), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($func))), - edition, - ) - }), - ); - )+ - } - } -} - -derive_traits! { - [None] - Clone => clone::expand_deriving_clone, - - [None] - Hash => hash::expand_deriving_hash, - - [None] - RustcEncodable => encodable::expand_deriving_rustc_encodable, - - [None] - RustcDecodable => decodable::expand_deriving_rustc_decodable, - - [None] - PartialEq => partial_eq::expand_deriving_partial_eq, - [None] - Eq => eq::expand_deriving_eq, - [None] - PartialOrd => partial_ord::expand_deriving_partial_ord, - [None] - Ord => ord::expand_deriving_ord, - - [None] - Debug => debug::expand_deriving_debug, - - [None] - Default => default::expand_deriving_default, - - [None] - Copy => bounds::expand_deriving_copy, - - // deprecated - [Some("derive(Encodable) is deprecated in favor of derive(RustcEncodable)")] - Encodable => encodable::expand_deriving_encodable, - [Some("derive(Decodable) is deprecated in favor of derive(RustcDecodable)")] - Decodable => decodable::expand_deriving_decodable, -} - /// Construct a name for the inner type parameter that can't collide with any type parameters of /// the item. This is achieved by starting with a base and then concatenating the names of all /// other type parameters. diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 400bfe796bb07..7940abed24597 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -5,19 +5,25 @@ #![deny(rust_2018_idioms)] #![deny(unused_lifetimes)] -#![feature(in_band_lifetimes)] +#![feature(crate_visibility_modifier)] +#![feature(decl_macro)] +#![feature(nll)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] #![feature(proc_macro_span)] -#![feature(decl_macro)] -#![feature(nll)] #![feature(rustc_diagnostic_macros)] #![feature(unicode_internals)] -#![recursion_limit="256"] - extern crate proc_macro; +use crate::deriving::*; + +use syntax::ast::Ident; +use syntax::edition::Edition; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, MacroExpanderFn}; +use syntax::ext::source_util; +use syntax::symbol::sym; + mod error_codes; mod asm; @@ -38,147 +44,71 @@ mod test_case; mod trace_macros; pub mod deriving; +pub mod plugin_macro_defs; pub mod proc_macro_decls; pub mod proc_macro_impl; -use rustc_data_structures::sync::Lrc; -use syntax::ast; -use syntax::attr::Stability; -use syntax::ext::base::MacroExpanderFn; -use syntax::ext::base::{NamedSyntaxExtension, SyntaxExtension, SyntaxExtensionKind}; -use syntax::edition::Edition; -use syntax::symbol::{sym, Symbol}; - -const EXPLAIN_ASM: &str = - "inline assembly is not stable enough for use and is subject to change"; -const EXPLAIN_GLOBAL_ASM: &str = - "`global_asm!` is not stable enough for use and is subject to change"; -const EXPLAIN_CUSTOM_TEST_FRAMEWORKS: &str = - "custom test frameworks are an unstable feature"; -const EXPLAIN_LOG_SYNTAX: &str = - "`log_syntax!` is not stable enough for use and is subject to change"; -const EXPLAIN_CONCAT_IDENTS: &str = - "`concat_idents` is not stable enough for use and is subject to change"; -const EXPLAIN_FORMAT_ARGS_NL: &str = - "`format_args_nl` is only for internal language use and is subject to change"; -const EXPLAIN_TRACE_MACROS: &str = - "`trace_macros` is not stable enough for use and is subject to change"; -const EXPLAIN_UNSTABLE_COLUMN: &str = - "internal implementation detail of the `column` macro"; - -pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, - user_exts: Vec, - edition: Edition) { - deriving::register_builtin_derives(resolver, edition); - - let mut register = |name, ext| { - resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Lrc::new(ext)); - }; - - macro_rules! register { - ($( $name:ident: $f:expr, )*) => { $( - register(sym::$name, SyntaxExtension::default( - SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)), edition - )); - )* } +pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, edition: Edition) { + let mut register = |name, kind| resolver.register_builtin_macro( + Ident::with_empty_ctxt(name), SyntaxExtension { + is_builtin: true, ..SyntaxExtension::default(kind, edition) + }, + ); + macro register_bang($($name:ident: $f:expr,)*) { + $(register(sym::$name, SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)));)* + } + macro register_attr($($name:ident: $f:expr,)*) { + $(register(sym::$name, SyntaxExtensionKind::LegacyAttr(Box::new($f)));)* } - macro_rules! register_unstable { - ($( [$feature:expr, $reason:expr, $issue:expr] $name:ident: $f:expr, )*) => { $( - register(sym::$name, SyntaxExtension { - stability: Some(Stability::unstable( - $feature, Some(Symbol::intern($reason)), $issue - )), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)), edition - ) - }); - )* } + macro register_derive($($name:ident: $f:expr,)*) { + $(register(sym::$name, SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($f))));)* } - use syntax::ext::source_util::*; - register! { - line: expand_line, - column: expand_column, - file: expand_file, - stringify: expand_stringify, - include: expand_include, - include_str: expand_include_str, - include_bytes: expand_include_bytes, - module_path: expand_mod, + register_bang! { + __rust_unstable_column: source_util::expand_column, + asm: asm::expand_asm, + assert: assert::expand_assert, cfg: cfg::expand_cfg, + column: source_util::expand_column, + compile_error: compile_error::expand_compile_error, + concat_idents: concat_idents::expand_syntax_ext, concat: concat::expand_syntax_ext, env: env::expand_env, - option_env: env::expand_option_env, - compile_error: compile_error::expand_compile_error, - assert: assert::expand_assert, - } - - register_unstable! { - [sym::__rust_unstable_column, EXPLAIN_UNSTABLE_COLUMN, 0] - __rust_unstable_column: expand_column, - [sym::asm, EXPLAIN_ASM, 29722] - asm: asm::expand_asm, - [sym::global_asm, EXPLAIN_GLOBAL_ASM, 35119] + file: source_util::expand_file, + format_args_nl: format::expand_format_args_nl, + format_args: format::expand_format_args, global_asm: global_asm::expand_global_asm, - [sym::concat_idents, EXPLAIN_CONCAT_IDENTS, 29599] - concat_idents: concat_idents::expand_syntax_ext, - [sym::log_syntax, EXPLAIN_LOG_SYNTAX, 29598] + include_bytes: source_util::expand_include_bytes, + include_str: source_util::expand_include_str, + include: source_util::expand_include, + line: source_util::expand_line, log_syntax: log_syntax::expand_syntax_ext, - [sym::trace_macros, EXPLAIN_TRACE_MACROS, 29598] + module_path: source_util::expand_mod, + option_env: env::expand_option_env, + stringify: source_util::expand_stringify, trace_macros: trace_macros::expand_trace_macros, } - let allow_internal_unstable = Some([sym::test, sym::rustc_attrs][..].into()); - register(sym::test_case, SyntaxExtension { - stability: Some(Stability::unstable( - sym::custom_test_frameworks, - Some(Symbol::intern(EXPLAIN_CUSTOM_TEST_FRAMEWORKS)), - 50297, - )), - allow_internal_unstable: allow_internal_unstable.clone(), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyAttr(Box::new(test_case::expand)), edition - ) - }); - register(sym::test, SyntaxExtension { - allow_internal_unstable: allow_internal_unstable.clone(), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_test)), edition - ) - }); - register(sym::bench, SyntaxExtension { - allow_internal_unstable, - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_bench)), edition - ) - }); - register(sym::global_allocator, SyntaxExtension { - allow_internal_unstable: Some([sym::rustc_attrs][..].into()), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyAttr(Box::new(global_allocator::expand)), edition - ) - }); - - let allow_internal_unstable = Some([sym::fmt_internals][..].into()); - register(sym::format_args, SyntaxExtension { - allow_internal_unstable: allow_internal_unstable.clone(), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args)), edition - ) - }); - register(sym::format_args_nl, SyntaxExtension { - stability: Some(Stability::unstable( - sym::format_args_nl, - Some(Symbol::intern(EXPLAIN_FORMAT_ARGS_NL)), - 0, - )), - allow_internal_unstable, - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args_nl)), edition - ) - }); + register_attr! { + bench: test::expand_bench, + global_allocator: global_allocator::expand, + test: test::expand_test, + test_case: test_case::expand, + } - for (name, ext) in user_exts { - register(name, ext); + register_derive! { + Clone: clone::expand_deriving_clone, + Copy: bounds::expand_deriving_copy, + Debug: debug::expand_deriving_debug, + Decodable: decodable::expand_deriving_decodable, + Default: default::expand_deriving_default, + Encodable: encodable::expand_deriving_encodable, + Eq: eq::expand_deriving_eq, + Hash: hash::expand_deriving_hash, + Ord: ord::expand_deriving_ord, + PartialEq: partial_eq::expand_deriving_partial_eq, + PartialOrd: partial_ord::expand_deriving_partial_ord, + RustcDecodable: decodable::expand_deriving_rustc_decodable, + RustcEncodable: encodable::expand_deriving_rustc_encodable, } } diff --git a/src/libsyntax_ext/plugin_macro_defs.rs b/src/libsyntax_ext/plugin_macro_defs.rs new file mode 100644 index 0000000000000..2fd1a42db95f3 --- /dev/null +++ b/src/libsyntax_ext/plugin_macro_defs.rs @@ -0,0 +1,64 @@ +//! Each macro must have a definition, so `#[plugin]` attributes +//! inject a dummy `macro_rules` item for each macro they define. + +use syntax::ast::*; +use syntax::attr; +use syntax::edition::Edition; +use syntax::ext::base::{Resolver, NamedSyntaxExtension}; +use syntax::parse::token; +use syntax::ptr::P; +use syntax::source_map::respan; +use syntax::symbol::sym; +use syntax::tokenstream::*; +use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::hygiene::{ExpnId, ExpnInfo, ExpnKind, MacroKind}; + +use std::mem; + +fn plugin_macro_def(name: Name, span: Span) -> P { + let rustc_builtin_macro = Attribute { + id: attr::mk_attr_id(), + style: AttrStyle::Outer, + path: Path::from_ident(Ident::new(sym::rustc_builtin_macro, span)), + tokens: TokenStream::empty(), + is_sugared_doc: false, + span, + }; + + let parens: TreeAndJoint = TokenTree::Delimited( + DelimSpan::from_single(span), token::Paren, TokenStream::empty() + ).into(); + let trees = vec![parens.clone(), TokenTree::token(token::FatArrow, span).into(), parens]; + + P(Item { + ident: Ident::new(name, span), + attrs: vec![rustc_builtin_macro], + id: DUMMY_NODE_ID, + node: ItemKind::MacroDef(MacroDef { tokens: TokenStream::new(trees), legacy: true }), + vis: respan(span, VisibilityKind::Inherited), + span: span, + tokens: None, + }) +} + +pub fn inject( + krate: &mut Crate, + resolver: &mut dyn Resolver, + named_exts: Vec, + edition: Edition, +) { + if !named_exts.is_empty() { + let mut extra_items = Vec::new(); + let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable( + ExpnKind::Macro(MacroKind::Attr, sym::plugin), DUMMY_SP, edition, + [sym::rustc_attrs][..].into(), + )); + for (name, ext) in named_exts { + resolver.register_builtin_macro(Ident::with_empty_ctxt(name), ext); + extra_items.push(plugin_macro_def(name, span)); + } + // The `macro_rules` items must be inserted before any other items. + mem::swap(&mut extra_items, &mut krate.module.items); + krate.module.items.append(&mut extra_items); + } +} diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index 08c40dde56c85..303d5f00deb1a 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -1,7 +1,5 @@ use std::mem; -use crate::deriving; - use syntax::ast::{self, Ident}; use syntax::attr; use syntax::source_map::{ExpnInfo, ExpnKind, respan}; @@ -136,10 +134,6 @@ impl<'a> CollectProcMacros<'a> { self.handler.span_err(trait_attr.span, &format!("`{}` cannot be a name of derive macro", trait_ident)); } - if deriving::is_builtin_trait(trait_ident.name) { - self.handler.span_err(trait_attr.span, - "cannot override a built-in derive macro"); - } let attributes_attr = list.get(1); let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { diff --git a/src/test/run-make-fulldeps/simd-ffi/simd.rs b/src/test/run-make-fulldeps/simd-ffi/simd.rs index b834e5cc463a4..75d95a4eaf146 100644 --- a/src/test/run-make-fulldeps/simd-ffi/simd.rs +++ b/src/test/run-make-fulldeps/simd-ffi/simd.rs @@ -5,7 +5,7 @@ #![feature(no_core, optin_builtin_traits)] #![no_core] -#![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items)] +#![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items, rustc_attrs)] #[repr(C)] @@ -74,3 +74,7 @@ pub mod marker { #[lang = "freeze"] auto trait Freeze {} + +#[macro_export] +#[rustc_builtin_macro] +macro_rules! Copy { () => () } diff --git a/src/test/rustdoc/intra-link-builtin-macros.rs b/src/test/rustdoc/intra-link-builtin-macros.rs new file mode 100644 index 0000000000000..4d40eb3b88f1b --- /dev/null +++ b/src/test/rustdoc/intra-link-builtin-macros.rs @@ -0,0 +1,3 @@ +// @has intra_link_builtin_macros/index.html +// @has - '//a/@href' 'https://doc.rust-lang.org/nightly/core/macro.cfg.html' +//! [cfg] diff --git a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs index 86441b4f73548..c2685c7f74c30 100644 --- a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs @@ -3,20 +3,21 @@ #![feature(plugin_registrar)] #![feature(rustc_private)] -extern crate syntax; - -extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; +extern crate rustc_plugin; +extern crate syntax; -use syntax::symbol::Symbol; -use syntax::feature_gate::AttributeType; use rustc_plugin::Registry; - +use syntax::ext::base::SyntaxExtension; +use syntax::feature_gate::AttributeType; +use syntax::symbol::Symbol; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { reg.register_attribute(Symbol::intern("foo"), AttributeType::Normal); reg.register_attribute(Symbol::intern("bar"), AttributeType::CrateLevel); reg.register_attribute(Symbol::intern("baz"), AttributeType::Whitelisted); + reg.register_syntax_extension( + Symbol::intern("mac"), SyntaxExtension::dummy_bang(reg.sess.edition()) + ); } diff --git a/src/test/ui-fulldeps/deprecated-derive.stderr b/src/test/ui-fulldeps/deprecated-derive.stderr index efaf82d9be165..1518c0cc541d2 100644 --- a/src/test/ui-fulldeps/deprecated-derive.stderr +++ b/src/test/ui-fulldeps/deprecated-derive.stderr @@ -2,7 +2,7 @@ warning: use of deprecated item 'Encodable': derive(Encodable) is deprecated in --> $DIR/deprecated-derive.rs:8:10 | LL | #[derive(Encodable)] - | ^^^^^^^^^ + | ^^^^^^^^^ help: replace the use of the deprecated item: `RustcEncodable` | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/plugin-reexport.rs b/src/test/ui-fulldeps/plugin-reexport.rs new file mode 100644 index 0000000000000..4d8ede1680830 --- /dev/null +++ b/src/test/ui-fulldeps/plugin-reexport.rs @@ -0,0 +1,10 @@ +// edition:2018 +// aux-build:attr-plugin-test.rs +// ignore-stage1 + +#![feature(plugin)] +#![plugin(attr_plugin_test)] + +pub use mac as reexport; //~ ERROR `mac` is private, and cannot be re-exported + +fn main() {} diff --git a/src/test/ui-fulldeps/plugin-reexport.stderr b/src/test/ui-fulldeps/plugin-reexport.stderr new file mode 100644 index 0000000000000..4ac64b8d04b87 --- /dev/null +++ b/src/test/ui-fulldeps/plugin-reexport.stderr @@ -0,0 +1,15 @@ +error[E0364]: `mac` is private, and cannot be re-exported + --> $DIR/plugin-reexport.rs:8:9 + | +LL | pub use mac as reexport; + | ^^^^^^^^^^^^^^^ + | +note: consider marking `mac` as `pub` in the imported module + --> $DIR/plugin-reexport.rs:8:9 + | +LL | pub use mac as reexport; + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0364`. diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs b/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs index 2d8868995f435..31eee88d1fac6 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs @@ -1,17 +1,10 @@ -// error-pattern: `main` function not found - -// At time of authorship, a crate-level #![bench] with no `--test` -// will cause compilation to error unconditionally with "main function -// not found" (despite having one), similar to #[bench]. -// -// (The non-crate level cases are in -// issue-43106-gating-of-builtin-attrs.rs.) - +// The non-crate level cases are in issue-43106-gating-of-builtin-attrs.rs. // See issue-12997-1.rs and issue-12997-2.rs to see how `#[bench]` is // handled in "weird places" when `--test` is passed. #![feature(custom_inner_attributes)] #![bench = "4100"] +//~^ ERROR cannot determine resolution for the attribute macro `bench` -fn main() { } +fn main() {} diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr index 37b5e792dc239..d0305c5160f7e 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr @@ -1,17 +1,10 @@ -warning: attribute must be of the form `#[bench]` - --> $DIR/issue-43106-gating-of-bench.rs:15:1 +error: cannot determine resolution for the attribute macro `bench` + --> $DIR/issue-43106-gating-of-bench.rs:7:4 | LL | #![bench = "4100"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ | - = note: `#[warn(ill_formed_attribute_input)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 - -error[E0601]: `main` function not found in crate `issue_43106_gating_of_bench` - | - = note: consider adding a `main` function to `$DIR/issue-43106-gating-of-bench.rs` + = note: import resolution is stuck, try simplifying macro imports error: aborting due to previous error -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.rs b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs index c0c49d353007c..d343746955f39 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-test.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs @@ -1,12 +1,6 @@ -// error-pattern: `main` function not found - -// At time of authorship, crate-level #[test] attribute with no -// `--test` signals unconditional error complaining of missing main -// function (despite having one), similar to #[bench]. -// -// (The non-crate level cases are in -// issue-43106-gating-of-builtin-attrs.rs.) +// The non-crate level cases are in issue-43106-gating-of-builtin-attrs.rs. #![test = "4200"] +//~^ ERROR cannot determine resolution for the attribute macro `test` -fn main() { } +fn main() {} diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr index dbffabf3e02f9..a7d3a1e16840e 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr @@ -1,17 +1,10 @@ -warning: attribute must be of the form `#[test]` - --> $DIR/issue-43106-gating-of-test.rs:10:1 +error: cannot determine resolution for the attribute macro `test` + --> $DIR/issue-43106-gating-of-test.rs:3:4 | LL | #![test = "4200"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ | - = note: `#[warn(ill_formed_attribute_input)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 - -error[E0601]: `main` function not found in crate `issue_43106_gating_of_test` - | - = note: consider adding a `main` function to `$DIR/issue-43106-gating-of-test.rs` + = note: import resolution is stuck, try simplifying macro imports error: aborting due to previous error -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs index 827ac3af8f1fa..506b21dc7d544 100644 --- a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs +++ b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs @@ -1,4 +1,4 @@ -#![feature(intrinsics, lang_items, no_core)] +#![feature(intrinsics, lang_items, no_core, rustc_attrs)] #![crate_type="rlib"] #![no_core] @@ -88,3 +88,7 @@ fn main() { cfg!(target_has_atomic = "ptr"); //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change } + +#[macro_export] +#[rustc_builtin_macro] +macro_rules! cfg { () => () } diff --git a/src/test/ui/imports/glob-shadowing.stderr b/src/test/ui/imports/glob-shadowing.stderr index 7962fcb9aec1d..4ef446f93c860 100644 --- a/src/test/ui/imports/glob-shadowing.stderr +++ b/src/test/ui/imports/glob-shadowing.stderr @@ -4,7 +4,7 @@ error[E0659]: `env` is ambiguous (glob import vs any other name from outer scope LL | let x = env!("PATH"); | ^^^ ambiguous name | - = note: `env` could refer to a built-in macro + = note: `env` could refer to a macro from prelude note: `env` could also refer to the macro imported here --> $DIR/glob-shadowing.rs:9:9 | @@ -19,7 +19,7 @@ error[E0659]: `env` is ambiguous (glob import vs any other name from outer scope LL | let x = env!("PATH"); | ^^^ ambiguous name | - = note: `env` could refer to a built-in macro + = note: `env` could refer to a macro from prelude note: `env` could also refer to the macro imported here --> $DIR/glob-shadowing.rs:17:13 | diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr index 13d3227d8b38f..5afdd8889ae7d 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr @@ -27,7 +27,7 @@ error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded LL | include!(); | ^^^^^^^ ambiguous name | - = note: `include` could refer to a built-in macro + = note: `include` could refer to a macro from prelude note: `include` could also refer to the macro defined here --> $DIR/local-modularized-tricky-fail-1.rs:17:5 | diff --git a/src/test/ui/issues/issue-28134.rs b/src/test/ui/issues/issue-28134.rs index 2bd4f93791d38..fa692db4bf66c 100644 --- a/src/test/ui/issues/issue-28134.rs +++ b/src/test/ui/issues/issue-28134.rs @@ -1,3 +1,3 @@ // compile-flags: --test -#![test] //~ ERROR only functions may be used as tests +#![test] //~ ERROR cannot determine resolution for the attribute macro `test` diff --git a/src/test/ui/issues/issue-28134.stderr b/src/test/ui/issues/issue-28134.stderr index b9189480048d8..5f8d27dd043b1 100644 --- a/src/test/ui/issues/issue-28134.stderr +++ b/src/test/ui/issues/issue-28134.stderr @@ -1,8 +1,10 @@ -error: only functions may be used as tests - --> $DIR/issue-28134.rs:3:1 +error: cannot determine resolution for the attribute macro `test` + --> $DIR/issue-28134.rs:3:4 | LL | #![test] - | ^^^^^^^^ + | ^^^^ + | + = note: import resolution is stuck, try simplifying macro imports error: aborting due to previous error diff --git a/src/test/ui/macros/unknown-builtin.rs b/src/test/ui/macros/unknown-builtin.rs new file mode 100644 index 0000000000000..a96b99ae4ff78 --- /dev/null +++ b/src/test/ui/macros/unknown-builtin.rs @@ -0,0 +1,14 @@ +// error-pattern: cannot find a built-in macro with name `line` + +#![feature(rustc_attrs)] + +#[rustc_builtin_macro] +macro_rules! unknown { () => () } //~ ERROR cannot find a built-in macro with name `unknown` + +#[rustc_builtin_macro] +macro_rules! line { () => () } + +fn main() { + line!(); + std::prelude::v1::line!(); +} diff --git a/src/test/ui/macros/unknown-builtin.stderr b/src/test/ui/macros/unknown-builtin.stderr new file mode 100644 index 0000000000000..33b7b055b4e4b --- /dev/null +++ b/src/test/ui/macros/unknown-builtin.stderr @@ -0,0 +1,14 @@ +error: cannot find a built-in macro with name `unknown` + --> $DIR/unknown-builtin.rs:6:1 + | +LL | macro_rules! unknown { () => () } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot find a built-in macro with name `line` + --> <::core::macros::builtin::line macros>:1:1 + | +LL | () => { } + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/proc-macro/attribute.rs b/src/test/ui/proc-macro/attribute.rs index 04c88dcef50ac..5531b32362125 100644 --- a/src/test/ui/proc-macro/attribute.rs +++ b/src/test/ui/proc-macro/attribute.rs @@ -40,8 +40,7 @@ pub fn foo8(input: TokenStream) -> TokenStream { input } //~^ ERROR: `self` cannot be a name of derive macro pub fn foo9(input: TokenStream) -> TokenStream { input } -#[proc_macro_derive(PartialEq)] -//~^ ERROR: cannot override a built-in derive macro +#[proc_macro_derive(PartialEq)] // OK pub fn foo10(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d11, a)] diff --git a/src/test/ui/proc-macro/attribute.stderr b/src/test/ui/proc-macro/attribute.stderr index e632875cb16e5..1503f62cb6c1a 100644 --- a/src/test/ui/proc-macro/attribute.stderr +++ b/src/test/ui/proc-macro/attribute.stderr @@ -40,56 +40,50 @@ error: `self` cannot be a name of derive macro LL | #[proc_macro_derive(self)] | ^^^^ -error: cannot override a built-in derive macro - --> $DIR/attribute.rs:43:21 - | -LL | #[proc_macro_derive(PartialEq)] - | ^^^^^^^^^ - error: second argument must be `attributes` - --> $DIR/attribute.rs:47:26 + --> $DIR/attribute.rs:46:26 | LL | #[proc_macro_derive(d11, a)] | ^ error: attribute must be of form: `attributes(foo, bar)` - --> $DIR/attribute.rs:47:26 + --> $DIR/attribute.rs:46:26 | LL | #[proc_macro_derive(d11, a)] | ^ error: attribute must be of form: `attributes(foo, bar)` - --> $DIR/attribute.rs:52:26 + --> $DIR/attribute.rs:51:26 | LL | #[proc_macro_derive(d12, attributes)] | ^^^^^^^^^^ error: not a meta item - --> $DIR/attribute.rs:56:37 + --> $DIR/attribute.rs:55:37 | LL | #[proc_macro_derive(d13, attributes("a"))] | ^^^ error: must only be one word - --> $DIR/attribute.rs:60:37 + --> $DIR/attribute.rs:59:37 | LL | #[proc_macro_derive(d14, attributes(a = ""))] | ^^^^^^ error: must only be one word - --> $DIR/attribute.rs:64:37 + --> $DIR/attribute.rs:63:37 | LL | #[proc_macro_derive(d15, attributes(m::a))] | ^^^^ error: must only be one word - --> $DIR/attribute.rs:68:37 + --> $DIR/attribute.rs:67:37 | LL | #[proc_macro_derive(d16, attributes(a(b)))] | ^^^^ error: `self` cannot be a name of derive helper attribute - --> $DIR/attribute.rs:72:37 + --> $DIR/attribute.rs:71:37 | LL | #[proc_macro_derive(d17, attributes(self))] | ^^^^ @@ -106,5 +100,5 @@ error: malformed `proc_macro_derive` attribute input LL | #[proc_macro_derive = ""] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` -error: aborting due to 18 previous errors +error: aborting due to 17 previous errors diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs index dd21de75aaf75..acb4bbebe7f53 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs +++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs @@ -3,7 +3,7 @@ // Tests that arbitrary crates (other than `core`, `std` and `meta`) // aren't allowed without `--extern`, even if they're in the sysroot. use alloc; //~ ERROR unresolved import `alloc` -use test; //~ ERROR cannot import a built-in macro +use test; // OK, imports the built-in attribute macro `#[test]`, but not the `test` crate. use proc_macro; // OK, imports the built-in `proc_macro` attribute, but not the `proc_macro` crate. fn main() {} diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr index 4e3fff98e6f4b..f324378d4ca68 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr +++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr @@ -1,15 +1,9 @@ -error: cannot import a built-in macro - --> $DIR/not-whitelisted.rs:6:5 - | -LL | use test; - | ^^^^ - error[E0432]: unresolved import `alloc` --> $DIR/not-whitelisted.rs:5:5 | LL | use alloc; | ^^^^^ no `alloc` external crate -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs b/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs index d717884c901b3..48c33d720dcad 100644 --- a/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs +++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs @@ -1,11 +1,6 @@ // edition:2018 -// Built-in macro -use env as env_imported; //~ ERROR cannot import a built-in macro - // Tool attribute use rustfmt::skip as imported_rustfmt_skip; //~ ERROR unresolved import `rustfmt` -fn main() { - env_imported!("PATH"); -} +fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr b/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr index 42daf7c6fb12f..97d4c736751aa 100644 --- a/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr +++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr @@ -1,15 +1,9 @@ -error: cannot import a built-in macro - --> $DIR/prelude-fail.rs:4:5 - | -LL | use env as env_imported; - | ^^^^^^^^^^^^^^^^^^^ - error[E0432]: unresolved import `rustfmt` - --> $DIR/prelude-fail.rs:7:5 + --> $DIR/prelude-fail.rs:4:5 | LL | use rustfmt::skip as imported_rustfmt_skip; | ^^^^^^^ `rustfmt` is a tool module, not a module -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rust-2018/uniform-paths/prelude.rs b/src/test/ui/rust-2018/uniform-paths/prelude.rs index dca9587c5d369..65763614ce028 100644 --- a/src/test/ui/rust-2018/uniform-paths/prelude.rs +++ b/src/test/ui/rust-2018/uniform-paths/prelude.rs @@ -10,9 +10,13 @@ use Vec as ImportedVec; // Built-in type use u8 as imported_u8; +// Built-in macro +use env as env_imported; + type A = imported_u8; fn main() { imported_vec![0]; ImportedVec::::new(); + env_imported!("PATH"); } diff --git a/src/test/ui/rust-unstable-column-gated.stderr b/src/test/ui/rust-unstable-column-gated.stderr index c581a16dbb038..7db1b01fb0e63 100644 --- a/src/test/ui/rust-unstable-column-gated.stderr +++ b/src/test/ui/rust-unstable-column-gated.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature '__rust_unstable_column': internal implementation detail of the `column` macro +error[E0658]: use of unstable library feature '__rust_unstable_column': internal implementation detail of the `panic` macro --> $DIR/rust-unstable-column-gated.rs:2:20 | LL | println!("{}", __rust_unstable_column!());