resolve: Support resolving macro paths without macro kind restrictions
This commit is contained in:
parent
a7726ce086
commit
1b4fbfca41
4 changed files with 18 additions and 17 deletions
|
@ -574,7 +574,7 @@ impl<'a> Resolver<'a> {
|
||||||
for derive in &parent_scope.derives {
|
for derive in &parent_scope.derives {
|
||||||
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
|
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
|
||||||
if let Ok((Some(ext), _)) = this.resolve_macro_path(
|
if let Ok((Some(ext), _)) = this.resolve_macro_path(
|
||||||
derive, MacroKind::Derive, &parent_scope, false, false
|
derive, Some(MacroKind::Derive), &parent_scope, false, false
|
||||||
) {
|
) {
|
||||||
suggestions.extend(ext.helper_attrs.iter().map(|name| {
|
suggestions.extend(ext.helper_attrs.iter().map(|name| {
|
||||||
TypoSuggestion::from_res(*name, res)
|
TypoSuggestion::from_res(*name, res)
|
||||||
|
|
|
@ -3684,13 +3684,11 @@ impl<'a> Resolver<'a> {
|
||||||
let path = Path { segments: path.iter().map(path_seg).collect(), span };
|
let path = Path { segments: path.iter().map(path_seg).collect(), span };
|
||||||
let parent_scope =
|
let parent_scope =
|
||||||
ParentScope { module: self.current_module, ..self.dummy_parent_scope() };
|
ParentScope { module: self.current_module, ..self.dummy_parent_scope() };
|
||||||
for macro_kind in &[MacroKind::Bang, MacroKind::Attr, MacroKind::Derive] {
|
if let Ok((_, res)) =
|
||||||
if let Ok((_, res)) = self.resolve_macro_path(&path, *macro_kind,
|
self.resolve_macro_path(&path, None, &parent_scope, false, false) {
|
||||||
&parent_scope, false, false) {
|
|
||||||
return Some(PartialRes::new(res));
|
return Some(PartialRes::new(res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fin_res
|
fin_res
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,7 +220,7 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
|
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
|
||||||
let (ext, res) = self.smart_resolve_macro_path(path, kind, &parent_scope, true, force)?;
|
let (ext, res) = self.smart_resolve_macro_path(path, kind, &parent_scope, force)?;
|
||||||
|
|
||||||
let span = invoc.span();
|
let span = invoc.span();
|
||||||
invoc.expansion_data.mark.set_expn_info(ext.expn_info(span, fast_print_path(path)));
|
invoc.expansion_data.mark.set_expn_info(ext.expn_info(span, fast_print_path(path)));
|
||||||
|
@ -269,10 +269,10 @@ impl<'a> Resolver<'a> {
|
||||||
path: &ast::Path,
|
path: &ast::Path,
|
||||||
kind: MacroKind,
|
kind: MacroKind,
|
||||||
parent_scope: &ParentScope<'a>,
|
parent_scope: &ParentScope<'a>,
|
||||||
trace: bool,
|
|
||||||
force: bool,
|
force: bool,
|
||||||
) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> {
|
) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> {
|
||||||
let (ext, res) = match self.resolve_macro_path(path, kind, parent_scope, trace, force) {
|
let (ext, res) = match self.resolve_macro_path(path, Some(kind), parent_scope,
|
||||||
|
true, force) {
|
||||||
Ok((Some(ext), res)) => (ext, res),
|
Ok((Some(ext), res)) => (ext, res),
|
||||||
// Use dummy syntax extensions for unresolved macros for better recovery.
|
// Use dummy syntax extensions for unresolved macros for better recovery.
|
||||||
Ok((None, res)) => (self.dummy_ext(kind), res),
|
Ok((None, res)) => (self.dummy_ext(kind), res),
|
||||||
|
@ -334,7 +334,7 @@ impl<'a> Resolver<'a> {
|
||||||
pub fn resolve_macro_path(
|
pub fn resolve_macro_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &ast::Path,
|
path: &ast::Path,
|
||||||
kind: MacroKind,
|
kind: Option<MacroKind>,
|
||||||
parent_scope: &ParentScope<'a>,
|
parent_scope: &ParentScope<'a>,
|
||||||
trace: bool,
|
trace: bool,
|
||||||
force: bool,
|
force: bool,
|
||||||
|
@ -343,7 +343,7 @@ impl<'a> Resolver<'a> {
|
||||||
let mut path = Segment::from_path(path);
|
let mut path = Segment::from_path(path);
|
||||||
|
|
||||||
// Possibly apply the macro helper hack
|
// Possibly apply the macro helper hack
|
||||||
if kind == MacroKind::Bang && path.len() == 1 &&
|
if kind == Some(MacroKind::Bang) && path.len() == 1 &&
|
||||||
path[0].ident.span.ctxt().outer_expn_info()
|
path[0].ident.span.ctxt().outer_expn_info()
|
||||||
.map_or(false, |info| info.local_inner_macros) {
|
.map_or(false, |info| info.local_inner_macros) {
|
||||||
let root = Ident::new(kw::DollarCrate, path[0].ident.span);
|
let root = Ident::new(kw::DollarCrate, path[0].ident.span);
|
||||||
|
@ -364,6 +364,7 @@ impl<'a> Resolver<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if trace {
|
if trace {
|
||||||
|
let kind = kind.expect("macro kind must be specified if tracing is enabled");
|
||||||
parent_scope.module.multi_segment_macro_resolutions.borrow_mut()
|
parent_scope.module.multi_segment_macro_resolutions.borrow_mut()
|
||||||
.push((path, path_span, kind, parent_scope.clone(), res.ok()));
|
.push((path, path_span, kind, parent_scope.clone(), res.ok()));
|
||||||
}
|
}
|
||||||
|
@ -371,14 +372,17 @@ impl<'a> Resolver<'a> {
|
||||||
self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span);
|
self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span);
|
||||||
res
|
res
|
||||||
} else {
|
} else {
|
||||||
|
// Macro without a specific kind restriction is equvalent to a macro import.
|
||||||
|
let scope_set = kind.map_or(ScopeSet::Import(MacroNS), ScopeSet::Macro);
|
||||||
let binding = self.early_resolve_ident_in_lexical_scope(
|
let binding = self.early_resolve_ident_in_lexical_scope(
|
||||||
path[0].ident, ScopeSet::Macro(kind), parent_scope, false, force, path_span
|
path[0].ident, scope_set, parent_scope, false, force, path_span
|
||||||
);
|
);
|
||||||
if let Err(Determinacy::Undetermined) = binding {
|
if let Err(Determinacy::Undetermined) = binding {
|
||||||
return Err(Determinacy::Undetermined);
|
return Err(Determinacy::Undetermined);
|
||||||
}
|
}
|
||||||
|
|
||||||
if trace {
|
if trace {
|
||||||
|
let kind = kind.expect("macro kind must be specified if tracing is enabled");
|
||||||
parent_scope.module.single_segment_macro_resolutions.borrow_mut()
|
parent_scope.module.single_segment_macro_resolutions.borrow_mut()
|
||||||
.push((path[0].ident, kind, parent_scope.clone(), binding.ok()));
|
.push((path[0].ident, kind, parent_scope.clone(), binding.ok()));
|
||||||
}
|
}
|
||||||
|
@ -452,7 +456,7 @@ impl<'a> Resolver<'a> {
|
||||||
let mut result = Err(Determinacy::Determined);
|
let mut result = Err(Determinacy::Determined);
|
||||||
for derive in &parent_scope.derives {
|
for derive in &parent_scope.derives {
|
||||||
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
|
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
|
||||||
match this.resolve_macro_path(derive, MacroKind::Derive,
|
match this.resolve_macro_path(derive, Some(MacroKind::Derive),
|
||||||
&parent_scope, true, force) {
|
&parent_scope, true, force) {
|
||||||
Ok((Some(ext), _)) => if ext.helper_attrs.contains(&ident.name) {
|
Ok((Some(ext), _)) => if ext.helper_attrs.contains(&ident.name) {
|
||||||
let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
|
let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
|
||||||
|
|
|
@ -6,6 +6,7 @@ use rustc::lint as lint;
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use syntax;
|
use syntax;
|
||||||
use syntax::ast::{self, Ident};
|
use syntax::ast::{self, Ident};
|
||||||
|
use syntax::ext::base::SyntaxExtensionKind;
|
||||||
use syntax::feature_gate::UnstableFeatures;
|
use syntax::feature_gate::UnstableFeatures;
|
||||||
use syntax::symbol::Symbol;
|
use syntax::symbol::Symbol;
|
||||||
use syntax_pos::DUMMY_SP;
|
use syntax_pos::DUMMY_SP;
|
||||||
|
@ -425,12 +426,10 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
|
||||||
|
|
||||||
/// Resolves a string as a macro.
|
/// Resolves a string as a macro.
|
||||||
fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
|
fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
|
||||||
use syntax::ext::base::{MacroKind, SyntaxExtensionKind};
|
let path = ast::Path::from_ident(Ident::from_str(path_str));
|
||||||
let segment = ast::PathSegment::from_ident(Ident::from_str(path_str));
|
|
||||||
let path = ast::Path { segments: vec![segment], span: DUMMY_SP };
|
|
||||||
cx.enter_resolver(|resolver| {
|
cx.enter_resolver(|resolver| {
|
||||||
if let Ok((Some(ext), res)) = resolver.resolve_macro_path(
|
if let Ok((Some(ext), res)) = resolver.resolve_macro_path(
|
||||||
&path, MacroKind::Bang, &resolver.dummy_parent_scope(), false, false
|
&path, None, &resolver.dummy_parent_scope(), false, false
|
||||||
) {
|
) {
|
||||||
if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind {
|
if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind {
|
||||||
return Some(res.map_id(|_| panic!("unexpected id")));
|
return Some(res.map_id(|_| panic!("unexpected id")));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue