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

Initial implementation of declarative macros 2.0 #40847

Merged
merged 13 commits into from
May 26, 2017
10 changes: 10 additions & 0 deletions src/doc/unstable-book/src/language-features/decl-macro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# `decl_macro`

The tracking issue for this feature is: [#39412]

[#39412]: https://github.com/rust-lang/rust/issues/39412

------------------------



2 changes: 1 addition & 1 deletion src/librustc/hir/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub type ExportMap = NodeMap<Vec<Export>>;

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Export {
pub name: ast::Name, // The name of the target.
pub ident: ast::Ident, // The name of the target.
pub def: Def, // The definition of the target.
pub span: Span, // The span of the target definition.
}
Expand Down
67 changes: 43 additions & 24 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ use hir::def_id::{DefIndex, DefId, CRATE_DEF_INDEX};
use hir::def::{Def, PathResolution};
use rustc_data_structures::indexed_vec::IndexVec;
use session::Session;
use util::nodemap::{DefIdMap, NodeMap};
use util::nodemap::{DefIdMap, FxHashMap, NodeMap};

use std::collections::BTreeMap;
use std::fmt::Debug;
Expand Down Expand Up @@ -77,6 +77,7 @@ pub struct LoweringContext<'a> {
// a definition, then we can properly create the def id.
parent_def: Option<DefIndex>,
resolver: &'a mut Resolver,
name_map: FxHashMap<Ident, Name>,

/// The items being lowered are collected here.
items: BTreeMap<NodeId, hir::Item>,
Expand Down Expand Up @@ -126,6 +127,7 @@ pub fn lower_crate(sess: &Session,
sess: sess,
parent_def: None,
resolver: resolver,
name_map: FxHashMap(),
items: BTreeMap::new(),
trait_items: BTreeMap::new(),
impl_items: BTreeMap::new(),
Expand Down Expand Up @@ -393,7 +395,7 @@ impl<'a> LoweringContext<'a> {
}

fn allow_internal_unstable(&self, reason: &'static str, mut span: Span) -> Span {
let mark = Mark::fresh();
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(codemap::ExpnInfo {
call_site: span,
callee: codemap::NameAndSpan {
Expand Down Expand Up @@ -495,6 +497,14 @@ impl<'a> LoweringContext<'a> {
}
}

fn lower_ident(&mut self, ident: Ident) -> Name {
let ident = ident.modern();
if ident.ctxt == SyntaxContext::empty() {
return ident.name;
}
*self.name_map.entry(ident).or_insert_with(|| Symbol::from_ident(ident))
}

fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned<Name>> {
o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
}
Expand Down Expand Up @@ -546,7 +556,7 @@ impl<'a> LoweringContext<'a> {
fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding {
hir::TypeBinding {
id: self.lower_node_id(b.id),
name: b.ident.name,
name: self.lower_ident(b.ident),
ty: self.lower_ty(&b.ty),
span: b.span,
}
Expand Down Expand Up @@ -844,7 +854,7 @@ impl<'a> LoweringContext<'a> {
}

hir::PathSegment {
name: segment.identifier.name,
name: self.lower_ident(segment.identifier),
parameters: parameters,
}
}
Expand Down Expand Up @@ -941,7 +951,7 @@ impl<'a> LoweringContext<'a> {
}

fn lower_ty_param(&mut self, tp: &TyParam, add_bounds: &[TyParamBound]) -> hir::TyParam {
let mut name = tp.ident.name;
let mut name = self.lower_ident(tp.ident);

// Don't expose `Self` (recovered "keyword used as ident" parse error).
// `rustc::ty` expects `Self` to be only used for a trait's `Self`.
Expand Down Expand Up @@ -975,7 +985,7 @@ impl<'a> LoweringContext<'a> {
fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
hir::Lifetime {
id: self.lower_node_id(l.id),
name: l.name,
name: self.lower_ident(l.ident),
span: l.span,
}
}
Expand Down Expand Up @@ -1137,7 +1147,11 @@ impl<'a> LoweringContext<'a> {
hir::StructField {
span: f.span,
id: self.lower_node_id(f.id),
name: f.ident.map(|ident| ident.name).unwrap_or(Symbol::intern(&index.to_string())),
name: self.lower_ident(match f.ident {
Some(ident) => ident,
// FIXME(jseyfried) positional field hygiene
None => Ident { name: Symbol::intern(&index.to_string()), ctxt: f.span.ctxt },
}),
vis: self.lower_visibility(&f.vis, None),
ty: self.lower_ty(&f.ty),
attrs: self.lower_attrs(&f.attrs),
Expand All @@ -1146,7 +1160,7 @@ impl<'a> LoweringContext<'a> {

fn lower_field(&mut self, f: &Field) -> hir::Field {
hir::Field {
name: respan(f.ident.span, f.ident.node.name),
name: respan(f.ident.span, self.lower_ident(f.ident.node)),
expr: P(self.lower_expr(&f.expr)),
span: f.span,
is_shorthand: f.is_shorthand,
Expand Down Expand Up @@ -1371,7 +1385,7 @@ impl<'a> LoweringContext<'a> {
self.with_parent_def(i.id, |this| {
hir::TraitItem {
id: this.lower_node_id(i.id),
name: i.ident.name,
name: this.lower_ident(i.ident),
attrs: this.lower_attrs(&i.attrs),
node: match i.node {
TraitItemKind::Const(ref ty, ref default) => {
Expand Down Expand Up @@ -1421,7 +1435,7 @@ impl<'a> LoweringContext<'a> {
};
hir::TraitItemRef {
id: hir::TraitItemId { node_id: i.id },
name: i.ident.name,
name: self.lower_ident(i.ident),
span: i.span,
defaultness: self.lower_defaultness(Defaultness::Default, has_default),
kind: kind,
Expand All @@ -1432,7 +1446,7 @@ impl<'a> LoweringContext<'a> {
self.with_parent_def(i.id, |this| {
hir::ImplItem {
id: this.lower_node_id(i.id),
name: i.ident.name,
name: this.lower_ident(i.ident),
attrs: this.lower_attrs(&i.attrs),
vis: this.lower_visibility(&i.vis, None),
defaultness: this.lower_defaultness(i.defaultness, true /* [1] */),
Expand Down Expand Up @@ -1461,7 +1475,7 @@ impl<'a> LoweringContext<'a> {
fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
hir::ImplItemRef {
id: hir::ImplItemId { node_id: i.id },
name: i.ident.name,
name: self.lower_ident(i.ident),
span: i.span,
vis: self.lower_visibility(&i.vis, Some(i.id)),
defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
Expand Down Expand Up @@ -1501,17 +1515,23 @@ impl<'a> LoweringContext<'a> {

pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> {
let mut name = i.ident.name;
let mut vis = self.lower_visibility(&i.vis, None);
let attrs = self.lower_attrs(&i.attrs);
if let ItemKind::MacroDef(ref tts) = i.node {
if i.attrs.iter().any(|attr| attr.path == "macro_export") {
if let ItemKind::MacroDef(ref def) = i.node {
if !def.legacy || i.attrs.iter().any(|attr| attr.path == "macro_export") {
self.exported_macros.push(hir::MacroDef {
name: name, attrs: attrs, id: i.id, span: i.span, body: tts.clone().into(),
name: name,
vis: vis,
attrs: attrs,
id: i.id,
span: i.span,
body: def.stream(),
legacy: def.legacy,
});
}
return None;
}

let mut vis = self.lower_visibility(&i.vis, None);
let node = self.with_parent_def(i.id, |this| {
this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node)
});
Expand Down Expand Up @@ -1654,7 +1674,7 @@ impl<'a> LoweringContext<'a> {
Spanned {
span: f.span,
node: hir::FieldPat {
name: f.node.ident.name,
name: self.lower_ident(f.node.ident),
pat: self.lower_pat(&f.node.pat),
is_shorthand: f.node.is_shorthand,
},
Expand Down Expand Up @@ -1824,7 +1844,7 @@ impl<'a> LoweringContext<'a> {
ExprKind::MethodCall(i, ref tps, ref args) => {
let tps = tps.iter().map(|x| self.lower_ty(x)).collect();
let args = args.iter().map(|x| self.lower_expr(x)).collect();
hir::ExprMethodCall(respan(i.span, i.node.name), tps, args)
hir::ExprMethodCall(respan(i.span, self.lower_ident(i.node)), tps, args)
}
ExprKind::Binary(binop, ref lhs, ref rhs) => {
let binop = self.lower_binop(binop);
Expand Down Expand Up @@ -1923,7 +1943,8 @@ impl<'a> LoweringContext<'a> {
P(self.lower_expr(er)))
}
ExprKind::Field(ref el, ident) => {
hir::ExprField(P(self.lower_expr(el)), respan(ident.span, ident.node.name))
hir::ExprField(P(self.lower_expr(el)),
respan(ident.span, self.lower_ident(ident.node)))
}
ExprKind::TupField(ref el, ident) => {
hir::ExprTupField(P(self.lower_expr(el)), ident)
Expand Down Expand Up @@ -2641,11 +2662,9 @@ impl<'a> LoweringContext<'a> {
let parent_def = self.parent_def.unwrap();
let def_id = {
let defs = self.resolver.definitions();
let def_path_data = DefPathData::Binding(name.as_str());
let def_index = defs.create_def_with_parent(parent_def,
id,
def_path_data,
REGULAR_SPACE);
let def_path_data = DefPathData::Binding(Ident::with_empty_ctxt(name));
let def_index = defs
.create_def_with_parent(parent_def, id, def_path_data, REGULAR_SPACE, Mark::root());
DefId::local(def_index)
};

Expand Down
49 changes: 25 additions & 24 deletions src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ use hir::def_id::{CRATE_DEF_INDEX, DefIndex, DefIndexAddressSpace};
use syntax::ast::*;
use syntax::ext::hygiene::Mark;
use syntax::visit;
use syntax::symbol::{Symbol, keywords};
use syntax::symbol::keywords;

use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE};

/// Creates def ids for nodes in the AST.
pub struct DefCollector<'a> {
definitions: &'a mut Definitions,
parent_def: Option<DefIndex>,
expansion: Mark,
pub visit_macro_invoc: Option<&'a mut FnMut(MacroInvocationData)>,
}

Expand All @@ -32,9 +33,10 @@ pub struct MacroInvocationData {
}

impl<'a> DefCollector<'a> {
pub fn new(definitions: &'a mut Definitions) -> Self {
pub fn new(definitions: &'a mut Definitions, expansion: Mark) -> Self {
DefCollector {
definitions: definitions,
expansion: expansion,
parent_def: None,
visit_macro_invoc: None,
}
Expand All @@ -54,7 +56,8 @@ impl<'a> DefCollector<'a> {
-> DefIndex {
let parent_def = self.parent_def.unwrap();
debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
self.definitions.create_def_with_parent(parent_def, node_id, data, address_space)
self.definitions
.create_def_with_parent(parent_def, node_id, data, address_space, self.expansion)
}

pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
Expand Down Expand Up @@ -100,14 +103,14 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
DefPathData::Impl,
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
DefPathData::TypeNs(i.ident.name.as_str()),
DefPathData::TypeNs(i.ident.modern()),
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
return visit::walk_item(self, i);
}
ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
ItemKind::Mod(..) => DefPathData::Module(i.ident.modern()),
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
DefPathData::ValueNs(i.ident.name.as_str()),
ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
DefPathData::ValueNs(i.ident.modern()),
ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.modern()),
ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
ItemKind::GlobalAsm(..) => DefPathData::Misc,
ItemKind::Use(ref view_path) => {
Expand Down Expand Up @@ -135,15 +138,13 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
for v in &enum_definition.variants {
let variant_def_index =
this.create_def(v.node.data.id(),
DefPathData::EnumVariant(v.node.name.name.as_str()),
DefPathData::EnumVariant(v.node.name.modern()),
REGULAR_SPACE);
this.with_parent(variant_def_index, |this| {
for (index, field) in v.node.data.fields().iter().enumerate() {
let name = field.ident.map(|ident| ident.name)
.unwrap_or_else(|| Symbol::intern(&index.to_string()));
this.create_def(field.id,
DefPathData::Field(name.as_str()),
REGULAR_SPACE);
let ident = field.ident.map(Ident::modern)
.unwrap_or_else(|| Ident::from_str(&index.to_string()));
this.create_def(field.id, DefPathData::Field(ident), REGULAR_SPACE);
}

if let Some(ref expr) = v.node.disr_expr {
Expand All @@ -161,9 +162,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
}

for (index, field) in struct_def.fields().iter().enumerate() {
let name = field.ident.map(|ident| ident.name.as_str())
.unwrap_or(Symbol::intern(&index.to_string()).as_str());
this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE);
let ident = field.ident.map(Ident::modern)
.unwrap_or_else(|| Ident::from_str(&index.to_string()));
this.create_def(field.id, DefPathData::Field(ident), REGULAR_SPACE);
}
}
_ => {}
Expand All @@ -174,7 +175,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {

fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
let def = self.create_def(foreign_item.id,
DefPathData::ValueNs(foreign_item.ident.name.as_str()),
DefPathData::ValueNs(foreign_item.ident.modern()),
REGULAR_SPACE);

self.with_parent(def, |this| {
Expand All @@ -185,7 +186,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
fn visit_generics(&mut self, generics: &'a Generics) {
for ty_param in generics.ty_params.iter() {
self.create_def(ty_param.id,
DefPathData::TypeParam(ty_param.ident.name.as_str()),
DefPathData::TypeParam(ty_param.ident.modern()),
REGULAR_SPACE);
}

Expand All @@ -195,8 +196,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
fn visit_trait_item(&mut self, ti: &'a TraitItem) {
let def_data = match ti.node {
TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
DefPathData::ValueNs(ti.ident.name.as_str()),
TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()),
DefPathData::ValueNs(ti.ident.modern()),
TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.modern()),
TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
};

Expand All @@ -213,8 +214,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
let def_data = match ii.node {
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
DefPathData::ValueNs(ii.ident.name.as_str()),
ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()),
DefPathData::ValueNs(ii.ident.modern()),
ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.modern()),
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
};

Expand All @@ -235,7 +236,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false),
PatKind::Ident(_, id, _) => {
let def = self.create_def(pat.id,
DefPathData::Binding(id.node.name.as_str()),
DefPathData::Binding(id.node.modern()),
REGULAR_SPACE);
self.parent_def = Some(def);
}
Expand Down Expand Up @@ -280,7 +281,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {

fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) {
self.create_def(def.lifetime.id,
DefPathData::LifetimeDef(def.lifetime.name.as_str()),
DefPathData::LifetimeDef(def.lifetime.ident.modern()),
REGULAR_SPACE);
}

Expand Down
Loading