Skip to content

Improve documentation for built-in macros #62243

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 7, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
@@ -75,6 +75,7 @@
#![feature(const_fn)]
#![feature(const_fn_union)]
#![feature(custom_inner_attributes)]
#![feature(decl_macro)]
#![feature(doc_cfg)]
#![feature(doc_spotlight)]
#![feature(extern_types)]
719 changes: 628 additions & 91 deletions src/libcore/macros.rs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
@@ -4010,7 +4010,7 @@ impl<'a> LoweringContext<'a> {
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_doc_only_macro) {
attr::contains_name(&i.attrs, sym::rustc_builtin_macro) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed anymore? The macro_rules! -> macro change would mean !def.legacy is now true.

Copy link
Contributor Author

@petrochenkov petrochenkov Jul 1, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this is no longer needed (UPD: for libcore, it's still needed for libstd).

let body = self.lower_token_stream(def.stream());
let hir_id = self.lower_node_id(i.id);
self.exported_macros.push(hir::MacroDef {
3 changes: 2 additions & 1 deletion src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@ use rustc_data_structures::fx::FxHashSet;
use syntax::ast::Ident;
use syntax::attr;
use syntax::symbol::{kw, sym};
use syntax_pos::hygiene::Transparency;
use syntax_pos::Span;

use std::{cmp, fmt, mem};
@@ -743,7 +744,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
}

fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
if md.legacy {
if attr::find_transparency(&md.attrs, md.legacy).0 != Transparency::Opaque {
self.update(md.hir_id, Some(AccessLevel::Public));
return
}
16 changes: 11 additions & 5 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
@@ -770,27 +770,33 @@ impl<'a> Resolver<'a> {
}

pub fn get_macro(&mut self, res: Res) -> Lrc<SyntaxExtension> {
self.opt_get_macro(res).expect("expected `DefKind::Macro` or `Res::NonMacroAttr`")
}

crate fn opt_get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
let def_id = match res {
Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) =>
return Some(self.non_macro_attr(true)), // some dummy extension
Res::Def(DefKind::Macro(..), def_id) => def_id,
Res::NonMacroAttr(attr_kind) =>
return self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool),
_ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
return Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
_ => return None,
};
if let Some(ext) = self.macro_map.get(&def_id) {
return ext.clone();
return Some(ext.clone());
}

let macro_def = match self.cstore.load_macro_untracked(def_id, &self.session) {
LoadedMacro::MacroDef(macro_def) => macro_def,
LoadedMacro::ProcMacro(ext) => return ext,
LoadedMacro::ProcMacro(ext) => return Some(ext),
};

let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
&self.session.features_untracked(),
&macro_def,
self.cstore.crate_edition_untracked(def_id.krate)));
self.macro_map.insert(def_id, ext.clone());
ext
Some(ext)
}

/// Ensures that the reduced graph rooted at the given external module
21 changes: 16 additions & 5 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
@@ -1106,6 +1106,19 @@ impl<'a> Resolver<'a> {
});
}

crate fn check_reserved_macro_name(&mut self, ident: Ident, res: Res) {
// Reserve some names that are not quite covered by the general check
// performed on `Resolver::builtin_attrs`.
if ident.name == sym::cfg || ident.name == sym::cfg_attr || ident.name == sym::derive {
let macro_kind = self.opt_get_macro(res).map(|ext| ext.macro_kind());
if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) {
self.session.span_err(
ident.span, &format!("name `{}` is reserved in attribute namespace", ident)
);
}
}
}

pub fn define_macro(&mut self,
item: &ast::Item,
expansion: Mark,
@@ -1117,13 +1130,14 @@ impl<'a> Resolver<'a> {
let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
&self.session.features_untracked(),
item, self.session.edition()));
let macro_kind = ext.macro_kind();
let res = Res::Def(DefKind::Macro(macro_kind), def_id);
self.macro_map.insert(def_id, ext);

