about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
author许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com>2025-03-16 09:40:04 +0800
committerGitHub <noreply@github.com>2025-03-16 09:40:04 +0800
commit8882dac3425e7ecbb2c1aeff7de48eaa830ae1de (patch)
tree80d7ad34e43169f8e8caabc3009603f41f19d6d7 /src
parentf16ce2ae6ce84428a7df8ed6b9745815ed6c1ca4 (diff)
parente3ac1fa81abd321abe193f491ed06c7d388f68fe (diff)
downloadrust-8882dac3425e7ecbb2c1aeff7de48eaa830ae1de.tar.gz
rust-8882dac3425e7ecbb2c1aeff7de48eaa830ae1de.zip
Rollup merge of #137956 - compiler-errors:rtn-rustdoc, r=fmease
Add RTN support to rustdoc

This adds support to rustdoc and rustdoc-json for rendering `(..)` RTN (return type notation) style generics.

---

Cleaning `rustc_middle::ty::Ty` is not correct still, though, and ends up rendering a function like:

```rust
pub fn foreign<T: Foreign<bar(..): Send>>()
where
    <T as Foreign>::bar(..): 'static,
    T::bar(..): Sync,
```

Into this:

```rust
pub fn foreign<T>()
where
    T: Foreign,
    impl Future<Output = ()>: Send + 'static + Sync,
```

This is because `clean_middle_ty` doesn't actually have sufficient context about whether the RPITIT is in its "defining scope" or not, so we don't know if the type was originally written like `-> impl Trait` or with RTN like `T::method(..)`.

Partially addresses #123996 (i.e., HIR side, not middle::ty one)
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/clean/mod.rs69
-rw-r--r--src/librustdoc/clean/simplify.rs4
-rw-r--r--src/librustdoc/clean/types.rs8
-rw-r--r--src/librustdoc/html/format.rs3
-rw-r--r--src/librustdoc/json/conversions.rs1
-rw-r--r--src/rustdoc-json-types/lib.rs4
-rw-r--r--src/tools/jsondoclint/src/validator.rs1
7 files changed, 59 insertions, 31 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 0f476c8c9ff..929402d4170 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1488,6 +1488,9 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
                                 // The only time this happens is if we're inside the rustdoc for Fn(),
                                 // which only has one associated type, which is not a GAT, so whatever.
                             }
+                            GenericArgs::ReturnTypeNotation => {
+                                // Never move these.
+                            }
                         }
                         bounds.extend(mem::take(pred_bounds));
                         false
@@ -2553,36 +2556,42 @@ fn clean_generic_args<'tcx>(
     generic_args: &hir::GenericArgs<'tcx>,
     cx: &mut DocContext<'tcx>,
 ) -> GenericArgs {
-    // FIXME(return_type_notation): Fix RTN parens rendering
-    if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() {
-        let inputs = inputs.iter().map(|x| clean_ty(x, cx)).collect();
-        let output = match output.kind {
-            hir::TyKind::Tup(&[]) => None,
-            _ => Some(Box::new(clean_ty(output, cx))),
-        };
-        GenericArgs::Parenthesized { inputs, output }
-    } else {
-        let args = generic_args
-            .args
-            .iter()
-            .map(|arg| match arg {
-                hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => {
-                    GenericArg::Lifetime(clean_lifetime(lt, cx))
-                }
-                hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
-                hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty.as_unambig_ty(), cx)),
-                hir::GenericArg::Const(ct) => {
-                    GenericArg::Const(Box::new(clean_const(ct.as_unambig_ct(), cx)))
-                }
-                hir::GenericArg::Infer(_inf) => GenericArg::Infer,
-            })
-            .collect();
-        let constraints = generic_args
-            .constraints
-            .iter()
-            .map(|c| clean_assoc_item_constraint(c, cx))
-            .collect::<ThinVec<_>>();
-        GenericArgs::AngleBracketed { args, constraints }
+    match generic_args.parenthesized {
+        hir::GenericArgsParentheses::No => {
+            let args = generic_args
+                .args
+                .iter()
+                .map(|arg| match arg {
+                    hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => {
+                        GenericArg::Lifetime(clean_lifetime(lt, cx))
+                    }
+                    hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
+                    hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty.as_unambig_ty(), cx)),
+                    hir::GenericArg::Const(ct) => {
+                        GenericArg::Const(Box::new(clean_const(ct.as_unambig_ct(), cx)))
+                    }
+                    hir::GenericArg::Infer(_inf) => GenericArg::Infer,
+                })
+                .collect();
+            let constraints = generic_args
+                .constraints
+                .iter()
+                .map(|c| clean_assoc_item_constraint(c, cx))
+                .collect::<ThinVec<_>>();
+            GenericArgs::AngleBracketed { args, constraints }
+        }
+        hir::GenericArgsParentheses::ParenSugar => {
+            let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() else {
+                bug!();
+            };
+            let inputs = inputs.iter().map(|x| clean_ty(x, cx)).collect();
+            let output = match output.kind {
+                hir::TyKind::Tup(&[]) => None,
+                _ => Some(Box::new(clean_ty(output, cx))),
+            };
+            GenericArgs::Parenthesized { inputs, output }
+        }
+        hir::GenericArgsParentheses::ReturnTypeNotation => GenericArgs::ReturnTypeNotation,
     }
 }
 
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index b8db82e540c..41943b94d1e 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -102,6 +102,10 @@ pub(crate) fn merge_bounds(
                     }
                 }
             },
