Skip to content

Commit 472e52e

Browse files
committed
Fix intra-doc links for primitives
- Add `PrimTy::name` and `PrimTy::name_str` - Use those new functions to distinguish between the name in scope and the canonical name - Fix diagnostics for primitive types - Add tests for primitives
1 parent dd7b8c8 commit 472e52e

File tree

4 files changed

+46
-10
lines changed

4 files changed

+46
-10
lines changed

compiler/rustc_hir/src/hir.rs

+24
Original file line numberDiff line numberDiff line change
@@ -2004,6 +2004,30 @@ pub enum PrimTy {
20042004
Char,
20052005
}
20062006

2007+
impl PrimTy {
2008+
pub fn name_str(self) -> &'static str {
2009+
match self {
2010+
PrimTy::Int(i) => i.name_str(),
2011+
PrimTy::Uint(u) => u.name_str(),
2012+
PrimTy::Float(f) => f.name_str(),
2013+
PrimTy::Str => "str",
2014+
PrimTy::Bool => "bool",
2015+
PrimTy::Char => "char",
2016+
}
2017+
}
2018+
2019+
pub fn name(self) -> Symbol {
2020+
match self {
2021+
PrimTy::Int(i) => i.name(),
2022+
PrimTy::Uint(u) => u.name(),
2023+
PrimTy::Float(f) => f.name(),
2024+
PrimTy::Str => sym::str,
2025+
PrimTy::Bool => sym::bool,
2026+
PrimTy::Char => sym::char,
2027+
}
2028+
}
2029+
}
2030+
20072031
#[derive(Debug, HashStable_Generic)]
20082032
pub struct BareFnTy<'hir> {
20092033
pub unsafety: Unsafety,

src/librustdoc/passes/collect_intra_doc_links.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -273,13 +273,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
273273
return handle_variant(cx, res, extra_fragment);
274274
}
275275
// Not a trait item; just return what we found.
276-
Res::PrimTy(..) => {
276+
Res::PrimTy(ty) => {
277277
if extra_fragment.is_some() {
278278
return Err(ErrorKind::AnchorFailure(
279279
AnchorFailure::RustdocAnchorConflict(res),
280280
));
281281
}
282-
return Ok((res, Some(path_str.to_owned())));
282+
return Ok((res, Some(ty.name_str().to_owned())));
283283
}
284284
Res::Def(DefKind::Mod, _) => {
285285
return Ok((res, extra_fragment.clone()));
@@ -292,6 +292,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
292292
if value != (ns == ValueNS) {
293293
return Err(ResolutionFailure::WrongNamespace(res, ns).into());
294294
}
295+
// FIXME: why is this necessary?
295296
} else if let Some((path, prim)) = is_primitive(path_str, ns) {
296297
if extra_fragment.is_some() {
297298
return Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(prim)));
@@ -1008,12 +1009,12 @@ impl LinkCollector<'_, '_> {
10081009
suggest_disambiguator(resolved, diag, path_str, dox, sp, &link_range);
10091010
});
10101011
};
1011-
if let Res::PrimTy(_) = res {
1012+
if let Res::PrimTy(ty) = res {
10121013
match disambiguator {
10131014
Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {
10141015
item.attrs.links.push(ItemLink {
10151016
link: ori_link,
1016-
link_text: path_str.to_owned(),
1017+
link_text,
10171018
did: None,
10181019
fragment,
10191020
});
@@ -1488,6 +1489,10 @@ fn resolution_failure(
14881489
link_range: Option<Range<usize>>,
14891490
kinds: SmallVec<[ResolutionFailure<'_>; 3]>,
14901491
) {
1492+
let has_primitive = kinds.iter().any(|err|
1493+
matches!(err, ResolutionFailure::NoPrimitiveAssocItem{..} | ResolutionFailure::NoPrimitiveImpl(_, _))
1494+
);
1495+
14911496
report_diagnostic(
14921497
collector.cx,
14931498
&format!("unresolved link to `{}`", path_str),
@@ -1528,6 +1533,7 @@ fn resolution_failure(
15281533

15291534
let module_id = *module_id;
15301535
// FIXME(jynelson): this might conflict with my `Self` fix in #76467
1536+
// FIXME: use itertools `collect_tuple` instead
15311537
fn split(path: &str) -> Option<(&str, &str)> {
15321538
let mut splitter = path.rsplitn(2, "::");
15331539
splitter.next().and_then(|right| splitter.next().map(|left| (left, right)))
@@ -1567,7 +1573,6 @@ fn resolution_failure(
15671573
};
15681574
// See if this was a module: `[path]` or `[std::io::nope]`
15691575
if let Some(module) = last_found_module {
1570-
// NOTE: uses an explicit `continue` so the `note:` will come before the `help:`
15711576
let module_name = collector.cx.tcx.item_name(module);
15721577
let note = format!(
15731578
"the module `{}` contains no item named `{}`",
@@ -1595,7 +1600,10 @@ fn resolution_failure(
15951600
diagnostic_name = collector.cx.tcx.item_name(def_id).as_str();
15961601
(Some(kind), &*diagnostic_name)
15971602
}
1598-
Res::PrimTy(_) => (None, name),
1603+
Res::PrimTy(_) => {
1604+
assert!(has_primitive);
1605+
continue;
1606+
}
15991607
_ => unreachable!("only ADTs and primitives are in scope at module level"),
16001608
};
16011609
let path_description = if let Some(kind) = kind {

src/test/rustdoc-ui/intra-link-errors.stderr

+1-4
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,7 @@ error: unresolved link to `u8::not_found`
8080
--> $DIR/intra-link-errors.rs:55:6
8181
|
8282
LL | /// [u8::not_found]
83-
| ^^^^^^^^^^^^^
84-
| |
85-
| the builtin type `u8` does not have an associated item named `not_found`
86-
| the builtin type `u8` has no builtin type named `not_found`
83+
| ^^^^^^^^^^^^^ the builtin type `u8` does not have an associated item named `not_found`
8784

8885
error: unresolved link to `S`
8986
--> $DIR/intra-link-errors.rs:59:6

src/test/rustdoc/primitive-link.rs

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.u32.html"]' 'u32'
66
// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i64.html"]' 'i64'
7+
// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html"]' 'std::primitive::i32'
8+
// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'std::primitive::str'
9+
10+
// FIXME: this doesn't resolve
11+
// @ has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html#associatedconstant.MAX"]' 'std::primitive::i32::MAX'
712

813
/// It contains [`u32`] and [i64].
14+
/// It also links to [std::primitive::i32], [std::primitive::str],
15+
/// and [`std::primitive::i32::MAX`].
916
pub struct Foo;

0 commit comments

Comments
 (0)