Skip to content

Commit d3b3bc5

Browse files
committed
Auto merge of #52368 - GuillaumeGomez:intra_doc_link_resolution_failure-documented, r=QuietMisdreavus
Add "self" intra-link support Fixes #49583. r? @QuietMisdreavus
2 parents aeca042 + 88f2643 commit d3b3bc5

File tree

3 files changed

+102
-4
lines changed

3 files changed

+102
-4
lines changed

src/librustdoc/clean/mod.rs

+59-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub use self::Visibility::{Public, Inherited};
2020

2121
use rustc_target::spec::abi::Abi;
2222
use syntax;
23-
use syntax::ast::{self, AttrStyle, NodeId, Ident};
23+
use syntax::ast::{self, AttrStyle, Name, NodeId, Ident};
2424
use syntax::attr;
2525
use syntax::codemap::{dummy_spanned, Spanned};
2626
use syntax::feature_gate::UnstableFeatures;
@@ -39,6 +39,7 @@ use rustc::hir::{self, GenericArg, HirVec};
3939
use rustc::hir::def::{self, Def, CtorKind};
4040
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
4141
use rustc::hir::def_id::DefIndexAddressSpace;
42+
use rustc::hir::map::Node;
4243
use rustc::ty::subst::Substs;
4344
use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
4445
use rustc::middle::stability;
@@ -584,10 +585,23 @@ impl Clean<Item> for doctree::Module {
584585
.next()
585586
.map_or(true, |a| a.style == AttrStyle::Inner) {
586587
// inner doc comment, use the module's own scope for resolution
588+
if self.id != NodeId::new(0) {
589+
*cx.current_item_name.borrow_mut() = Some(cx.tcx.hir.name(self.id));
590+
} else {
591+
*cx.current_item_name.borrow_mut() = None;
592+
}
587593
cx.mod_ids.borrow_mut().push(self.id);
588594
self.attrs.clean(cx)
589595
} else {
590596
// outer doc comment, use its parent's scope
597+
match cx.mod_ids.borrow().last() {
598+
Some(parent) if *parent != NodeId::new(0) => {
599+
*cx.current_item_name.borrow_mut() = Some(cx.tcx.hir.name(*parent));
600+
}
601+
_ => {
602+
*cx.current_item_name.borrow_mut() = None;
603+
}
604+
}
591605
let attrs = self.attrs.clean(cx);
592606
cx.mod_ids.borrow_mut().push(self.id);
593607
attrs
@@ -1165,11 +1179,17 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option
11651179
};
11661180

11671181
let mut path = if let Some(second) = split.next() {
1168-
second
1182+
second.to_owned()
11691183
} else {
11701184
return Err(())
11711185
};
11721186

1187+
if path == "self" || path == "Self" {
1188+
if let Some(name) = *cx.current_item_name.borrow() {
1189+
path = name.to_string();
1190+
}
1191+
}
1192+
11731193
let ty = cx.resolver.borrow_mut()
11741194
.with_scope(*id,
11751195
|resolver| {
@@ -2143,6 +2163,8 @@ impl Clean<Item> for doctree::Function {
21432163
let (generics, decl) = enter_impl_trait(cx, || {
21442164
(self.generics.clean(cx), (&self.decl, self.body).clean(cx))
21452165
});
2166+
2167+
*cx.current_item_name.borrow_mut() = Some(self.name);
21462168
Item {
21472169
name: Some(self.name.clean(cx)),
21482170
attrs: self.attrs.clean(cx),
@@ -2321,6 +2343,7 @@ pub struct Trait {
23212343

23222344
impl Clean<Item> for doctree::Trait {
23232345
fn clean(&self, cx: &DocContext) -> Item {
2346+
*cx.current_item_name.borrow_mut() = Some(self.name);
23242347
let attrs = self.attrs.clean(cx);
23252348
let is_spotlight = attrs.has_doc_flag("spotlight");
23262349
Item {
@@ -2392,6 +2415,7 @@ impl Clean<Item> for hir::TraitItem {
23922415
AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
23932416
}
23942417
};
2418+
*cx.current_item_name.borrow_mut() = Some(self.ident.name);
23952419
Item {
23962420
name: Some(self.ident.name.clean(cx)),
23972421
attrs: self.attrs.clean(cx),
@@ -2424,6 +2448,7 @@ impl Clean<Item> for hir::ImplItem {
24242448
generics: Generics::default(),
24252449
}, true),
24262450
};
2451+
*cx.current_item_name.borrow_mut() = Some(self.ident.name);
24272452
Item {
24282453
name: Some(self.ident.name.clean(cx)),
24292454
source: self.span.clean(cx),
@@ -3217,6 +3242,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
32173242

32183243
impl Clean<Item> for hir::StructField {
32193244
fn clean(&self, cx: &DocContext) -> Item {
3245+
*cx.current_item_name.borrow_mut() = Some(self.ident.name);
32203246
Item {
32213247
name: Some(self.ident.name).clean(cx),
32223248
attrs: self.attrs.clean(cx),
@@ -3295,6 +3321,7 @@ impl Clean<Vec<Item>> for doctree::Struct {
32953321
let name = self.name.clean(cx);
32963322
let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
32973323

3324+
*cx.current_item_name.borrow_mut() = Some(self.name);
32983325
ret.push(Item {
32993326
name: Some(name),
33003327
attrs: self.attrs.clean(cx),
@@ -3320,6 +3347,7 @@ impl Clean<Vec<Item>> for doctree::Union {
33203347
let name = self.name.clean(cx);
33213348
let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
33223349

3350+
*cx.current_item_name.borrow_mut() = Some(self.name);
33233351
ret.push(Item {
33243352
name: Some(name),
33253353
attrs: self.attrs.clean(cx),
@@ -3372,6 +3400,7 @@ impl Clean<Vec<Item>> for doctree::Enum {
33723400
let name = self.name.clean(cx);
33733401
let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
33743402

3403+
*cx.current_item_name.borrow_mut() = Some(self.name);
33753404
ret.push(Item {
33763405
name: Some(name),
33773406
attrs: self.attrs.clean(cx),
@@ -3398,6 +3427,7 @@ pub struct Variant {
33983427

33993428
impl Clean<Item> for doctree::Variant {
34003429
fn clean(&self, cx: &DocContext) -> Item {
3430+
*cx.current_item_name.borrow_mut() = Some(self.name);
34013431
Item {
34023432
name: Some(self.name.clean(cx)),
34033433
attrs: self.attrs.clean(cx),
@@ -3693,6 +3723,7 @@ pub struct Typedef {
36933723

36943724
impl Clean<Item> for doctree::Typedef {
36953725
fn clean(&self, cx: &DocContext) -> Item {
3726+
*cx.current_item_name.borrow_mut() = Some(self.name);
36963727
Item {
36973728
name: Some(self.name.clean(cx)),
36983729
attrs: self.attrs.clean(cx),
@@ -3768,6 +3799,7 @@ pub struct Static {
37683799
impl Clean<Item> for doctree::Static {
37693800
fn clean(&self, cx: &DocContext) -> Item {
37703801
debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
3802+
*cx.current_item_name.borrow_mut() = Some(self.name);
37713803
Item {
37723804
name: Some(self.name.clean(cx)),
37733805
attrs: self.attrs.clean(cx),
@@ -3793,6 +3825,7 @@ pub struct Constant {
37933825

37943826
impl Clean<Item> for doctree::Constant {
37953827
fn clean(&self, cx: &DocContext) -> Item {
3828+
*cx.current_item_name.borrow_mut() = Some(self.name);
37963829
Item {
37973830
name: Some(self.name.clean(cx)),
37983831
attrs: self.attrs.clean(cx),
@@ -3862,6 +3895,23 @@ pub fn get_auto_traits_with_def_id(cx: &DocContext, id: DefId) -> Vec<Item> {
38623895
finder.get_with_def_id(id)
38633896
}
38643897

3898+
fn get_name_if_possible(cx: &DocContext, node: NodeId) -> Option<Name> {
3899+
match cx.tcx.hir.get(node) {
3900+
Node::NodeItem(_) |
3901+
Node::NodeForeignItem(_) |
3902+
Node::NodeImplItem(_) |
3903+
Node::NodeTraitItem(_) |
3904+
Node::NodeVariant(_) |
3905+
Node::NodeField(_) |
3906+
Node::NodeLifetime(_) |
3907+
Node::NodeGenericParam(_) |
3908+
Node::NodeBinding(&hir::Pat { node: hir::PatKind::Binding(_,_,_,_), .. }) |
3909+
Node::NodeStructCtor(_) => {}
3910+
_ => return None,
3911+
}
3912+
Some(cx.tcx.hir.name(node))
3913+
}
3914+
38653915
impl Clean<Vec<Item>> for doctree::Impl {
38663916
fn clean(&self, cx: &DocContext) -> Vec<Item> {
38673917
let mut ret = Vec::new();
@@ -3881,6 +3931,7 @@ impl Clean<Vec<Item>> for doctree::Impl {
38813931
.collect()
38823932
}).unwrap_or(FxHashSet());
38833933

3934+
*cx.current_item_name.borrow_mut() = get_name_if_possible(cx, self.for_.id);
38843935
ret.push(Item {
38853936
name: None,
38863937
attrs: self.attrs.clean(cx),
@@ -3967,6 +4018,7 @@ fn build_deref_target_impls(cx: &DocContext,
39674018

39684019
impl Clean<Item> for doctree::ExternCrate {
39694020
fn clean(&self, cx: &DocContext) -> Item {
4021+
*cx.current_item_name.borrow_mut() = Some(self.name);
39704022
Item {
39714023
name: None,
39724024
attrs: self.attrs.clean(cx),
@@ -4013,6 +4065,8 @@ impl Clean<Vec<Item>> for doctree::Import {
40134065
}
40144066
Import::Simple(name.clean(cx), resolve_use_source(cx, path))
40154067
};
4068+
4069+
*cx.current_item_name.borrow_mut() = Some(self.name);
40164070
vec![Item {
40174071
name: None,
40184072
attrs: self.attrs.clean(cx),
@@ -4081,6 +4135,8 @@ impl Clean<Item> for hir::ForeignItem {
40814135
ForeignTypeItem
40824136
}
40834137
};
4138+
4139+
*cx.current_item_name.borrow_mut() = Some(self.name);
40844140
Item {
40854141
name: Some(self.name.clean(cx)),
40864142
attrs: self.attrs.clean(cx),
@@ -4256,6 +4312,7 @@ pub struct Macro {
42564312
impl Clean<Item> for doctree::Macro {
42574313
fn clean(&self, cx: &DocContext) -> Item {
42584314
let name = self.name.clean(cx);
4315+
*cx.current_item_name.borrow_mut() = None;
42594316
Item {
42604317
name: Some(name.clone()),
42614318
attrs: self.attrs.clean(cx),

src/librustdoc/core.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_metadata::creader::CrateLoader;
2525
use rustc_metadata::cstore::CStore;
2626
use rustc_target::spec::TargetTriple;
2727

28-
use syntax::ast::NodeId;
28+
use syntax::ast::{Name, NodeId};
2929
use syntax::codemap;
3030
use syntax::edition::Edition;
3131
use syntax::feature_gate::UnstableFeatures;
@@ -82,7 +82,8 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
8282
pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
8383
pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
8484
/// Maps (type_id, trait_id) -> auto trait impl
85-
pub generated_synthetics: RefCell<FxHashSet<(DefId, DefId)>>
85+
pub generated_synthetics: RefCell<FxHashSet<(DefId, DefId)>>,
86+
pub current_item_name: RefCell<Option<Name>>,
8687
}
8788

8889
impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> {
@@ -383,6 +384,7 @@ pub fn run_core(search_paths: SearchPaths,
383384
fake_def_ids: RefCell::new(FxHashMap()),
384385
all_fake_def_ids: RefCell::new(FxHashSet()),
385386
generated_synthetics: RefCell::new(FxHashSet()),
387+
current_item_name: RefCell::new(None),
386388
};
387389
debug!("crate: {:?}", tcx.hir.krate());
388390

src/test/rustdoc/intra-link-self.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_name = "foo"]
12+
13+
// @has foo/index.html '//a/@href' '../foo/struct.Foo.html#method.new'
14+
// @has foo/struct.Foo.html '//a/@href' '../foo/struct.Foo.html#method.new'
15+
16+
/// Use [`new`] to create a new instance.
17+
///
18+
/// [`new`]: Self::new
19+
pub struct Foo;
20+
21+
impl Foo {
22+
pub fn new() -> Self {
23+
unimplemented!()
24+
}
25+
}
26+
27+
// @has foo/index.html '//a/@href' '../foo/struct.Bar.html#method.new2'
28+
// @has foo/struct.Bar.html '//a/@href' '../foo/struct.Bar.html#method.new2'
29+
30+
/// Use [`new2`] to create a new instance.
31+
///
32+
/// [`new2`]: Self::new2
33+
pub struct Bar;
34+
35+
impl Bar {
36+
pub fn new2() -> Self {
37+
unimplemented!()
38+
}
39+
}

0 commit comments

Comments
 (0)