about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustdoc/json/conversions.rs17
-rw-r--r--src/librustdoc/json/mod.rs2
-rw-r--r--src/rustdoc-json-types/lib.rs8
-rw-r--r--src/tools/jsondoclint/src/validator.rs13
-rw-r--r--tests/rustdoc-json/generic-args.rs4
5 files changed, 21 insertions, 23 deletions
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 4719bd5d118..cb4c1f7fbc0 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -169,10 +169,13 @@ pub(crate) fn from_deprecation(deprecation: attrs::Deprecation) -> Deprecation {
     Deprecation { since, note: note.map(|s| s.to_string()) }
 }
 
-impl FromClean<clean::GenericArgs> for GenericArgs {
+impl FromClean<clean::GenericArgs> for Option<Box<GenericArgs>> {
     fn from_clean(args: &clean::GenericArgs, renderer: &JsonRenderer<'_>) -> Self {
         use clean::GenericArgs::*;
-        match args {
+        if args.is_empty() {
+            return None;
+        }
+        Some(Box::new(match args {
             AngleBracketed { args, constraints } => GenericArgs::AngleBracketed {
                 args: args.into_json(renderer),
                 constraints: constraints.into_json(renderer),
@@ -182,7 +185,7 @@ impl FromClean<clean::GenericArgs> for GenericArgs {
                 output: output.as_ref().map(|a| a.as_ref().into_json(renderer)),
             },
             ReturnTypeNotation => GenericArgs::ReturnTypeNotation,
-        }
+        }))
     }
 }
 
@@ -588,11 +591,7 @@ impl FromClean<clean::Path> for Path {
                     // used in the final segment, e.g. `std::vec::Vec<u32>`. So
                     // check that the non-final segments have no generic args.
                     assert!(rest_segs.iter().all(|seg| seg.args.is_empty()));
-                    if final_seg.args.is_empty() {
-                        None
-                    } else {
-                        Some(Box::new(final_seg.args.into_json(renderer)))
-                    }
+                    final_seg.args.into_json(renderer)
                 } else {
                     None // no generics on any segments because there are no segments
                 }
@@ -607,7 +606,7 @@ impl FromClean<clean::QPathData> for Type {
 
         Self::QualifiedPath {
             name: assoc.name.to_string(),
-            args: Box::new(assoc.args.into_json(renderer)),
+            args: assoc.args.into_json(renderer),
             self_type: Box::new(self_type.into_json(renderer)),
             trait_: trait_.as_ref().map(|trait_| trait_.into_json(renderer)),
         }
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index f5064ae55b8..600a4b429f3 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -388,7 +388,7 @@ mod size_asserts {
 
     use super::types::*;
     // tidy-alphabetical-start
-    static_assert_size!(AssocItemConstraint, 208);
+    static_assert_size!(AssocItemConstraint, 112);
     static_assert_size!(Crate, 184);
     static_assert_size!(ExternalCrate, 48);
     static_assert_size!(FunctionPointer, 168);
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 0404f3ff034..c9b4da183a3 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -37,8 +37,8 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc
 // will instead cause conflicts. See #94591 for more. (This paragraph and the "Latest feature" line
 // are deliberately not in a doc comment, because they need not be in public docs.)
 //
-// Latest feature: Pretty printing of cold attributes changed
-pub const FORMAT_VERSION: u32 = 50;
+// Latest feature: improve handling of generic args
+pub const FORMAT_VERSION: u32 = 51;
 
 /// The root of the emitted JSON blob.
 ///
@@ -362,7 +362,7 @@ pub struct AssocItemConstraint {
     /// The name of the associated type/constant.
     pub name: String,
     /// Arguments provided to the associated type/constant.
-    pub args: GenericArgs,
+    pub args: Option<Box<GenericArgs>>,
     /// The kind of bound applied to the associated type/constant.
     pub binding: AssocItemConstraintKind,
 }
@@ -1118,7 +1118,7 @@ pub enum Type {
         /// <core::slice::IterMut<'static, u32> as BetterIterator>::Item<'static>
         /// //                                                          ^^^^^^^^^
         /// ```
-        args: Box<GenericArgs>,
+        args: Option<Box<GenericArgs>>,
         /// The type with which this type is associated.
         ///
         /// ```ignore (incomplete expression)
diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs
index 8c9e4c8bb3a..0a4051fcbe8 100644
--- a/src/tools/jsondoclint/src/validator.rs
+++ b/src/tools/jsondoclint/src/validator.rs
@@ -271,7 +271,7 @@ impl<'a> Validator<'a> {
             Type::RawPointer { is_mutable: _, type_ } => self.check_type(&**type_),
             Type::BorrowedRef { lifetime: _, is_mutable: _, type_ } => self.check_type(&**type_),
             Type::QualifiedPath { name: _, args, self_type, trait_ } => {
-                self.check_generic_args(&**args);
+                self.check_opt_generic_args(&args);
                 self.check_type(&**self_type);
                 if let Some(trait_) = trait_ {
                     self.check_path(trait_, PathKind::Trait);
@@ -309,13 +309,12 @@ impl<'a> Validator<'a> {
             self.fail(&x.id, ErrorKind::Custom(format!("No entry in '$.paths' for {x:?}")));
         }
 
-        if let Some(args) = &x.args {
-            self.check_generic_args(&**args);
-        }
+        self.check_opt_generic_args(&x.args);
     }
 
-    fn check_generic_args(&mut self, x: &'a GenericArgs) {
-        match x {
+    fn check_opt_generic_args(&mut self, x: &'a Option<Box<GenericArgs>>) {
+        let Some(x) = x else { return };
+        match &**x {
             GenericArgs::AngleBracketed { args, constraints } => {
                 args.iter().for_each(|arg| self.check_generic_arg(arg));
                 constraints.iter().for_each(|bind| self.check_assoc_item_constraint(bind));
@@ -355,7 +354,7 @@ impl<'a> Validator<'a> {
     }
 
     fn check_assoc_item_constraint(&mut self, bind: &'a AssocItemConstraint) {
-        self.check_generic_args(&bind.args);
+        self.check_opt_generic_args(&bind.args);
         match &bind.binding {
             AssocItemConstraintKind::Equality(term) => self.check_term(term),
             AssocItemConstraintKind::Constraint(bounds) => {
diff --git a/tests/rustdoc-json/generic-args.rs b/tests/rustdoc-json/generic-args.rs
index e87c1e62304..0f588820da7 100644
--- a/tests/rustdoc-json/generic-args.rs
+++ b/tests/rustdoc-json/generic-args.rs
@@ -10,11 +10,11 @@ impl MyTrait for MyStruct {
     fn my_fn(&self) {}
 }
 
-//@ is "$.index[?(@.name=='my_fn1')].inner.function.sig.inputs[0][1].qualified_path.args" {\"angle_bracketed\":{\"args\":[],\"constraints\":[]}}
+//@ is "$.index[?(@.name=='my_fn1')].inner.function.sig.inputs[0][1].qualified_path.args" null
 //@ is "$.index[?(@.name=='my_fn1')].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.args" null
 pub fn my_fn1(_: <MyStruct as MyTrait>::MyType) {}
 
-//@ is "$.index[?(@.name=='my_fn2')].inner.function.sig.inputs[0][1].dyn_trait.traits[0].trait.args.angle_bracketed.constraints[0].args" {\"angle_bracketed\":{\"args\":[],\"constraints\":[]}}
+//@ is "$.index[?(@.name=='my_fn2')].inner.function.sig.inputs[0][1].dyn_trait.traits[0].trait.args.angle_bracketed.constraints[0].args" null
 pub fn my_fn2(_: IntoIterator<Item = MyStruct, IntoIter = impl Clone>) {}
 
 fn main() {}