diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index d1ece73374d..b055e355b78 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -154,6 +154,28 @@ impl<'tcx> SpanMapVisitor<'tcx> {
self.matches.insert(new_span, link_from_src);
true
}
+
+ fn handle_call(&mut self, hir_id: HirId, expr_hir_id: Option, span: Span) {
+ let hir = self.tcx.hir();
+ let body_id = hir.enclosing_body_owner(hir_id);
+ // FIXME: this is showing error messages for parts of the code that are not
+ // compiled (because of cfg)!
+ //
+ // See discussion in https://github.com/rust-lang/rust/issues/69426#issuecomment-1019412352
+ let typeck_results = self
+ .tcx
+ .typeck_body(hir.maybe_body_owned_by(body_id).expect("a body which isn't a body"));
+ // Interestingly enough, for method calls, we need the whole expression whereas for static
+ // method/function calls, we need the call expression specifically.
+ if let Some(def_id) = typeck_results.type_dependent_def_id(expr_hir_id.unwrap_or(hir_id)) {
+ let link = if def_id.as_local().is_some() {
+ LinkFromSrc::Local(rustc_span(def_id, self.tcx))
+ } else {
+ LinkFromSrc::External(def_id)
+ };
+ self.matches.insert(span, link);
+ }
+ }
}
impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
@@ -191,27 +213,17 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
}
fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'tcx>) {
- if let ExprKind::MethodCall(segment, ..) = expr.kind {
- let hir = self.tcx.hir();
- let body_id = hir.enclosing_body_owner(segment.hir_id);
- // FIXME: this is showing error messages for parts of the code that are not
- // compiled (because of cfg)!
- //
- // See discussion in https://github.com/rust-lang/rust/issues/69426#issuecomment-1019412352
- let typeck_results = self
- .tcx
- .typeck_body(hir.maybe_body_owned_by(body_id).expect("a body which isn't a body"));
- if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
- let link = if def_id.as_local().is_some() {
- LinkFromSrc::Local(rustc_span(def_id, self.tcx))
- } else {
- LinkFromSrc::External(def_id)
- };
- self.matches.insert(segment.ident.span, link);
+ match expr.kind {
+ ExprKind::MethodCall(segment, ..) => {
+ self.handle_call(segment.hir_id, Some(expr.hir_id), segment.ident.span)
+ }
+ ExprKind::Call(call, ..) => self.handle_call(call.hir_id, None, call.span),
+ _ => {
+ if self.handle_macro(expr.span) {
+ // We don't want to go deeper into the macro.
+ return;
+ }
}
- } else if self.handle_macro(expr.span) {
- // We don't want to go deeper into the macro.
- return;
}
intravisit::walk_expr(self, expr);
}
diff --git a/tests/rustdoc/check-source-code-urls-to-def.rs b/tests/rustdoc/check-source-code-urls-to-def.rs
index b803c7e9e86..c31c579030e 100644
--- a/tests/rustdoc/check-source-code-urls-to-def.rs
+++ b/tests/rustdoc/check-source-code-urls-to-def.rs
@@ -62,7 +62,7 @@ pub trait AnotherTrait2 {}
// @has - '//pre[@class="rust"]//a[@href="#61"]' 'AnotherTrait2'
pub fn foo4() {
- let x: Vec = Vec::new();
+ let x: Vec<&dyn AnotherTrait2> = Vec::new();
}
// @has - '//pre[@class="rust"]//a[@href="../../foo/primitive.bool.html"]' 'bool'
diff --git a/tests/rustdoc/jump-to-def-doc-links-calls.rs b/tests/rustdoc/jump-to-def-doc-links-calls.rs
new file mode 100644
index 00000000000..549d068528e
--- /dev/null
+++ b/tests/rustdoc/jump-to-def-doc-links-calls.rs
@@ -0,0 +1,27 @@
+// compile-flags: -Zunstable-options --generate-link-to-definition
+
+#![crate_name = "foo"]
+
+// @has 'src/foo/jump-to-def-doc-links-calls.rs.html'
+
+// @has - '//a[@href="../../foo/struct.Bar.html"]' 'Bar'
+pub struct Bar;
+
+impl std::default::Default for Bar {
+ // @has - '//a[@href="#20-22"]' 'Self::new'
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+// @has - '//a[@href="#8"]' 'Bar'
+impl Bar {
+ // @has - '//a[@href="#24-26"]' 'Self::bar'
+ pub fn new()-> Self {
+ Self::bar()
+ }
+
+ pub fn bar() -> Self {
+ Self
+ }
+}