1
Fork 0

resolve: Scope visiting doesn't need an Ident

This commit is contained in:
Vadim Petrochenkov 2021-01-07 15:23:25 +03:00
parent bf5f30684a
commit 3ff866ed7c
6 changed files with 90 additions and 57 deletions

View file

@ -595,7 +595,8 @@ impl<'a> Resolver<'a> {
filter_fn: &impl Fn(Res) -> bool, filter_fn: &impl Fn(Res) -> bool,
) -> Option<TypoSuggestion> { ) -> Option<TypoSuggestion> {
let mut suggestions = Vec::new(); let mut suggestions = Vec::new();
self.visit_scopes(scope_set, parent_scope, ident, |this, scope, use_prelude, _| { let ctxt = ident.span.ctxt();
self.visit_scopes(scope_set, parent_scope, ctxt, |this, scope, use_prelude, _| {
match scope { match scope {
Scope::DeriveHelpers(expn_id) => { Scope::DeriveHelpers(expn_id) => {
let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);

View file

@ -262,52 +262,60 @@ impl<'a> PathSource<'a> {
crate fn is_expected(self, res: Res) -> bool { crate fn is_expected(self, res: Res) -> bool {
match self { match self {
PathSource::Type => matches!(res, Res::Def( PathSource::Type => matches!(
res,
Res::Def(
DefKind::Struct DefKind::Struct
| DefKind::Union | DefKind::Union
| DefKind::Enum | DefKind::Enum
| DefKind::Trait | DefKind::Trait
| DefKind::TraitAlias | DefKind::TraitAlias
| DefKind::TyAlias | DefKind::TyAlias
| DefKind::AssocTy | DefKind::AssocTy
| DefKind::TyParam | DefKind::TyParam
| DefKind::OpaqueTy | DefKind::OpaqueTy
| DefKind::ForeignTy, | DefKind::ForeignTy,
_, _,
) ) | Res::PrimTy(..)
| Res::PrimTy(..) | Res::SelfTy(..)
| Res::SelfTy(..)), ),
PathSource::Trait(AliasPossibility::No) => matches!(res, Res::Def(DefKind::Trait, _)), PathSource::Trait(AliasPossibility::No) => matches!(res, Res::Def(DefKind::Trait, _)),
PathSource::Trait(AliasPossibility::Maybe) => { PathSource::Trait(AliasPossibility::Maybe) => {
matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _))
} }
PathSource::Expr(..) => matches!(res, Res::Def( PathSource::Expr(..) => matches!(
res,
Res::Def(
DefKind::Ctor(_, CtorKind::Const | CtorKind::Fn) DefKind::Ctor(_, CtorKind::Const | CtorKind::Fn)
| DefKind::Const | DefKind::Const
| DefKind::Static | DefKind::Static
| DefKind::Fn | DefKind::Fn
| DefKind::AssocFn | DefKind::AssocFn
| DefKind::AssocConst | DefKind::AssocConst
| DefKind::ConstParam, | DefKind::ConstParam,
_, _,
) ) | Res::Local(..)
| Res::Local(..) | Res::SelfCtor(..)
| Res::SelfCtor(..)), ),
PathSource::Pat => matches!(res, Res::Def( PathSource::Pat => matches!(
res,
Res::Def(
DefKind::Ctor(_, CtorKind::Const) | DefKind::Const | DefKind::AssocConst, DefKind::Ctor(_, CtorKind::Const) | DefKind::Const | DefKind::AssocConst,
_, _,
) ) | Res::SelfCtor(..)
| Res::SelfCtor(..)), ),
PathSource::TupleStruct(..) => res.expected_in_tuple_struct_pat(), PathSource::TupleStruct(..) => res.expected_in_tuple_struct_pat(),
PathSource::Struct => matches!(res, Res::Def( PathSource::Struct => matches!(
res,
Res::Def(
DefKind::Struct DefKind::Struct
| DefKind::Union | DefKind::Union
| DefKind::Variant | DefKind::Variant
| DefKind::TyAlias | DefKind::TyAlias
| DefKind::AssocTy, | DefKind::AssocTy,
_, _,
) ) | Res::SelfTy(..)
| Res::SelfTy(..)), ),
PathSource::TraitItem(ns) => match res { PathSource::TraitItem(ns) => match res {
Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) if ns == ValueNS => true, Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) if ns == ValueNS => true,
Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true, Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
@ -2397,8 +2405,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
&mut found_traits, &mut found_traits,
&self.parent_scope, &self.parent_scope,
); );
search_module = let mut span_data = ident.span.data();
unwrap_or!(self.r.hygienic_lexical_parent(search_module, &mut ident.span), break); search_module = unwrap_or!(
self.r.hygienic_lexical_parent(search_module, &mut span_data.ctxt),
break
);
ident.span = span_data.span();
} }
if let Some(prelude) = self.r.prelude { if let Some(prelude) = self.r.prelude {

View file

@ -50,6 +50,7 @@ use rustc_middle::{bug, span_bug};
use rustc_session::lint; use rustc_session::lint;
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::edition::Edition;
use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency}; use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency};
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Ident, Symbol};
@ -759,10 +760,13 @@ impl<'a> NameBinding<'a> {
} }
fn is_variant(&self) -> bool { fn is_variant(&self) -> bool {
matches!(self.kind, NameBindingKind::Res( matches!(
self.kind,
NameBindingKind::Res(
Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..), _), Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..), _),
_, _,
)) )
)
} }
fn is_extern_crate(&self) -> bool { fn is_extern_crate(&self) -> bool {
@ -1626,8 +1630,13 @@ impl<'a> Resolver<'a> {
&mut self, &mut self,
scope_set: ScopeSet, scope_set: ScopeSet,
parent_scope: &ParentScope<'a>, parent_scope: &ParentScope<'a>,
ident: Ident, ctxt: SyntaxContext,
mut visitor: impl FnMut(&mut Self, Scope<'a>, /*use_prelude*/ bool, Ident) -> Option<T>, mut visitor: impl FnMut(
&mut Self,
Scope<'a>,
/*use_prelude*/ bool,
SyntaxContext,
) -> Option<T>,
) -> Option<T> { ) -> Option<T> {
// General principles: // General principles:
// 1. Not controlled (user-defined) names should have higher priority than controlled names // 1. Not controlled (user-defined) names should have higher priority than controlled names
@ -1670,7 +1679,7 @@ impl<'a> Resolver<'a> {
// 4c. Standard library prelude (de-facto closed, controlled). // 4c. Standard library prelude (de-facto closed, controlled).
// 6. Language prelude: builtin attributes (closed, controlled). // 6. Language prelude: builtin attributes (closed, controlled).
let rust_2015 = ident.span.rust_2015(); let rust_2015 = ctxt.edition() == Edition::Edition2015;
let (ns, macro_kind, is_absolute_path) = match scope_set { let (ns, macro_kind, is_absolute_path) = match scope_set {
ScopeSet::All(ns, _) => (ns, None, false), ScopeSet::All(ns, _) => (ns, None, false),
ScopeSet::AbsolutePath(ns) => (ns, None, true), ScopeSet::AbsolutePath(ns) => (ns, None, true),
@ -1683,7 +1692,7 @@ impl<'a> Resolver<'a> {
TypeNS | ValueNS => Scope::Module(module), TypeNS | ValueNS => Scope::Module(module),
MacroNS => Scope::DeriveHelpers(parent_scope.expansion), MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
}; };
let mut ident = ident.normalize_to_macros_2_0(); let mut ctxt = ctxt.normalize_to_macros_2_0();
let mut use_prelude = !module.no_implicit_prelude; let mut use_prelude = !module.no_implicit_prelude;
loop { loop {
@ -1719,7 +1728,7 @@ impl<'a> Resolver<'a> {
}; };
if visit { if visit {
if let break_result @ Some(..) = visitor(self, scope, use_prelude, ident) { if let break_result @ Some(..) = visitor(self, scope, use_prelude, ctxt) {
return break_result; return break_result;
} }
} }
@ -1749,17 +1758,17 @@ impl<'a> Resolver<'a> {
}, },
Scope::CrateRoot => match ns { Scope::CrateRoot => match ns {
TypeNS => { TypeNS => {
ident.span.adjust(ExpnId::root()); ctxt.adjust(ExpnId::root());
Scope::ExternPrelude Scope::ExternPrelude
} }
ValueNS | MacroNS => break, ValueNS | MacroNS => break,
}, },
Scope::Module(module) => { Scope::Module(module) => {
use_prelude = !module.no_implicit_prelude; use_prelude = !module.no_implicit_prelude;
match self.hygienic_lexical_parent(module, &mut ident.span) { match self.hygienic_lexical_parent(module, &mut ctxt) {
Some(parent_module) => Scope::Module(parent_module), Some(parent_module) => Scope::Module(parent_module),
None => { None => {
ident.span.adjust(ExpnId::root()); ctxt.adjust(ExpnId::root());
match ns { match ns {
TypeNS => Scope::ExternPrelude, TypeNS => Scope::ExternPrelude,
ValueNS => Scope::StdLibPrelude, ValueNS => Scope::StdLibPrelude,
@ -1882,16 +1891,18 @@ impl<'a> Resolver<'a> {
ident = normalized_ident; ident = normalized_ident;
let mut poisoned = None; let mut poisoned = None;
loop { loop {
let mut span_data = ident.span.data();
let opt_module = if let Some(node_id) = record_used_id { let opt_module = if let Some(node_id) = record_used_id {
self.hygienic_lexical_parent_with_compatibility_fallback( self.hygienic_lexical_parent_with_compatibility_fallback(
module, module,
&mut ident.span, &mut span_data.ctxt,
node_id, node_id,
&mut poisoned, &mut poisoned,
) )
} else { } else {
self.hygienic_lexical_parent(module, &mut ident.span) self.hygienic_lexical_parent(module, &mut span_data.ctxt)
}; };
ident.span = span_data.span();
module = unwrap_or!(opt_module, break); module = unwrap_or!(opt_module, break);
let adjusted_parent_scope = &ParentScope { module, ..*parent_scope }; let adjusted_parent_scope = &ParentScope { module, ..*parent_scope };
let result = self.resolve_ident_in_module_unadjusted( let result = self.resolve_ident_in_module_unadjusted(
@ -1965,10 +1976,10 @@ impl<'a> Resolver<'a> {
fn hygienic_lexical_parent( fn hygienic_lexical_parent(
&mut self, &mut self,
module: Module<'a>, module: Module<'a>,
span: &mut Span, ctxt: &mut SyntaxContext,
) -> Option<Module<'a>> { ) -> Option<Module<'a>> {
if !module.expansion.outer_expn_is_descendant_of(span.ctxt()) { if !module.expansion.outer_expn_is_descendant_of(*ctxt) {
return Some(self.macro_def_scope(span.remove_mark())); return Some(self.macro_def_scope(ctxt.remove_mark()));
} }
if let ModuleKind::Block(..) = module.kind { if let ModuleKind::Block(..) = module.kind {
@ -1981,11 +1992,11 @@ impl<'a> Resolver<'a> {
fn hygienic_lexical_parent_with_compatibility_fallback( fn hygienic_lexical_parent_with_compatibility_fallback(
&mut self, &mut self,
module: Module<'a>, module: Module<'a>,
span: &mut Span, ctxt: &mut SyntaxContext,
node_id: NodeId, node_id: NodeId,
poisoned: &mut Option<NodeId>, poisoned: &mut Option<NodeId>,
) -> Option<Module<'a>> { ) -> Option<Module<'a>> {
if let module @ Some(..) = self.hygienic_lexical_parent(module, span) { if let module @ Some(..) = self.hygienic_lexical_parent(module, ctxt) {
return module; return module;
} }
@ -2010,7 +2021,7 @@ impl<'a> Resolver<'a> {
let ext = self.get_macro_by_def_id(def_id); let ext = self.get_macro_by_def_id(def_id);
if !ext.is_builtin if !ext.is_builtin
&& ext.macro_kind() == MacroKind::Derive && ext.macro_kind() == MacroKind::Derive
&& parent.expansion.outer_expn_is_descendant_of(span.ctxt()) && parent.expansion.outer_expn_is_descendant_of(*ctxt)
{ {
*poisoned = Some(node_id); *poisoned = Some(node_id);
return module.parent; return module.parent;

View file

@ -618,8 +618,9 @@ impl<'a> Resolver<'a> {
let break_result = self.visit_scopes( let break_result = self.visit_scopes(
scope_set, scope_set,
parent_scope, parent_scope,
orig_ident, orig_ident.span.ctxt(),
|this, scope, use_prelude, ident| { |this, scope, use_prelude, ctxt| {
let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt));
let ok = |res, span, arenas| { let ok = |res, span, arenas| {
Ok(( Ok((
(res, ty::Visibility::Public, span, ExpnId::root()).to_name_binding(arenas), (res, ty::Visibility::Public, span, ExpnId::root()).to_name_binding(arenas),

View file

@ -622,6 +622,10 @@ impl SyntaxContext {
pub fn dollar_crate_name(self) -> Symbol { pub fn dollar_crate_name(self) -> Symbol {
HygieneData::with(|data| data.syntax_context_data[self.0 as usize].dollar_crate_name) HygieneData::with(|data| data.syntax_context_data[self.0 as usize].dollar_crate_name)
} }
pub fn edition(self) -> Edition {
self.outer_expn_data().edition
}
} }
impl fmt::Debug for SyntaxContext { impl fmt::Debug for SyntaxContext {

View file

@ -300,6 +300,10 @@ pub struct SpanData {
} }
impl SpanData { impl SpanData {
#[inline]
pub fn span(&self) -> Span {
Span::new(self.lo, self.hi, self.ctxt)
}
#[inline] #[inline]
pub fn with_lo(&self, lo: BytePos) -> Span { pub fn with_lo(&self, lo: BytePos) -> Span {
Span::new(lo, self.hi, self.ctxt) Span::new(lo, self.hi, self.ctxt)
@ -468,7 +472,7 @@ impl Span {
/// Edition of the crate from which this span came. /// Edition of the crate from which this span came.
pub fn edition(self) -> edition::Edition { pub fn edition(self) -> edition::Edition {
self.ctxt().outer_expn_data().edition self.ctxt().edition()
} }
#[inline] #[inline]