Skip to content

Commit 2c0f09c

Browse files
committed
rustdoc_json: Fix handling of paths with no generic args.
A path without generic args, like `Reader`, currently has JSON produced like this: ``` {"path":"Reader","id":286,"args":{"angle_bracketed":{"args":[],"constraints":[]}}} ``` Even though `types::Path::args` is `Option` and allows for "no args", instead it gets represented as "empty args". (More like `Reader<>` than `Reader`.) This is due to a problem in `clean::Path::from_clean`. It only produces `None` if the path is an empty string. This commit changes it to also produce `None` if there are no generic args. The example above becomes: ``` {"path":"Reader","id":286,"args":null} ``` I looked at a few examples and saw this reduce the size of the JSON output by 3-9%. The commit also adds an assertion that non-final segments don't have any generics; something the old code was implicitly relying on. Note: the original sin here is that `clean::PathSegment::args` is not an `Option`, unlike `{ast,hir}::PathSegment::args`. I want to fix that, but it can be done separately.
1 parent 0cc1e16 commit 2c0f09c

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

src/librustdoc/json/conversions.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,24 @@ impl FromClean<clean::Path> for Path {
580580
Path {
581581
path: path.whole_name(),
582582
id: renderer.id_from_item_default(path.def_id().into()),
583-
args: path.segments.last().map(|args| Box::new(args.args.into_json(renderer))),
583+
args: {
584+
if let Some((final_seg, rest_segs)) = path.segments.split_last() {
585+
// In general, `clean::Path` can hold things like
586+
// `std::vec::Vec::<u32>::new`, where generic args appear
587+
// in a middle segment. But for the places where `Path` is
588+
// used by rustdoc-json-types, generic args can only be
589+
// used in the final segment, e.g. `std::vec::Vec<u32>`. So
590+
// check that the non-final segments have no generic args.
591+
assert!(rest_segs.iter().all(|seg| seg.args.is_empty()));
592+
if final_seg.args.is_empty() {
593+
None
594+
} else {
595+
Some(Box::new(final_seg.args.into_json(renderer)))
596+
}
597+
} else {
598+
None // no generics on any segments because there are no segments
599+
}
600+
},
584601
}
585602
}
586603
}

0 commit comments

Comments
 (0)