diff options
| author | Michael Goulet <michael@errs.io> | 2024-01-05 10:57:23 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-05 10:57:23 -0500 |
| commit | 3f19de635203f0e8dbef04fff4cda524d76d4021 (patch) | |
| tree | 9fb057d28617774b2dd9df7221e59890fd85f5d2 | |
| parent | 8bea1df254ca5225c547e8b2fdeb434dd8ac0226 (diff) | |
| parent | 5bc76873517d152fc5753c28059b247daabbf341 (diff) | |
Rollup merge of #119586 - GuillaumeGomez:jump-to-def-static-methods, r=notriddle
[rustdoc] Fix invalid handling for static method calls in jump to definition feature I realized when working on a clippy lint that static method calls on `Self` could not give me the method `Res`. For that, we need to use `typeck` and so that's what I did in here. It fixes the linking to static method calls. r? ````@notriddle````
| -rw-r--r-- | src/librustdoc/html/render/span_map.rs | 52 | ||||
| -rw-r--r-- | tests/rustdoc/check-source-code-urls-to-def.rs | 2 | ||||
| -rw-r--r-- | tests/rustdoc/jump-to-def-doc-links-calls.rs | 27 |
3 files changed, 60 insertions, 21 deletions
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<HirId>, 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<AnotherTrait2> = 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 + } +} |
