Delegation implementation: step 1
This commit is contained in:
parent
2b1365b34f
commit
d69cd6473c
50 changed files with 1634 additions and 93 deletions
|
@ -16,7 +16,7 @@ use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError
|
|||
|
||||
use rustc_ast::visit::{self, AssocCtxt, Visitor};
|
||||
use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind};
|
||||
use rustc_ast::{Block, Fn, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
|
||||
use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
|
||||
use rustc_attr as attr;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{struct_span_code_err, Applicability};
|
||||
|
@ -686,10 +686,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
// These items live in the value namespace.
|
||||
ItemKind::Static(..) => {
|
||||
self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
|
||||
}
|
||||
ItemKind::Const(..) => {
|
||||
ItemKind::Const(..) | ItemKind::Delegation(..) | ItemKind::Static(..) => {
|
||||
self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
|
||||
}
|
||||
ItemKind::Fn(..) => {
|
||||
|
@ -701,11 +698,11 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
// These items live in the type namespace.
|
||||
ItemKind::TyAlias(..) => {
|
||||
ItemKind::TyAlias(..) | ItemKind::TraitAlias(..) => {
|
||||
self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
|
||||
}
|
||||
|
||||
ItemKind::Enum(_, _) => {
|
||||
ItemKind::Enum(_, _) | ItemKind::Trait(..) => {
|
||||
let module = self.r.new_module(
|
||||
Some(parent),
|
||||
ModuleKind::Def(def_kind, def_id, ident.name),
|
||||
|
@ -717,10 +714,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||
self.parent_scope.module = module;
|
||||
}
|
||||
|
||||
ItemKind::TraitAlias(..) => {
|
||||
self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
|
||||
}
|
||||
|
||||
// These items live in both the type and value namespaces.
|
||||
ItemKind::Struct(ref vdata, _) => {
|
||||
// Define a name in the type namespace.
|
||||
|
@ -778,19 +771,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||
self.insert_field_visibilities_local(def_id, vdata);
|
||||
}
|
||||
|
||||
ItemKind::Trait(..) => {
|
||||
// Add all the items within to a new module.
|
||||
let module = self.r.new_module(
|
||||
Some(parent),
|
||||
ModuleKind::Def(def_kind, def_id, ident.name),
|
||||
expansion.to_expn_id(),
|
||||
item.span,
|
||||
parent.no_implicit_prelude,
|
||||
);
|
||||
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
||||
self.parent_scope.module = module;
|
||||
}
|
||||
|
||||
// These items do not add names to modules.
|
||||
ItemKind::Impl(box Impl { of_trait: Some(..), .. }) => {
|
||||
self.r.trait_impl_items.insert(local_def_id);
|
||||
|
@ -1358,13 +1338,9 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
|||
|
||||
if ctxt == AssocCtxt::Trait {
|
||||
let ns = match item.kind {
|
||||
AssocItemKind::Const(..) => ValueNS,
|
||||
AssocItemKind::Fn(box Fn { ref sig, .. }) => {
|
||||
if sig.decl.has_self() {
|
||||
self.r.has_self.insert(local_def_id);
|
||||
}
|
||||
ValueNS
|
||||
}
|
||||
AssocItemKind::Const(..)
|
||||
| AssocItemKind::Delegation(..)
|
||||
| AssocItemKind::Fn(..) => ValueNS,
|
||||
AssocItemKind::Type(..) => TypeNS,
|
||||
AssocItemKind::MacCall(_) => bug!(), // handled above
|
||||
};
|
||||
|
|
|
@ -111,7 +111,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
|||
ItemKind::TyAlias(..) => DefKind::TyAlias,
|
||||
ItemKind::Static(s) => DefKind::Static(s.mutability),
|
||||
ItemKind::Const(..) => DefKind::Const,
|
||||
ItemKind::Fn(..) => DefKind::Fn,
|
||||
ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
|
||||
ItemKind::MacroDef(..) => {
|
||||
let macro_data = self.resolver.compile_macro(i, self.resolver.tcx.sess.edition());
|
||||
let macro_kind = macro_data.ext.macro_kind();
|
||||
|
@ -259,7 +259,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
|||
|
||||
fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
|
||||
let def_kind = match &i.kind {
|
||||
AssocItemKind::Fn(..) => DefKind::AssocFn,
|
||||
AssocItemKind::Fn(..) | AssocItemKind::Delegation(..) => DefKind::AssocFn,
|
||||
AssocItemKind::Const(..) => DefKind::AssocConst,
|
||||
AssocItemKind::Type(..) => DefKind::AssocTy,
|
||||
AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
|
||||
|
|
|
@ -277,7 +277,8 @@ impl<'r, 'ast, 'tcx> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r, 't
|
|||
| ast::ItemKind::TraitAlias(..)
|
||||
| ast::ItemKind::MacroDef(..)
|
||||
| ast::ItemKind::ForeignMod(..)
|
||||
| ast::ItemKind::Fn(..) => return,
|
||||
| ast::ItemKind::Fn(..)
|
||||
| ast::ItemKind::Delegation(..) => return,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -394,13 +394,18 @@ pub(crate) enum PathSource<'a> {
|
|||
TupleStruct(Span, &'a [Span]),
|
||||
// `m::A::B` in `<T as m::A>::B::C`.
|
||||
TraitItem(Namespace),
|
||||
// Paths in delegation item
|
||||
Delegation,
|
||||
}
|
||||
|
||||
impl<'a> PathSource<'a> {
|
||||
fn namespace(self) -> Namespace {
|
||||
match self {
|
||||
PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS,
|
||||
PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct(..) => ValueNS,
|
||||
PathSource::Expr(..)
|
||||
| PathSource::Pat
|
||||
| PathSource::TupleStruct(..)
|
||||
| PathSource::Delegation => ValueNS,
|
||||
PathSource::TraitItem(ns) => ns,
|
||||
}
|
||||
}
|
||||
|
@ -412,7 +417,7 @@ impl<'a> PathSource<'a> {
|
|||
| PathSource::Pat
|
||||
| PathSource::Struct
|
||||
| PathSource::TupleStruct(..) => true,
|
||||
PathSource::Trait(_) | PathSource::TraitItem(..) => false,
|
||||
PathSource::Trait(_) | PathSource::TraitItem(..) | PathSource::Delegation => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -454,6 +459,7 @@ impl<'a> PathSource<'a> {
|
|||
},
|
||||
_ => "value",
|
||||
},
|
||||
PathSource::Delegation => "function",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -521,6 +527,7 @@ impl<'a> PathSource<'a> {
|
|||
Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -533,8 +540,8 @@ impl<'a> PathSource<'a> {
|
|||
(PathSource::Type, false) => error_code!(E0412),
|
||||
(PathSource::Struct, true) => error_code!(E0574),
|
||||
(PathSource::Struct, false) => error_code!(E0422),
|
||||
(PathSource::Expr(..), true) => error_code!(E0423),
|
||||
(PathSource::Expr(..), false) => error_code!(E0425),
|
||||
(PathSource::Expr(..), true) | (PathSource::Delegation, true) => error_code!(E0423),
|
||||
(PathSource::Expr(..), false) | (PathSource::Delegation, false) => error_code!(E0425),
|
||||
(PathSource::Pat | PathSource::TupleStruct(..), true) => error_code!(E0532),
|
||||
(PathSource::Pat | PathSource::TupleStruct(..), false) => error_code!(E0531),
|
||||
(PathSource::TraitItem(..), true) => error_code!(E0575),
|
||||
|
@ -1805,7 +1812,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
PathSource::Expr(..)
|
||||
| PathSource::Pat
|
||||
| PathSource::Struct
|
||||
| PathSource::TupleStruct(..) => true,
|
||||
| PathSource::TupleStruct(..)
|
||||
| PathSource::Delegation => true,
|
||||
};
|
||||
if inferred {
|
||||
// Do not create a parameter for patterns and expressions: type checking can infer
|
||||
|
@ -2514,6 +2522,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
visit::walk_item(self, item);
|
||||
}
|
||||
|
||||
ItemKind::Delegation(ref delegation) => {
|
||||
self.resolve_delegation(delegation);
|
||||
}
|
||||
|
||||
ItemKind::ExternCrate(..) => {}
|
||||
|
||||
ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"),
|
||||
|
@ -2790,6 +2802,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
AssocItemKind::Fn(box Fn { generics, .. }) => {
|
||||
walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
|
||||
}
|
||||
AssocItemKind::Delegation(delegation) => {
|
||||
self.resolve_delegation(delegation);
|
||||
}
|
||||
AssocItemKind::Type(box TyAlias { generics, .. }) => self
|
||||
.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
|
||||
walk_assoc_item(this, generics, LifetimeBinderKind::Item, item)
|
||||
|
@ -3036,6 +3051,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
},
|
||||
);
|
||||
}
|
||||
AssocItemKind::Delegation(box delegation) => {
|
||||
debug!("resolve_implementation AssocItemKind::Delegation");
|
||||
self.check_trait_item(
|
||||
item.id,
|
||||
item.ident,
|
||||
&item.kind,
|
||||
ValueNS,
|
||||
item.span,
|
||||
seen_trait_items,
|
||||
|i, s, c| MethodNotMemberOfTrait(i, s, c),
|
||||
);
|
||||
self.resolve_delegation(delegation);
|
||||
}
|
||||
AssocItemKind::MacCall(_) => {
|
||||
panic!("unexpanded macro in resolve!")
|
||||
}
|
||||
|
@ -3123,7 +3151,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
match (def_kind, kind) {
|
||||
(DefKind::AssocTy, AssocItemKind::Type(..))
|
||||
| (DefKind::AssocFn, AssocItemKind::Fn(..))
|
||||
| (DefKind::AssocConst, AssocItemKind::Const(..)) => {
|
||||
| (DefKind::AssocConst, AssocItemKind::Const(..))
|
||||
| (DefKind::AssocFn, AssocItemKind::Delegation(..)) => {
|
||||
self.r.record_partial_res(id, PartialRes::new(res));
|
||||
return;
|
||||
}
|
||||
|
@ -3136,6 +3165,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
AssocItemKind::Const(..) => (rustc_errors::error_code!(E0323), "const"),
|
||||
AssocItemKind::Fn(..) => (rustc_errors::error_code!(E0324), "method"),
|
||||
AssocItemKind::Type(..) => (rustc_errors::error_code!(E0325), "type"),
|
||||
AssocItemKind::Delegation(..) => (rustc_errors::error_code!(E0324), "method"),
|
||||
AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"),
|
||||
};
|
||||
let trait_path = path_names_to_string(path);
|
||||
|
@ -3159,6 +3189,32 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
fn resolve_delegation(&mut self, delegation: &'ast Delegation) {
|
||||
self.smart_resolve_path(
|
||||
delegation.id,
|
||||
&delegation.qself,
|
||||
&delegation.path,
|
||||
PathSource::Delegation,
|
||||
);
|
||||
if let Some(qself) = &delegation.qself {
|
||||
self.visit_ty(&qself.ty);
|
||||
}
|
||||
self.visit_path(&delegation.path, delegation.id);
|
||||
if let Some(body) = &delegation.body {
|
||||
// `PatBoundCtx` is not necessary in this context
|
||||
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
|
||||
|
||||
let span = delegation.path.segments.last().unwrap().ident.span;
|
||||
self.fresh_binding(
|
||||
Ident::new(kw::SelfLower, span),
|
||||
delegation.id,
|
||||
PatternSource::FnParam,
|
||||
&mut bindings,
|
||||
);
|
||||
self.visit_block(body);
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_params(&mut self, params: &'ast [Param]) {
|
||||
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
|
||||
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
|
||||
|
@ -4551,13 +4607,24 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
struct LifetimeCountVisitor<'a, 'b, 'tcx> {
|
||||
/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
|
||||
/// lifetime generic parameters and function parameters.
|
||||
struct ItemInfoCollector<'a, 'b, 'tcx> {
|
||||
r: &'b mut Resolver<'a, 'tcx>,
|
||||
}
|
||||
|
||||
/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
|
||||
/// lifetime generic parameters.
|
||||
impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
|
||||
impl ItemInfoCollector<'_, '_, '_> {
|
||||
fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) {
|
||||
let def_id = self.r.local_def_id(id);
|
||||
self.r.fn_parameter_counts.insert(def_id, sig.decl.inputs.len());
|
||||
|
||||
if sig.decl.has_self() {
|
||||
self.r.has_self.insert(def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
|
||||
fn visit_item(&mut self, item: &'ast Item) {
|
||||
match &item.kind {
|
||||
ItemKind::TyAlias(box TyAlias { ref generics, .. })
|
||||
|
@ -4569,6 +4636,10 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
|
|||
| ItemKind::Impl(box Impl { ref generics, .. })
|
||||
| ItemKind::Trait(box Trait { ref generics, .. })
|
||||
| ItemKind::TraitAlias(ref generics, _) => {
|
||||
if let ItemKind::Fn(box Fn { ref sig, .. }) = &item.kind {
|
||||
self.collect_fn_info(sig, item.id);
|
||||
}
|
||||
|
||||
let def_id = self.r.local_def_id(item.id);
|
||||
let count = generics
|
||||
.params
|
||||
|
@ -4586,14 +4657,27 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
|
|||
| ItemKind::MacroDef(..)
|
||||
| ItemKind::GlobalAsm(..)
|
||||
| ItemKind::MacCall(..) => {}
|
||||
ItemKind::Delegation(..) => {
|
||||
// Delegated functions have lifetimes, their count is not necessarily zero.
|
||||
// But skipping the delegation items here doesn't mean that the count will be considered zero,
|
||||
// it means there will be a panic when retrieving the count,
|
||||
// but for delegation items we are never actually retrieving that count in practice.
|
||||
}
|
||||
}
|
||||
visit::walk_item(self, item)
|
||||
}
|
||||
|
||||
fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) {
|
||||
if let AssocItemKind::Fn(box Fn { ref sig, .. }) = &item.kind {
|
||||
self.collect_fn_info(sig, item.id);
|
||||
}
|
||||
visit::walk_assoc_item(self, item, ctxt);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
|
||||
visit::walk_crate(&mut LifetimeCountVisitor { r: self }, krate);
|
||||
visit::walk_crate(&mut ItemInfoCollector { r: self }, krate);
|
||||
let mut late_resolution_visitor = LateResolutionVisitor::new(self);
|
||||
late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
|
||||
visit::walk_crate(&mut late_resolution_visitor, krate);
|
||||
|
|
|
@ -656,7 +656,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||
let typo_sugg = self
|
||||
.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected)
|
||||
.to_opt_suggestion();
|
||||
if path.len() == 1 && self.self_type_is_available() {
|
||||
if path.len() == 1
|
||||
&& !matches!(source, PathSource::Delegation)
|
||||
&& self.self_type_is_available()
|
||||
{
|
||||
if let Some(candidate) =
|
||||
self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call())
|
||||
{
|
||||
|
@ -1899,6 +1902,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||
(AssocItemKind::Const(..), Res::Def(DefKind::AssocConst, _)) => true,
|
||||
(AssocItemKind::Fn(_), Res::Def(DefKind::AssocFn, _)) => true,
|
||||
(AssocItemKind::Type(..), Res::Def(DefKind::AssocTy, _)) => true,
|
||||
(AssocItemKind::Delegation(_), Res::Def(DefKind::AssocFn, _)) => true,
|
||||
_ => false,
|
||||
})
|
||||
.map(|(key, _)| key.ident.name)
|
||||
|
@ -1960,6 +1964,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||
}
|
||||
ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called },
|
||||
ast::AssocItemKind::Type(..) => AssocSuggestion::AssocType,
|
||||
ast::AssocItemKind::Delegation(..)
|
||||
if self.r.has_self.contains(&self.r.local_def_id(assoc_item.id)) =>
|
||||
{
|
||||
AssocSuggestion::MethodWithSelf { called }
|
||||
}
|
||||
ast::AssocItemKind::Delegation(..) => AssocSuggestion::AssocFn { called },
|
||||
ast::AssocItemKind::MacCall(_) => continue,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1101,6 +1101,8 @@ pub struct Resolver<'a, 'tcx> {
|
|||
legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>,
|
||||
/// Amount of lifetime parameters for each item in the crate.
|
||||
item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>,
|
||||
/// Amount of parameters for each function in the crate.
|
||||
fn_parameter_counts: LocalDefIdMap<usize>,
|
||||
|
||||
main_def: Option<MainDefinition>,
|
||||
trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
|
||||
|
@ -1439,6 +1441,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
doc_link_resolutions: Default::default(),
|
||||
doc_link_traits_in_scope: Default::default(),
|
||||
all_macro_rules: Default::default(),
|
||||
fn_parameter_counts: Default::default(),
|
||||
};
|
||||
|
||||
let root_parent_scope = ParentScope::module(graph_root, &resolver);
|
||||
|
@ -1542,6 +1545,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
trait_map: self.trait_map,
|
||||
lifetime_elision_allowed: self.lifetime_elision_allowed,
|
||||
lint_buffer: Steal::new(self.lint_buffer),
|
||||
has_self: self.has_self,
|
||||
fn_parameter_counts: self.fn_parameter_counts,
|
||||
};
|
||||
ResolverOutputs { global_ctxt, ast_lowering }
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue