Rollup merge of #127289 - aDotInTheVoid:rustdoc-json-lt, r=GuillaumeGomez

rustdoc-json: Better representation of lifetime bounds in where clauses.

As suggested [on zulip][1] (CC `@its-the-shrimp),` there's no need to use `GenericBound` here, as the only bound a lifetime can have is that it outlives other lifetimes.

While we're making breaking changes here, I also renamed it from using "region" to "lifetime", as this is more user-aligned. See [this comment][2] for details.

[1]: https://rust-lang.zulipchat.com/#narrow/stream/266220-t-rustdoc/topic/.60ItemEnum.3A.3AOpaqueTy.60/near/448871430
[2]: https://github.com/rust-lang/rust/issues/100961#issuecomment-2206565556

r? `@GuillaumeGomez`
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 3b1a883..fe01d17 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1286,7 +1286,7 @@ pub(crate) fn get_trait_path(&self) -> Option<Path> {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
 pub(crate) struct Lifetime(pub Symbol);
 
 impl Lifetime {
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index b965ab0..5111e36 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -10,6 +10,7 @@
 use rustc_attr::DeprecatedSince;
 use rustc_hir::{def::CtorKind, def::DefKind, def_id::DefId};
 use rustc_metadata::rendered_const;
+use rustc_middle::bug;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::{Pos, Symbol};
@@ -512,9 +513,15 @@ fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self {
                     })
                     .collect(),
             },
-            RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate {
+            RegionPredicate { lifetime, bounds } => WherePredicate::LifetimePredicate {
                 lifetime: convert_lifetime(lifetime),
-                bounds: bounds.into_tcx(tcx),
+                outlives: bounds
+                    .iter()
+                    .map(|bound| match bound {
+                        clean::GenericBound::Outlives(lt) => convert_lifetime(*lt),
+                        _ => bug!("found non-outlives-bound on lifetime predicate"),
+                    })
+                    .collect(),
             },
             EqPredicate { lhs, rhs } => {
                 WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) }
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 6803049..89115d4 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -8,7 +8,7 @@
 use std::path::PathBuf;
 
 /// rustdoc format-version.
-pub const FORMAT_VERSION: u32 = 30;
+pub const FORMAT_VERSION: u32 = 31;
 
 /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
 /// about the language items in the local crate, as well as info about external items to allow
@@ -511,9 +511,9 @@ pub enum WherePredicate {
         /// ```
         generic_params: Vec<GenericParamDef>,
     },
-    RegionPredicate {
+    LifetimePredicate {
         lifetime: String,
-        bounds: Vec<GenericBound>,
+        outlives: Vec<String>,
     },
     EqPredicate {
         lhs: Type,
diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs
index 1713a4d..cd011dc 100644
--- a/src/tools/jsondoclint/src/validator.rs
+++ b/src/tools/jsondoclint/src/validator.rs
@@ -374,8 +374,8 @@ fn check_where_predicate(&mut self, w: &'a WherePredicate) {
                 bounds.iter().for_each(|b| self.check_generic_bound(b));
                 generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
             }
-            WherePredicate::RegionPredicate { lifetime: _, bounds } => {
-                bounds.iter().for_each(|b| self.check_generic_bound(b));
+            WherePredicate::LifetimePredicate { lifetime: _, outlives: _ } => {
+                // nop, all strings.
             }
             WherePredicate::EqPredicate { lhs, rhs } => {
                 self.check_type(lhs);
diff --git a/tests/rustdoc-json/lifetime/outlives_in_param.rs b/tests/rustdoc-json/lifetime/outlives_in_param.rs
new file mode 100644
index 0000000..f6db93c
--- /dev/null
+++ b/tests/rustdoc-json/lifetime/outlives_in_param.rs
@@ -0,0 +1,8 @@
+// ignore-tidy-linelength
+
+// @count '$.index[*][?(@.name=="outlives")].inner.function.generics.params[*]' 2
+// @is    '$.index[*][?(@.name=="outlives")].inner.function.generics.params[0].name' \"\'a\"
+// @is    '$.index[*][?(@.name=="outlives")].inner.function.generics.params[0].kind.lifetime.outlives' []
+// @is    '$.index[*][?(@.name=="outlives")].inner.function.generics.params[1].name' '"T"'
+// @is    '$.index[*][?(@.name=="outlives")].inner.function.generics.params[1].kind.type.bounds' '[{"outlives": "'\''a"}]'
+pub fn outlives<'a, T: 'a>() {}
diff --git a/tests/rustdoc-json/lifetime/outlives_in_where.rs b/tests/rustdoc-json/lifetime/outlives_in_where.rs
new file mode 100644
index 0000000..ca3e1a1
--- /dev/null
+++ b/tests/rustdoc-json/lifetime/outlives_in_where.rs
@@ -0,0 +1,24 @@
+// ignore-tidy-linelength
+
+// @is '$.index[*][?(@.name=="on_lifetimes")].inner.function.generics.where_predicates' '[{"lifetime_predicate": {"lifetime": "'\''all", "outlives": ["'\''a", "'\''b", "'\''c"]}}]'
+pub fn on_lifetimes<'a, 'b, 'c, 'all>()
+where
+    'all: 'a + 'b + 'c,
+{
+}
+
+// @count '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[*]' 2
+// @is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[0].name' \"\'a\"
+// @is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[0].kind.lifetime.outlives' []
+// @is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[1].name' '"T"'
+// @is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[1].kind.type.bounds' []
+// @is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[1].kind.type.bounds' []
+// @count '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[*]' 1
+// @is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.type.generic' '"T"'
+// @count '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.bounds[*]' 1
+// @is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.bounds[0].outlives' \"\'a\"
+pub fn on_trait<'a, T>()
+where
+    T: 'a,
+{
+}