resolve: Make bindings for derive helper attributes unique
instead of creating them every time such attribute is used
This commit is contained in:
parent
02640f9d59
commit
50bbe01de0
4 changed files with 25 additions and 28 deletions
|
@ -1032,7 +1032,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
.get(&expn_id)
|
.get(&expn_id)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|ident| TypoSuggestion::typo_from_ident(*ident, res)),
|
.map(|(ident, _)| TypoSuggestion::typo_from_ident(*ident, res)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -421,26 +421,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
orig_ident.span.ctxt(),
|
orig_ident.span.ctxt(),
|
||||||
|this, scope, use_prelude, ctxt| {
|
|this, scope, use_prelude, ctxt| {
|
||||||
let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt));
|
let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt));
|
||||||
let ok = |res, span, arenas| {
|
|
||||||
Ok((
|
|
||||||
(res, Visibility::Public, span, LocalExpnId::ROOT).to_name_binding(arenas),
|
|
||||||
Flags::empty(),
|
|
||||||
))
|
|
||||||
};
|
|
||||||
let result = match scope {
|
let result = match scope {
|
||||||
Scope::DeriveHelpers(expn_id) => {
|
Scope::DeriveHelpers(expn_id) => {
|
||||||
if let Some(attr) = this
|
if let Some(binding) = this.helper_attrs.get(&expn_id).and_then(|attrs| {
|
||||||
.helper_attrs
|
attrs.iter().rfind(|(i, _)| ident == *i).map(|(_, binding)| *binding)
|
||||||
.get(&expn_id)
|
}) {
|
||||||
.and_then(|attrs| attrs.iter().rfind(|i| ident == **i))
|
|
||||||
{
|
|
||||||
let binding = (
|
|
||||||
Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
|
|
||||||
Visibility::Public,
|
|
||||||
attr.span,
|
|
||||||
expn_id,
|
|
||||||
)
|
|
||||||
.to_name_binding(this.arenas);
|
|
||||||
Ok((binding, Flags::empty()))
|
Ok((binding, Flags::empty()))
|
||||||
} else {
|
} else {
|
||||||
Err(Determinacy::Determined)
|
Err(Determinacy::Determined)
|
||||||
|
@ -459,11 +444,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
) {
|
) {
|
||||||
Ok((Some(ext), _)) => {
|
Ok((Some(ext), _)) => {
|
||||||
if ext.helper_attrs.contains(&ident.name) {
|
if ext.helper_attrs.contains(&ident.name) {
|
||||||
result = ok(
|
let binding = (
|
||||||
Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat),
|
Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat),
|
||||||
|
Visibility::Public,
|
||||||
derive.span,
|
derive.span,
|
||||||
this.arenas,
|
LocalExpnId::ROOT,
|
||||||
);
|
)
|
||||||
|
.to_name_binding(this.arenas);
|
||||||
|
result = Ok((binding, Flags::empty()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1047,7 +1047,7 @@ pub struct Resolver<'a, 'tcx> {
|
||||||
/// `macro_rules` scopes produced by `macro_rules` item definitions.
|
/// `macro_rules` scopes produced by `macro_rules` item definitions.
|
||||||
macro_rules_scopes: FxHashMap<LocalDefId, MacroRulesScopeRef<'a>>,
|
macro_rules_scopes: FxHashMap<LocalDefId, MacroRulesScopeRef<'a>>,
|
||||||
/// Helper attributes that are in scope for the given expansion.
|
/// Helper attributes that are in scope for the given expansion.
|
||||||
helper_attrs: FxHashMap<LocalExpnId, Vec<Ident>>,
|
helper_attrs: FxHashMap<LocalExpnId, Vec<(Ident, NameBinding<'a>)>>,
|
||||||
/// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute
|
/// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute
|
||||||
/// with the given `ExpnId`.
|
/// with the given `ExpnId`.
|
||||||
derive_data: FxHashMap<LocalExpnId, DeriveData>,
|
derive_data: FxHashMap<LocalExpnId, DeriveData>,
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::errors::{
|
||||||
use crate::Namespace::*;
|
use crate::Namespace::*;
|
||||||
use crate::{BuiltinMacroState, Determinacy};
|
use crate::{BuiltinMacroState, Determinacy};
|
||||||
use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
|
use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
|
||||||
use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment};
|
use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
|
||||||
use rustc_ast::expand::StrippedCfgItem;
|
use rustc_ast::expand::StrippedCfgItem;
|
||||||
use rustc_ast::{self as ast, attr, Crate, Inline, ItemKind, ModKind, NodeId};
|
use rustc_ast::{self as ast, attr, Crate, Inline, ItemKind, ModKind, NodeId};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
|
@ -20,10 +20,10 @@ use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||||
use rustc_expand::compile_declarative_macro;
|
use rustc_expand::compile_declarative_macro;
|
||||||
use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion};
|
use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion};
|
||||||
use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
|
use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
|
||||||
use rustc_hir::def_id::{CrateNum, LocalDefId};
|
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
|
||||||
use rustc_middle::middle::stability;
|
use rustc_middle::middle::stability;
|
||||||
use rustc_middle::ty::RegisteredTools;
|
use rustc_middle::ty::RegisteredTools;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::{TyCtxt, Visibility};
|
||||||
use rustc_session::lint::builtin::{
|
use rustc_session::lint::builtin::{
|
||||||
LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE, UNKNOWN_DIAGNOSTIC_ATTRIBUTES,
|
LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE, UNKNOWN_DIAGNOSTIC_ATTRIBUTES,
|
||||||
};
|
};
|
||||||
|
@ -401,8 +401,17 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
// Sort helpers in a stable way independent from the derive resolution order.
|
// Sort helpers in a stable way independent from the derive resolution order.
|
||||||
entry.helper_attrs.sort_by_key(|(i, _)| *i);
|
entry.helper_attrs.sort_by_key(|(i, _)| *i);
|
||||||
self.helper_attrs
|
let helper_attrs = entry
|
||||||
.insert(expn_id, entry.helper_attrs.iter().map(|(_, ident)| *ident).collect());
|
.helper_attrs
|
||||||
|
.iter()
|
||||||
|
.map(|(_, ident)| {
|
||||||
|
let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
|
||||||
|
let binding = (res, Visibility::<DefId>::Public, ident.span, expn_id)
|
||||||
|
.to_name_binding(self.arenas);
|
||||||
|
(*ident, binding)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
self.helper_attrs.insert(expn_id, helper_attrs);
|
||||||
// Mark this derive as having `Copy` either if it has `Copy` itself or if its parent derive
|
// Mark this derive as having `Copy` either if it has `Copy` itself or if its parent derive
|
||||||
// has `Copy`, to support cases like `#[derive(Clone, Copy)] #[derive(Debug)]`.
|
// has `Copy`, to support cases like `#[derive(Clone, Copy)] #[derive(Debug)]`.
|
||||||
if entry.has_derive_copy || self.has_derive_copy(parent_scope.expansion) {
|
if entry.has_derive_copy || self.has_derive_copy(parent_scope.expansion) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue