name = "rustc_privacy"
version = "0.0.0"
dependencies = [
+ "rustc_ast",
"rustc_attr",
"rustc_data_structures",
"rustc_errors",
self.lower_item_id_use_tree(use_tree, i.id, &mut vec);
vec
}
- ItemKind::MacroDef(..) => SmallVec::new(),
ItemKind::Fn(..) | ItemKind::Impl(box ImplKind { of_trait: None, .. }) => {
smallvec![i.id]
}
pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item<'hir>> {
let mut ident = i.ident;
let mut vis = self.lower_visibility(&i.vis, None);
-
- if let ItemKind::MacroDef(MacroDef { ref body, macro_rules }) = i.kind {
- if !macro_rules || self.sess.contains_name(&i.attrs, sym::macro_export) {
- let hir_id = self.lower_node_id(i.id);
- self.lower_attrs(hir_id, &i.attrs);
- let body = P(self.lower_mac_args(body));
- self.insert_macro_def(hir::MacroDef {
- ident,
- vis,
- def_id: hir_id.expect_owner(),
- span: i.span,
- ast: MacroDef { body, macro_rules },
- });
- } else {
- for a in i.attrs.iter() {
- let a = self.lower_attr(a);
- self.non_exported_macro_attrs.push(a);
- }
- }
- return None;
- }
-
let hir_id = self.lower_node_id(i.id);
let attrs = self.lower_attrs(hir_id, &i.attrs);
let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, &mut vis, &i.kind);
self.lower_generics(generics, ImplTraitContext::disallowed()),
self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
),
- ItemKind::MacroDef(..) | ItemKind::MacCall(..) => {
+ ItemKind::MacroDef(MacroDef { ref body, macro_rules }) => {
+ let body = P(self.lower_mac_args(body));
+
+ hir::ItemKind::Macro(ast::MacroDef { body, macro_rules })
+ }
+ ItemKind::MacCall(..) => {
panic!("`TyMac` should have been expanded by now")
}
}
/// The items being lowered are collected here.
owners: IndexVec<LocalDefId, Option<hir::OwnerNode<'hir>>>,
bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
- non_exported_macro_attrs: Vec<ast::Attribute>,
trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
trait_impls: BTreeMap::new(),
modules: BTreeMap::new(),
attrs: BTreeMap::default(),
- non_exported_macro_attrs: Vec::new(),
catch_scopes: Vec::new(),
loop_scopes: Vec::new(),
is_in_loop_condition: false,
}
let krate = hir::Crate {
- non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs),
owners: self.owners,
bodies: self.bodies,
body_ids,
id
}
- fn insert_macro_def(&mut self, item: hir::MacroDef<'hir>) {
- let def_id = item.def_id;
- let item = self.arena.alloc(item);
- self.owners.ensure_contains_elem(def_id, || None);
- self.owners[def_id] = Some(hir::OwnerNode::MacroDef(item));
- }
-
fn allocate_hir_id_counter(&mut self, owner: NodeId) -> hir::HirId {
// Set up the counter if needed.
self.item_local_id_counters.entry(owner).or_insert(0);
}
}
+ fn print_mac_def(
+ &mut self,
+ macro_def: &ast::MacroDef,
+ ident: &Ident,
+ sp: &Span,
+ print_visibility: impl FnOnce(&mut Self),
+ ) {
+ let (kw, has_bang) = if macro_def.macro_rules {
+ ("macro_rules", true)
+ } else {
+ print_visibility(self);
+ ("macro", false)
+ };
+ self.print_mac_common(
+ Some(MacHeader::Keyword(kw)),
+ has_bang,
+ Some(*ident),
+ macro_def.body.delim(),
+ ¯o_def.body.inner_tokens(),
+ true,
+ *sp,
+ );
+ if macro_def.body.need_semicolon() {
+ self.word(";");
+ }
+ }
+
fn print_path(&mut self, path: &ast::Path, colons_before_params: bool, depth: usize) {
self.maybe_print_comment(path.span.lo());
}
}
ast::ItemKind::MacroDef(ref macro_def) => {
- let (kw, has_bang) = if macro_def.macro_rules {
- ("macro_rules", true)
- } else {
- self.print_visibility(&item.vis);
- ("macro", false)
- };
- self.print_mac_common(
- Some(MacHeader::Keyword(kw)),
- has_bang,
- Some(item.ident),
- macro_def.body.delim(),
- ¯o_def.body.inner_tokens(),
- true,
- item.span,
- );
- if macro_def.body.need_semicolon() {
- self.word(";");
- }
+ self.print_mac_def(macro_def, &item.ident, &item.span, |state| {
+ state.print_visibility(&item.vis)
+ });
}
}
self.ann.post(self, AnnNode::Item(item))
InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {}
InlineAsmArch::Hexagon => {}
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {}
+ InlineAsmArch::S390x => {}
InlineAsmArch::SpirV => {}
InlineAsmArch::Wasm32 => {}
InlineAsmArch::Bpf => {}
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
+ InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("LLVM backend does not support SPIR-V")
}
}
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
InlineAsmRegClass::Bpf(_) => None,
+ InlineAsmRegClass::S390x(_) => None,
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("LLVM backend does not support SPIR-V")
}
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(),
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(),
+ InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => cx.type_i32(),
+ InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(),
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("LLVM backend does not support SPIR-V")
}
[few] inline_asm: rustc_hir::InlineAsm<$tcx>,
[few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
[] local: rustc_hir::Local<$tcx>,
- [few] macro_def: rustc_hir::MacroDef<$tcx>,
[few] mod_: rustc_hir::Mod<$tcx>,
[] param: rustc_hir::Param<$tcx>,
[] pat: rustc_hir::Pat<$tcx>,
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
#[derive(Debug)]
pub struct Crate<'hir> {
- // Attributes from non-exported macros, kept only for collecting the library feature list.
- pub non_exported_macro_attrs: &'hir [Attribute],
-
pub owners: IndexVec<LocalDefId, Option<OwnerNode<'hir>>>,
pub bodies: BTreeMap<BodyId, Body<'hir>>,
pub trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
OwnerNode::ImplItem(item) => visitor.visit_impl_item(item),
OwnerNode::TraitItem(item) => visitor.visit_trait_item(item),
- OwnerNode::MacroDef(_) | OwnerNode::Crate(_) => {}
+ OwnerNode::Crate(_) => {}
}
}
}
Some(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item),
Some(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item),
Some(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item),
- Some(OwnerNode::MacroDef(_)) | Some(OwnerNode::Crate(_)) | None => {}
+ Some(OwnerNode::Crate(_)) | None => {}
})
}
_ => None,
})
}
-
- pub fn exported_macros<'hir>(&'hir self) -> impl Iterator<Item = &'hir MacroDef<'hir>> + 'hir {
- self.owners.iter().filter_map(|owner| match owner {
- Some(OwnerNode::MacroDef(macro_def)) => Some(*macro_def),
- _ => None,
- })
- }
-}
-
-/// A macro definition, in this crate or imported from another.
-///
-/// Not parsed directly, but created on macro import or `macro_rules!` expansion.
-#[derive(Debug)]
-pub struct MacroDef<'hir> {
- pub ident: Ident,
- pub vis: Visibility<'hir>,
- pub def_id: LocalDefId,
- pub span: Span,
- pub ast: ast::MacroDef,
-}
-
-impl MacroDef<'_> {
- #[inline]
- pub fn hir_id(&self) -> HirId {
- HirId::make_owner(self.def_id)
- }
}
/// A block of statements `{ .. }`, which may have a label (in this case the
pub type Visibility<'hir> = Spanned<VisibilityKind<'hir>>;
-#[derive(Debug)]
+#[derive(Copy, Clone, Debug)]
pub enum VisibilityKind<'hir> {
Public,
Crate(CrateSugar),
Const(&'hir Ty<'hir>, BodyId),
/// A function declaration.
Fn(FnSig<'hir>, Generics<'hir>, BodyId),
+ /// A MBE macro definition (`macro_rules!` or `macro`).
+ Macro(ast::MacroDef),
/// A module.
Mod(Mod<'hir>),
/// An external module, e.g. `extern { .. }`.
ItemKind::Static(..) => "static item",
ItemKind::Const(..) => "constant item",
ItemKind::Fn(..) => "function",
+ ItemKind::Macro(..) => "macro",
ItemKind::Mod(..) => "module",
ItemKind::ForeignMod { .. } => "extern block",
ItemKind::GlobalAsm(..) => "global asm item",
ForeignItem(&'hir ForeignItem<'hir>),
TraitItem(&'hir TraitItem<'hir>),
ImplItem(&'hir ImplItem<'hir>),
- MacroDef(&'hir MacroDef<'hir>),
Crate(&'hir Mod<'hir>),
}
OwnerNode::Item(Item { ident, .. })
| OwnerNode::ForeignItem(ForeignItem { ident, .. })
| OwnerNode::ImplItem(ImplItem { ident, .. })
- | OwnerNode::TraitItem(TraitItem { ident, .. })
- | OwnerNode::MacroDef(MacroDef { ident, .. }) => Some(*ident),
+ | OwnerNode::TraitItem(TraitItem { ident, .. }) => Some(*ident),
OwnerNode::Crate(..) => None,
}
}
| OwnerNode::ForeignItem(ForeignItem { span, .. })
| OwnerNode::ImplItem(ImplItem { span, .. })
| OwnerNode::TraitItem(TraitItem { span, .. })
- | OwnerNode::MacroDef(MacroDef { span, .. })
| OwnerNode::Crate(Mod { inner: span, .. }) => *span,
}
}
OwnerNode::Item(Item { def_id, .. })
| OwnerNode::TraitItem(TraitItem { def_id, .. })
| OwnerNode::ImplItem(ImplItem { def_id, .. })
- | OwnerNode::ForeignItem(ForeignItem { def_id, .. })
- | OwnerNode::MacroDef(MacroDef { def_id, .. }) => *def_id,
+ | OwnerNode::ForeignItem(ForeignItem { def_id, .. }) => *def_id,
OwnerNode::Crate(..) => crate::CRATE_HIR_ID.owner,
}
}
_ => panic!(),
}
}
-
- pub fn expect_macro_def(self) -> &'hir MacroDef<'hir> {
- match self {
- OwnerNode::MacroDef(n) => n,
- _ => panic!(),
- }
- }
}
impl<'hir> Into<OwnerNode<'hir>> for &'hir Item<'hir> {
}
}
-impl<'hir> Into<OwnerNode<'hir>> for &'hir MacroDef<'hir> {
- fn into(self) -> OwnerNode<'hir> {
- OwnerNode::MacroDef(self)
- }
-}
-
impl<'hir> Into<Node<'hir>> for OwnerNode<'hir> {
fn into(self) -> Node<'hir> {
match self {
OwnerNode::ForeignItem(n) => Node::ForeignItem(n),
OwnerNode::ImplItem(n) => Node::ImplItem(n),
OwnerNode::TraitItem(n) => Node::TraitItem(n),
- OwnerNode::MacroDef(n) => Node::MacroDef(n),
OwnerNode::Crate(n) => Node::Crate(n),
}
}
Arm(&'hir Arm<'hir>),
Block(&'hir Block<'hir>),
Local(&'hir Local<'hir>),
- MacroDef(&'hir MacroDef<'hir>),
/// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants
/// with synthesized constructors.
| Node::ForeignItem(ForeignItem { ident, .. })
| Node::Field(FieldDef { ident, .. })
| Node::Variant(Variant { ident, .. })
- | Node::MacroDef(MacroDef { ident, .. })
| Node::Item(Item { ident, .. })
| Node::PathSegment(PathSegment { ident, .. }) => Some(*ident),
Node::Lifetime(lt) => Some(lt.name.ident()),
Node::Item(Item { def_id, .. })
| Node::TraitItem(TraitItem { def_id, .. })
| Node::ImplItem(ImplItem { def_id, .. })
- | Node::ForeignItem(ForeignItem { def_id, .. })
- | Node::MacroDef(MacroDef { def_id, .. }) => Some(HirId::make_owner(*def_id)),
+ | Node::ForeignItem(ForeignItem { def_id, .. }) => Some(HirId::make_owner(*def_id)),
Node::Field(FieldDef { hir_id, .. })
| Node::AnonConst(AnonConst { hir_id, .. })
| Node::Expr(Expr { hir_id, .. })
Node::ForeignItem(i) => Some(OwnerNode::ForeignItem(i)),
Node::TraitItem(i) => Some(OwnerNode::TraitItem(i)),
Node::ImplItem(i) => Some(OwnerNode::ImplItem(i)),
- Node::MacroDef(i) => Some(OwnerNode::MacroDef(i)),
Node::Crate(i) => Some(OwnerNode::Crate(i)),
_ => None,
}
walk_assoc_type_binding(self, type_binding)
}
fn visit_attribute(&mut self, _id: HirId, _attr: &'v Attribute) {}
- fn visit_macro_def(&mut self, macro_def: &'v MacroDef<'v>) {
- walk_macro_def(self, macro_def)
- }
fn visit_vis(&mut self, vis: &'v Visibility<'v>) {
walk_vis(self, vis)
}
pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) {
let top_mod = krate.module();
visitor.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID);
- walk_list!(visitor, visit_macro_def, krate.exported_macros());
for (&id, attrs) in krate.attrs.iter() {
for a in *attrs {
visitor.visit_attribute(id, a)
}
}
-pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef<'v>) {
- visitor.visit_id(macro_def.hir_id());
- visitor.visit_ident(macro_def.ident);
-}
-
pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) {
visitor.visit_id(mod_hir_id);
for &item_id in module.item_ids {
item.span,
item.hir_id(),
),
+ ItemKind::Macro(_) => {
+ visitor.visit_id(item.hir_id());
+ }
ItemKind::Mod(ref module) => {
// `visit_mod()` takes care of visiting the `Item`'s `HirId`.
visitor.visit_mod(module, item.span, item.hir_id())
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
use crate::hir::{
- BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, MacroDef, Mod,
- TraitItem, TraitItemId, Ty, VisibilityKind,
+ BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem,
+ TraitItemId, Ty, VisibilityKind,
};
use crate::hir_id::{HirId, ItemLocalId};
use rustc_span::def_id::DefPathHash;
});
}
}
-
-impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for MacroDef<'_> {
- fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
- let MacroDef { ident, def_id: _, ref ast, ref vis, span } = *self;
-
- hcx.hash_hir_item_like(|hcx| {
- ident.name.hash_stable(hcx, hasher);
- ast.hash_stable(hcx, hasher);
- vis.hash_stable(hcx, hasher);
- span.hash_stable(hcx, hasher);
- });
- }
-}
ItemKind::Static(..) => Target::Static,
ItemKind::Const(..) => Target::Const,
ItemKind::Fn(..) => Target::Fn,
+ ItemKind::Macro(..) => Target::MacroDef,
ItemKind::Mod(..) => Target::Mod,
ItemKind::ForeignMod { .. } => Target::ForeignMod,
ItemKind::GlobalAsm(..) => Target::GlobalAsm,
// printing.
Node::Ctor(..) => panic!("cannot print isolated Ctor"),
Node::Local(a) => self.print_local_decl(&a),
- Node::MacroDef(_) => panic!("cannot print MacroDef"),
Node::Crate(..) => panic!("cannot print Crate"),
}
}
self.end(); // need to close a box
self.ann.nested(self, Nested::Body(body));
}
+ hir::ItemKind::Macro(ref macro_def) => {
+ self.print_mac_def(macro_def, &item.ident, &item.span, |state| {
+ state.print_visibility(&item.vis)
+ });
+ }
hir::ItemKind::Mod(ref _mod) => {
self.head(visibility_qualified(&item.vis, "mod"));
self.print_ident(item.ident);
fn check_crate(&mut self, cx: &LateContext<'_>, krate: &hir::Crate<'_>) {
self.check_missing_docs_attrs(cx, CRATE_DEF_ID, krate.module().inner, "the", "crate");
-
- for macro_def in krate.exported_macros() {
- // Non exported macros should be skipped, since `missing_docs` only
- // applies to externally visible items.
- if !cx.access_levels.is_exported(macro_def.def_id) {
- continue;
- }
-
- let attrs = cx.tcx.hir().attrs(macro_def.hir_id());
- let has_doc = attrs.iter().any(has_doc);
- if !has_doc {
- cx.struct_span_lint(
- MISSING_DOCS,
- cx.tcx.sess.source_map().guess_head_span(macro_def.span),
- |lint| lint.build("missing documentation for macro").emit(),
- );
- }
- }
}
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
hir::ItemKind::TyAlias(..)
| hir::ItemKind::Fn(..)
+ | hir::ItemKind::Macro(..)
| hir::ItemKind::Mod(..)
| hir::ItemKind::Enum(..)
| hir::ItemKind::Struct(..)
lint_callback!(cx, check_crate, krate);
hir_visit::walk_crate(cx, krate);
- for attr in krate.non_exported_macro_attrs {
- // This HIR ID is a lie, since the macro ID isn't available.
- cx.visit_attribute(hir::CRATE_HIR_ID, attr);
- }
lint_callback!(cx, check_crate_post, krate);
})
let push = builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), &store, true);
builder.levels.register_id(hir::CRATE_HIR_ID);
- for macro_def in krate.exported_macros() {
- builder.levels.register_id(macro_def.hir_id());
- }
intravisit::walk_crate(&mut builder, krate);
builder.levels.pop(push);
let vis = self.get_visibility(child_index);
let def_id = self.local_def_id(child_index);
let res = Res::Def(kind, def_id);
- callback(Export { res, ident, vis, span });
+
+ // FIXME: Macros are currently encoded twice, once as items and once as
+ // reexports. We ignore the items here and only use the reexports.
+ if !matches!(kind, DefKind::Macro(..)) {
+ callback(Export { res, ident, vis, span });
+ }
+
// For non-re-export structs and variants add their constructors to children.
// Re-export lists automatically contain constructors when necessary.
match kind {
}
krate.visit_all_item_likes(&mut self.as_deep_visitor());
- for macro_def in krate.exported_macros() {
- self.visit_macro_def(macro_def);
- }
}
fn encode_def_path_table(&mut self) {
EntryKind::Fn(self.lazy(data))
}
+ hir::ItemKind::Macro(ref macro_def) => {
+ EntryKind::MacroDef(self.lazy(macro_def.clone()))
+ }
hir::ItemKind::Mod(ref m) => {
return self.encode_info_for_mod(item.def_id, m);
}
}
}
- /// Serialize the text of exported macros
- fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef<'_>) {
- let def_id = macro_def.def_id.to_def_id();
- record!(self.tables.kind[def_id] <- EntryKind::MacroDef(self.lazy(macro_def.ast.clone())));
- self.encode_ident_span(def_id, macro_def.ident);
- }
-
fn encode_info_for_generic_param(&mut self, def_id: DefId, kind: EntryKind, encode_type: bool) {
record!(self.tables.kind[def_id] <- kind);
if encode_type {
intravisit::walk_generics(self, generics);
self.encode_info_for_generics(generics);
}
- fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef<'tcx>) {
- self.encode_info_for_macro_def(macro_def);
- }
}
impl EncodeContext<'a, 'tcx> {
hir::ItemKind::Static(..)
| hir::ItemKind::Const(..)
| hir::ItemKind::Fn(..)
+ | hir::ItemKind::Macro(..)
| hir::ItemKind::Mod(..)
| hir::ItemKind::ForeignMod { .. }
| hir::ItemKind::GlobalAsm(..)
}
}
- fn visit_macro_def(&mut self, macro_def: &'hir MacroDef<'hir>) {
- // Exported macros are visited directly from the crate root,
- // so they do not have `parent_node` set.
- // Find the correct enclosing module from their DefKey.
- let def_key = self.definitions.def_key(macro_def.def_id);
- let parent = def_key.parent.map_or(hir::CRATE_HIR_ID, |local_def_index| {
- self.definitions.local_def_id_to_hir_id(LocalDefId { local_def_index })
- });
- self.insert_owner(macro_def.def_id, OwnerNode::MacroDef(macro_def));
- self.with_parent(parent, |this| {
- this.insert_nested(macro_def.def_id);
- });
- }
-
fn visit_variant(&mut self, v: &'hir Variant<'hir>, g: &'hir Generics<'hir>, item_id: HirId) {
self.insert(v.span, v.id, Node::Variant(v));
self.with_parent(v.id, |this| {
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
use rustc_hir::intravisit;
-use rustc_hir::intravisit::Visitor;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::*;
use rustc_index::vec::Idx;
ItemKind::Static(..) => DefKind::Static,
ItemKind::Const(..) => DefKind::Const,
ItemKind::Fn(..) => DefKind::Fn,
+ ItemKind::Macro(..) => DefKind::Macro(MacroKind::Bang),
ItemKind::Mod(..) => DefKind::Mod,
ItemKind::OpaqueTy(..) => DefKind::OpaqueTy,
ItemKind::TyAlias(..) => DefKind::TyAlias,
ExprKind::Closure(.., Some(_)) => DefKind::Generator,
_ => bug!("def_kind: unsupported node: {}", self.node_to_string(hir_id)),
},
- Node::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
Node::GenericParam(param) => match param.kind {
GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
GenericParamKind::Type { .. } => DefKind::TyParam,
}
}
- pub fn visit_exported_macros_in_krate<V>(&self, visitor: &mut V)
- where
- V: Visitor<'hir>,
- {
- for macro_def in self.krate().exported_macros() {
- visitor.visit_macro_def(macro_def);
- }
- }
-
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> {
/// in a module, trait, or impl.
pub fn get_parent_item(&self, hir_id: HirId) -> HirId {
if let Some((hir_id, _node)) = self.parent_owner_iter(hir_id).next() {
- // A MacroDef does not have children.
- debug_assert!(!matches!(_node, OwnerNode::MacroDef(_)));
hir_id
} else {
CRATE_HIR_ID
}
}
- pub fn expect_macro_def(&self, id: HirId) -> &'hir MacroDef<'hir> {
- match self.tcx.hir_owner(id.expect_owner()) {
- Some(Owner { node: OwnerNode::MacroDef(macro_def) }) => macro_def,
- _ => bug!("expected macro def, found {}", self.node_to_string(id)),
- }
- }
-
pub fn expect_expr(&self, id: HirId) -> &'hir Expr<'hir> {
match self.find(id) {
Some(Node::Expr(expr)) => expr,
Node::GenericParam(param) => param.name.ident().name,
Node::Binding(&Pat { kind: PatKind::Binding(_, _, l, _), .. }) => l.name,
Node::Ctor(..) => self.name(self.get_parent_item(id)),
- Node::MacroDef(md) => md.ident.name,
_ => return None,
})
}
Node::Infer(i) => i.span,
Node::Visibility(v) => bug!("unexpected Visibility {:?}", v),
Node::Local(local) => local.span,
- Node::MacroDef(macro_def) => macro_def.span,
Node::Crate(item) => item.inner,
};
Some(span)
source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher);
- tcx.untracked_crate.non_exported_macro_attrs.hash_stable(&mut hcx, &mut stable_hasher);
let crate_hash: Fingerprint = stable_hasher.finish();
Svh::new(crate_hash.to_smaller_hash())
ItemKind::Static(..) => "static",
ItemKind::Const(..) => "const",
ItemKind::Fn(..) => "fn",
+ ItemKind::Macro(..) => "macro",
ItemKind::Mod(..) => "mod",
ItemKind::ForeignMod { .. } => "foreign mod",
ItemKind::GlobalAsm(..) => "global asm",
Some(Node::Lifetime(_)) => node_str("lifetime"),
Some(Node::GenericParam(ref param)) => format!("generic_param {:?}{}", param, id_str),
Some(Node::Visibility(ref vis)) => format!("visibility {:?}{}", vis, id_str),
- Some(Node::MacroDef(_)) => format!("macro {}{}", path_str(), id_str),
Some(Node::Crate(..)) => String::from("root_crate"),
None => format!("unknown node{}", id_str),
}
match item.kind {
hir::ItemKind::ExternCrate(..)
| hir::ItemKind::Use(..)
+ | hir::ItemKind::Macro(..)
| hir::ItemKind::ForeignMod { .. }
| hir::ItemKind::TyAlias(..)
| hir::ItemKind::Trait(..)
}
fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
+ // Historically we've run more checks on non-exported than exported macros,
+ // so this lets us continue to run them while maintaining backwards compatibility.
+ // In the long run, the checks should be harmonized.
+ if let ItemKind::Macro(ref macro_def) = item.kind {
+ let def_id = item.def_id.to_def_id();
+ if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) {
+ check_non_exported_macro_for_invalid_attrs(self.tcx, item);
+ }
+ }
+
let target = Target::from_item(item);
self.check_attributes(item.hir_id(), &item.span, target, Some(ItemLike::Item(item)));
intravisit::walk_item(self, item)
intravisit::walk_variant(self, variant, generics, item_id)
}
- fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef<'tcx>) {
- self.check_attributes(macro_def.hir_id(), ¯o_def.span, Target::MacroDef, None);
- intravisit::walk_macro_def(self, macro_def);
- }
-
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
self.check_attributes(param.hir_id, ¶m.span, Target::Param, None);
}
}
-fn check_invalid_macro_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
+fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>) {
+ let attrs = tcx.hir().attrs(item.hir_id());
+
for attr in attrs {
if attr.has_name(sym::inline) {
struct_span_err!(
if module_def_id.is_top_level_module() {
check_attr_visitor.check_attributes(CRATE_HIR_ID, &DUMMY_SP, Target::Mod, None);
check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs());
- tcx.hir().visit_exported_macros_in_krate(check_attr_visitor);
- check_invalid_macro_level_attr(tcx, tcx.hir().krate().non_exported_macro_attrs);
}
}
// Collect diagnostic items in this crate.
tcx.hir().krate().visit_all_item_likes(&mut collector);
- for m in tcx.hir().krate().exported_macros() {
- collector.observe_item(m.def_id);
- }
-
collector.items
}
fn visit_attribute(&mut self, _: hir::HirId, attr: &'v ast::Attribute) {
self.record("Attribute", Id::Attr(attr.id), attr);
}
-
- fn visit_macro_def(&mut self, macro_def: &'v hir::MacroDef<'v>) {
- self.record("MacroDef", Id::Node(macro_def.hir_id()), macro_def);
- hir_visit::walk_macro_def(self, macro_def)
- }
}
impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
fn get_lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures {
let mut collector = LibFeatureCollector::new(tcx);
let krate = tcx.hir().krate();
- for attr in krate.non_exported_macro_attrs {
- collector.visit_attribute(rustc_hir::CRATE_HIR_ID, attr);
- }
+
intravisit::walk_crate(&mut collector, krate);
collector.lib_features
}
| hir::ItemKind::Use(..)
| hir::ItemKind::OpaqueTy(..)
| hir::ItemKind::TyAlias(..)
+ | hir::ItemKind::Macro(..)
| hir::ItemKind::Mod(..)
| hir::ItemKind::ForeignMod { .. }
| hir::ItemKind::Impl { .. }
| Node::Ctor(..)
| Node::Field(_)
| Node::Ty(_)
- | Node::Crate(_)
- | Node::MacroDef(_) => {}
+ | Node::Crate(_) => {}
_ => {
bug!(
"found unexpected node kind in worklist: {} ({:?})",
);
}
- fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
- self.annotate(
- md.def_id,
- md.span,
- None,
- AnnotationKind::Required,
- InheritDeprecation::Yes,
- InheritConstStability::No,
- InheritStability::No,
- |_| {},
- );
- }
-
fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
let kind = match &p.kind {
// Allow stability attributes on default generic arguments.
self.check_missing_stability(i.def_id, i.span);
intravisit::walk_foreign_item(self, i);
}
-
- fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
- self.check_missing_stability(md.def_id, md.span);
- }
-
// Note that we don't need to `check_missing_stability` for default generic parameters,
// as we assume that any default generic parameters without attributes are automatically
// stable (assuming they have not inherited instability from their parent).
[dependencies]
rustc_middle = { path = "../rustc_middle" }
+rustc_ast = { path = "../rustc_ast" }
rustc_attr = { path = "../rustc_attr" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
#![feature(associated_type_defaults)]
#![recursion_limit = "256"]
+use rustc_ast::MacroDef;
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::struct_span_err;
use rustc_middle::ty::{self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable};
use rustc_session::lint;
use rustc_span::hygiene::Transparency;
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
use rustc_trait_selection::traits::const_evaluatable::{self, AbstractConst};
}
}
+ // We have to make sure that the items that macros might reference
+ // are reachable, since they might be exported transitively.
+ fn update_reachability_from_macro(&mut self, local_def_id: LocalDefId, md: &MacroDef) {
+ // Non-opaque macros cannot make other items more accessible than they already are.
+
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id);
+ let attrs = self.tcx.hir().attrs(hir_id);
+ if attr::find_transparency(&attrs, md.macro_rules).0 != Transparency::Opaque {
+ return;
+ }
+
+ let item_def_id = local_def_id.to_def_id();
+ let macro_module_def_id =
+ ty::DefIdTree::parent(self.tcx, item_def_id).unwrap().expect_local();
+ if self.tcx.hir().opt_def_kind(macro_module_def_id) != Some(DefKind::Mod) {
+ // The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252).
+ return;
+ }
+
+ if self.get(local_def_id).is_none() {
+ return;
+ }
+
+ // Since we are starting from an externally visible module,
+ // all the parents in the loop below are also guaranteed to be modules.
+ let mut module_def_id = macro_module_def_id;
+ loop {
+ let changed_reachability =
+ self.update_macro_reachable(module_def_id, macro_module_def_id);
+ if changed_reachability || module_def_id == CRATE_DEF_ID {
+ break;
+ }
+ module_def_id =
+ ty::DefIdTree::parent(self.tcx, module_def_id.to_def_id()).unwrap().expect_local();
+ }
+ }
+
/// Updates the item as being reachable through a macro defined in the given
/// module. Returns `true` if the level has changed.
fn update_macro_reachable(
}
match def_kind {
// No type privacy, so can be directly marked as reachable.
- DefKind::Const
- | DefKind::Macro(_)
- | DefKind::Static
- | DefKind::TraitAlias
- | DefKind::TyAlias => {
+ DefKind::Const | DefKind::Static | DefKind::TraitAlias | DefKind::TyAlias => {
if vis.is_accessible_from(module.to_def_id(), self.tcx) {
self.update(def_id, level);
}
}
+ // Hygine isn't really implemented for `macro_rules!` macros at the
+ // moment. Accordingly, marking them as reachable is unwise. `macro` macros
+ // have normal hygine, so we can treat them like other items without type
+ // privacy and mark them reachable.
+ DefKind::Macro(_) => {
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
+ let item = self.tcx.hir().expect_item(hir_id);
+ if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }) = item.kind {
+ if vis.is_accessible_from(module.to_def_id(), self.tcx) {
+ self.update(def_id, level);
+ }
+ }
+ }
+
// We can't use a module name as the final segment of a path, except
// in use statements. Since re-export checking doesn't consider
// hygiene these don't need to be marked reachable. The contents of
hir::ItemKind::Impl { .. } => {
Option::<AccessLevel>::of_impl(item.def_id, self.tcx, &self.access_levels)
}
+ // Only exported `macro_rules!` items are public, but they always are.
+ hir::ItemKind::Macro(MacroDef { macro_rules: true, .. }) => {
+ let def_id = item.def_id.to_def_id();
+ let is_macro_export = self.tcx.has_attr(def_id, sym::macro_export);
+ if is_macro_export { Some(AccessLevel::Public) } else { None }
+ }
// Foreign modules inherit level from parents.
hir::ItemKind::ForeignMod { .. } => self.prev_level,
// Other `pub` items inherit levels from parents.
| hir::ItemKind::ExternCrate(..)
| hir::ItemKind::GlobalAsm(..)
| hir::ItemKind::Fn(..)
+ | hir::ItemKind::Macro(..)
| hir::ItemKind::Mod(..)
| hir::ItemKind::Static(..)
| hir::ItemKind::Struct(..)
}
}
}
+ hir::ItemKind::Macro(ref macro_def) => {
+ self.update_reachability_from_macro(item.def_id, macro_def);
+ }
hir::ItemKind::ForeignMod { items, .. } => {
for foreign_item in items {
if foreign_item.vis.node.is_pub() {
}
}
}
+
hir::ItemKind::OpaqueTy(..)
| hir::ItemKind::Use(..)
| hir::ItemKind::Static(..)
// Mark all items in interfaces of reachable items as reachable.
match item.kind {
// The interface is empty.
- hir::ItemKind::ExternCrate(..) => {}
+ hir::ItemKind::Macro(..) | hir::ItemKind::ExternCrate(..) => {}
// All nested items are checked by `visit_item`.
hir::ItemKind::Mod(..) => {}
// Re-exports are handled in `visit_mod`. However, in order to avoid looping over
intravisit::walk_mod(self, m, id);
}
-
- fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
- // Non-opaque macros cannot make other items more accessible than they already are.
- let attrs = self.tcx.hir().attrs(md.hir_id());
- if attr::find_transparency(&attrs, md.ast.macro_rules).0 != Transparency::Opaque {
- // `#[macro_export]`-ed `macro_rules!` are `Public` since they
- // ignore their containing path to always appear at the crate root.
- if md.ast.macro_rules {
- self.update(md.def_id, Some(AccessLevel::Public));
- }
- return;
- }
-
- let macro_module_def_id =
- ty::DefIdTree::parent(self.tcx, md.def_id.to_def_id()).unwrap().expect_local();
- if self.tcx.hir().opt_def_kind(macro_module_def_id) != Some(DefKind::Mod) {
- // The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252).
- return;
- }
-
- let level = if md.vis.node.is_pub() { self.get(macro_module_def_id) } else { None };
- let new_level = self.update(md.def_id, level);
- if new_level.is_none() {
- return;
- }
-
- // Since we are starting from an externally visible module,
- // all the parents in the loop below are also guaranteed to be modules.
- let mut module_def_id = macro_module_def_id;
- loop {
- let changed_reachability =
- self.update_macro_reachable(module_def_id, macro_module_def_id);
- if changed_reachability || module_def_id == CRATE_DEF_ID {
- break;
- }
- module_def_id =
- ty::DefIdTree::parent(self.tcx, module_def_id.to_def_id()).unwrap().expect_local();
- }
- }
}
impl ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
// Checked in resolve.
hir::ItemKind::Use(..) => {}
// No subitems.
- hir::ItemKind::GlobalAsm(..) => {}
+ hir::ItemKind::Macro(..) | hir::ItemKind::GlobalAsm(..) => {}
// Subitems of these items have inherited publicity.
hir::ItemKind::Const(..)
| hir::ItemKind::Static(..)
hir::ItemKind::ExternCrate(_)
| hir::ItemKind::Use(..)
+ | hir::ItemKind::Macro(..)
| hir::ItemKind::Mod(..)
| hir::ItemKind::ForeignMod { .. }
| hir::ItemKind::GlobalAsm(..) => {
Ok(sig)
}
+ hir::ItemKind::Macro(_) => {
+ let mut text = "macro".to_owned();
+ let name = self.ident.to_string();
+ text.push_str(&name);
+ text.push_str(&"! {}");
+
+ Ok(text_sig(text))
+ }
hir::ItemKind::Mod(ref _mod) => {
let mut text = "mod ".to_owned();
let name = self.ident.to_string();
mod nvptx;
mod powerpc;
mod riscv;
+mod s390x;
mod spirv;
mod wasm;
mod x86;
pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass};
pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
+pub use s390x::{S390xInlineAsmReg, S390xInlineAsmRegClass};
pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass};
pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass};
pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
Mips64,
PowerPC,
PowerPC64,
+ S390x,
SpirV,
Wasm32,
Bpf,
"hexagon" => Ok(Self::Hexagon),
"mips" => Ok(Self::Mips),
"mips64" => Ok(Self::Mips64),
+ "s390x" => Ok(Self::S390x),
"spirv" => Ok(Self::SpirV),
"wasm32" => Ok(Self::Wasm32),
"bpf" => Ok(Self::Bpf),
PowerPC(PowerPCInlineAsmReg),
Hexagon(HexagonInlineAsmReg),
Mips(MipsInlineAsmReg),
+ S390x(S390xInlineAsmReg),
SpirV(SpirVInlineAsmReg),
Wasm(WasmInlineAsmReg),
Bpf(BpfInlineAsmReg),
Self::PowerPC(r) => r.name(),
Self::Hexagon(r) => r.name(),
Self::Mips(r) => r.name(),
+ Self::S390x(r) => r.name(),
Self::Bpf(r) => r.name(),
Self::Err => "<reg>",
}
Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()),
Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()),
Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
+ Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()),
Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()),
Self::Err => InlineAsmRegClass::Err,
}
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?)
}
+ InlineAsmArch::S390x => {
+ Self::S390x(S390xInlineAsmReg::parse(arch, has_feature, target, &name)?)
+ }
InlineAsmArch::SpirV => {
Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?)
}
Self::PowerPC(r) => r.emit(out, arch, modifier),
Self::Hexagon(r) => r.emit(out, arch, modifier),
Self::Mips(r) => r.emit(out, arch, modifier),
+ Self::S390x(r) => r.emit(out, arch, modifier),
Self::Bpf(r) => r.emit(out, arch, modifier),
Self::Err => unreachable!("Use of InlineAsmReg::Err"),
}
Self::PowerPC(_) => cb(self),
Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
Self::Mips(_) => cb(self),
+ Self::S390x(_) => cb(self),
Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
Self::Err => unreachable!("Use of InlineAsmReg::Err"),
}
PowerPC(PowerPCInlineAsmRegClass),
Hexagon(HexagonInlineAsmRegClass),
Mips(MipsInlineAsmRegClass),
+ S390x(S390xInlineAsmRegClass),
SpirV(SpirVInlineAsmRegClass),
Wasm(WasmInlineAsmRegClass),
Bpf(BpfInlineAsmRegClass),
Self::PowerPC(r) => r.name(),
Self::Hexagon(r) => r.name(),
Self::Mips(r) => r.name(),
+ Self::S390x(r) => r.name(),
Self::SpirV(r) => r.name(),
Self::Wasm(r) => r.name(),
Self::Bpf(r) => r.name(),
Self::PowerPC(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::PowerPC),
Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon),
Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
+ Self::S390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::S390x),
Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf),
Self::PowerPC(r) => r.suggest_modifier(arch, ty),
Self::Hexagon(r) => r.suggest_modifier(arch, ty),
Self::Mips(r) => r.suggest_modifier(arch, ty),
+ Self::S390x(r) => r.suggest_modifier(arch, ty),
Self::SpirV(r) => r.suggest_modifier(arch, ty),
Self::Wasm(r) => r.suggest_modifier(arch, ty),
Self::Bpf(r) => r.suggest_modifier(arch, ty),
Self::PowerPC(r) => r.default_modifier(arch),
Self::Hexagon(r) => r.default_modifier(arch),
Self::Mips(r) => r.default_modifier(arch),
+ Self::S390x(r) => r.default_modifier(arch),
Self::SpirV(r) => r.default_modifier(arch),
Self::Wasm(r) => r.default_modifier(arch),
Self::Bpf(r) => r.default_modifier(arch),
Self::PowerPC(r) => r.supported_types(arch),
Self::Hexagon(r) => r.supported_types(arch),
Self::Mips(r) => r.supported_types(arch),
+ Self::S390x(r) => r.supported_types(arch),
Self::SpirV(r) => r.supported_types(arch),
Self::Wasm(r) => r.supported_types(arch),
Self::Bpf(r) => r.supported_types(arch),
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?)
}
+ InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(arch, name)?),
InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?),
InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?),
InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?),
Self::PowerPC(r) => r.valid_modifiers(arch),
Self::Hexagon(r) => r.valid_modifiers(arch),
Self::Mips(r) => r.valid_modifiers(arch),
+ Self::S390x(r) => r.valid_modifiers(arch),
Self::SpirV(r) => r.valid_modifiers(arch),
Self::Wasm(r) => r.valid_modifiers(arch),
Self::Bpf(r) => r.valid_modifiers(arch),
mips::fill_reg_map(arch, has_feature, target, &mut map);
map
}
+ InlineAsmArch::S390x => {
+ let mut map = s390x::regclass_map();
+ s390x::fill_reg_map(arch, has_feature, target, &mut map);
+ map
+ }
InlineAsmArch::SpirV => {
let mut map = spirv::regclass_map();
spirv::fill_reg_map(arch, has_feature, target, &mut map);
--- /dev/null
+use super::{InlineAsmArch, InlineAsmType};
+use rustc_macros::HashStable_Generic;
+use std::fmt;
+
+def_reg_class! {
+ S390x S390xInlineAsmRegClass {
+ reg,
+ freg,
+ }
+}
+
+impl S390xInlineAsmRegClass {
+ pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
+ &[]
+ }
+
+ pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
+ None
+ }
+
+ pub fn suggest_modifier(
+ self,
+ _arch: InlineAsmArch,
+ _ty: InlineAsmType,
+ ) -> Option<(char, &'static str)> {
+ None
+ }
+
+ pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
+ None
+ }
+
+ pub fn supported_types(
+ self,
+ arch: InlineAsmArch,
+ ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+ match (self, arch) {
+ (Self::reg, _) => types! { _: I8, I16, I32, I64; },
+ (Self::freg, _) => types! { _: F32, F64; },
+ }
+ }
+}
+
+def_regs! {
+ S390x S390xInlineAsmReg S390xInlineAsmRegClass {
+ r0: reg = ["r0"],
+ r1: reg = ["r1"],
+ r2: reg = ["r2"],
+ r3: reg = ["r3"],
+ r4: reg = ["r4"],
+ r5: reg = ["r5"],
+ r6: reg = ["r6"],
+ r7: reg = ["r7"],
+ r8: reg = ["r8"],
+ r9: reg = ["r9"],
+ r10: reg = ["r10"],
+ r12: reg = ["r12"],
+ r13: reg = ["r13"],
+ r14: reg = ["r14"],
+ f0: freg = ["f0"],
+ f1: freg = ["f1"],
+ f2: freg = ["f2"],
+ f3: freg = ["f3"],
+ f4: freg = ["f4"],
+ f5: freg = ["f5"],
+ f6: freg = ["f6"],
+ f7: freg = ["f7"],
+ f8: freg = ["f8"],
+ f9: freg = ["f9"],
+ f10: freg = ["f10"],
+ f11: freg = ["f11"],
+ f12: freg = ["f12"],
+ f13: freg = ["f13"],
+ f14: freg = ["f14"],
+ f15: freg = ["f15"],
+ #error = ["r11"] =>
+ "The frame pointer cannot be used as an operand for inline asm",
+ #error = ["r15"] =>
+ "The stack pointer cannot be used as an operand for inline asm",
+ #error = [
+ "c0", "c1", "c2", "c3",
+ "c4", "c5", "c6", "c7",
+ "c8", "c9", "c10", "c11",
+ "c12", "c13", "c14", "c15"
+ ] =>
+ "control registers are reserved by the kernel and cannot be used as operands for inline asm",
+ #error = [
+ "a0", "a1", "a2", "a3",
+ "a4", "a5", "a6", "a7",
+ "a8", "a9", "a10", "a11",
+ "a12", "a13", "a14", "a15"
+ ] =>
+ "access registers are not supported and cannot be used as operands for inline asm",
+ }
+}
+
+impl S390xInlineAsmReg {
+ pub fn emit(
+ self,
+ out: &mut dyn fmt::Write,
+ _arch: InlineAsmArch,
+ _modifier: Option<char>,
+ ) -> fmt::Result {
+ write!(out, "%{}", self.name())
+ }
+}
// These don't define types.
hir::ItemKind::ExternCrate(_)
| hir::ItemKind::Use(..)
+ | hir::ItemKind::Macro(_)
| hir::ItemKind::Mod(_)
| hir::ItemKind::GlobalAsm(_) => {}
hir::ItemKind::ForeignMod { items, .. } => {
}
ItemKind::Trait(..)
| ItemKind::TraitAlias(..)
+ | ItemKind::Macro(..)
| ItemKind::Mod(..)
| ItemKind::ForeignMod { .. }
| ItemKind::GlobalAsm(..)
items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
items.extend(self.mods.iter().map(|x| x.clean(cx)));
items.extend(self.items.iter().map(|x| x.clean(cx)).flatten());
- items.extend(self.macros.iter().map(|x| x.clean(cx)));
// determine if we should display the inner contents or
// the outer `mod` item for the source code.
ItemKind::Fn(ref sig, ref generics, body_id) => {
clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
}
+ ItemKind::Macro(ref macro_def) => MacroItem(Macro {
+ source: display_macro_source(cx, name, ¯o_def, def_id, &item.vis),
+ imported_from: None,
+ }),
ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
let items = item_ids
.iter()
}
}
-impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
- fn clean(&self, cx: &mut DocContext<'_>) -> Item {
- let (item, renamed) = self;
- let name = renamed.unwrap_or(item.ident.name);
- let def_id = item.def_id.to_def_id();
-
- Item::from_hir_id_and_parts(
- item.hir_id(),
- Some(name),
- MacroItem(Macro {
- source: display_macro_source(cx, name, &item.ast, def_id, &item.vis),
- imported_from: None,
- }),
- cx,
- )
- }
-}
-
impl Clean<TypeBinding> for hir::TypeBinding<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> TypeBinding {
TypeBinding { name: self.ident.name, kind: self.kind.clean(cx) }
}
fn visit_item(&mut self, item: &'hir hir::Item<'_>) {
- let name = if let hir::ItemKind::Impl(impl_) = &item.kind {
- rustc_hir_pretty::id_to_string(&self.map, impl_.self_ty.hir_id)
- } else {
- item.ident.to_string()
+ let name = match &item.kind {
+ hir::ItemKind::Macro(ref macro_def) => {
+ // FIXME(#88038): Non exported macros have historically not been tested,
+ // but we really ought to start testing them.
+ let def_id = item.def_id.to_def_id();
+ if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) {
+ intravisit::walk_item(self, item);
+ return;
+ }
+ item.ident.to_string()
+ }
+ hir::ItemKind::Impl(impl_) => {
+ rustc_hir_pretty::id_to_string(&self.map, impl_.self_ty.hir_id)
+ }
+ _ => item.ident.to_string(),
};
self.visit_testable(name, item.hir_id(), item.span, |this| {
intravisit::walk_field_def(this, f);
});
}
-
- fn visit_macro_def(&mut self, macro_def: &'hir hir::MacroDef<'_>) {
- self.visit_testable(
- macro_def.ident.to_string(),
- macro_def.hir_id(),
- macro_def.span,
- |_| (),
- );
- }
}
#[cfg(test)]
use rustc_hir as hir;
+#[derive(Debug)]
crate struct Module<'hir> {
crate name: Symbol,
crate where_inner: Span,
// (item, renamed)
crate items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>)>,
crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>)>,
- crate macros: Vec<(&'hir hir::MacroDef<'hir>, Option<Symbol>)>,
}
impl Module<'hir> {
crate fn new(name: Symbol, id: hir::HirId, where_inner: Span) -> Module<'hir> {
- Module {
- name,
- id,
- where_inner,
- mods: Vec::new(),
- items: Vec::new(),
- foreigns: Vec::new(),
- macros: Vec::new(),
- }
+ Module { name, id, where_inner, mods: Vec::new(), items: Vec::new(), foreigns: Vec::new() }
}
crate fn where_outer(&self, tcx: TyCtxt<'_>) -> Span {
use rustc_middle::middle::privacy::AccessLevel;
use rustc_middle::ty::TyCtxt;
use rustc_span;
-use rustc_span::def_id::LOCAL_CRATE;
+use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Symbol};
&krate.module(),
self.cx.tcx.crate_name(LOCAL_CRATE),
);
- // Attach the crate's exported macros to the top-level module.
- // In the case of macros 2.0 (`pub macro`), and for built-in `derive`s or attributes as
- // well (_e.g._, `Copy`), these are wrongly bundled in there too, so we need to fix that by
- // moving them back to their correct locations.
- 'exported_macros: for def in krate.exported_macros() {
- // The `def` of a macro in `exported_macros` should correspond to either:
- // - a `#[macro_export] macro_rules!` macro,
- // - a built-in `derive` (or attribute) macro such as the ones in `::core`,
- // - a `pub macro`.
- // Only the last two need to be fixed, thus:
- if def.ast.macro_rules {
- top_level_module.macros.push((def, None));
- continue 'exported_macros;
- }
- let tcx = self.cx.tcx;
- // Note: this is not the same as `.parent_module()`. Indeed, the latter looks
- // for the closest module _ancestor_, which is not necessarily a direct parent
- // (since a direct parent isn't necessarily a module, c.f. #77828).
- let macro_parent_def_id = {
- use rustc_middle::ty::DefIdTree;
- tcx.parent(def.def_id.to_def_id()).unwrap()
- };
- let macro_parent_path = tcx.def_path(macro_parent_def_id);
- // HACK: rustdoc has no way to lookup `doctree::Module`s by their HirId. Instead,
- // lookup the module by its name, by looking at each path segment one at a time.
- let mut cur_mod = &mut top_level_module;
- for path_segment in macro_parent_path.data {
- // Path segments may refer to a module (in which case they belong to the type
- // namespace), which is _necessary_ for the macro to be accessible outside it
- // (no "associated macros" as of yet). Else we bail with an outer `continue`.
- let path_segment_ty_ns = match path_segment.data {
- rustc_hir::definitions::DefPathData::TypeNs(symbol) => symbol,
- _ => continue 'exported_macros,
- };
- // Descend into the child module that matches this path segment (if any).
- match cur_mod.mods.iter_mut().find(|child| child.name == path_segment_ty_ns) {
- Some(child_mod) => cur_mod = &mut *child_mod,
- None => continue 'exported_macros,
+
+ // `#[macro_export] macro_rules!` items are reexported at the top level of the
+ // crate, regardless of where they're defined. We want to document the
+ // top level rexport of the macro, not its original definition, since
+ // the rexport defines the path that a user will actually see. Accordingly,
+ // we add the rexport as an item here, and then skip over the original
+ // definition in `visit_item()` below.
+ for export in self.cx.tcx.module_exports(CRATE_DEF_ID).unwrap_or(&[]) {
+ if let Res::Def(DefKind::Macro(_), def_id) = export.res {
+ if let Some(local_def_id) = def_id.as_local() {
+ if self.cx.tcx.has_attr(def_id, sym::macro_export) {
+ let hir_id = self.cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
+ let item = self.cx.tcx.hir().expect_item(hir_id);
+ top_level_module.items.push((item, None));
+ }
}
}
- let cur_mod_def_id = tcx.hir().local_def_id(cur_mod.id).to_def_id();
- assert_eq!(cur_mod_def_id, macro_parent_def_id);
- cur_mod.macros.push((def, None));
}
self.cx.cache.exact_paths = self.exact_paths;
top_level_module
self.inlining = prev;
true
}
- Node::MacroDef(def) if !glob => {
- om.macros.push((def, renamed));
- true
- }
_ => false,
};
self.view_item_stack.remove(&res_hir_id);
debug!("visiting item {:?}", item);
let name = renamed.unwrap_or(item.ident.name);
- if item.vis.node.is_pub() {
+ let def_id = item.def_id.to_def_id();
+ let is_pub = item.vis.node.is_pub() || self.cx.tcx.has_attr(def_id, sym::macro_export);
+
+ if is_pub {
self.store_path(item.def_id.to_def_id());
}
}
}
// If we're inlining, skip private items.
- _ if self.inlining && !item.vis.node.is_pub() => {}
+ _ if self.inlining && !is_pub => {}
hir::ItemKind::GlobalAsm(..) => {}
hir::ItemKind::Use(_, hir::UseKind::ListStem) => {}
hir::ItemKind::Use(ref path, kind) => {
// If there was a private module in the current path then don't bother inlining
// anything as it will probably be stripped anyway.
- if item.vis.node.is_pub() && self.inside_public_path {
+ if is_pub && self.inside_public_path {
let please_inline = attrs.iter().any(|item| match item.meta_item_list() {
Some(ref list) if item.has_name(sym::doc) => {
list.iter().any(|i| i.has_name(sym::inline))
om.items.push((item, renamed))
}
+ hir::ItemKind::Macro(ref macro_def) => {
+ // `#[macro_export] macro_rules!` items are handled seperately in `visit()`,
+ // above, since they need to be documented at the module top level. Accordingly,
+ // we only want to handle macros if one of three conditions holds:
+ //
+ // 1. This macro was defined by `macro`, and thus isn't covered by the case
+ // above.
+ // 2. This macro isn't marked with `#[macro_export]`, and thus isn't covered
+ // by the case above.
+ // 3. We're inlining, since a reexport where inlining has been requested
+ // should be inlined even if it is also documented at the top level.
+
+ let def_id = item.def_id.to_def_id();
+ let is_macro_2_0 = !macro_def.macro_rules;
+ let nonexported = !self.cx.tcx.has_attr(def_id, sym::macro_export);
+
+ if is_macro_2_0 || nonexported || self.inlining {
+ om.items.push((item, renamed));
+ }
+ }
hir::ItemKind::Mod(ref m) => {
om.mods.push(self.visit_mod_contents(&item.vis, item.hir_id(), m, name));
}
--- /dev/null
+// min-llvm-version: 10.0.1
+// revisions: s390x
+// assembly-output: emit-asm
+//[s390x] compile-flags: --target s390x-unknown-linux-gnu
+//[s390x] needs-llvm-components: systemz
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+ () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+ () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+ () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *const i32;
+
+impl Copy for i8 {}
+impl Copy for u8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for f32 {}
+impl Copy for f64 {}
+impl Copy for ptr {}
+
+extern "C" {
+ fn extern_func();
+ static extern_static: u8;
+}
+
+// Hack to avoid function merging
+extern "Rust" {
+ fn dont_merge(s: &str);
+}
+
+macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
+ #[no_mangle]
+ pub unsafe fn $func(x: $ty) -> $ty {
+ dont_merge(stringify!($func));
+
+ let y;
+ asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
+ y
+ }
+};}
+
+macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
+ #[no_mangle]
+ pub unsafe fn $func(x: $ty) -> $ty {
+ dont_merge(stringify!($func));
+
+ let y;
+ asm!(concat!($mov, " %", $reg, ", %", $reg), lateout($reg) y, in($reg) x);
+ y
+ }
+};}
+
+// CHECK-LABEL: sym_fn_32:
+// CHECK: #APP
+// CHECK: brasl %r14, extern_func
+// CHECK: #NO_APP
+#[cfg(s390x)]
+#[no_mangle]
+pub unsafe fn sym_fn_32() {
+ asm!("brasl %r14, {}", sym extern_func);
+}
+
+// CHECK-LABEL: sym_static:
+// CHECK: #APP
+// CHECK: brasl %r14, extern_static
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_static() {
+ asm!("brasl %r14, {}", sym extern_static);
+}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i8, i8, reg, "lgr");
+
+// CHECK-LABEL: reg_i16:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i16, i16, reg, "lgr");
+
+// CHECK-LABEL: reg_i32:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i32, i32, reg, "lgr");
+
+// CHECK-LABEL: reg_i64:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i64, i64, reg, "lgr");
+
+// CHECK-LABEL: reg_f32:
+// CHECK: #APP
+// CHECK: ler %f{{[0-9]+}}, %f{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f32, f32, freg, "ler");
+
+// CHECK-LABEL: reg_f64:
+// CHECK: #APP
+// CHECK: ldr %f{{[0-9]+}}, %f{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f64, f64, freg, "ldr");
+
+// CHECK-LABEL: reg_ptr:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_ptr, ptr, reg, "lgr");
+
+// CHECK-LABEL: r0_i8:
+// CHECK: #APP
+// CHECK: lr %r0, %r0
+// CHECK: #NO_APP
+check_reg!(r0_i8, i8, "r0", "lr");
+
+// CHECK-LABEL: r0_i16:
+// CHECK: #APP
+// CHECK: lr %r0, %r0
+// CHECK: #NO_APP
+check_reg!(r0_i16, i16, "r0", "lr");
+
+// CHECK-LABEL: r0_i32:
+// CHECK: #APP
+// CHECK: lr %r0, %r0
+// CHECK: #NO_APP
+check_reg!(r0_i32, i32, "r0", "lr");
+
+// CHECK-LABEL: r0_i64:
+// CHECK: #APP
+// CHECK: lr %r0, %r0
+// CHECK: #NO_APP
+check_reg!(r0_i64, i64, "r0", "lr");
+
+// CHECK-LABEL: f0_f32:
+// CHECK: #APP
+// CHECK: ler %f0, %f0
+// CHECK: #NO_APP
+check_reg!(f0_f32, f32, "f0", "ler");
+
+// CHECK-LABEL: f0_f64:
+// CHECK: #APP
+// CHECK: ldr %f0, %f0
+// CHECK: #NO_APP
+check_reg!(f0_f64, f64, "f0", "ldr");
-error: missing documentation for macro
+error: missing documentation for a macro
--> $DIR/deny-missing-docs-macro.rs:6:1
|
LL | macro_rules! foo {
--- /dev/null
+// FIXME: If two macros in the same module have the same name
+// (yes, that's a thing), rustdoc lists both of them on the index page,
+// but only documents the first one on the page for the macro.
+// Fortunately, this can only happen in document private items mode,
+// but it still isn't ideal beahvior.
+//
+// See https://github.com/rust-lang/rust/pull/88019#discussion_r693920453
+//
+// compile-flags: --document-private-items
+
+// @has macro_document_private_duplicate/index.html 'Doc 1.'
+// @has macro_document_private_duplicate/macro.a_macro.html 'Doc 1.'
+/// Doc 1.
+macro_rules! a_macro {
+ () => ()
+}
+
+// @has macro_document_private_duplicate/index.html 'Doc 2.'
+// @!has macro_document_private_duplicate/macro.a_macro.html 'Doc 2.'
+/// Doc 2.
+macro_rules! a_macro {
+ () => ()
+}
--- /dev/null
+// Checks that private macros are documented when `--document-private-items`
+// is present.
+//
+// This is a regression test for issue #73754.
+//
+// compile-flags: --document-private-items
+
+#![feature(decl_macro)]
+
+
+// @has macro_document_private/macro.some_macro.html
+macro some_macro {
+ (a: tt) => {}
+}
+
+// @has macro_document_private/macro.another_macro.html
+macro_rules! another_macro {
+ (a: tt) => {}
+}
--- /dev/null
+// Checks that it is possible to make a macro public through a `pub use` of its
+// parent module.
+//
+// This is a regression test for issue #87257.
+
+#![feature(decl_macro)]
+
+mod outer {
+ pub mod inner {
+ pub macro some_macro() {}
+ }
+}
+
+// @has macro_indirect_use/inner/index.html
+// @has macro_indirect_use/inner/macro.some_macro.html
+pub use outer::inner;
--- /dev/null
+// This checks that exported macros lint as part of their module of origin, not
+// the root module.
+//
+// check-pass
+
+//! Top level documentation
+#![deny(missing_docs)]
+
+#[allow(missing_docs)]
+mod module {
+ #[macro_export]
+ macro_rules! hello {
+ () => ()
+ }
+}
+
+fn main() {}
--- /dev/null
+// Checks that you can set a lint level specficially for a macro definition.
+//
+// This is a regression test for issue #59306.
+//
+// check-pass
+
+
+#[deny(missing_docs)]
+mod module {
+ #[allow(missing_docs)]
+ #[macro_export]
+ macro_rules! hello {
+ () => ()
+ }
+}
+
+fn main() {}
#[macro_export]
macro_rules! exported_to_top_level {
- //~^ ERROR missing documentation for macro
+ //~^ ERROR missing documentation for a macro
() => ()
}
}
pub macro top_level_pub_macro {
- //~^ ERROR missing documentation for macro
+ //~^ ERROR missing documentation for a macro
() => ()
}
-error: missing documentation for macro
+error: missing documentation for a macro
--> $DIR/missing-doc-private-macro.rs:31:5
|
LL | macro_rules! exported_to_top_level {
LL | #![deny(missing_docs)]
| ^^^^^^^^^^^^
-error: missing documentation for macro
+error: missing documentation for a macro
--> $DIR/missing-doc-private-macro.rs:37:1
|
LL | pub macro top_level_pub_macro {
// run-pass
// aux-build:unstable-macros.rs
-#![feature(unstable_macros, local_unstable)]
+#![unstable(feature = "one_two_three_testing", issue = "none")]
+#![feature(staged_api, unstable_macros, local_unstable)]
#[macro_use] extern crate unstable_macros;
},
hir::ItemKind::Const(..)
| hir::ItemKind::Enum(..)
+ | hir::ItemKind::Macro(..)
| hir::ItemKind::Mod(..)
| hir::ItemKind::Static(..)
| hir::ItemKind::Struct(..)
},
hir::ItemKind::Const(..)
| hir::ItemKind::Enum(..)
+ | hir::ItemKind::Macro(..)
| hir::ItemKind::Mod(..)
| hir::ItemKind::Static(..)
| hir::ItemKind::Struct(..)
let item_ty = cx.tcx.type_of(did);
println!("function of type {:#?}", item_ty);
},
+ hir::ItemKind::Macro(ref macro_def) => {
+ if macro_def.macro_rules {
+ println!("macro introduced by `macro_rules!`");
+ } else {
+ println!("macro introduced by `macro`");
+ }
+ },
hir::ItemKind::Mod(..) => println!("module"),
hir::ItemKind::ForeignMod { abi, .. } => println!("foreign module with abi: {}", abi),
hir::ItemKind::GlobalAsm(asm) => println!("global asm: {:?}", asm),