Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Improve documentation for built-in macros #62243

Merged
merged 6 commits into from
Jul 7, 2019
Merged
Show file tree
Hide file tree
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
Expand Up @@ -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)]
Expand Down
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
Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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
}
Expand Down
16 changes: 11 additions & 5 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 16 additions & 5 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -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);
Expand Down
20 changes: 5 additions & 15 deletions src/librustc_resolve/resolve_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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) {
Expand Down
32 changes: 16 additions & 16 deletions src/libstd/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 */ });
Expand Down Expand Up @@ -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 */ });
Expand Down Expand Up @@ -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 */ });
Expand All @@ -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 */ });
Expand Down Expand Up @@ -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 */ });
Expand All @@ -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 */ });
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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 */ });
Expand Down Expand Up @@ -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 */ });
Expand All @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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 */ });
Expand Down Expand Up @@ -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 */ });
Expand Down
33 changes: 33 additions & 0 deletions src/libsyntax/attr/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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
Expand Up @@ -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::*;
Expand Down
Loading