Auto merge of #111195 - GuillaumeGomez:fix-ice-intra-doc-link, r=petrochenkov
Prevent crash when a path is not resolved in intra-doc link Fixes https://github.com/rust-lang/rust/issues/111189. cc `@petrochenkov` r? `@notriddle`
This commit is contained in:
commit
d69787f098
4 changed files with 40 additions and 8 deletions
|
@ -17,7 +17,7 @@ use rustc_ast::*;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||||
use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg};
|
use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg};
|
||||||
use rustc_hir::def::Namespace::{self, *};
|
use rustc_hir::def::Namespace::{self, *};
|
||||||
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
|
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||||
use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
|
use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
|
||||||
use rustc_middle::middle::resolve_bound_vars::Set1;
|
use rustc_middle::middle::resolve_bound_vars::Set1;
|
||||||
|
@ -4287,12 +4287,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> bool {
|
fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> Option<Res> {
|
||||||
// FIXME: This caching may be incorrect in case of multiple `macro_rules`
|
// FIXME: This caching may be incorrect in case of multiple `macro_rules`
|
||||||
// items with the same name in the same module.
|
// items with the same name in the same module.
|
||||||
// Also hygiene is not considered.
|
// Also hygiene is not considered.
|
||||||
let mut doc_link_resolutions = std::mem::take(&mut self.r.doc_link_resolutions);
|
let mut doc_link_resolutions = std::mem::take(&mut self.r.doc_link_resolutions);
|
||||||
let res = doc_link_resolutions
|
let res = *doc_link_resolutions
|
||||||
.entry(self.parent_scope.module.nearest_parent_mod().expect_local())
|
.entry(self.parent_scope.module.nearest_parent_mod().expect_local())
|
||||||
.or_default()
|
.or_default()
|
||||||
.entry((Symbol::intern(path_str), ns))
|
.entry((Symbol::intern(path_str), ns))
|
||||||
|
@ -4307,8 +4307,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
})
|
});
|
||||||
.is_some();
|
|
||||||
self.r.doc_link_resolutions = doc_link_resolutions;
|
self.r.doc_link_resolutions = doc_link_resolutions;
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
@ -4343,8 +4342,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||||
let mut any_resolved = false;
|
let mut any_resolved = false;
|
||||||
let mut need_assoc = false;
|
let mut need_assoc = false;
|
||||||
for ns in [TypeNS, ValueNS, MacroNS] {
|
for ns in [TypeNS, ValueNS, MacroNS] {
|
||||||
if self.resolve_and_cache_rustdoc_path(&path_str, ns) {
|
if let Some(res) = self.resolve_and_cache_rustdoc_path(&path_str, ns) {
|
||||||
any_resolved = true;
|
// Rustdoc ignores tool attribute resolutions and attempts
|
||||||
|
// to resolve their prefixes for diagnostics.
|
||||||
|
any_resolved = !matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Tool));
|
||||||
} else if ns != MacroNS {
|
} else if ns != MacroNS {
|
||||||
need_assoc = true;
|
need_assoc = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ impl TryFrom<ResolveRes> for Res {
|
||||||
Def(kind, id) => Ok(Res::Def(kind, id)),
|
Def(kind, id) => Ok(Res::Def(kind, id)),
|
||||||
PrimTy(prim) => Ok(Res::Primitive(PrimitiveType::from_hir(prim))),
|
PrimTy(prim) => Ok(Res::Primitive(PrimitiveType::from_hir(prim))),
|
||||||
// e.g. `#[derive]`
|
// e.g. `#[derive]`
|
||||||
NonMacroAttr(..) | Err => Result::Err(()),
|
ToolMod | NonMacroAttr(..) | Err => Result::Err(()),
|
||||||
other => bug!("unrecognized res {:?}", other),
|
other => bug!("unrecognized res {:?}", other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.rs
Normal file
10
tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// Regression test for <https://github.com/rust-lang/rust/issues/111189>.
|
||||||
|
// This test ensures that it doesn't crash.
|
||||||
|
|
||||||
|
#![deny(warnings)]
|
||||||
|
|
||||||
|
/// #[rustfmt::skip]
|
||||||
|
//~^ ERROR unresolved link to `rustfmt::skip`
|
||||||
|
/// #[clippy::whatever]
|
||||||
|
//~^ ERROR unresolved link to `clippy::whatever`
|
||||||
|
pub fn foo() {}
|
|
@ -0,0 +1,21 @@
|
||||||
|
error: unresolved link to `rustfmt::skip`
|
||||||
|
--> $DIR/issue-111189-resolution-ice.rs:6:7
|
||||||
|
|
|
||||||
|
LL | /// #[rustfmt::skip]
|
||||||
|
| ^^^^^^^^^^^^^ no item named `rustfmt` in scope
|
||||||
|
|
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/issue-111189-resolution-ice.rs:4:9
|
||||||
|
|
|
||||||
|
LL | #![deny(warnings)]
|
||||||
|
| ^^^^^^^^
|
||||||
|
= note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
|
||||||
|
|
||||||
|
error: unresolved link to `clippy::whatever`
|
||||||
|
--> $DIR/issue-111189-resolution-ice.rs:8:7
|
||||||
|
|
|
||||||
|
LL | /// #[clippy::whatever]
|
||||||
|
| ^^^^^^^^^^^^^^^^ no item named `clippy` in scope
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue