Unsafe binder support in rustdoc
This commit is contained in:
parent
7f75bfa1ad
commit
aac741a465
7 changed files with 68 additions and 12 deletions
|
@ -1844,8 +1844,8 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
|||
DynTrait(bounds, lifetime)
|
||||
}
|
||||
TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
|
||||
TyKind::UnsafeBinder(..) => {
|
||||
unimplemented!("unsafe binders are not supported yet")
|
||||
TyKind::UnsafeBinder(unsafe_binder_ty) => {
|
||||
UnsafeBinder(Box::new(clean_unsafe_binder_ty(unsafe_binder_ty, cx)))
|
||||
}
|
||||
// Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
|
||||
TyKind::Infer
|
||||
|
@ -2075,6 +2075,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
|||
abi: sig.abi(),
|
||||
}))
|
||||
}
|
||||
ty::UnsafeBinder(inner) => {
|
||||
let generic_params = clean_bound_vars(inner.bound_vars());
|
||||
let ty = clean_middle_ty(inner.into(), cx, None, None);
|
||||
UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, ty }))
|
||||
}
|
||||
ty::Adt(def, args) => {
|
||||
let did = def.did();
|
||||
let kind = match def.adt_kind() {
|
||||
|
@ -2253,7 +2258,6 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binders)"),
|
||||
ty::Closure(..) => panic!("Closure"),
|
||||
ty::CoroutineClosure(..) => panic!("CoroutineClosure"),
|
||||
ty::Coroutine(..) => panic!("Coroutine"),
|
||||
|
@ -2564,6 +2568,21 @@ fn clean_bare_fn_ty<'tcx>(
|
|||
BareFunctionDecl { safety: bare_fn.safety, abi: bare_fn.abi, decl, generic_params }
|
||||
}
|
||||
|
||||
fn clean_unsafe_binder_ty<'tcx>(
|
||||
unsafe_binder_ty: &hir::UnsafeBinderTy<'tcx>,
|
||||
cx: &mut DocContext<'tcx>,
|
||||
) -> UnsafeBinderTy {
|
||||
// NOTE: generics must be cleaned before args
|
||||
let generic_params = unsafe_binder_ty
|
||||
.generic_params
|
||||
.iter()
|
||||
.filter(|p| !is_elided_lifetime(p))
|
||||
.map(|x| clean_generic_param(cx, None, x))
|
||||
.collect();
|
||||
let ty = clean_ty(unsafe_binder_ty.inner_ty, cx);
|
||||
UnsafeBinderTy { generic_params, ty }
|
||||
}
|
||||
|
||||
pub(crate) fn reexport_chain(
|
||||
tcx: TyCtxt<'_>,
|
||||
import_def_id: LocalDefId,
|
||||
|
|
|
@ -32,7 +32,7 @@ use {rustc_ast as ast, rustc_hir as hir};
|
|||
pub(crate) use self::ItemKind::*;
|
||||
pub(crate) use self::Type::{
|
||||
Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
|
||||
RawPointer, SelfTy, Slice, Tuple,
|
||||
RawPointer, SelfTy, Slice, Tuple, UnsafeBinder,
|
||||
};
|
||||
use crate::clean::cfg::Cfg;
|
||||
use crate::clean::clean_middle_path;
|
||||
|
@ -1511,6 +1511,8 @@ pub(crate) enum Type {
|
|||
|
||||
/// An `impl Trait`: `impl TraitA + TraitB + ...`
|
||||
ImplTrait(Vec<GenericBound>),
|
||||
|
||||
UnsafeBinder(Box<UnsafeBinderTy>),
|
||||
}
|
||||
|
||||
impl Type {
|
||||
|
@ -1703,7 +1705,7 @@ impl Type {
|
|||
Type::Pat(..) => PrimitiveType::Pat,
|
||||
RawPointer(..) => PrimitiveType::RawPointer,
|
||||
QPath(box QPathData { ref self_type, .. }) => return self_type.def_id(cache),
|
||||
Generic(_) | SelfTy | Infer | ImplTrait(_) => return None,
|
||||
Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
|
||||
};
|
||||
Primitive(t).def_id(cache)
|
||||
}
|
||||
|
@ -2343,6 +2345,12 @@ pub(crate) struct BareFunctionDecl {
|
|||
pub(crate) abi: ExternAbi,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub(crate) struct UnsafeBinderTy {
|
||||
pub(crate) generic_params: Vec<GenericParamDef>,
|
||||
pub(crate) ty: Type,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct Static {
|
||||
pub(crate) type_: Box<Type>,
|
||||
|
|
|
@ -282,7 +282,8 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
|
|||
|
||||
match pred {
|
||||
clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
|
||||
print_higher_ranked_params_with_space(bound_params, cx).fmt(f)?;
|
||||
print_higher_ranked_params_with_space(bound_params, cx, "for")
|
||||
.fmt(f)?;
|
||||
ty.print(cx).fmt(f)?;
|
||||
f.write_str(":")?;
|
||||
if !bounds.is_empty() {
|
||||
|
@ -386,7 +387,7 @@ impl clean::ConstantKind {
|
|||
impl clean::PolyTrait {
|
||||
fn print<'a, 'tcx: 'a>(&'a self, cx: &'a Context<'tcx>) -> impl Display + 'a + Captures<'tcx> {
|
||||
display_fn(move |f| {
|
||||
print_higher_ranked_params_with_space(&self.generic_params, cx).fmt(f)?;
|
||||
print_higher_ranked_params_with_space(&self.generic_params, cx, "for").fmt(f)?;
|
||||
self.trait_.print(cx).fmt(f)
|
||||
})
|
||||
}
|
||||
|
@ -968,10 +969,12 @@ fn tybounds<'a, 'tcx: 'a>(
|
|||
fn print_higher_ranked_params_with_space<'a, 'tcx: 'a>(
|
||||
params: &'a [clean::GenericParamDef],
|
||||
cx: &'a Context<'tcx>,
|
||||
keyword: &'static str,
|
||||
) -> impl Display + 'a + Captures<'tcx> {
|
||||
display_fn(move |f| {
|
||||
if !params.is_empty() {
|
||||
f.write_str(if f.alternate() { "for<" } else { "for<" })?;
|
||||
f.write_str(keyword)?;
|
||||
f.write_str(if f.alternate() { "<" } else { "<" })?;
|
||||
comma_sep(params.iter().map(|lt| lt.print(cx)), true).fmt(f)?;
|
||||
f.write_str(if f.alternate() { "> " } else { "> " })?;
|
||||
}
|
||||
|
@ -1027,7 +1030,7 @@ fn fmt_type(
|
|||
primitive_link(f, prim, format_args!("{}", prim.as_sym().as_str()), cx)
|
||||
}
|
||||
clean::BareFunction(ref decl) => {
|
||||
print_higher_ranked_params_with_space(&decl.generic_params, cx).fmt(f)?;
|
||||
print_higher_ranked_params_with_space(&decl.generic_params, cx, "for").fmt(f)?;
|
||||
decl.safety.print_with_space().fmt(f)?;
|
||||
print_abi_with_space(decl.abi).fmt(f)?;
|
||||
if f.alternate() {
|
||||
|
@ -1037,6 +1040,10 @@ fn fmt_type(
|
|||
}
|
||||
decl.decl.print(cx).fmt(f)
|
||||
}
|
||||
clean::UnsafeBinder(ref binder) => {
|
||||
print_higher_ranked_params_with_space(&binder.generic_params, cx, "unsafe").fmt(f)?;
|
||||
binder.ty.print(cx).fmt(f)
|
||||
}
|
||||
clean::Tuple(ref typs) => match &typs[..] {
|
||||
&[] => primitive_link(f, PrimitiveType::Unit, format_args!("()"), cx),
|
||||
[one] => {
|
||||
|
@ -1354,7 +1361,7 @@ impl clean::Impl {
|
|||
// Hardcoded anchor library/core/src/primitive_docs.rs
|
||||
// Link should match `# Trait implementations`
|
||||
|
||||
print_higher_ranked_params_with_space(&bare_fn.generic_params, cx).fmt(f)?;
|
||||
print_higher_ranked_params_with_space(&bare_fn.generic_params, cx, "for").fmt(f)?;
|
||||
bare_fn.safety.print_with_space().fmt(f)?;
|
||||
print_abi_with_space(bare_fn.abi).fmt(f)?;
|
||||
let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" };
|
||||
|
|
|
@ -900,7 +900,8 @@ fn get_index_type_id(
|
|||
| clean::Generic(_)
|
||||
| clean::SelfTy
|
||||
| clean::ImplTrait(_)
|
||||
| clean::Infer => None,
|
||||
| clean::Infer
|
||||
| clean::UnsafeBinder(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -573,7 +573,7 @@ impl FromClean<clean::Type> for Type {
|
|||
fn from_clean(ty: clean::Type, renderer: &JsonRenderer<'_>) -> Self {
|
||||
use clean::Type::{
|
||||
Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath,
|
||||
RawPointer, SelfTy, Slice, Tuple,
|
||||
RawPointer, SelfTy, Slice, Tuple, UnsafeBinder,
|
||||
};
|
||||
|
||||
match ty {
|
||||
|
@ -613,6 +613,8 @@ impl FromClean<clean::Type> for Type {
|
|||
self_type: Box::new(self_type.into_json(renderer)),
|
||||
trait_: trait_.map(|trait_| trait_.into_json(renderer)),
|
||||
},
|
||||
// FIXME(unsafe_binder): Implement rustdoc-json.
|
||||
UnsafeBinder(_) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
4
tests/rustdoc/auxiliary/unsafe-binder-dep.rs
Normal file
4
tests/rustdoc/auxiliary/unsafe-binder-dep.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
#![feature(unsafe_binders)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub fn woof() -> unsafe<'a> &'a str { todo!() }
|
15
tests/rustdoc/unsafe-binder.rs
Normal file
15
tests/rustdoc/unsafe-binder.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
//@ aux-build:unsafe-binder-dep.rs
|
||||
|
||||
#![feature(unsafe_binders)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
extern crate unsafe_binder_dep;
|
||||
|
||||
//@ has 'unsafe_binder/fn.woof.html' //pre "fn woof() -> unsafe<'a> &'a str"
|
||||
pub use unsafe_binder_dep::woof;
|
||||
|
||||
//@ has 'unsafe_binder/fn.meow.html' //pre "fn meow() -> unsafe<'a> &'a str"
|
||||
pub fn meow() -> unsafe<'a> &'a str { todo!() }
|
||||
|
||||
//@ has 'unsafe_binder/fn.meow_squared.html' //pre "fn meow_squared() -> unsafe<'b, 'a> &'a &'b str"
|
||||
pub fn meow_squared() -> unsafe<'b, 'a> &'a &'b str { todo!() }
|
Loading…
Add table
Add a link
Reference in a new issue