Skip to content

Commit 92fa359

Browse files
authored
Unrolled build for #142502
Rollup merge of #142502 - nnethercote:rustdoc-json-GenericArgs, r=aDotInTheVoid rustdoc_json: improve handling of generic args This PR fixes some inconsistencies and inefficiencies in how generic args are handled by rustdoc-json-types. r? `@aDotInTheVoid`
2 parents df4ad9e + 7fa8901 commit 92fa359

File tree

5 files changed

+84
-19
lines changed

5 files changed

+84
-19
lines changed

src/librustdoc/json/conversions.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,13 @@ pub(crate) fn from_deprecation(deprecation: attrs::Deprecation) -> Deprecation {
169169
Deprecation { since, note: note.map(|s| s.to_string()) }
170170
}
171171

172-
impl FromClean<clean::GenericArgs> for GenericArgs {
172+
impl FromClean<clean::GenericArgs> for Option<Box<GenericArgs>> {
173173
fn from_clean(args: &clean::GenericArgs, renderer: &JsonRenderer<'_>) -> Self {
174174
use clean::GenericArgs::*;
175-
match args {
175+
if args.is_empty() {
176+
return None;
177+
}
178+
Some(Box::new(match args {
176179
AngleBracketed { args, constraints } => GenericArgs::AngleBracketed {
177180
args: args.into_json(renderer),
178181
constraints: constraints.into_json(renderer),
@@ -182,7 +185,7 @@ impl FromClean<clean::GenericArgs> for GenericArgs {
182185
output: output.as_ref().map(|a| a.as_ref().into_json(renderer)),
183186
},
184187
ReturnTypeNotation => GenericArgs::ReturnTypeNotation,
185-
}
188+
}))
186189
}
187190
}
188191

@@ -579,7 +582,20 @@ impl FromClean<clean::Path> for Path {
579582
Path {
580583
path: path.whole_name(),
581584
id: renderer.id_from_item_default(path.def_id().into()),
582-
args: path.segments.last().map(|args| Box::new(args.args.into_json(renderer))),
585+
args: {
586+
if let Some((final_seg, rest_segs)) = path.segments.split_last() {
587+
// In general, `clean::Path` can hold things like
588+
// `std::vec::Vec::<u32>::new`, where generic args appear
589+
// in a middle segment. But for the places where `Path` is
590+
// used by rustdoc-json-types, generic args can only be
591+
// used in the final segment, e.g. `std::vec::Vec<u32>`. So
592+
// check that the non-final segments have no generic args.
593+
assert!(rest_segs.iter().all(|seg| seg.args.is_empty()));
594+
final_seg.args.into_json(renderer)
595+
} else {
596+
None // no generics on any segments because there are no segments
597+
}
598+
},
583599
}
584600
}
585601
}
@@ -590,7 +606,7 @@ impl FromClean<clean::QPathData> for Type {
590606

591607
Self::QualifiedPath {
592608
name: assoc.name.to_string(),
593-
args: Box::new(assoc.args.into_json(renderer)),
609+
args: assoc.args.into_json(renderer),
594610
self_type: Box::new(self_type.into_json(renderer)),
595611
trait_: trait_.as_ref().map(|trait_| trait_.into_json(renderer)),
596612
}

src/librustdoc/json/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,3 +377,33 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
377377
}
378378
}
379379
}
380+
381+
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
382+
//
383+
// These assertions are here, not in `src/rustdoc-json-types/lib.rs` where the types are defined,
384+
// because we have access to `static_assert_size` here.
385+
#[cfg(target_pointer_width = "64")]
386+
mod size_asserts {
387+
use rustc_data_structures::static_assert_size;
388+
389+
use super::types::*;
390+
// tidy-alphabetical-start
391+
static_assert_size!(AssocItemConstraint, 112);
392+
static_assert_size!(Crate, 184);
393+
static_assert_size!(ExternalCrate, 48);
394+
static_assert_size!(FunctionPointer, 168);
395+
static_assert_size!(GenericArg, 80);
396+
static_assert_size!(GenericArgs, 104);
397+
static_assert_size!(GenericBound, 72);
398+
static_assert_size!(GenericParamDef, 136);
399+
static_assert_size!(Impl, 304);
400+
// `Item` contains a `PathBuf`, which is different sizes on different OSes.
401+
static_assert_size!(Item, 528 + size_of::<std::path::PathBuf>());
402+
static_assert_size!(ItemSummary, 32);
403+
static_assert_size!(PolyTrait, 64);
404+
static_assert_size!(PreciseCapturingArg, 32);
405+
static_assert_size!(TargetFeature, 80);
406+
static_assert_size!(Type, 80);
407+
static_assert_size!(WherePredicate, 160);
408+
// tidy-alphabetical-end
409+
}

