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

As suggested [on zulip][1], 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
This commit is contained in:
Alona Enraght-Moony 2024-07-03 19:57:15 +00:00
parent c872a1418a
commit 7e8aac553e
6 changed files with 47 additions and 8 deletions

View File

@ -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); pub(crate) struct Lifetime(pub Symbol);
impl Lifetime { impl Lifetime {

View File

@ -10,6 +10,7 @@
use rustc_attr::DeprecatedSince; use rustc_attr::DeprecatedSince;
use rustc_hir::{def::CtorKind, def::DefKind, def_id::DefId}; use rustc_hir::{def::CtorKind, def::DefKind, def_id::DefId};
use rustc_metadata::rendered_const; use rustc_metadata::rendered_const;
use rustc_middle::bug;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::{Pos, Symbol}; use rustc_span::{Pos, Symbol};
@ -512,9 +513,15 @@ fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self {
}) })
.collect(), .collect(),
}, },
RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate { RegionPredicate { lifetime, bounds } => WherePredicate::LifetimePredicate {
lifetime: convert_lifetime(lifetime), 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 } => { EqPredicate { lhs, rhs } => {
WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) } WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) }

View File

@ -8,7 +8,7 @@
use std::path::PathBuf; use std::path::PathBuf;
/// rustdoc format-version. /// 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 /// 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 /// 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>, generic_params: Vec<GenericParamDef>,
}, },
RegionPredicate { LifetimePredicate {
lifetime: String, lifetime: String,
bounds: Vec<GenericBound>, outlives: Vec<String>,
}, },
EqPredicate { EqPredicate {
lhs: Type, lhs: Type,

View File

@ -374,8 +374,8 @@ fn check_where_predicate(&mut self, w: &'a WherePredicate) {
bounds.iter().for_each(|b| self.check_generic_bound(b)); bounds.iter().for_each(|b| self.check_generic_bound(b));
generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd)); generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
} }
WherePredicate::RegionPredicate { lifetime: _, bounds } => { WherePredicate::LifetimePredicate { lifetime: _, outlives: _ } => {
bounds.iter().for_each(|b| self.check_generic_bound(b)); // nop, all strings.
} }
WherePredicate::EqPredicate { lhs, rhs } => { WherePredicate::EqPredicate { lhs, rhs } => {
self.check_type(lhs); self.check_type(lhs);

View File

@ -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>() {}

View File

@ -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,
{
}