let def = match item.node { ast::ItemKind::MacroDef(ref def) => def, _ => unreachable!() };
if def.legacy {
let ident = ident.modern();
self.macro_names.insert(ident);
let res = Res::Def(DefKind::Macro(MacroKind::Bang), def_id);
let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export);
let vis = if is_macro_export {
ty::Visibility::Public
@@ -1142,14 +1156,11 @@ impl<'a> Resolver<'a> {
self.define(module, ident, MacroNS,
(res, vis, item.span, expansion, IsMacroExport));
} else {
if !attr::contains_name(&item.attrs, sym::rustc_doc_only_macro) {
self.check_reserved_macro_name(ident, MacroNS);
}
self.check_reserved_macro_name(ident, res);
self.unused_macros.insert(def_id);
}
} else {
let module = self.current_module;
let res = Res::Def(DefKind::Macro(MacroKind::Bang), def_id);
let vis = self.resolve_visibility(&item.vis);
if vis != ty::Visibility::Public {
self.unused_macros.insert(def_id);
20 changes: 5 additions & 15 deletions src/librustc_resolve/resolve_imports.rs
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ use rustc::{bug, span_bug};
use syntax::ast::{self, Ident, Name, NodeId, CRATE_NODE_ID};
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
use syntax::ext::hygiene::Mark;
use syntax::symbol::{kw, sym};
use syntax::symbol::kw;
use syntax::util::lev_distance::find_best_match_for_name;
use syntax::{struct_span_err, unwrap_or};
use syntax_pos::{MultiSpan, Span};
@@ -492,35 +492,25 @@ impl<'a> Resolver<'a> {
})
}

crate fn check_reserved_macro_name(&self, ident: Ident, ns: Namespace) {
// Reserve some names that are not quite covered by the general check
// performed on `Resolver::builtin_attrs`.
if ns == MacroNS &&
(ident.name == sym::cfg || ident.name == sym::cfg_attr ||
ident.name == sym::derive) {
self.session.span_err(ident.span,
&format!("name `{}` is reserved in macro namespace", ident));
}
}

