Skip to content

Commit 6a8e601

Browse files
authored
Rollup merge of rust-lang#74078 - jyn514:lut, r=Manishearth
Always resolve type@primitive as a primitive, not a module Previously, if there were a module in scope with the same name as the primitive, that would take precedence. Coupled with rust-lang#58699, this made it impossible to link to the primitive when that module was in scope. This approach could be extended so that `struct@foo` would no longer resolve to any type, etc. However, it could not be used for glob imports: ```rust pub mod foo { pub struct Bar; } pub enum Bar {} use foo::*; // This is expected to link to `inner::Bar`, but instead it will link to the enum. /// Link to [struct@Bar] pub struct MyDocs; ``` The reason for this is that this change does not affect the resolution algorithm of rustc_resolve at all. The only reason we could special-case primitives is because we have a list of all possible primitives ahead of time. Closes rust-lang#74063 r? @Manishearth
2 parents 51d7220 + e46c187 commit 6a8e601

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

src/librustdoc/passes/collect_intra_doc_links.rs

+28-5
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
164164
fn resolve(
165165
&self,
166166
path_str: &str,
167+
disambiguator: Option<&str>,
167168
ns: Namespace,
168169
current_item: &Option<String>,
169170
parent_id: Option<hir::HirId>,
@@ -203,11 +204,22 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
203204
}
204205
return Ok((res, Some(path_str.to_owned())));
205206
}
206-
other => {
207-
debug!(
208-
"failed to resolve {} in namespace {:?} (got {:?})",
209-
path_str, ns, other
210-
);
207+
Res::Def(DefKind::Mod, _) => {
208+
// This resolved to a module, but if we were passed `type@`,
209+
// we want primitive types to take precedence instead.
210+
if disambiguator == Some("type") {
211+
if let Some(prim) = is_primitive(path_str, ns) {
212+
if extra_fragment.is_some() {
213+
return Err(ErrorKind::AnchorFailure(
214+
"primitive types cannot be followed by anchors",
215+
));
216+
}
217+
return Ok((prim, Some(path_str.to_owned())));
218+
}
219+
}
220+
return Ok((res, extra_fragment.clone()));
221+
}
222+
_ => {
211223
return Ok((res, extra_fragment.clone()));
212224
}
213225
};
@@ -566,11 +578,13 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
566578
let mut path_str;
567579
let (res, fragment) = {
568580
let mut kind = None;
581+
let mut disambiguator = None;
569582
path_str = if let Some(prefix) = ["struct@", "enum@", "type@", "trait@", "union@"]
570583
.iter()
571584
.find(|p| link.starts_with(**p))
572585
{
573586
kind = Some(TypeNS);
587+
disambiguator = Some(&prefix[..prefix.len() - 1]);
574588
link.trim_start_matches(prefix)
575589
} else if let Some(prefix) = [
576590
"const@",
@@ -586,18 +600,23 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
586600
.find(|p| link.starts_with(**p))
587601
{
588602
kind = Some(ValueNS);
603+
disambiguator = Some(&prefix[..prefix.len() - 1]);
589604
link.trim_start_matches(prefix)
590605
} else if link.ends_with("()") {
591606
kind = Some(ValueNS);
607+
disambiguator = Some("fn");
592608
link.trim_end_matches("()")
593609
} else if link.starts_with("macro@") {
594610
kind = Some(MacroNS);
611+
disambiguator = Some("macro");
595612
link.trim_start_matches("macro@")
596613
} else if link.starts_with("derive@") {
597614
kind = Some(MacroNS);
615+
disambiguator = Some("derive");
598616
link.trim_start_matches("derive@")
599617
} else if link.ends_with('!') {
600618
kind = Some(MacroNS);
619+
disambiguator = Some("macro");
601620
link.trim_end_matches('!')
602621
} else {
603622
&link[..]
@@ -634,6 +653,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
634653
Some(ns @ ValueNS) => {
635654
match self.resolve(
636655
path_str,
656+
disambiguator,
637657
ns,
638658
&current_item,
639659
base_node,
@@ -657,6 +677,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
657677
Some(ns @ TypeNS) => {
658678
match self.resolve(
659679
path_str,
680+
disambiguator,
660681
ns,
661682
&current_item,
662683
base_node,
@@ -683,6 +704,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
683704
.map(|res| (res, extra_fragment.clone())),
684705
type_ns: match self.resolve(
685706
path_str,
707+
disambiguator,
686708
TypeNS,
687709
&current_item,
688710
base_node,
@@ -697,6 +719,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
697719
},
698720
value_ns: match self.resolve(
699721
path_str,
722+
disambiguator,
700723
ValueNS,
701724
&current_item,
702725
base_node,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// ignore-tidy-linelength
2+
#![deny(intra_doc_resolution_failure)]
3+
4+
pub mod char {}
5+
6+
/// See also [type@char]
7+
// @has intra_link_prim_precedence/struct.MyString.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html'
8+
pub struct MyString;
9+
10+
/// See also [char]
11+
// @has intra_link_prim_precedence/struct.MyString2.html '//a/@href' 'intra_link_prim_precedence/char/index.html'
12+
pub struct MyString2;

0 commit comments

Comments
 (0)