+            PP::ReturnTypeNotation => {
+                // Cannot merge bounds with RTN.
+                return false;
+            }
         };
         true
     })
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 228d9108e4e..3f9023659db 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -2259,8 +2259,12 @@ impl GenericArg {
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub(crate) enum GenericArgs {
+    /// `<args, constraints = ..>`
     AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> },
+    /// `(inputs) -> output`
     Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> },
+    /// `(..)`
+    ReturnTypeNotation,
 }
 
 impl GenericArgs {
@@ -2270,6 +2274,7 @@ impl GenericArgs {
                 args.is_empty() && constraints.is_empty()
             }
             GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
+            GenericArgs::ReturnTypeNotation => false,
         }
     }
     pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
@@ -2294,6 +2299,7 @@ impl GenericArgs {
                     })
                     .into_iter(),
             ),
+            GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
         }
     }
 }
@@ -2305,8 +2311,10 @@ impl<'a> IntoIterator for &'a GenericArgs {
         match self {
             GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()),
             GenericArgs::Parenthesized { inputs, .. } => {
+                // FIXME: This isn't really right, since `Fn(A, B)` is `Fn<(A, B)>`
                 Box::new(inputs.iter().cloned().map(GenericArg::Type))
             }
+            GenericArgs::ReturnTypeNotation => Box::new([].into_iter()),
         }
     }
 }
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index e93b9eb272a..41e9a5a6651 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -332,6 +332,9 @@ impl clean::GenericArgs {
                         }
                     }
                 }
+                clean::GenericArgs::ReturnTypeNotation => {
+                    f.write_str("(..)")?;
+                }
             }
             Ok(())
         })
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 6369433a4b5..a5351b350dd 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -176,6 +176,7 @@ impl FromClean<clean::GenericArgs> for GenericArgs {
                 inputs: inputs.into_json(renderer),
                 output: output.map(|a| (*a).into_json(renderer)),
             },
+            ReturnTypeNotation => GenericArgs::ReturnTypeNotation,
         }
     }
 }
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 8ec7cffe066..44e82c7d8b1 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc
 /// This integer is incremented with every breaking change to the API,
 /// and is returned along with the JSON blob as [`Crate::format_version`].
 /// Consuming code should assert that this value matches the format version(s) that it supports.
-pub const FORMAT_VERSION: u32 = 41;
+pub const FORMAT_VERSION: u32 = 42;
 
 /// The root of the emitted JSON blob.
 ///
@@ -229,6 +229,8 @@ pub enum GenericArgs {
         /// The output type provided after the `->`, if present.
         output: Option<Type>,
     },
+    /// `T::method(..)`
+    ReturnTypeNotation,
 }
 
 /// One argument in a list of generic arguments to a path segment.
diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs
index 791b231c27a..8c9e4c8bb3a 100644
--- a/src/tools/jsondoclint/src/validator.rs
+++ b/src/tools/jsondoclint/src/validator.rs
@@ -326,6 +326,7 @@ impl<'a> Validator<'a> {
                     self.check_type(o);
                 }
             }
+            GenericArgs::ReturnTypeNotation => {}
         }
     }