Skip to content

Commit af1dfe5

Browse files
committed
feat: Support templated lambdas
1 parent 5a7c068 commit af1dfe5

File tree

2 files changed

+97
-8
lines changed

2 files changed

+97
-8
lines changed

src/ast.rs

+85-8
Original file line numberDiff line numberDiff line change
@@ -4918,6 +4918,63 @@ impl<'a> Hash for &'a TemplateParam {
49184918
}
49194919
}
49204920

4921+
/// The `<template-param-decl>` production.
4922+
///
4923+
/// ```text
4924+
/// <template-param-decl> ::= Ty # type parameter
4925+
/// ::= Tn <type> # non-type parameter
4926+
/// ::= Tt <template-param-decl>* E # template parameter
4927+
/// ::= Tp <template-param-decl> # parameter pack
4928+
/// ```
4929+
#[derive(Clone, Debug, PartialEq, Eq)]
4930+
pub enum TemplateParamDecl {
4931+
/// Type Parameter (numbered)
4932+
Type(u8),
4933+
}
4934+
4935+
impl Parse for TemplateParamDecl {
4936+
fn parse<'a, 'b>(
4937+
ctx: &'a ParseContext,
4938+
_subs: &'a mut SubstitutionTable,
4939+
input: IndexStr<'b>,
4940+
) -> Result<(TemplateParamDecl, IndexStr<'b>)> {
4941+
try_begin_parse!("TemplateParamDecl", ctx, input);
4942+
4943+
let tail = consume(b"T", input)?;
4944+
4945+
if let Ok(tail) = consume(b"y", tail) {
4946+
// TODO: implement a counter
4947+
return Ok((TemplateParamDecl::Type(0), tail));
4948+
}
4949+
4950+
// TODO: implement other types as well
4951+
Err(error::Error::UnexpectedText)
4952+
}
4953+
}
4954+
4955+
impl<'subs, W> Demangle<'subs, W> for TemplateParamDecl
4956+
where
4957+
W: 'subs + DemangleWrite,
4958+
{
4959+
fn demangle<'prev, 'ctx>(
4960+
&'subs self,
4961+
ctx: &'ctx mut DemangleContext<'subs, W>,
4962+
scope: Option<ArgScopeStack<'prev, 'subs>>,
4963+
) -> fmt::Result {
4964+
let ctx = try_begin_demangle!(self, ctx, scope);
4965+
4966+
match self {
4967+
TemplateParamDecl::Type(n) => {
4968+
write!(ctx, "typename $T")?;
4969+
if *n > 0 {
4970+
write!(ctx, "{}", n - 1)?;
4971+
}
4972+
}
4973+
}
4974+
Ok(())
4975+
}
4976+
}
4977+
49214978
/// The `<template-template-param>` production.
49224979
///
49234980
/// ```text
@@ -6912,7 +6969,7 @@ impl Parse for Discriminator {
69126969
/// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
69136970
/// ```
69146971
#[derive(Clone, Debug, PartialEq, Eq)]
6915-
pub struct ClosureTypeName(LambdaSig, Option<usize>);
6972+
pub struct ClosureTypeName(Vec<TemplateParamDecl>, LambdaSig, Option<usize>);
69166973

69176974
impl Parse for ClosureTypeName {
69186975
fn parse<'a, 'b>(
@@ -6922,7 +6979,13 @@ impl Parse for ClosureTypeName {
69226979
) -> Result<(ClosureTypeName, IndexStr<'b>)> {
69236980
try_begin_parse!("ClosureTypeName", ctx, input);
69246981

6925-
let tail = consume(b"Ul", input)?;
6982+
let mut tail = consume(b"Ul", input)?;
6983+
let mut params = vec![];
6984+
while let Ok(_) = consume(b"T", tail) {
6985+
let (decl, _tail) = TemplateParamDecl::parse(ctx, subs, tail)?;
6986+
params.push(decl);
6987+
tail = _tail;
6988+
}
69266989
let (sig, tail) = LambdaSig::parse(ctx, subs, tail)?;
69276990
let tail = consume(b"E", tail)?;
69286991
let (num, tail) = if let Ok((num, tail)) = parse_number(10, false, tail) {
@@ -6931,7 +6994,7 @@ impl Parse for ClosureTypeName {
69316994
(None, tail)
69326995
};
69336996
let tail = consume(b"_", tail)?;
6934-
Ok((ClosureTypeName(sig, num), tail))
6997+
Ok((ClosureTypeName(params, sig, num), tail))
69356998
}
69366999
}
69377000

@@ -6946,9 +7009,22 @@ where
69467009
) -> fmt::Result {
69477010
let ctx = try_begin_demangle!(self, ctx, scope);
69487011

6949-
write!(ctx, "{{lambda(")?;
6950-
self.0.demangle(ctx, scope)?;
6951-
write!(ctx, ")#{}}}", self.1.map_or(1, |n| n + 2))?;
7012+
write!(ctx, "{{lambda")?;
7013+
if !self.0.is_empty() {
7014+
write!(ctx, "<")?;
7015+
let mut need_comma = false;
7016+
for arg in &self.0 {
7017+
if need_comma {
7018+
write!(ctx, ", ")?;
7019+
}
7020+
arg.demangle(ctx, scope)?;
7021+
need_comma = true;
7022+
}
7023+
write!(ctx, ">")?;
7024+
}
7025+
write!(ctx, "(")?;
7026+
self.1.demangle(ctx, scope)?;
7027+
write!(ctx, ")#{}}}", self.2.map_or(1, |n| n + 2))?;
69527028
Ok(())
69537029
}
69547030
}
@@ -10307,11 +10383,11 @@ mod tests {
1030710383
assert_parse!(ClosureTypeName {
1030810384
Ok => {
1030910385
b"UlvE_..." => {
10310-
ClosureTypeName(LambdaSig(vec![]), None),
10386+
ClosureTypeName(vec![], LambdaSig(vec![]), None),
1031110387
b"..."
1031210388
}
1031310389
b"UlvE36_..." => {
10314-
ClosureTypeName(LambdaSig(vec![]), Some(36)),
10390+
ClosureTypeName(vec![], LambdaSig(vec![]), Some(36)),
1031510391
b"..."
1031610392
}
1031710393
}
@@ -10835,6 +10911,7 @@ mod tests {
1083510911
b"UllE_..." => {
1083610912
UnqualifiedName::ClosureType(
1083710913
ClosureTypeName(
10914+
vec![],
1083810915
LambdaSig(vec![
1083910916
TypeHandle::Builtin(
1084010917
BuiltinType::Standard(

tests/tests.rs

+12
Original file line numberDiff line numberDiff line change
@@ -564,3 +564,15 @@ demangles!(
564564
___ZN19URLConnectionClient33_clientInterface_cancelConnectionEP16dispatch_queue_sU13block_pointerFvvE_block_invoke14,
565565
"invocation function for block in URLConnectionClient::_clientInterface_cancelConnection(dispatch_queue_s*, void () block_pointer)"
566566
);
567+
568+
demangles!(
569+
_ZNSt6__ndk110__function6__funcIZN10xxxxxxxxxx20xxxxxxxxxxxxxxxxxxxx11xxxxxxxxxxxIN8xxxxxxxx14xxxxxxxxxxxxxxINS6_INS6_INS5_10xxxxxxxxxxEN14xxxxxxxxxxxxxx23xxxxxxxxxxxxxxxxxxxxxxxEEENS8_21xxxxxxxxxxxxxxxxxxxxxI18xxxxxxxxxxxxxxxxxxEEEE15xxxxxxxxxxxxxxxEESF_EEvRNS5_20xxxxxxxxxxxxxxxxxxxxIT_T0_EENS_8functionIFRS3_PSJ_EEEEUlTyRSI_iE_NS_9allocatorISS_EEFvRNS6_INS6_ISG_SF_EEiEERKiEED0Ev,
570+
"std::__ndk1::__function::__func<void xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx::xxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>(xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>&, std::__ndk1::function<xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx& (xxxxxxxxxxxxxxx*)>)::{lambda<typename $T>(auto:1&, int)#1}, std::__ndk1::allocator<void xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx::xxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>(xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>&, std::__ndk1::function<xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx& (xxxxxxxxxxxxxxx*)>)::{lambda<typename $T>(auto:1&, int)#1}>, void (xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>, int>&, int const&)>::~__func()"
571+
// "std::__ndk1::__function::__func<void xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx::xxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>(xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>&, std::__ndk1::function<xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx& (xxxxxxxxxxxxxxx*)>)::'lambda'<typename $T>(xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>&, int), std::__ndk1::allocator<void xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx::xxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>(xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>&, std::__ndk1::function<xxxxxxxxxx::xxxxxxxxxxxxxxxxxxxx& (xxxxxxxxxxxxxxx*)>)::'lambda'<typename $T>(xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>&, int)>, void (xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxxxx>, xxxxxxxxxxxxxx::xxxxxxxxxxxxxxxxxxxxx<xxxxxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx>, xxxxxxxxxxxxxxx>, int>&, int const&)>::~__func()"
572+
);
573+
574+
demangles!(
575+
_ZNKSt6__ndk110__function6__funcIZN8xxxxxxxx9xxxxxxxxxINS_10shared_ptrINS2_20xxxxxxxxxxxxxxxxxxxxINS2_10xxxxxxxxxxE15xxxxxxxxxxxxxxxEEEES7_bEEODaT_MT0_T1_PKcEUlTyTyRSB_RSC_E_NS_9allocatorISJ_EEFvRNS2_14xxxxxxxxxxxxxxINSM_IS6_S7_EEbEERKbEE7__cloneEPNS0_6__baseISS_EE,
576+
"std::__ndk1::__function::__func<auto&& xxxxxxxx::xxxxxxxxx<std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx, bool>(std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, bool xxxxxxxxxxxxxxx::*, char const*)::{lambda<typename $T, typename $T>(auto:1&, auto:2&)#1}, std::__ndk1::allocator<auto&& xxxxxxxx::xxxxxxxxx<std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx, bool>(std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, bool xxxxxxxxxxxxxxx::*, char const*)::{lambda<typename $T, typename $T>(auto:1&, auto:2&)#1}>, void (xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx>, bool>&, bool const&)>::__clone(std::__ndk1::__function::__base<void (xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx>, bool>&, bool const&)>*) const"
577+
// "std::__ndk1::__function::__func<auto&& xxxxxxxx::xxxxxxxxx<std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx, bool>(std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, bool xxxxxxxxxxxxxxx::*, char const*)::'lambda'<typename $T, typename $T0>(std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >&, xxxxxxxxxxxxxxx&), std::__ndk1::allocator<auto&& xxxxxxxx::xxxxxxxxx<std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, xxxxxxxxxxxxxxx, bool>(std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >, bool xxxxxxxxxxxxxxx::*, char const*)::'lambda'<typename $T, typename $T0>(std::__ndk1::shared_ptr<xxxxxxxx::xxxxxxxxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx> >&, xxxxxxxxxxxxxxx&)>, void (xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx>, bool>&, bool const&)>::__clone(std::__ndk1::__function::__base<void (xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxxxxxx<xxxxxxxx::xxxxxxxxxx, xxxxxxxxxxxxxxx>, bool>&, bool const&)>*) const"
578+
);

0 commit comments

Comments
 (0)