}
visit::walk_attribute(self, attr);
}
-
- fn visit_ident(&mut self, ident: Ident) {
- if ident.name == keywords::DollarCrate.name() {
- let name = match self.resolver.resolve_crate_root(ident).kind {
- ModuleKind::Def(_, name) if name != keywords::Invalid.name() => name,
- _ => keywords::Crate.name(),
- };
- ident.span.ctxt().set_dollar_crate_name(name);
- }
- visit::walk_ident(self, ident);
- }
}
use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
use {CrateLint, Resolver, ResolutionError, ScopeSet, Weak};
-use {Module, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
+use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
use {is_known_tool, resolve_error};
use ModuleOrUniformRoot;
use Namespace::*;
use syntax::attr;
use syntax::errors::DiagnosticBuilder;
use syntax::ext::base::{self, Determinacy};
-use syntax::ext::base::{MacroKind, SyntaxExtension};
+use syntax::ext::base::{Annotatable, MacroKind, SyntaxExtension};
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
use syntax::ext::hygiene::{self, Mark};
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::{feature_err, is_builtin_attr_name, GateIssue};
use syntax::symbol::{Symbol, keywords};
+use syntax::visit::Visitor;
use syntax::util::lev_distance::find_best_match_for_name;
use syntax_pos::{Span, DUMMY_SP};
use errors::Applicability;
mark
}
+ fn resolve_dollar_crates(&mut self, annotatable: &Annotatable) {
+ pub struct ResolveDollarCrates<'a, 'b: 'a> {
+ pub resolver: &'a mut Resolver<'b>,
+ }
+ impl<'a> Visitor<'a> for ResolveDollarCrates<'a, '_> {
+ fn visit_ident(&mut self, ident: Ident) {
+ if ident.name == keywords::DollarCrate.name() {
+ let name = match self.resolver.resolve_crate_root(ident).kind {
+ ModuleKind::Def(_, name) if name != keywords::Invalid.name() => name,
+ _ => keywords::Crate.name(),
+ };
+ ident.span.ctxt().set_dollar_crate_name(name);
+ }
+ }
+ fn visit_mac(&mut self, _: &ast::Mac) {}
+ }
+
+ annotatable.visit_with(&mut ResolveDollarCrates { resolver: self });
+ }
+
fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
derives: &[Mark]) {
let invocation = self.invocations[&mark];
use ptr::P;
use smallvec::SmallVec;
use symbol::{keywords, Ident, Symbol};
+use visit::Visitor;
use ThinVec;
use rustc_data_structures::fx::FxHashMap;
_ => false,
}
}
+
+ pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
+ match self {
+ Annotatable::Item(item) => visitor.visit_item(item),
+ Annotatable::TraitItem(trait_item) => visitor.visit_trait_item(trait_item),
+ Annotatable::ImplItem(impl_item) => visitor.visit_impl_item(impl_item),
+ Annotatable::ForeignItem(foreign_item) => visitor.visit_foreign_item(foreign_item),
+ Annotatable::Stmt(stmt) => visitor.visit_stmt(stmt),
+ Annotatable::Expr(expr) => visitor.visit_expr(expr),
+ }
+ }
}
// A more flexible ItemDecorator.
fn next_node_id(&mut self) -> ast::NodeId;
fn get_module_scope(&mut self, id: ast::NodeId) -> Mark;
+ fn resolve_dollar_crates(&mut self, annotatable: &Annotatable);
fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
derives: &[Mark]);
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID }
fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }
+ fn resolve_dollar_crates(&mut self, _annotatable: &Annotatable) {}
fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment,
_derives: &[Mark]) {}
fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
Some(invoc.fragment_kind.expect_from_annotatables(items))
}
AttrProcMacro(ref mac, ..) => {
+ // Resolve `$crate`s in case we have to go though stringification.
+ self.cx.resolver.resolve_dollar_crates(&item);
self.gate_proc_macro_attr_item(attr.span, &item);
let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item {
Annotatable::Item(item) => token::NtItem(item),
match *ext {
ProcMacroDerive(ref ext, ..) => {
+ // Resolve `$crate`s in case we have to go though stringification.
+ self.cx.resolver.resolve_dollar_crates(&item);
invoc.expansion_data.mark.set_expn_info(expn_info);
let span = span.with_ctxt(self.cx.backtrace());
let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
+// compile-pass
// edition:2018
// aux-build:dollar-crate.rs
struct M($crate::S);
}
- #[dollar_crate::a] //~ ERROR expected type, found `$`
+ #[dollar_crate::a]
struct A($crate::S);
};
}
+++ /dev/null
-error: expected type, found `$`
- --> $DIR/dollar-crate-in-tokens.rs:18:9
- |
-LL | #[dollar_crate::a] //~ ERROR expected type, found `$`
- | ^^^^^^^^^^^^^^^^^^
-...
-LL | m!();
- | ----- in this macro invocation
-
-error: aborting due to previous error
-
span: #2 bytes(LO..HI)
}
]
-ATTRIBUTE INPUT (PRETTY-PRINTED): struct A($crate::S);
+ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(crate::S);
ATTRIBUTE INPUT: TokenStream [
Ident {
ident: "struct",
- span: #0 bytes(0..0)
+ span: #2 bytes(LO..HI)
},
Ident {
ident: "A",
- span: #0 bytes(0..0)
+ span: #2 bytes(LO..HI)
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
- Punct {
- ch: '$',
- spacing: Alone,
- span: #0 bytes(0..0)
- },
Ident {
- ident: "crate",
- span: #0 bytes(0..0)
+ ident: "$crate",
+ span: #2 bytes(LO..HI)
},
Punct {
ch: ':',
spacing: Joint,
- span: #0 bytes(0..0)
+ span: #2 bytes(LO..HI)
},
Punct {
ch: ':',
spacing: Alone,
- span: #0 bytes(0..0)
+ span: #2 bytes(LO..HI)
},
Ident {
ident: "S",
- span: #0 bytes(0..0)
+ span: #2 bytes(LO..HI)
}
],
- span: #0 bytes(0..0)
+ span: #2 bytes(LO..HI)
},
Punct {
ch: ';',
spacing: Alone,
- span: #0 bytes(0..0)
+ span: #2 bytes(LO..HI)
}
]