1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use std::borrow::Cow;
use rustdoc_types::{GenericArgs, Type};
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct Receiver<'a>(&'a Type);
impl<'a> Receiver<'a> {
pub(super) fn new(ty: &'a Type) -> Self {
Self(ty)
}
#[inline]
pub(super) fn by_value(&self) -> bool {
!matches!(self.0, Type::BorrowedRef { .. })
}
#[inline]
pub(super) fn by_reference(&self) -> bool {
matches!(
self.0,
Type::BorrowedRef {
is_mutable: false,
..
}
)
}
#[inline]
pub(super) fn by_mut_reference(&self) -> bool {
matches!(
self.0,
Type::BorrowedRef {
is_mutable: true,
..
}
)
}
pub(super) fn kind(&self) -> Cow<'_, str> {
extract_kind_string(self.0)
}
}
fn extract_kind_string(ty: &Type) -> Cow<'_, str> {
match ty {
// For &self and &mut self, we need to extract the inner type
Type::BorrowedRef { type_, .. } => extract_kind_string(type_),
// Generic receiver components can be `Self` or any named type parameter.
Type::Generic(name) => Cow::Borrowed(name.as_str()),
// Handle ResolvedPath types like Box<Self>, Pin<&mut Self>, etc.
Type::ResolvedPath(path) => {
// Get just the type name without the path
let name = path.path.split("::").last().unwrap_or(&path.path);
if let Some(args) = &path.args {
match args.as_ref() {
GenericArgs::AngleBracketed { args, .. } => {
let args_str: Vec<Cow<'_, str>> = args
.iter()
.map(|arg| match arg {
rustdoc_types::GenericArg::Type(t) => {
// For Pin<&mut Self>, we need to preserve the &mut
match t {
Type::BorrowedRef {
is_mutable, type_, ..
} => {
let inner = extract_kind_string(type_);
if *is_mutable {
Cow::Owned(format!("&mut {inner}"))
} else {
Cow::Owned(format!("&{inner}"))
}
}
_ => extract_kind_string(t),
}
}
rustdoc_types::GenericArg::Lifetime(lt) => {
Cow::Borrowed(lt.as_str())
}
rustdoc_types::GenericArg::Const(c) => {
Cow::Borrowed(c.expr.as_str())
}
_ => unreachable!("should not encounter infer"),
})
.collect();
let args_joined = args_str
.iter()
.map(|cow| cow.as_ref())
.collect::<Vec<_>>()
.join(", ");
Cow::Owned(format!("{name}<{args_joined}>"))
}
_ => Cow::Borrowed(name),
}
} else {
Cow::Borrowed(name)
}
}
// should not encounter other types
_ => unreachable!("unsupported type: {:?}", ty),
}
}