Skip to content

Commit

Permalink
Unsafe binder support in rustdoc
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Dec 31, 2024
1 parent 7f75bfa commit aac741a
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 12 deletions.
25 changes: 22 additions & 3 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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"),
Expand Down Expand Up @@ -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,
Expand Down
12 changes: 10 additions & 2 deletions src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1511,6 +1511,8 @@ pub(crate) enum Type {

/// An `impl Trait`: `impl TraitA + TraitB + ...`
ImplTrait(Vec<GenericBound>),

UnsafeBinder(Box<UnsafeBinderTy>),
}

impl Type {
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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>,
Expand Down
17 changes: 12 additions & 5 deletions src/librustdoc/html/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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)
})
}
Expand Down Expand Up @@ -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&lt;" })?;
f.write_str(keyword)?;
f.write_str(if f.alternate() { "<" } else { "&lt;" })?;
comma_sep(params.iter().map(|lt| lt.print(cx)), true).fmt(f)?;
f.write_str(if f.alternate() { "> " } else { "&gt; " })?;
}
Expand Down Expand Up @@ -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() {
Expand All @@ -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] => {
Expand Down Expand Up @@ -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 { "" };
Expand Down
3 changes: 2 additions & 1 deletion src/librustdoc/html/render/search_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -900,7 +900,8 @@ fn get_index_type_id(
| clean::Generic(_)
| clean::SelfTy
| clean::ImplTrait(_)
| clean::Infer => None,
| clean::Infer
| clean::UnsafeBinder(_) => None,
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/librustdoc/json/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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!(),
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions tests/rustdoc/auxiliary/unsafe-binder-dep.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#![feature(unsafe_binders)]
#![allow(incomplete_features)]

pub fn woof() -> unsafe<'a> &'a str { todo!() }
15 changes: 15 additions & 0 deletions tests/rustdoc/unsafe-binder.rs
Original file line number Diff line number Diff line change
@@ -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!() }

0 comments on commit aac741a

Please sign in to comment.