src/rustdoc-json-types/lib.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc
3737
// will instead cause conflicts. See #94591 for more. (This paragraph and the "Latest feature" line
3838
// are deliberately not in a doc comment, because they need not be in public docs.)
3939
//
40-
// Latest feature: Pretty printing of cold attributes changed
41-
pub const FORMAT_VERSION: u32 = 50;
40+
// Latest feature: improve handling of generic args
41+
pub const FORMAT_VERSION: u32 = 51;
4242

4343
/// The root of the emitted JSON blob.
4444
///
@@ -277,8 +277,8 @@ pub struct PolyTrait {
277277
/// A set of generic arguments provided to a path segment, e.g.
278278
///
279279
/// ```text
280-
/// std::option::Option::<u32>::None
281-
/// ^^^^^
280+
/// std::option::Option<u32>
281+
/// ^^^^^
282282
/// ```
283283
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
284284
#[serde(rename_all = "snake_case")]
@@ -331,7 +331,7 @@ pub enum GenericArg {
331331
Const(Constant),
332332
/// A generic argument that's explicitly set to be inferred.
333333
/// ```text
334-
/// std::vec::Vec::<_>::new()
334+
/// std::vec::Vec::<_>
335335
/// ^
336336
/// ```
337337
Infer,
@@ -362,7 +362,7 @@ pub struct AssocItemConstraint {
362362
/// The name of the associated type/constant.
363363
pub name: String,
364364
/// Arguments provided to the associated type/constant.
365-
pub args: GenericArgs,
365+
pub args: Option<Box<GenericArgs>>,
366366
/// The kind of bound applied to the associated type/constant.
367367
pub binding: AssocItemConstraintKind,
368368
}
@@ -1118,7 +1118,7 @@ pub enum Type {
11181118
/// <core::slice::IterMut<'static, u32> as BetterIterator>::Item<'static>
11191119
/// // ^^^^^^^^^
11201120
/// ```
1121-
args: Box<GenericArgs>,
1121+
args: Option<Box<GenericArgs>>,
11221122
/// The type with which this type is associated.
11231123
///
11241124
/// ```ignore (incomplete expression)

src/tools/jsondoclint/src/validator.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ impl<'a> Validator<'a> {
271271
Type::RawPointer { is_mutable: _, type_ } => self.check_type(&**type_),
272272
Type::BorrowedRef { lifetime: _, is_mutable: _, type_ } => self.check_type(&**type_),
273273
Type::QualifiedPath { name: _, args, self_type, trait_ } => {
274-
self.check_generic_args(&**args);
274+
self.check_opt_generic_args(&args);
275275
self.check_type(&**self_type);
276276
if let Some(trait_) = trait_ {
277277
self.check_path(trait_, PathKind::Trait);
@@ -309,13 +309,12 @@ impl<'a> Validator<'a> {
309309
self.fail(&x.id, ErrorKind::Custom(format!("No entry in '$.paths' for {x:?}")));
310310
}
311311

312-
if let Some(args) = &x.args {
313-
self.check_generic_args(&**args);
314-
}
312+
self.check_opt_generic_args(&x.args);
315313
}
316314

317-
fn check_generic_args(&mut self, x: &'a GenericArgs) {
318-
match x {
315+
fn check_opt_generic_args(&mut self, x: &'a Option<Box<GenericArgs>>) {
316+
let Some(x) = x else { return };
317+
match &**x {
319318
GenericArgs::AngleBracketed { args, constraints } => {
320319
args.iter().for_each(|arg| self.check_generic_arg(arg));
321320
constraints.iter().for_each(|bind| self.check_assoc_item_constraint(bind));
@@ -355,7 +354,7 @@ impl<'a> Validator<'a> {
355354
}
356355

357356
fn check_assoc_item_constraint(&mut self, bind: &'a AssocItemConstraint) {
358-
self.check_generic_args(&bind.args);
357+
self.check_opt_generic_args(&bind.args);
359358
match &bind.binding {
360359
AssocItemConstraintKind::Equality(term) => self.check_term(term),
361360
AssocItemConstraintKind::Constraint(bounds) => {

tests/rustdoc-json/generic-args.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
pub struct MyStruct(u32);
2+
3+
pub trait MyTrait {
4+
type MyType;
5+
fn my_fn(&self);
6+
}
7+
8+
impl MyTrait for MyStruct {
9+
type MyType = u32;
10+
fn my_fn(&self) {}
11+
}
12+
13+
//@ is "$.index[?(@.name=='my_fn1')].inner.function.sig.inputs[0][1].qualified_path.args" null
14+
//@ is "$.index[?(@.name=='my_fn1')].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.args" null
15+
pub fn my_fn1(_: <MyStruct as MyTrait>::MyType) {}
16+
17+
//@ is "$.index[?(@.name=='my_fn2')].inner.function.sig.inputs[0][1].dyn_trait.traits[0].trait.args.angle_bracketed.constraints[0].args" null
18+
pub fn my_fn2(_: IntoIterator<Item = MyStruct, IntoIter = impl Clone>) {}
19+
20+
fn main() {}

0 commit comments

Comments
 (0)