Skip to content

Commit

Permalink
Move resolve_invoc from syntax to resolve.
Browse files Browse the repository at this point in the history
  • Loading branch information
jseyfried authored and alexcrichton committed Mar 10, 2017
1 parent 212b6c2 commit e839486
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 72 deletions.
76 changes: 67 additions & 9 deletions src/librustc_resolve/macros.rs
Expand Up @@ -17,16 +17,14 @@ use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex}
use rustc::hir::def::{Def, Export};
use rustc::hir::map::{self, DefCollector};
use rustc::ty;
use std::cell::Cell;
use std::rc::Rc;
use syntax::ast::{self, Name, Ident};
use syntax::attr;
use syntax::attr::{self, HasAttrs};
use syntax::errors::DiagnosticBuilder;
use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
use syntax::ext::base::{Resolver as SyntaxResolver, SyntaxExtension};
use syntax::ext::base::MacroKind;
use syntax::ext::expand::Expansion;
use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator};
use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
use syntax::ext::expand::{Expansion, ExpansionKind, Invocation, InvocationKind, find_attr_invoc};
use syntax::ext::hygiene::Mark;
use syntax::ext::placeholders::placeholder;
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::{self, emit_feature_err, GateIssue};
use syntax::fold::{self, Folder};
Expand All @@ -35,6 +33,10 @@ use syntax::symbol::{Symbol, keywords};
use syntax::util::lev_distance::find_best_match_for_name;
use syntax_pos::{Span, DUMMY_SP};

use std::cell::Cell;
use std::mem;
use std::rc::Rc;

#[derive(Clone)]
pub struct InvocationData<'a> {
pub module: Cell<Module<'a>>,
Expand Down Expand Up @@ -235,8 +237,64 @@ impl<'a> base::Resolver for Resolver<'a> {
None
}

fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind,
force: bool) -> Result<Rc<SyntaxExtension>, Determinacy> {
fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
-> Result<Option<Rc<SyntaxExtension>>, Determinacy> {
let (attr, traits, item) = match invoc.kind {
InvocationKind::Attr { attr: None, .. } => return Ok(None),
InvocationKind::Attr { ref mut attr, ref traits, ref mut item } => (attr, traits, item),
InvocationKind::Bang { ref mac, .. } => {
return self.resolve_macro(scope, &mac.node.path, MacroKind::Bang, force).map(Some);
}
InvocationKind::Derive { name, span, .. } => {
let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name));
return self.resolve_macro(scope, &path, MacroKind::Derive, force).map(Some);
}
};

let (attr_name, path) = {
let attr = attr.as_ref().unwrap();
(attr.name(), ast::Path::from_ident(attr.span, Ident::with_empty_ctxt(attr.name())))
};

let mut determined = true;
match self.resolve_macro(scope, &path, MacroKind::Attr, force) {
Ok(ext) => return Ok(Some(ext)),
Err(Determinacy::Undetermined) => determined = false,
Err(Determinacy::Determined) if force => return Err(Determinacy::Determined),
Err(Determinacy::Determined) => {}
}

for &(name, span) in traits {
let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name));
match self.resolve_macro(scope, &path, MacroKind::Derive, force) {
Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs) = *ext {
if inert_attrs.contains(&attr_name) {
// FIXME(jseyfried) Avoid `mem::replace` here.
let dummy_item = placeholder(ExpansionKind::Items, ast::DUMMY_NODE_ID)
.make_items().pop().unwrap();
let dummy_item = Annotatable::Item(dummy_item);
*item = mem::replace(item, dummy_item).map_attrs(|mut attrs| {
let inert_attr = attr.take().unwrap();
attr::mark_known(&inert_attr);
if self.proc_macro_enabled {
*attr = find_attr_invoc(&mut attrs);
}
attrs.push(inert_attr);
attrs
});
}
return Err(Determinacy::Undetermined);
},
Err(Determinacy::Undetermined) => determined = false,
Err(Determinacy::Determined) => {}
}
}

Err(if determined { Determinacy::Determined } else { Determinacy::Undetermined })
}

fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
-> Result<Rc<SyntaxExtension>, Determinacy> {
let ast::Path { ref segments, span } = *path;
if segments.iter().any(|segment| segment.parameters.is_some()) {
let kind =
Expand Down
12 changes: 9 additions & 3 deletions src/libsyntax/ext/base.rs
Expand Up @@ -15,7 +15,7 @@ use attr::HasAttrs;
use codemap::{self, CodeMap, ExpnInfo, Spanned, respan};
use syntax_pos::{Span, ExpnId, NO_EXPANSION};
use errors::{DiagnosticBuilder, FatalError};
use ext::expand::{self, Expansion};
use ext::expand::{self, Expansion, Invocation};
use ext::hygiene::Mark;
use fold::{self, Folder};
use parse::{self, parser, DirectoryOwnership};
Expand Down Expand Up @@ -557,8 +557,10 @@ pub trait Resolver {
fn resolve_imports(&mut self);
// Resolves attribute and derive legacy macros from `#![plugin(..)]`.
fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>;
fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind,
force: bool) -> Result<Rc<SyntaxExtension>, Determinacy>;
fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
-> Result<Option<Rc<SyntaxExtension>>, Determinacy>;
fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
-> Result<Rc<SyntaxExtension>, Determinacy>;
}

#[derive(Copy, Clone, Debug)]
Expand All @@ -580,6 +582,10 @@ impl Resolver for DummyResolver {

fn resolve_imports(&mut self) {}
fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>) -> Option<Attribute> { None }
fn resolve_invoc(&mut self, _invoc: &mut Invocation, _scope: Mark, _force: bool)
-> Result<Option<Rc<SyntaxExtension>>, Determinacy> {
Err(Determinacy::Determined)
}
fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _kind: MacroKind,
_force: bool) -> Result<Rc<SyntaxExtension>, Determinacy> {
Err(Determinacy::Determined)
Expand Down
62 changes: 2 additions & 60 deletions src/libsyntax/ext/expand.rs
Expand Up @@ -251,7 +251,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {

let scope =
if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
let ext = match self.resolve_invoc(&mut invoc, scope, force) {
let ext = match self.cx.resolver.resolve_invoc(&mut invoc, scope, force) {
Ok(ext) => Some(ext),
Err(Determinacy::Determined) => None,
Err(Determinacy::Undetermined) => {
Expand Down Expand Up @@ -364,64 +364,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
result
}

fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
-> Result<Option<Rc<SyntaxExtension>>, Determinacy> {
let (attr, traits, item) = match invoc.kind {
InvocationKind::Bang { ref mac, .. } => {
return self.cx.resolver.resolve_macro(scope, &mac.node.path,
MacroKind::Bang, force).map(Some);
}
InvocationKind::Attr { attr: None, .. } => return Ok(None),
InvocationKind::Derive { name, span, .. } => {
let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name));
return self.cx.resolver.resolve_macro(scope, &path,
MacroKind::Derive, force).map(Some)
}
InvocationKind::Attr { ref mut attr, ref traits, ref mut item } => (attr, traits, item),
};

let (attr_name, path) = {
let attr = attr.as_ref().unwrap();
(attr.name(), ast::Path::from_ident(attr.span, Ident::with_empty_ctxt(attr.name())))
};

let mut determined = true;
match self.cx.resolver.resolve_macro(scope, &path, MacroKind::Attr, force) {
Ok(ext) => return Ok(Some(ext)),
Err(Determinacy::Undetermined) => determined = false,
Err(Determinacy::Determined) if force => return Err(Determinacy::Determined),
_ => {}
}

for &(name, span) in traits {
let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name));
match self.cx.resolver.resolve_macro(scope, &path, MacroKind::Derive, force) {
Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs) = *ext {
if inert_attrs.contains(&attr_name) {
// FIXME(jseyfried) Avoid `mem::replace` here.
let dummy_item = placeholder(ExpansionKind::Items, ast::DUMMY_NODE_ID)
.make_items().pop().unwrap();
*item = mem::replace(item, Annotatable::Item(dummy_item))
.map_attrs(|mut attrs| {
let inert_attr = attr.take().unwrap();
attr::mark_known(&inert_attr);
if self.cx.ecfg.proc_macro_enabled() {
*attr = find_attr_invoc(&mut attrs);
}
attrs.push(inert_attr);
attrs
});
}
return Err(Determinacy::Undetermined);
},
Err(Determinacy::Undetermined) => determined = false,
Err(Determinacy::Determined) => {}
}
}

Err(if determined { Determinacy::Determined } else { Determinacy::Undetermined })
}

fn expand_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
match invoc.kind {
InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext),
Expand Down Expand Up @@ -802,7 +744,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
}
}

fn find_attr_invoc(attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
pub fn find_attr_invoc(attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
for i in 0 .. attrs.len() {
if !attr::is_known(&attrs[i]) && !is_builtin_attr(&attrs[i]) {
return Some(attrs.remove(i));
Expand Down

0 comments on commit e839486

Please sign in to comment.