Commit 41492937 by Chris Mihelich Committed by Copybara-Service

Recognize dyn-trait-type in Rust demangling.

PiperOrigin-RevId: 636563266
Change-Id: Id4ee907c30d7dac400f1f85776cc5f1fcb3e20b7
parent 1a31b81c
......@@ -277,7 +277,7 @@ class RustSymbolParser {
goto type;
}
if (Eat('F')) goto fn_type;
if (Eat('D')) return false; // dyn-trait-type not yet implemented
if (Eat('D')) goto dyn_trait_type;
if (Eat('B')) goto type_backref;
goto path;
......@@ -349,6 +349,54 @@ class RustSymbolParser {
--silence_depth_;
continue;
// dyn-trait-type -> D dyn-bounds lifetime (D already consumed)
// dyn-bounds -> binder? dyn-trait* E
//
// The grammar strangely allows an empty trait list, even though the
// compiler should never output one. We follow existing demanglers in
// rendering DEL_ as "dyn ".
//
// Because auto traits lengthen a type name considerably without
// providing much value to a search for related source code, it would be
// desirable to abbreviate
// dyn main::Trait + std::marker::Copy + std::marker::Send
// to
// dyn main::Trait + ...,
// eliding the auto traits. But it is difficult to do so correctly, in
// part because there is no guarantee that the mangling will list the
// main trait first. So we just print all the traits in their order of
// appearance in the mangled name.
dyn_trait_type:
if (!Emit("dyn ")) return false;
if (!ParseOptionalBinder()) return false;
if (!Eat('E')) {
ABSL_DEMANGLER_RECURSE(dyn_trait, kBeginAutoTraits);
while (!Eat('E')) {
if (!Emit(" + ")) return false;
ABSL_DEMANGLER_RECURSE(dyn_trait, kContinueAutoTraits);
}
}
if (!ParseRequiredLifetime()) return false;
continue;
// dyn-trait -> path dyn-trait-assoc-binding*
// dyn-trait-assoc-binding -> p undisambiguated-identifier type
//
// We render nonempty binding lists as <>, omitting their contents as
// for generic-args.
dyn_trait:
ABSL_DEMANGLER_RECURSE(path, kContinueDynTrait);
if (Peek() == 'p') {
if (!Emit("<>")) return false;
++silence_depth_;
while (Eat('p')) {
if (!ParseUndisambiguatedIdentifier()) return false;
ABSL_DEMANGLER_RECURSE(type, kContinueAssocBinding);
}
--silence_depth_;
}
continue;
// const -> type const-data | p | backref
//
// const is a C++ keyword, so we use the label `constant` instead.
......@@ -477,6 +525,10 @@ class RustSymbolParser {
kAfterSubsequentTupleElement,
kContinueParameterList,
kFinishFn,
kBeginAutoTraits,
kContinueAutoTraits,
kContinueDynTrait,
kContinueAssocBinding,
kConstData,
kBeginGenericArgList,
kContinueGenericArgList,
......@@ -750,6 +802,13 @@ class RustSymbolParser {
return ParseBase62Number(ignored_de_bruijn_index);
}
// Consumes a lifetime just like ParseOptionalLifetime, but returns false if
// there is no lifetime here.
ABSL_MUST_USE_RESULT bool ParseRequiredLifetime() {
if (Peek() != 'L') return false;
return ParseOptionalLifetime();
}
// Pushes ns onto the namespace stack and returns true if the stack is not
// full, else returns false.
ABSL_MUST_USE_RESULT bool PushNamespace(char ns) {
......
......@@ -534,6 +534,50 @@ TEST(DemangleRust, LifetimeInGenericArgs) {
"c::f::<>");
}
TEST(DemangleRust, EmptyDynTrait) {
// This shouldn't happen, but the grammar allows it and existing demanglers
// accept it.
EXPECT_DEMANGLING("_RNvYDEL_NtC1c1t1f",
"<dyn as c::t>::f");
}
TEST(DemangleRust, SimpleDynTrait) {
EXPECT_DEMANGLING("_RNvYDNtC1c1tEL_NtC1d1u1f",
"<dyn c::t as d::u>::f");
}
TEST(DemangleRust, DynTraitWithOneAssociatedType) {
EXPECT_DEMANGLING(
"_RNvYDNtC1c1tp1xlEL_NtC1d1u1f", // <dyn c::t<x = i32> as d::u>::f
"<dyn c::t<> as d::u>::f");
}
TEST(DemangleRust, DynTraitWithTwoAssociatedTypes) {
EXPECT_DEMANGLING(
// <dyn c::t<x = i32, y = u32> as d::u>::f
"_RNvYDNtC1c1tp1xlp1ymEL_NtC1d1u1f",
"<dyn c::t<> as d::u>::f");
}
TEST(DemangleRust, DynTraitPlusAutoTrait) {
EXPECT_DEMANGLING(
"_RNvYDNtC1c1tNtNtC3std6marker4SendEL_NtC1d1u1f",
"<dyn c::t + std::marker::Send as d::u>::f");
}
TEST(DemangleRust, DynTraitPlusTwoAutoTraits) {
EXPECT_DEMANGLING(
"_RNvYDNtC1c1tNtNtC3std6marker4CopyNtBc_4SyncEL_NtC1d1u1f",
"<dyn c::t + std::marker::Copy + std::marker::Sync as d::u>::f");
}
TEST(DemangleRust, HigherRankedDynTrait) {
EXPECT_DEMANGLING(
// <dyn for<'a> c::t::<&'a i32> as d::u>::f
"_RNvYDG_INtC1c1tRL0_lEEL_NtC1d1u1f",
"<dyn c::t::<> as d::u>::f");
}
} // namespace
} // namespace debugging_internal
ABSL_NAMESPACE_END
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment