Skip to content

Commit

Permalink
Rollup merge of rust-lang#119586 - GuillaumeGomez:jump-to-def-static-…
Browse files Browse the repository at this point in the history
…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```
  • Loading branch information
GuillaumeGomez authored Jan 5, 2024
2 parents c224f4d + 5bc7687 commit eef3320
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 21 deletions.
52 changes: 32 additions & 20 deletions src/librustdoc/html/render/span_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/rustdoc/check-source-code-urls-to-def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
27 changes: 27 additions & 0 deletions tests/rustdoc/jump-to-def-doc-links-calls.rs
Original file line number Diff line number Diff line change
@@ -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
}
}

0 comments on commit eef3320

Please sign in to comment.