summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_resolve/src/late
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_resolve/src/late.rs265
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs142
2 files changed, 305 insertions, 102 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");
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 6d448433e..b8ddc4552 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -25,9 +25,9 @@ use rustc_middle::ty::DefIdTree;
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_session::Session;
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
use rustc_span::hygiene::MacroKind;
-use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Span};
@@ -166,11 +166,11 @@ impl TypoCandidate {
}
}
-impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
+impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
fn def_span(&self, def_id: DefId) -> Option<Span> {
match def_id.krate {
LOCAL_CRATE => self.r.opt_span(def_id),
- _ => Some(self.r.cstore().get_span_untracked(def_id, self.r.session)),
+ _ => Some(self.r.cstore().get_span_untracked(def_id, self.r.tcx.sess)),
}
}
@@ -200,7 +200,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
Res::Def(DefKind::Fn, _) => {
// Verify whether this is a fn call or an Fn used as a type.
self.r
- .session
+ .tcx
+ .sess
.source_map()
.span_to_snippet(span)
.map(|snippet| snippet.ends_with(')'))
@@ -227,20 +228,27 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
&& let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt()
&& let Some(items) = self.diagnostic_metadata.current_impl_items
&& let Some(item) = items.iter().find(|i| {
- if let AssocItemKind::Fn(_) = &i.kind && i.ident.name == item_str.name
+ if let AssocItemKind::Fn(..) | AssocItemKind::Const(..) = &i.kind
+ && i.ident.name == item_str.name
{
debug!(?item_str.name);
return true
}
false
})
- && let AssocItemKind::Fn(fn_) = &item.kind
{
- debug!(?fn_);
- let self_sugg = if fn_.sig.decl.has_self() { "self." } else { "Self::" };
+ let self_sugg = match &item.kind {
+ AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => "self.",
+ _ => "Self::",
+ };
+
Some((
item_span.shrink_to_lo(),
- "consider using the associated function",
+ match &item.kind {
+ AssocItemKind::Fn(..) => "consider using the associated function",
+ AssocItemKind::Const(..) => "consider using the associated constant",
+ _ => unreachable!("item kind was filtered above"),
+ },
self_sugg.to_string()
))
} else {
@@ -248,7 +256,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
};
(String::new(), "this scope".to_string(), suggestion)
} else if path.len() == 2 && path[0].ident.name == kw::PathRoot {
- if self.r.session.edition() > Edition::Edition2015 {
+ if self.r.tcx.sess.edition() > Edition::Edition2015 {
// In edition 2018 onwards, the `::foo` syntax may only pull from the extern prelude
// which overrides all other expectations of item type
expected = "crate";
@@ -311,12 +319,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
span: Span,
source: PathSource<'_>,
res: Option<Res>,
- ) -> (DiagnosticBuilder<'a, ErrorGuaranteed>, Vec<ImportSuggestion>) {
+ ) -> (DiagnosticBuilder<'tcx, ErrorGuaranteed>, Vec<ImportSuggestion>) {
debug!(?res, ?source);
let base_error = self.make_base_error(path, span, source, res);
let code = source.error_code(res.is_some());
let mut err =
- self.r.session.struct_span_err_with_code(base_error.span, &base_error.msg, code);
+ self.r.tcx.sess.struct_span_err_with_code(base_error.span, &base_error.msg, code);
self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span);
@@ -425,7 +433,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
} else {
(
self.r
- .session
+ .tcx
+ .sess
.source_map()
.span_through_char(*fn_span, '(')
.shrink_to_hi(),
@@ -498,7 +507,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
{
if self
.r
- .session
+ .tcx
+ .sess
.parse_sess
.type_ascription_path_suggestions
.borrow()
@@ -535,7 +545,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
}
- // Try Levenshtein algorithm.
+ // Try finding a suitable replacement.
let typo_sugg =
self.lookup_typo_candidate(path, source.namespace(), is_expected).to_opt_suggestion();
if path.len() == 1 && self.self_type_is_available() {
@@ -589,7 +599,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
if let Some((call_span, args_span)) = self.call_has_self_arg(source) {
let mut args_snippet = String::new();
if let Some(args_span) = args_span {
- if let Ok(snippet) = self.r.session.source_map().span_to_snippet(args_span) {
+ if let Ok(snippet) = self.r.tcx.sess.source_map().span_to_snippet(args_span) {
args_snippet = snippet;
}
}
@@ -725,7 +735,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let ident_span = path.last().map_or(span, |ident| ident.ident.span);
let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected);
let is_in_same_file = &|sp1, sp2| {
- let source_map = self.r.session.source_map();
+ let source_map = self.r.tcx.sess.source_map();
let file1 = source_map.span_to_filename(sp1);
let file2 = source_map.span_to_filename(sp2);
file1 == file2
@@ -763,7 +773,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
_ => {}
}
- // If the trait has a single item (which wasn't matched by Levenshtein), suggest it
+ // If the trait has a single item (which wasn't matched by the algorithm), suggest it
let suggestion = self.get_single_associated_item(&path, &source, is_expected);
if !self.r.add_typo_suggestion(err, suggestion, ident_span) {
fallback = !self.let_binding_suggestion(err, ident_span);
@@ -868,7 +878,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
);
let is_assoc_fn = self.self_type_is_available();
if let Some((fn_kind, span)) = &self.diagnostic_metadata.current_function {
- // The current function has a `self' parameter, but we were unable to resolve
+ // The current function has a `self` parameter, but we were unable to resolve
// a reference to `self`. This can only happen if the `self` identifier we
// are resolving came from a different hygiene context.
if fn_kind.decl().inputs.get(0).map_or(false, |p| p.is_self()) {
@@ -888,7 +898,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
.map_or(*span, |ident| span.with_lo(ident.span.hi()));
(
self.r
- .session
+ .tcx
+ .sess
.source_map()
.span_through_char(span, '(')
.shrink_to_hi(),
@@ -942,9 +953,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
&& let PathSource::Trait(_) = source
&& let Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)) = res
&& let Ok(self_ty_str) =
- self.r.session.source_map().span_to_snippet(self_ty.span)
+ self.r.tcx.sess.source_map().span_to_snippet(self_ty.span)
&& let Ok(trait_ref_str) =
- self.r.session.source_map().span_to_snippet(trait_ref.path.span)
+ self.r.tcx.sess.source_map().span_to_snippet(trait_ref.path.span)
{
err.multipart_suggestion(
"`impl` items mention the trait being implemented first and the type it is being implemented for second",
@@ -1088,7 +1099,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
format!(
"{}: {}<{} = {}>",
self.r
- .session
+ .tcx
+ .sess
.source_map()
.span_to_snippet(ty.span) // Account for `<&'a T as Foo>::Bar`.
.unwrap_or_else(|_| constrain_ident.to_string()),
@@ -1157,7 +1169,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
// parser issue where a struct literal is being used on an expression
// where a brace being opened means a block is being started. Look
// ahead for the next text to see if `span` is followed by a `{`.
- let sm = self.r.session.source_map();
+ let sm = self.r.tcx.sess.source_map();
let sp = sm.span_look_ahead(span, None, Some(50));
let followed_by_brace = matches!(sm.span_to_snippet(sp), Ok(ref snippet) if snippet == "{");
// In case this could be a struct literal that needs to be surrounded
@@ -1205,7 +1217,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
true
} else if kind == DefKind::Struct
&& let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
- && let Ok(snippet) = self.r.session.source_map().span_to_snippet(lhs_source_span)
+ && let Ok(snippet) = self.r.tcx.sess.source_map().span_to_snippet(lhs_source_span)
{
// The LHS is a type that originates from a macro call.
// We have to add angle brackets around it.
@@ -1336,7 +1348,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
"!",
Applicability::MaybeIncorrect,
);
- if path_str == "try" && span.rust_2015() {
+ if path_str == "try" && span.is_rust_2015() {
err.note("if you want the `try` keyword, you need Rust 2018 or later");
}
}
@@ -1345,11 +1357,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
(Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => {
err.span_label(span, "type aliases cannot be used as traits");
- if self.r.session.is_nightly_build() {
+ if self.r.tcx.sess.is_nightly_build() {
let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \
`type` alias";
if let Some(span) = self.def_span(def_id) {
- if let Ok(snip) = self.r.session.source_map().span_to_snippet(span) {
+ if let Ok(snip) = self.r.tcx.sess.source_map().span_to_snippet(span) {
// The span contains a type alias so we should be able to
// replace `type` with `trait`.
let snip = snip.replacen("type", "trait", 1);
@@ -1380,7 +1392,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
.last()
.map(|sp| {
self.r
- .session
+ .tcx
+ .sess
.parse_sess
.type_ascription_path_suggestions
.borrow()
@@ -1687,17 +1700,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let extern_prelude = self.r.extern_prelude.clone();
names.extend(extern_prelude.iter().flat_map(|(ident, _)| {
self.r
- .crate_loader()
- .maybe_process_path_extern(ident.name)
+ .crate_loader(|c| c.maybe_process_path_extern(ident.name))
.and_then(|crate_id| {
let crate_mod =
Res::Def(DefKind::Mod, crate_id.as_def_id());
- if filter_fn(crate_mod) {
- Some(TypoSuggestion::typo_from_ident(*ident, crate_mod))
- } else {
- None
- }
+ filter_fn(crate_mod).then(|| {
+ TypoSuggestion::typo_from_ident(*ident, crate_mod)
+ })
})
}));
@@ -1769,12 +1779,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
/// Only used in a specific case of type ascription suggestions
fn get_colon_suggestion_span(&self, start: Span) -> Span {
- let sm = self.r.session.source_map();
+ let sm = self.r.tcx.sess.source_map();
start.to(sm.next_point(start))
}
fn type_ascription_suggestion(&self, err: &mut Diagnostic, base_span: Span) -> bool {
- let sm = self.r.session.source_map();
+ let sm = self.r.tcx.sess.source_map();
let base_snippet = sm.span_to_snippet(base_span);
if let Some(&sp) = self.diagnostic_metadata.current_type_ascription.last() {
if let Ok(snippet) = sm.span_to_snippet(sp) {
@@ -1804,7 +1814,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
show_label = false;
if !self
.r
- .session
+ .tcx
+ .sess
.parse_sess
.type_ascription_path_suggestions
.borrow_mut()
@@ -2237,19 +2248,23 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
None => {
debug!(?param.ident, ?param.ident.span);
-
let deletion_span = deletion_span();
- self.r.lint_buffer.buffer_lint_with_diagnostic(
- lint::builtin::UNUSED_LIFETIMES,
- param.id,
- param.ident.span,
- &format!("lifetime parameter `{}` never used", param.ident),
- lint::BuiltinLintDiagnostics::SingleUseLifetime {
- param_span: param.ident.span,
- use_span: None,
- deletion_span,
- },
- );
+ // the give lifetime originates from expanded code so we won't be able to remove it #104432
+ let lifetime_only_in_expanded_code =
+ deletion_span.map(|sp| sp.in_derive_expansion()).unwrap_or(true);
+ if !lifetime_only_in_expanded_code {
+ self.r.lint_buffer.buffer_lint_with_diagnostic(
+ lint::builtin::UNUSED_LIFETIMES,
+ param.id,
+ param.ident.span,
+ &format!("lifetime parameter `{}` never used", param.ident),
+ lint::BuiltinLintDiagnostics::SingleUseLifetime {
+ param_span: param.ident.span,
+ use_span: None,
+ deletion_span,
+ },
+ );
+ }
}
}
}
@@ -2263,7 +2278,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
debug_assert_ne!(lifetime_ref.ident.name, kw::UnderscoreLifetime);
let mut err = if let Some(outer) = outer_lifetime_ref {
let mut err = struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
lifetime_ref.ident.span,
E0401,
"can't use generic parameters from outer item",
@@ -2273,7 +2288,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
err
} else {
let mut err = struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
lifetime_ref.ident.span,
E0261,
"use of undeclared lifetime name `{}`",
@@ -2331,8 +2346,13 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
);
(span, sugg)
} else {
- let span =
- self.r.session.source_map().span_through_char(span, '<').shrink_to_hi();
+ let span = self
+ .r
+ .tcx
+ .sess
+ .source_map()
+ .span_through_char(span, '<')
+ .shrink_to_hi();
let sugg = format!("{}, ", name.unwrap_or("'a"));
(span, sugg)
};
@@ -2366,7 +2386,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
pub(crate) fn emit_non_static_lt_in_const_generic_error(&self, lifetime_ref: &ast::Lifetime) {
struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
lifetime_ref.ident.span,
E0771,
"use of non-static lifetime `{}` in const generic",
@@ -2386,10 +2406,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
&self,
lifetime_ref: &ast::Lifetime,
) {
- let feature_active = self.r.session.features_untracked().generic_const_exprs;
+ let feature_active = self.r.tcx.sess.features_untracked().generic_const_exprs;
if !feature_active {
feature_err(
- &self.r.session.parse_sess,
+ &self.r.tcx.sess.parse_sess,
sym::generic_const_exprs,
lifetime_ref.ident.span,
"a non-static lifetime is not allowed in a `const`",
@@ -2407,7 +2427,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect();
let mut err = struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
spans,
E0106,
"missing lifetime specifier{}",
@@ -2615,7 +2635,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
/// Report lifetime/lifetime shadowing as an error.
-pub fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
+pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
let mut err = struct_span_err!(
sess,
shadower.span,
@@ -2630,7 +2650,7 @@ pub fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
/// Shadowing involving a label is only a warning for historical reasons.
//FIXME: make this a proper lint.
-pub fn signal_label_shadowing(sess: &Session, orig: Span, shadower: Ident) {
+pub(super) fn signal_label_shadowing(sess: &Session, orig: Span, shadower: Ident) {
let name = shadower.name;
let shadower = shadower.span;
let mut err = sess.struct_span_warn(