Rollup merge of #108335 - compiler-errors:non_lifetime_binders-rustdoc, r=GuillaumeGomez

rustdoc + rustdoc-json support for `feature(non_lifetime_binders)`

Makes `for<T> T: Trait` and `for<const N: usize> ..` in where clause operate correctly.

Fixes #108158
This commit is contained in:
Dylan DPC 2023-03-29 14:07:26 +05:30 committed by GitHub
commit 777df024b1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 73 additions and 29 deletions

View file

@ -31,7 +31,6 @@
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{self, ExpnKind};
use std::assert_matches::assert_matches;
use std::borrow::Cow;
use std::collections::hash_map::Entry;
use std::collections::BTreeMap;
@ -270,15 +269,7 @@ fn clean_where_predicate<'tcx>(
let bound_params = wbp
.bound_generic_params
.iter()
.map(|param| {
// Higher-ranked params must be lifetimes.
// Higher-ranked lifetimes can't have bounds.
assert_matches!(
param,
hir::GenericParam { kind: hir::GenericParamKind::Lifetime { .. }, .. }
);
Lifetime(param.name.ident().name)
})
.map(|param| clean_generic_param(cx, None, param))
.collect();
WherePredicate::BoundPredicate {
ty: clean_ty(wbp.bounded_ty, cx),
@ -410,7 +401,7 @@ fn clean_projection_predicate<'tcx>(
.collect_referenced_late_bound_regions(&pred)
.into_iter()
.filter_map(|br| match br {
ty::BrNamed(_, name) if br.is_named() => Some(Lifetime(name)),
ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)),
_ => None,
})
.collect();
@ -508,7 +499,6 @@ fn clean_generic_param_def<'tcx>(
ty::GenericParamDefKind::Const { has_default } => (
def.name,
GenericParamDefKind::Const {
did: def.def_id,
ty: Box::new(clean_middle_ty(
ty::Binder::dummy(
cx.tcx
@ -578,7 +568,6 @@ fn clean_generic_param<'tcx>(
hir::GenericParamKind::Const { ty, default } => (
param.name.ident().name,
GenericParamDefKind::Const {
did: param.def_id.to_def_id(),
ty: Box::new(clean_ty(ty, cx)),
default: default
.map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())),
@ -831,7 +820,7 @@ fn clean_ty_generics<'tcx>(
p.get_bound_params()
.into_iter()
.flatten()
.map(|param| GenericParamDef::lifetime(param.0))
.cloned()
.collect(),
));
}

View file

@ -49,11 +49,7 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> ThinVec<WP
equalities.retain(|(lhs, rhs, bound_params)| {
let Some((ty, trait_did, name)) = lhs.projection() else { return true; };
let Some((bounds, _)) = tybounds.get_mut(ty) else { return true };
let bound_params = bound_params
.into_iter()
.map(|param| clean::GenericParamDef::lifetime(param.0))
.collect();
merge_bounds(cx, bounds, bound_params, trait_did, name, rhs)
merge_bounds(cx, bounds, bound_params.clone(), trait_did, name, rhs)
});
// And finally, let's reassemble everything

View file

@ -1236,9 +1236,9 @@ pub(crate) fn elided() -> Lifetime {
#[derive(Clone, Debug)]
pub(crate) enum WherePredicate {
BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> },
BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
EqPredicate { lhs: Box<Type>, rhs: Box<Term>, bound_params: Vec<Lifetime> },
EqPredicate { lhs: Box<Type>, rhs: Box<Term>, bound_params: Vec<GenericParamDef> },
}
impl WherePredicate {
@ -1250,7 +1250,7 @@ pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
}
}
pub(crate) fn get_bound_params(&self) -> Option<&[Lifetime]> {
pub(crate) fn get_bound_params(&self) -> Option<&[GenericParamDef]> {
match self {
Self::BoundPredicate { bound_params, .. } | Self::EqPredicate { bound_params, .. } => {
Some(bound_params)
@ -1264,7 +1264,7 @@ pub(crate) fn get_bound_params(&self) -> Option<&[Lifetime]> {
pub(crate) enum GenericParamDefKind {
Lifetime { outlives: Vec<Lifetime> },
Type { did: DefId, bounds: Vec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
Const { did: DefId, ty: Box<Type>, default: Option<Box<String>> },
Const { ty: Box<Type>, default: Option<Box<String>> },
}
impl GenericParamDefKind {

View file

@ -307,13 +307,13 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
write!(
f,
"for<{:#}> {ty_cx:#}: {generic_bounds:#}",
comma_sep(bound_params.iter().map(|lt| lt.print()), true)
comma_sep(bound_params.iter().map(|lt| lt.print(cx)), true)
)
} else {
write!(
f,
"for&lt;{}&gt; {ty_cx}: {generic_bounds}",
comma_sep(bound_params.iter().map(|lt| lt.print()), true)
comma_sep(bound_params.iter().map(|lt| lt.print(cx)), true)
)
}
}

View file

@ -456,7 +456,7 @@ fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self {
default: default.map(|x| (*x).into_tcx(tcx)),
synthetic,
},
Const { did: _, ty, default } => GenericParamDefKind::Const {
Const { ty, default } => GenericParamDefKind::Const {
type_: (*ty).into_tcx(tcx),
default: default.map(|x| *x),
},
@ -473,9 +473,35 @@ fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self {
bounds: bounds.into_tcx(tcx),
generic_params: bound_params
.into_iter()
.map(|x| GenericParamDef {
name: x.0.to_string(),
kind: GenericParamDefKind::Lifetime { outlives: vec![] },
.map(|x| {
let name = x.name.to_string();
let kind = match x.kind {
clean::GenericParamDefKind::Lifetime { outlives } => {
GenericParamDefKind::Lifetime {
outlives: outlives.iter().map(|lt| lt.0.to_string()).collect(),
}
}
clean::GenericParamDefKind::Type {
did: _,
bounds,
default,
synthetic,
} => GenericParamDefKind::Type {
bounds: bounds
.into_iter()
.map(|bound| bound.into_tcx(tcx))
.collect(),
default: default.map(|ty| (*ty).into_tcx(tcx)),
synthetic,
},
clean::GenericParamDefKind::Const { ty, default } => {
GenericParamDefKind::Const {
type_: (*ty).into_tcx(tcx),
default: default.map(|d| *d),
}
}
};
GenericParamDef { name, kind }
})
.collect(),
},

View file

@ -0,0 +1,24 @@
// ignore-tidy-linelength
#![feature(non_lifetime_binders)]
#![allow(incomplete_features)]
#![no_core]
#![feature(lang_items, no_core)]
#[lang = "sized"]
pub trait Sized {}
pub trait Trait {}
#[lang = "phantom_data"]
struct PhantomData<T_>;
pub struct Wrapper<T_>(PhantomData<T_>);
// @count "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[*]" 2
// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\"
// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[1].name" \"T\"
// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "synthetic": false } }'
pub fn foo() where for<'a, T> &'a Wrapper<T>: Trait {}

View file

@ -0,0 +1,9 @@
#![feature(non_lifetime_binders)]
#![allow(incomplete_features)]
pub trait Trait {}
pub struct Wrapper<T: ?Sized>(Box<T>);
// @has non_lifetime_binders/fn.foo.html '//pre' "fn foo()where for<'a, T> &'a Wrapper<T>: Trait"
pub fn foo() where for<'a, T> &'a Wrapper<T>: Trait {}