// Define the name or return the existing binding if there is a collision.
pub fn try_define(&mut self,
module: Module<'a>,
ident: Ident,
ns: Namespace,
binding: &'a NameBinding<'a>)
-> Result<(), &'a NameBinding<'a>> {
self.check_reserved_macro_name(ident, ns);
let res = binding.res();
self.check_reserved_macro_name(ident, res);
self.set_binding_parent_module(binding, module);
self.update_resolution(module, ident, ns, |this, resolution| {
if let Some(old_binding) = resolution.binding {
if binding.res() == Res::Err {
if res == Res::Err {
// Do not override real bindings with `Res::Err`s from error recovery.
return Ok(());
}
match (old_binding.is_glob_import(), binding.is_glob_import()) {
(true, true) => {
if binding.res() != old_binding.res() {
if res != old_binding.res() {
resolution.binding = Some(this.ambiguity(AmbiguityKind::GlobVsGlob,
old_binding, binding));
} else if !old_binding.vis.is_at_least(binding.vis, &*this) {
32 changes: 16 additions & 16 deletions src/libstd/macros.rs
Original file line number Diff line number Diff line change
@@ -410,7 +410,7 @@ mod builtin {
///
/// [`panic!`]: ../std/macro.panic.html
#[stable(feature = "compile_error_macro", since = "1.20.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! compile_error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, these are unchanged. What needs to happen before these can just be reexports of the libcore ones?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rustc_builtin_macro stubs acting like the real macros.

#62086 removes the duplicate macros from libstd, but also pub uses their libcore versions from libstd's root (for documentation).
...And stub macros pub used in libstd root break all the dependent crates that inject #[macro_use] extern crate std during rustdoc build.

Alternatively, some doc attribute for selectively documenting private items would also solve the problem (pub use could be replaced with #[doc(force)] use then).

($msg:expr) => ({ /* compiler built-in */ });
($msg:expr,) => ({ /* compiler built-in */ });
@@ -462,7 +462,7 @@ mod builtin {
/// assert_eq!(s, format!("hello {}", "world"));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! format_args {
($fmt:expr) => ({ /* compiler built-in */ });
($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ });
@@ -500,7 +500,7 @@ mod builtin {
/// error: what's that?!
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! env {
($name:expr) => ({ /* compiler built-in */ });
($name:expr,) => ({ /* compiler built-in */ });
@@ -526,7 +526,7 @@ mod builtin {
/// println!("the secret key might be: {:?}", key);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! option_env {
($name:expr) => ({ /* compiler built-in */ });
($name:expr,) => ({ /* compiler built-in */ });
@@ -557,7 +557,7 @@ mod builtin {
/// # }
/// ```
#[unstable(feature = "concat_idents_macro", issue = "29599")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! concat_idents {
($($e:ident),+) => ({ /* compiler built-in */ });
($($e:ident,)+) => ({ /* compiler built-in */ });
@@ -579,7 +579,7 @@ mod builtin {
/// assert_eq!(s, "test10btrue");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! concat {
($($e:expr),*) => ({ /* compiler built-in */ });
($($e:expr,)*) => ({ /* compiler built-in */ });
@@ -607,7 +607,7 @@ mod builtin {
/// println!("defined on line: {}", current_line);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! line { () => ({ /* compiler built-in */ }) }

/// Expands to the column number at which it was invoked.
@@ -632,7 +632,7 @@ mod builtin {
/// println!("defined on column: {}", current_col);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! column { () => ({ /* compiler built-in */ }) }

/// Expands to the file name in which it was invoked.
@@ -656,7 +656,7 @@ mod builtin {
/// println!("defined in file: {}", this_file);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! file { () => ({ /* compiler built-in */ }) }

/// Stringifies its arguments.
@@ -675,7 +675,7 @@ mod builtin {
/// assert_eq!(one_plus_one, "1 + 1");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! stringify { ($($t:tt)*) => ({ /* compiler built-in */ }) }

/// Includes a utf8-encoded file as a string.
@@ -709,7 +709,7 @@ mod builtin {
///
/// Compiling 'main.rs' and running the resulting binary will print "adiós".
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! include_str {
($file:expr) => ({ /* compiler built-in */ });
($file:expr,) => ({ /* compiler built-in */ });
@@ -746,7 +746,7 @@ mod builtin {
///
/// Compiling 'main.rs' and running the resulting binary will print "adiós".
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! include_bytes {
($file:expr) => ({ /* compiler built-in */ });
($file:expr,) => ({ /* compiler built-in */ });
@@ -770,7 +770,7 @@ mod builtin {
/// test::foo();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! module_path { () => ({ /* compiler built-in */ }) }

/// Evaluates boolean combinations of configuration flags at compile-time.
@@ -794,7 +794,7 @@ mod builtin {
/// };
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) }

/// Parses a file as an expression or an item according to the context.
@@ -837,7 +837,7 @@ mod builtin {
/// Compiling 'main.rs' and running the resulting binary will print
/// "🙈🙊🙉🙈🙊🙉".
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! include {
($file:expr) => ({ /* compiler built-in */ });
($file:expr,) => ({ /* compiler built-in */ });
@@ -889,7 +889,7 @@ mod builtin {
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_doc_only_macro]
#[rustc_builtin_macro]
macro_rules! assert {
($cond:expr) => ({ /* compiler built-in */ });
($cond:expr,) => ({ /* compiler built-in */ });
33 changes: 33 additions & 0 deletions src/libsyntax/attr/builtin.rs
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ use crate::feature_gate::{Features, GatedCfg};
use crate::parse::ParseSess;

use errors::{Applicability, Handler};
use syntax_pos::hygiene::Transparency;
use syntax_pos::{symbol::Symbol, symbol::sym, Span};

use super::{mark_used, MetaItemKind};
@@ -854,3 +855,35 @@ fn int_type_of_word(s: Symbol) -> Option<IntType> {
_ => None
}
}

pub enum TransparencyError {
UnknownTransparency(Symbol, Span),
MultipleTransparencyAttrs(Span, Span),
}

pub fn find_transparency(
attrs: &[Attribute], is_legacy: bool
) -> (Transparency, Option<TransparencyError>) {
let mut transparency = None;
let mut error = None;
for attr in attrs {
if attr.check_name(sym::rustc_macro_transparency) {
if let Some((_, old_span)) = transparency {
error = Some(TransparencyError::MultipleTransparencyAttrs(old_span, attr.span));
break;
} else if let Some(value) = attr.value_str() {
transparency = Some((match &*value.as_str() {
"transparent" => Transparency::Transparent,
"semitransparent" => Transparency::SemiTransparent,
"opaque" => Transparency::Opaque,
_ => {
error = Some(TransparencyError::UnknownTransparency(value, attr.span));
continue;
}
}, attr.span));
}
}
}
let fallback = if is_legacy { Transparency::SemiTransparent } else { Transparency::Opaque };
(transparency.map_or(fallback, |t| t.0), error)
}
6 changes: 1 addition & 5 deletions src/libsyntax/attr/mod.rs
Original file line number Diff line number Diff line change
@@ -2,11 +2,7 @@

mod builtin;

pub use builtin::{
cfg_matches, contains_feature_attr, eval_condition, find_crate_name, find_deprecation,
find_repr_attrs, find_stability, find_unwind_attr, Deprecation, InlineAttr, OptimizeAttr,
IntType, ReprAttr, RustcDeprecation, Stability, StabilityLevel, UnwindAttr,
};
pub use builtin::*;
pub use IntType::*;
pub use ReprAttr::*;
pub use StabilityLevel::*;
Loading