summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_resolve/src/late.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_resolve/src/late.rs')
-rw-r--r--compiler/rustc_resolve/src/late.rs265
1 files changed, 224 insertions, 41 deletions
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 83932c089..7df17376b 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -8,7 +8,7 @@
use RibKind::*;
-use crate::{path_names_to_string, BindingError, Finalize, LexicalScopeBinding};
+use crate::{path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding};
use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
use crate::{ResolutionError, Resolver, Segment, UseError};
@@ -21,15 +21,16 @@ use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
-use rustc_middle::middle::resolve_lifetime::Set1;
+use rustc_middle::middle::resolve_bound_vars::Set1;
use rustc_middle::ty::DefIdTree;
use rustc_middle::{bug, span_bug};
+use rustc_session::config::{CrateType, ResolveDocLinks};
use rustc_session::lint;
+use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{BytePos, Span};
+use rustc_span::{BytePos, Span, SyntaxContext};
use smallvec::{smallvec, SmallVec};
-use rustc_span::source_map::{respan, Spanned};
use std::assert_matches::debug_assert_matches;
use std::borrow::Cow;
use std::collections::{hash_map::Entry, BTreeSet};
@@ -55,7 +56,7 @@ struct BindingInfo {
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum PatternSource {
+pub(crate) enum PatternSource {
Match,
Let,
For,
@@ -69,7 +70,7 @@ enum IsRepeatExpr {
}
impl PatternSource {
- pub fn descr(self) -> &'static str {
+ fn descr(self) -> &'static str {
match self {
PatternSource::Match => "match binding",
PatternSource::Let => "let binding",
@@ -493,6 +494,30 @@ impl<'a> PathSource<'a> {
}
}
+/// At this point for most items we can answer whether that item is exported or not,
+/// but some items like impls require type information to determine exported-ness, so we make a
+/// conservative estimate for them (e.g. based on nominal visibility).
+#[derive(Clone, Copy)]
+enum MaybeExported<'a> {
+ Ok(NodeId),
+ Impl(Option<DefId>),
+ ImplItem(Result<DefId, &'a Visibility>),
+}
+
+impl MaybeExported<'_> {
+ fn eval(self, r: &Resolver<'_, '_>) -> bool {
+ let def_id = match self {
+ MaybeExported::Ok(node_id) => Some(r.local_def_id(node_id)),
+ MaybeExported::Impl(Some(trait_def_id)) | MaybeExported::ImplItem(Ok(trait_def_id)) => {
+ trait_def_id.as_local()
+ }
+ MaybeExported::Impl(None) => return true,
+ MaybeExported::ImplItem(Err(vis)) => return vis.kind.is_pub(),
+ };
+ def_id.map_or(true, |def_id| r.effective_visibilities.is_exported(def_id))
+ }
+}
+
#[derive(Default)]
struct DiagnosticMetadata<'ast> {
/// The current trait's associated items' ident, used for diagnostic suggestions.
@@ -559,8 +584,8 @@ struct DiagnosticMetadata<'ast> {
current_elision_failures: Vec<MissingLifetime>,
}
-struct LateResolutionVisitor<'a, 'b, 'ast> {
- r: &'b mut Resolver<'a>,
+struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
+ r: &'b mut Resolver<'a, 'tcx>,
/// The module that represents the current item scope.
parent_scope: ParentScope<'a>,
@@ -603,7 +628,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast> {
}
/// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
-impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
+impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
fn visit_attribute(&mut self, _: &'ast Attribute) {
// We do not want to resolve expressions that appear in attributes,
// as they do not correspond to actual code.
@@ -620,7 +645,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
self.resolve_arm(arm);
}
fn visit_block(&mut self, block: &'ast Block) {
+ let old_macro_rules = self.parent_scope.macro_rules;
self.resolve_block(block);
+ self.parent_scope.macro_rules = old_macro_rules;
}
fn visit_anon_const(&mut self, constant: &'ast AnonConst) {
// We deal with repeat expressions explicitly in `resolve_expr`.
@@ -655,7 +682,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
// Elided lifetime in reference: we resolve as if there was some lifetime `'_` with
// NodeId `ty.id`.
// This span will be used in case of elision failure.
- let span = self.r.session.source_map().start_point(ty.span);
+ let span = self.r.tcx.sess.source_map().start_point(ty.span);
self.resolve_elided_lifetime(ty.id, span);
visit::walk_ty(self, ty);
}
@@ -771,6 +798,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
);
}
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
+ self.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id));
match foreign_item.kind {
ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
self.with_generic_param_rib(
@@ -1159,10 +1187,20 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
})
});
}
+
+ fn visit_variant(&mut self, v: &'ast Variant) {
+ self.resolve_doc_links(&v.attrs, MaybeExported::Ok(v.id));
+ visit::walk_variant(self, v)
+ }
+
+ fn visit_field_def(&mut self, f: &'ast FieldDef) {
+ self.resolve_doc_links(&f.attrs, MaybeExported::Ok(f.id));
+ visit::walk_field_def(self, f)
+ }
}
-impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
- fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b, 'ast> {
+impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
+ fn new(resolver: &'b mut Resolver<'a, 'tcx>) -> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
// During late resolution we only track the module component of the parent scope,
// although it may be useful to track other components as well for diagnostics.
let graph_root = resolver.graph_root;
@@ -1533,7 +1571,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
("`'_` cannot be used here", "`'_` is a reserved lifetime name")
};
let mut diag = rustc_errors::struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
lifetime.ident.span,
E0637,
"{}",
@@ -1710,7 +1748,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// impl Foo for std::cell::Ref<u32> // note lack of '_
// async fn foo(_: std::cell::Ref<u32>) { ... }
LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } => {
- let sess = self.r.session;
+ let sess = self.r.tcx.sess;
let mut err = rustc_errors::struct_span_err!(
sess,
path_span,
@@ -1725,7 +1763,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
!segment.has_generic_args,
elided_lifetime_span,
);
- err.note("assuming a `'static` lifetime...");
err.emit();
should_lint = false;
@@ -1992,13 +2029,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
/// List all the lifetimes that appear in the provided type.
fn find_lifetime_for_self(&self, ty: &'ast Ty) -> Set1<LifetimeRes> {
- struct SelfVisitor<'r, 'a> {
- r: &'r Resolver<'a>,
+ struct SelfVisitor<'r, 'a, 'tcx> {
+ r: &'r Resolver<'a, 'tcx>,
impl_self: Option<Res>,
lifetime: Set1<LifetimeRes>,
}
- impl SelfVisitor<'_, '_> {
+ impl SelfVisitor<'_, '_, '_> {
// Look for `self: &'a Self` - also desugared from `&'a self`,
// and if that matches, use it for elision and return early.
fn is_self_ty(&self, ty: &Ty) -> bool {
@@ -2016,7 +2053,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
}
}
- impl<'a> Visitor<'a> for SelfVisitor<'_, '_> {
+ impl<'a> Visitor<'a> for SelfVisitor<'_, '_, '_> {
fn visit_ty(&mut self, ty: &'a Ty) {
trace!("SelfVisitor considering ty={:?}", ty);
if let TyKind::Ref(lt, ref mt) = ty.kind && self.is_self_ty(&mt.ty) {
@@ -2145,7 +2182,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let segments = &use_tree.prefix.segments;
if !segments.is_empty() {
let ident = segments[0].ident;
- if ident.is_path_segment_keyword() || ident.span.rust_2015() {
+ if ident.is_path_segment_keyword() || ident.span.is_rust_2015() {
return;
}
@@ -2157,7 +2194,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let what = if ns == TypeNS { "type parameters" } else { "local variables" };
if this.should_report_errs() {
this.r
- .session
+ .tcx
+ .sess
.span_err(ident.span, &format!("imports cannot refer to {}", what));
}
};
@@ -2185,6 +2223,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
}
fn resolve_item(&mut self, item: &'ast Item) {
+ let mod_inner_docs =
+ matches!(item.kind, ItemKind::Mod(..)) && rustdoc::inner_docs(&item.attrs);
+ if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..)) {
+ self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
+ }
+
let name = item.ident.name;
debug!("(resolving item) resolving {} ({:?})", name, item.kind);
@@ -2229,7 +2273,14 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
..
}) => {
self.diagnostic_metadata.current_impl_items = Some(impl_items);
- self.resolve_implementation(generics, of_trait, &self_ty, item.id, impl_items);
+ self.resolve_implementation(
+ &item.attrs,
+ generics,
+ of_trait,
+ &self_ty,
+ item.id,
+ impl_items,
+ );
self.diagnostic_metadata.current_impl_items = None;
}
@@ -2274,9 +2325,20 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
);
}
- ItemKind::Mod(..) | ItemKind::ForeignMod(_) => {
+ ItemKind::Mod(..) => {
self.with_scope(item.id, |this| {
+ if mod_inner_docs {
+ this.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
+ }
+ let old_macro_rules = this.parent_scope.macro_rules;
visit::walk_item(this, item);
+ // Maintain macro_rules scopes in the same way as during early resolution
+ // for diagnostics and doc links.
+ if item.attrs.iter().all(|attr| {
+ !attr.has_name(sym::macro_use) && !attr.has_name(sym::macro_escape)
+ }) {
+ this.parent_scope.macro_rules = old_macro_rules;
+ }
});
}
@@ -2309,14 +2371,21 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.future_proof_import(use_tree);
}
- ItemKind::ExternCrate(..) | ItemKind::MacroDef(..) => {
- // do nothing, these are just around to be encoded
+ ItemKind::MacroDef(ref macro_def) => {
+ // Maintain macro_rules scopes in the same way as during early resolution
+ // for diagnostics and doc links.
+ if macro_def.macro_rules {
+ let def_id = self.r.local_def_id(item.id);
+ self.parent_scope.macro_rules = self.r.macro_rules_scopes[&def_id];
+ }
}
- ItemKind::GlobalAsm(_) => {
+ ItemKind::ForeignMod(_) | ItemKind::GlobalAsm(_) => {
visit::walk_item(self, item);
}
+ ItemKind::ExternCrate(..) => {}
+
ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"),
}
}
@@ -2370,7 +2439,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
if let GenericParamKind::Lifetime = param.kind
&& let Some(&original) = seen_lifetimes.get(&ident)
{
- diagnostics::signal_lifetime_shadowing(self.r.session, original, param.ident);
+ diagnostics::signal_lifetime_shadowing(self.r.tcx.sess, original, param.ident);
// Record lifetime res, so lowering knows there is something fishy.
self.record_lifetime_param(param.id, LifetimeRes::Error);
continue;
@@ -2394,7 +2463,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
if param.ident.name == kw::UnderscoreLifetime {
rustc_errors::struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
param.ident.span,
E0637,
"`'_` cannot be used here"
@@ -2408,7 +2477,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
if param.ident.name == kw::StaticLifetime {
rustc_errors::struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
param.ident.span,
E0262,
"invalid lifetime parameter name: `{}`",
@@ -2437,7 +2506,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let res = match kind {
ItemRibKind(..) | AssocItemRibKind => Res::Def(def_kind, def_id.to_def_id()),
- NormalRibKind => Res::Err,
+ NormalRibKind => {
+ if self.r.tcx.sess.features_untracked().non_lifetime_binders {
+ Res::Def(def_kind, def_id.to_def_id())
+ } else {
+ Res::Err
+ }
+ }
_ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind),
};
self.r.record_partial_res(param.id, PartialRes::new(res));
@@ -2544,6 +2619,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
};
for item in trait_items {
+ self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
match &item.kind {
AssocItemKind::Const(_, ty, default) => {
self.visit_ty(ty);
@@ -2631,6 +2707,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
fn resolve_implementation(
&mut self,
+ attrs: &[ast::Attribute],
generics: &'ast Generics,
opt_trait_reference: &'ast Option<TraitRef>,
self_type: &'ast Ty,
@@ -2661,6 +2738,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
opt_trait_reference.as_ref(),
self_type,
|this, trait_id| {
+ this.resolve_doc_links(attrs, MaybeExported::Impl(trait_id));
+
let item_def_id = this.r.local_def_id(item_id);
// Register the trait definitions from here.
@@ -2694,7 +2773,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
let mut seen_trait_items = Default::default();
for item in impl_items {
- this.resolve_impl_item(&**item, &mut seen_trait_items);
+ this.resolve_impl_item(&**item, &mut seen_trait_items, trait_id);
}
});
});
@@ -2712,8 +2791,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
&mut self,
item: &'ast AssocItem,
seen_trait_items: &mut FxHashMap<DefId, Span>,
+ trait_id: Option<DefId>,
) {
use crate::ResolutionError::*;
+ self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis)));
match &item.kind {
AssocItemKind::Const(_, ty, default) => {
debug!("resolve_implementation AssocItemKind::Const");
@@ -3304,7 +3385,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
Res::SelfCtor(_) => {
// We resolve `Self` in pattern position as an ident sometimes during recovery,
// so delay a bug instead of ICEing.
- self.r.session.delay_span_bug(
+ self.r.tcx.sess.delay_span_bug(
ident.span,
"unexpected `SelfCtor` in pattern, expected identifier"
);
@@ -3584,7 +3665,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
#[inline]
/// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items.
fn should_report_errs(&self) -> bool {
- !(self.r.session.opts.actually_rustdoc && self.in_func_body)
+ !(self.r.tcx.sess.opts.actually_rustdoc && self.in_func_body)
}
// Resolve in alternative namespaces if resolution in the primary namespace fails.
@@ -3749,7 +3830,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
}
if let Ok((_, orig_span)) = self.resolve_label(label.ident) {
- diagnostics::signal_label_shadowing(self.r.session, orig_span, label.ident)
+ diagnostics::signal_label_shadowing(self.r.tcx.sess, orig_span, label.ident)
}
self.with_label_rib(NormalRibKind, |this| {
@@ -4055,9 +4136,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &'ast Expr) {
match expr.kind {
ExprKind::Field(_, ident) => {
- // FIXME(#6890): Even though you can't treat a method like a
- // field, we need to add any trait methods we find that match
- // the field name so that we can do some nice error reporting
+ // #6890: Even though you can't treat a method like a field,
+ // we need to add any trait methods we find that match the
+ // field name so that we can do some nice error reporting
// later on in typeck.
let traits = self.traits_in_scope(ident, ValueNS);
self.r.trait_map.insert(expr.id, traits);
@@ -4116,15 +4197,116 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
}
}
+
+ fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> bool {
+ // FIXME: This caching may be incorrect in case of multiple `macro_rules`
+ // items with the same name in the same module.
+ // Also hygiene is not considered.
+ let mut doc_link_resolutions = std::mem::take(&mut self.r.doc_link_resolutions);
+ let res = doc_link_resolutions
+ .entry(self.parent_scope.module.nearest_parent_mod().expect_local())
+ .or_default()
+ .entry((Symbol::intern(path_str), ns))
+ .or_insert_with_key(|(path, ns)| {
+ let res = self.r.resolve_rustdoc_path(path.as_str(), *ns, self.parent_scope);
+ if let Some(res) = res
+ && let Some(def_id) = res.opt_def_id()
+ && !def_id.is_local()
+ && self.r.tcx.sess.crate_types().contains(&CrateType::ProcMacro)
+ && matches!(self.r.tcx.sess.opts.resolve_doc_links, ResolveDocLinks::ExportedMetadata) {
+ // Encoding foreign def ids in proc macro crate metadata will ICE.
+ return None;
+ }
+ res
+ })
+ .is_some();
+ self.r.doc_link_resolutions = doc_link_resolutions;
+ res
+ }
+
+ fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExported<'_>) {
+ match self.r.tcx.sess.opts.resolve_doc_links {
+ ResolveDocLinks::None => return,
+ ResolveDocLinks::ExportedMetadata
+ if !self.r.tcx.sess.crate_types().iter().copied().any(CrateType::has_metadata)
+ || !maybe_exported.eval(self.r) =>
+ {
+ return;
+ }
+ ResolveDocLinks::Exported if !maybe_exported.eval(self.r) => {
+ return;
+ }
+ ResolveDocLinks::ExportedMetadata
+ | ResolveDocLinks::Exported
+ | ResolveDocLinks::All => {}
+ }
+
+ if !attrs.iter().any(|attr| attr.may_have_doc_links()) {
+ return;
+ }
+
+ let mut need_traits_in_scope = false;
+ for path_str in rustdoc::attrs_to_preprocessed_links(attrs) {
+ // Resolve all namespaces due to no disambiguator or for diagnostics.
+ let mut any_resolved = false;
+ let mut need_assoc = false;
+ for ns in [TypeNS, ValueNS, MacroNS] {
+ if self.resolve_and_cache_rustdoc_path(&path_str, ns) {
+ any_resolved = true;
+ } else if ns != MacroNS {
+ need_assoc = true;
+ }
+ }
+
+ // Resolve all prefixes for type-relative resolution or for diagnostics.
+ if need_assoc || !any_resolved {
+ let mut path = &path_str[..];
+ while let Some(idx) = path.rfind("::") {
+ path = &path[..idx];
+ need_traits_in_scope = true;
+ for ns in [TypeNS, ValueNS, MacroNS] {
+ self.resolve_and_cache_rustdoc_path(path, ns);
+ }
+ }
+ }
+ }
+
+ if need_traits_in_scope {
+ // FIXME: hygiene is not considered.
+ let mut doc_link_traits_in_scope = std::mem::take(&mut self.r.doc_link_traits_in_scope);
+ doc_link_traits_in_scope
+ .entry(self.parent_scope.module.nearest_parent_mod().expect_local())
+ .or_insert_with(|| {
+ self.r
+ .traits_in_scope(None, &self.parent_scope, SyntaxContext::root(), None)
+ .into_iter()
+ .filter_map(|tr| {
+ if !tr.def_id.is_local()
+ && self.r.tcx.sess.crate_types().contains(&CrateType::ProcMacro)
+ && matches!(
+ self.r.tcx.sess.opts.resolve_doc_links,
+ ResolveDocLinks::ExportedMetadata
+ )
+ {
+ // Encoding foreign def ids in proc macro crate metadata will ICE.
+ return None;
+ }
+ Some(tr.def_id)
+ })
+ .collect()
+ });
+ self.r.doc_link_traits_in_scope = doc_link_traits_in_scope;
+ }
+ }
}
-struct LifetimeCountVisitor<'a, 'b> {
- r: &'b mut Resolver<'a>,
+struct LifetimeCountVisitor<'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<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
fn visit_item(&mut self, item: &'ast Item) {
match &item.kind {
ItemKind::TyAlias(box TyAlias { ref generics, .. })
@@ -4158,10 +4340,11 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_> {
}
}
-impl<'a> Resolver<'a> {
+impl<'a, 'tcx> Resolver<'a, 'tcx> {
pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
visit::walk_crate(&mut LifetimeCountVisitor { 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);
for (id, span) in late_resolution_visitor.diagnostic_metadata.unused_labels.iter() {
self.lint_buffer.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label");