mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
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:
commit
777df024b1
@ -31,7 +31,6 @@ use rustc_span::hygiene::{AstPass, MacroKind};
|
|||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{self, ExpnKind};
|
use rustc_span::{self, ExpnKind};
|
||||||
|
|
||||||
use std::assert_matches::assert_matches;
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
@ -270,15 +269,7 @@ fn clean_where_predicate<'tcx>(
|
|||||||
let bound_params = wbp
|
let bound_params = wbp
|
||||||
.bound_generic_params
|
.bound_generic_params
|
||||||
.iter()
|
.iter()
|
||||||
.map(|param| {
|
.map(|param| clean_generic_param(cx, None, 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)
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
WherePredicate::BoundPredicate {
|
WherePredicate::BoundPredicate {
|
||||||
ty: clean_ty(wbp.bounded_ty, cx),
|
ty: clean_ty(wbp.bounded_ty, cx),
|
||||||
@ -410,7 +401,7 @@ fn clean_projection_predicate<'tcx>(
|
|||||||
.collect_referenced_late_bound_regions(&pred)
|
.collect_referenced_late_bound_regions(&pred)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|br| match br {
|
.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,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@ -508,7 +499,6 @@ fn clean_generic_param_def<'tcx>(
|
|||||||
ty::GenericParamDefKind::Const { has_default } => (
|
ty::GenericParamDefKind::Const { has_default } => (
|
||||||
def.name,
|
def.name,
|
||||||
GenericParamDefKind::Const {
|
GenericParamDefKind::Const {
|
||||||
did: def.def_id,
|
|
||||||
ty: Box::new(clean_middle_ty(
|
ty: Box::new(clean_middle_ty(
|
||||||
ty::Binder::dummy(
|
ty::Binder::dummy(
|
||||||
cx.tcx
|
cx.tcx
|
||||||
@ -578,7 +568,6 @@ fn clean_generic_param<'tcx>(
|
|||||||
hir::GenericParamKind::Const { ty, default } => (
|
hir::GenericParamKind::Const { ty, default } => (
|
||||||
param.name.ident().name,
|
param.name.ident().name,
|
||||||
GenericParamDefKind::Const {
|
GenericParamDefKind::Const {
|
||||||
did: param.def_id.to_def_id(),
|
|
||||||
ty: Box::new(clean_ty(ty, cx)),
|
ty: Box::new(clean_ty(ty, cx)),
|
||||||
default: default
|
default: default
|
||||||
.map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())),
|
.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()
|
p.get_bound_params()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|param| GenericParamDef::lifetime(param.0))
|
.cloned()
|
||||||
.collect(),
|
.collect(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -49,11 +49,7 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> ThinVec<WP
|
|||||||
equalities.retain(|(lhs, rhs, bound_params)| {
|
equalities.retain(|(lhs, rhs, bound_params)| {
|
||||||
let Some((ty, trait_did, name)) = lhs.projection() else { return true; };
|
let Some((ty, trait_did, name)) = lhs.projection() else { return true; };
|
||||||
let Some((bounds, _)) = tybounds.get_mut(ty) else { return true };
|
let Some((bounds, _)) = tybounds.get_mut(ty) else { return true };
|
||||||
let bound_params = bound_params
|
merge_bounds(cx, bounds, bound_params.clone(), trait_did, name, rhs)
|
||||||
.into_iter()
|
|
||||||
.map(|param| clean::GenericParamDef::lifetime(param.0))
|
|
||||||
.collect();
|
|
||||||
merge_bounds(cx, bounds, bound_params, trait_did, name, rhs)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// And finally, let's reassemble everything
|
// And finally, let's reassemble everything
|
||||||
|
@ -1236,9 +1236,9 @@ impl Lifetime {
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) enum WherePredicate {
|
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> },
|
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 {
|
impl WherePredicate {
|
||||||
@ -1250,7 +1250,7 @@ impl WherePredicate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_bound_params(&self) -> Option<&[Lifetime]> {
|
pub(crate) fn get_bound_params(&self) -> Option<&[GenericParamDef]> {
|
||||||
match self {
|
match self {
|
||||||
Self::BoundPredicate { bound_params, .. } | Self::EqPredicate { bound_params, .. } => {
|
Self::BoundPredicate { bound_params, .. } | Self::EqPredicate { bound_params, .. } => {
|
||||||
Some(bound_params)
|
Some(bound_params)
|
||||||
@ -1264,7 +1264,7 @@ impl WherePredicate {
|
|||||||
pub(crate) enum GenericParamDefKind {
|
pub(crate) enum GenericParamDefKind {
|
||||||
Lifetime { outlives: Vec<Lifetime> },
|
Lifetime { outlives: Vec<Lifetime> },
|
||||||
Type { did: DefId, bounds: Vec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
|
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 {
|
impl GenericParamDefKind {
|
||||||
|
@ -307,13 +307,13 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
|
|||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"for<{:#}> {ty_cx:#}: {generic_bounds:#}",
|
"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 {
|
} else {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"for<{}> {ty_cx}: {generic_bounds}",
|
"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)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -456,7 +456,7 @@ impl FromWithTcx<clean::GenericParamDefKind> for GenericParamDefKind {
|
|||||||
default: default.map(|x| (*x).into_tcx(tcx)),
|
default: default.map(|x| (*x).into_tcx(tcx)),
|
||||||
synthetic,
|
synthetic,
|
||||||
},
|
},
|
||||||
Const { did: _, ty, default } => GenericParamDefKind::Const {
|
Const { ty, default } => GenericParamDefKind::Const {
|
||||||
type_: (*ty).into_tcx(tcx),
|
type_: (*ty).into_tcx(tcx),
|
||||||
default: default.map(|x| *x),
|
default: default.map(|x| *x),
|
||||||
},
|
},
|
||||||
@ -473,9 +473,35 @@ impl FromWithTcx<clean::WherePredicate> for WherePredicate {
|
|||||||
bounds: bounds.into_tcx(tcx),
|
bounds: bounds.into_tcx(tcx),
|
||||||
generic_params: bound_params
|
generic_params: bound_params
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| GenericParamDef {
|
.map(|x| {
|
||||||
name: x.0.to_string(),
|
let name = x.name.to_string();
|
||||||
kind: GenericParamDefKind::Lifetime { outlives: vec![] },
|
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(),
|
.collect(),
|
||||||
},
|
},
|
||||||
|
24
tests/rustdoc-json/non_lifetime_binders.rs
Normal file
24
tests/rustdoc-json/non_lifetime_binders.rs
Normal 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 {}
|
9
tests/rustdoc/non_lifetime_binders.rs
Normal file
9
tests/rustdoc/non_lifetime_binders.rs
Normal 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 {}
|
Loading…
Reference in New Issue
Block a user