Skip to content

Commit 934d6af

Browse files
committed
[ntuple] Propagate type aliases from item fields
When constructing compound types from item fields, propagate alias types from the item fields to the parent field. This is already done globally in RFieldBase::Create() because the entire type name is compared to the unresolved type name. However, the type alias propagation was missing when a field is directly constructed with an item field.
1 parent 4a16b19 commit 934d6af

File tree

4 files changed

+206
-7
lines changed

4 files changed

+206
-7
lines changed

tree/ntuple/src/RField.cxx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,9 @@ ROOT::RNullableField::RNullableField(std::string_view fieldName, const std::stri
842842
: ROOT::RFieldBase(fieldName, typePrefix + "<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kCollection,
843843
false /* isSimple */)
844844
{
845+
if (!itemField->GetTypeAlias().empty())
846+
fTypeAlias = typePrefix + "<" + itemField->GetTypeAlias() + ">";
847+
845848
Attach(std::move(itemField));
846849
}
847850

@@ -1183,6 +1186,10 @@ ROOT::RAtomicField::RAtomicField(std::string_view fieldName, std::unique_ptr<RFi
11831186
fTraits |= kTraitTriviallyConstructible;
11841187
if (itemField->GetTraits() & kTraitTriviallyDestructible)
11851188
fTraits |= kTraitTriviallyDestructible;
1189+
1190+
if (!itemField->GetTypeAlias().empty())
1191+
fTypeAlias = "std::atomic<" + itemField->GetTypeAlias() + ">";
1192+
11861193
Attach(std::move(itemField));
11871194
}
11881195

tree/ntuple/src/RFieldMeta.cxx

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ std::string GetTypeList(std::span<std::unique_ptr<ROOT::RFieldBase>> itemFields,
8989
return result;
9090
}
9191

92-
std::string BuildSetTypeName(ROOT::RSetField::ESetType setType, const ROOT::RFieldBase &innerField)
92+
std::string BuildSetTypeName(ROOT::RSetField::ESetType setType, const ROOT::RFieldBase &innerField, bool useTypeAlias)
9393
{
9494
std::string typePrefix;
9595
switch (setType) {
@@ -99,10 +99,13 @@ std::string BuildSetTypeName(ROOT::RSetField::ESetType setType, const ROOT::RFie
9999
case ROOT::RSetField::ESetType::kUnorderedMultiSet: typePrefix = "std::unordered_multiset<"; break;
100100
default: R__ASSERT(false);
101101
}
102-
return typePrefix + innerField.GetTypeName() + ">";
102+
return typePrefix +
103+
((useTypeAlias && !innerField.GetTypeAlias().empty()) ? innerField.GetTypeAlias()
104+
: innerField.GetTypeName()) +
105+
">";
103106
}
104107

105-
std::string BuildMapTypeName(ROOT::RMapField::EMapType mapType, const ROOT::RFieldBase *innerField)
108+
std::string BuildMapTypeName(ROOT::RMapField::EMapType mapType, const ROOT::RFieldBase *innerField, bool useTypeAliases)
106109
{
107110
if (const auto pairField = dynamic_cast<const ROOT::RPairField *>(innerField)) {
108111
std::string typePrefix;
@@ -113,8 +116,18 @@ std::string BuildMapTypeName(ROOT::RMapField::EMapType mapType, const ROOT::RFie
113116
case ROOT::RMapField::EMapType::kUnorderedMultiMap: typePrefix = "std::unordered_multimap<"; break;
114117
default: R__ASSERT(false);
115118
}
116-
auto subFields = pairField->GetConstSubfields();
117-
return typePrefix + subFields[0]->GetTypeName() + "," + subFields[1]->GetTypeName() + ">";
119+
const auto &items = pairField->GetConstSubfields();
120+
std::string type = typePrefix;
121+
for (int i : {0, 1}) {
122+
if (useTypeAliases && !items[i]->GetTypeAlias().empty()) {
123+
type += items[i]->GetTypeAlias();
124+
} else {
125+
type += items[i]->GetTypeName();
126+
}
127+
if (i == 0)
128+
type.push_back(',');
129+
}
130+
return type + ">";
118131
}
119132

120133
throw ROOT::RException(R__FAIL("RMapField inner field type must be of RPairField"));
@@ -689,6 +702,10 @@ ROOT::RPairField::RPairField(std::string_view fieldName, std::array<std::unique_
689702
const std::array<std::size_t, 2> &offsets)
690703
: ROOT::RRecordField(fieldName, "std::pair<" + GetTypeList(itemFields, false /* useTypeAliases */) + ">")
691704
{
705+
const std::string typeAlias = "std::pair<" + GetTypeList(itemFields, true /* useTypeAliases */) + ">";
706+
if (typeAlias != GetTypeName())
707+
fTypeAlias = typeAlias;
708+
692709
AttachItemFields(std::move(itemFields));
693710
fOffsets.push_back(offsets[0]);
694711
fOffsets.push_back(offsets[1]);
@@ -697,6 +714,10 @@ ROOT::RPairField::RPairField(std::string_view fieldName, std::array<std::unique_
697714
ROOT::RPairField::RPairField(std::string_view fieldName, std::array<std::unique_ptr<RFieldBase>, 2> itemFields)
698715
: ROOT::RRecordField(fieldName, "std::pair<" + GetTypeList(itemFields, false /* useTypeAliases */) + ">")
699716
{
717+
const std::string typeAlias = "std::pair<" + GetTypeList(itemFields, true /* useTypeAliases */) + ">";
718+
if (typeAlias != GetTypeName())
719+
fTypeAlias = typeAlias;
720+
700721
AttachItemFields(std::move(itemFields));
701722

702723
// ISO C++ does not guarantee any specific layout for `std::pair`; query TClass for the member offsets
@@ -942,8 +963,13 @@ void ROOT::RProxiedCollectionField::AcceptVisitor(ROOT::Detail::RFieldVisitor &v
942963
//------------------------------------------------------------------------------
943964

944965
ROOT::RMapField::RMapField(std::string_view fieldName, EMapType mapType, std::unique_ptr<RFieldBase> itemField)
945-
: RProxiedCollectionField(fieldName, EnsureValidClass(BuildMapTypeName(mapType, itemField.get()))), fMapType(mapType)
966+
: RProxiedCollectionField(fieldName,
967+
EnsureValidClass(BuildMapTypeName(mapType, itemField.get(), false /* useTypeAliases */))),
968+
fMapType(mapType)
946969
{
970+
if (!itemField->GetTypeAlias().empty())
971+
fTypeAlias = BuildMapTypeName(mapType, itemField.get(), true /* useTypeAliases */);
972+
947973
auto *itemClass = fProxy->GetValueClass();
948974
fItemSize = itemClass->GetClassSize();
949975

@@ -973,10 +999,15 @@ void ROOT::RMapField::ReconcileOnDiskField(const RNTupleDescriptor &desc)
973999
//------------------------------------------------------------------------------
9741000

9751001
ROOT::RSetField::RSetField(std::string_view fieldName, ESetType setType, std::unique_ptr<RFieldBase> itemField)
976-
: ROOT::RProxiedCollectionField(fieldName, EnsureValidClass(BuildSetTypeName(setType, *itemField))),
1002+
: ROOT::RProxiedCollectionField(fieldName,
1003+
EnsureValidClass(BuildSetTypeName(setType, *itemField, false /* useTypeAlias */))),
9771004
fSetType(setType)
9781005
{
1006+
if (!itemField->GetTypeAlias().empty())
1007+
fTypeAlias = BuildSetTypeName(setType, *itemField, true /* useTypeAlias */);
1008+
9791009
fItemSize = itemField->GetValueSize();
1010+
9801011
Attach(std::move(itemField));
9811012
}
9821013

@@ -1285,13 +1316,21 @@ ROOT::RTupleField::RTupleField(std::string_view fieldName, std::vector<std::uniq
12851316
const std::vector<std::size_t> &offsets)
12861317
: ROOT::RRecordField(fieldName, "std::tuple<" + GetTypeList(itemFields, false /* useTypeAliases */) + ">")
12871318
{
1319+
const std::string typeAlias = "std::tuple<" + GetTypeList(itemFields, true /* useTypeAliases */) + ">";
1320+
if (typeAlias != GetTypeName())
1321+
fTypeAlias = typeAlias;
1322+
12881323
AttachItemFields(std::move(itemFields));
12891324
fOffsets = offsets;
12901325
}
12911326

12921327
ROOT::RTupleField::RTupleField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields)
12931328
: ROOT::RRecordField(fieldName, "std::tuple<" + GetTypeList(itemFields, false /* useTypeAliases */) + ">")
12941329
{
1330+
const std::string typeAlias = "std::tuple<" + GetTypeList(itemFields, true /* useTypeAliases */) + ">";
1331+
if (typeAlias != GetTypeName())
1332+
fTypeAlias = typeAlias;
1333+
12951334
AttachItemFields(std::move(itemFields));
12961335

12971336
auto *c = TClass::GetClass(GetTypeName().c_str());
@@ -1383,6 +1422,10 @@ ROOT::RVariantField::RVariantField(std::string_view fieldName, std::vector<std::
13831422
// The variant needs to initialize its own tag member
13841423
fTraits |= kTraitTriviallyDestructible & ~kTraitTriviallyConstructible;
13851424

1425+
const std::string typeAlias = "std::variant<" + GetTypeList(itemFields, true /* useTypeAliases */) + ">";
1426+
if (typeAlias != GetTypeName())
1427+
fTypeAlias = typeAlias;
1428+
13861429
auto nFields = itemFields.size();
13871430
if (nFields == 0 || nFields > kMaxVariants) {
13881431
throw RException(R__FAIL("invalid number of variant fields (outside [1.." + std::to_string(kMaxVariants) + ")"));

tree/ntuple/src/RFieldSequenceContainer.cxx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ ROOT::RArrayField::RArrayField(std::string_view fieldName, std::unique_ptr<RFiel
124124
fArrayLength(arrayLength)
125125
{
126126
fTraits |= itemField->GetTraits() & ~kTraitMappable;
127+
if (!itemField->GetTypeAlias().empty()) {
128+
fTypeAlias = "std::array<" + itemField->GetTypeAlias() + "," +
129+
Internal::GetNormalizedInteger(static_cast<unsigned long long>(arrayLength)) + ">";
130+
}
127131
Attach(std::move(itemField));
128132
}
129133

@@ -245,6 +249,8 @@ ROOT::RRVecField::RRVecField(std::string_view fieldName, std::unique_ptr<RFieldB
245249
{
246250
if (!(itemField->GetTraits() & kTraitTriviallyDestructible))
247251
fItemDeleter = GetDeleterOf(*itemField);
252+
if (!itemField->GetTypeAlias().empty())
253+
fTypeAlias = "ROOT::VecOps::RVec<" + itemField->GetTypeAlias() + ">";
248254
Attach(std::move(itemField));
249255
fValueSize = EvalRVecValueSize(fSubfields[0]->GetAlignment(), fSubfields[0]->GetValueSize(), GetAlignment());
250256

@@ -549,6 +555,9 @@ ROOT::RVectorField::RVectorField(std::string_view fieldName, std::unique_ptr<RFi
549555
if (emulatedFromType && !emulatedFromType->empty())
550556
fTraits |= kTraitEmulatedField;
551557

558+
if (!itemField->GetTypeAlias().empty())
559+
fTypeAlias = "std::vector<" + itemField->GetTypeAlias() + ">";
560+
552561
if (!(itemField->GetTraits() & kTraitTriviallyDestructible))
553562
fItemDeleter = GetDeleterOf(*itemField);
554563
Attach(std::move(itemField));
@@ -859,6 +868,8 @@ ROOT::RArrayAsRVecField::RArrayAsRVecField(std::string_view fieldName, std::uniq
859868
fItemSize(itemField->GetValueSize()),
860869
fArrayLength(arrayLength)
861870
{
871+
if (!itemField->GetTypeAlias().empty())
872+
fTypeAlias = "ROOT::VecOps::RVec<" + itemField->GetTypeAlias() + ">";
862873
Attach(std::move(itemField));
863874
fValueSize = EvalRVecValueSize(fSubfields[0]->GetAlignment(), fSubfields[0]->GetValueSize(), GetAlignment());
864875
if (!(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
@@ -961,6 +972,8 @@ ROOT::RArrayAsVectorField::RArrayAsVectorField(std::string_view fieldName, std::
961972
fItemSize(itemField->GetValueSize()),
962973
fArrayLength(arrayLength)
963974
{
975+
if (!itemField->GetTypeAlias().empty())
976+
fTypeAlias = "std::vector<" + itemField->GetTypeAlias() + ">";
964977
Attach(std::move(itemField));
965978
if (!(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
966979
fItemDeleter = GetDeleterOf(*fSubfields[0]);

tree/ntuple/test/ntuple_type_name.cxx

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,3 +411,139 @@ TEST(RNTuple, NeedsMetaNameAsAlias)
411411
EXPECT_TRUE(NeedsMetaNameAsAlias("MyClass<std::map<Long64_t, ULong64_t>>", renormalizedAlias));
412412
EXPECT_EQ("MyClass<std::map<Long64_t,ULong64_t>>", renormalizedAlias);
413413
}
414+
415+
TEST(RNTuple, PropagateTypeAlias)
416+
{
417+
{
418+
auto f = ROOT::RFieldBase::Create("f", "std::vector<Double32_t>").Unwrap();
419+
EXPECT_EQ("std::vector<double>", f->GetTypeName());
420+
EXPECT_EQ("std::vector<Double32_t>", f->GetTypeAlias());
421+
}
422+
423+
{
424+
auto f = ROOT::RFieldBase::Create("f", "ROOT::RVec<Double32_t>").Unwrap();
425+
EXPECT_EQ("ROOT::VecOps::RVec<double>", f->GetTypeName());
426+
EXPECT_EQ("ROOT::VecOps::RVec<Double32_t>", f->GetTypeAlias());
427+
}
428+
429+
{
430+
auto f = ROOT::RFieldBase::Create("f", "std::array<Double32_t, 2>").Unwrap();
431+
EXPECT_EQ("std::array<double,2>", f->GetTypeName());
432+
EXPECT_EQ("std::array<Double32_t,2>", f->GetTypeAlias());
433+
}
434+
435+
{
436+
auto f = ROOT::RFieldBase::Create("f", "std::variant<Double32_t, int>").Unwrap();
437+
EXPECT_EQ("std::variant<double,std::int32_t>", f->GetTypeName());
438+
EXPECT_EQ("std::variant<Double32_t,std::int32_t>", f->GetTypeAlias());
439+
}
440+
441+
{
442+
auto f = ROOT::RFieldBase::Create("f", "std::pair<Double32_t, int>").Unwrap();
443+
EXPECT_EQ("std::pair<double,std::int32_t>", f->GetTypeName());
444+
EXPECT_EQ("std::pair<Double32_t,std::int32_t>", f->GetTypeAlias());
445+
}
446+
447+
{
448+
auto f = ROOT::RFieldBase::Create("f", "std::tuple<Double32_t, int>").Unwrap();
449+
EXPECT_EQ("std::tuple<double,std::int32_t>", f->GetTypeName());
450+
EXPECT_EQ("std::tuple<Double32_t,std::int32_t>", f->GetTypeAlias());
451+
}
452+
453+
{
454+
auto f = ROOT::RFieldBase::Create("f", "std::optional<Double32_t>").Unwrap();
455+
EXPECT_EQ("std::optional<double>", f->GetTypeName());
456+
EXPECT_EQ("std::optional<Double32_t>", f->GetTypeAlias());
457+
}
458+
459+
{
460+
auto f = ROOT::RFieldBase::Create("f", "std::multiset<Double32_t>").Unwrap();
461+
EXPECT_EQ("std::multiset<double>", f->GetTypeName());
462+
EXPECT_EQ("std::multiset<Double32_t>", f->GetTypeAlias());
463+
}
464+
465+
{
466+
auto f = ROOT::RFieldBase::Create("f", "std::multimap<Double32_t, int>").Unwrap();
467+
EXPECT_EQ("std::multimap<double,std::int32_t>", f->GetTypeName());
468+
EXPECT_EQ("std::multimap<Double32_t,std::int32_t>", f->GetTypeAlias());
469+
}
470+
471+
{
472+
auto f = ROOT::RFieldBase::Create("f", "std::atomic<Double32_t>").Unwrap();
473+
EXPECT_EQ("std::atomic<double>", f->GetTypeName());
474+
EXPECT_EQ("std::atomic<Double32_t>", f->GetTypeAlias());
475+
}
476+
477+
auto GetDouble32Item = []() {
478+
auto item = std::make_unique<ROOT::RField<double>>("_0");
479+
item->SetDouble32();
480+
return item;
481+
};
482+
483+
{
484+
auto f = std::make_unique<ROOT::RVectorField>("f", GetDouble32Item());
485+
EXPECT_EQ("std::vector<double>", f->GetTypeName());
486+
EXPECT_EQ("std::vector<Double32_t>", f->GetTypeAlias());
487+
}
488+
489+
{
490+
auto f = std::make_unique<ROOT::RRVecField>("f", GetDouble32Item());
491+
EXPECT_EQ("ROOT::VecOps::RVec<double>", f->GetTypeName());
492+
EXPECT_EQ("ROOT::VecOps::RVec<Double32_t>", f->GetTypeAlias());
493+
}
494+
495+
{
496+
auto f = std::make_unique<ROOT::RArrayField>("f", GetDouble32Item(), 2);
497+
EXPECT_EQ("std::array<double,2>", f->GetTypeName());
498+
EXPECT_EQ("std::array<Double32_t,2>", f->GetTypeAlias());
499+
}
500+
501+
{
502+
std::vector<std::unique_ptr<RFieldBase>> items;
503+
items.emplace_back(GetDouble32Item());
504+
items.emplace_back(std::make_unique<RField<int>>("f"));
505+
auto f = std::make_unique<ROOT::RVariantField>("f", std::move(items));
506+
EXPECT_EQ("std::variant<double,std::int32_t>", f->GetTypeName());
507+
EXPECT_EQ("std::variant<Double32_t,std::int32_t>", f->GetTypeAlias());
508+
}
509+
510+
{
511+
std::array<std::unique_ptr<RFieldBase>, 2> items;
512+
items[0] = GetDouble32Item();
513+
items[1] = std::make_unique<RField<int>>("f");
514+
auto f = std::make_unique<ROOT::RPairField>("f", std::move(items));
515+
EXPECT_EQ("std::pair<double,std::int32_t>", f->GetTypeName());
516+
EXPECT_EQ("std::pair<Double32_t,std::int32_t>", f->GetTypeAlias());
517+
}
518+
519+
{
520+
std::vector<std::unique_ptr<RFieldBase>> items;
521+
items.emplace_back(GetDouble32Item());
522+
items.emplace_back(std::make_unique<RField<int>>("f"));
523+
auto f = std::make_unique<ROOT::RTupleField>("f", std::move(items));
524+
EXPECT_EQ("std::tuple<double,std::int32_t>", f->GetTypeName());
525+
EXPECT_EQ("std::tuple<Double32_t,std::int32_t>", f->GetTypeAlias());
526+
}
527+
528+
{
529+
auto f = std::make_unique<ROOT::ROptionalField>("f", GetDouble32Item());
530+
EXPECT_EQ("std::optional<double>", f->GetTypeName());
531+
EXPECT_EQ("std::optional<Double32_t>", f->GetTypeAlias());
532+
}
533+
534+
{
535+
std::array<std::unique_ptr<RFieldBase>, 2> items;
536+
items[0] = GetDouble32Item();
537+
items[1] = std::make_unique<RField<int>>("f");
538+
auto f = std::make_unique<ROOT::RMapField>("f", ROOT::RMapField::EMapType::kMultiMap,
539+
std::make_unique<ROOT::RPairField>("f", std::move(items)));
540+
EXPECT_EQ("std::multimap<double,std::int32_t>", f->GetTypeName());
541+
EXPECT_EQ("std::multimap<Double32_t,std::int32_t>", f->GetTypeAlias());
542+
}
543+
544+
{
545+
auto f = std::make_unique<ROOT::RAtomicField>("f", GetDouble32Item());
546+
EXPECT_EQ("std::atomic<double>", f->GetTypeName());
547+
EXPECT_EQ("std::atomic<Double32_t>", f->GetTypeAlias());
548+
}
549+
}

0 commit comments

Comments
 (0)