Skip to content

Commit dc28693

Browse files
committed
types: Fix dict iterator dereference values destruction. #SW-7582
1 parent a7a91d8 commit dc28693

2 files changed

Lines changed: 34 additions & 28 deletions

File tree

src/pytypes.cpp

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -595,20 +595,13 @@ class ListInterface : public ObjectInterfaceBase<Storage, qi::ListTypeInterface>
595595

596596
using DefaultImpl = DefaultTypeImplMethods<Iterator, TypeByPointerPOD<Iterator>>;
597597

598-
void* initializeStorage(void* ptr = nullptr) override
599-
{
600-
return DefaultImpl::initializeStorage(ptr);
601-
}
602-
598+
void* initializeStorage(void* ptr = nullptr) override { return DefaultImpl::initializeStorage(ptr); }
603599
void* clone(void* storage) override { return DefaultImpl::clone(storage); }
604-
void destroy(void* storage) override
605-
{
606-
destroyDisownedReferences(storage);
607-
return DefaultImpl::destroy(storage);
608-
}
600+
void destroy(void* storage) override { return DefaultImpl::destroy(storage); }
609601
const TypeInfo& info() override { return DefaultImpl::info(); }
610602
void* ptrFromStorage(void** s) override { return DefaultImpl::ptrFromStorage(s); }
611603
bool less(void* a, void* b) override { return DefaultImpl::less(a, b); }
604+
612605
Iterator* asIterPtr(void** storage) { return static_cast<Iterator*>(ptrFromStorage(storage)); }
613606
Iterator& asIter(void** storage) { return *asIterPtr(storage); }
614607
};
@@ -680,34 +673,27 @@ class DictInterface: public ObjectInterfaceBase<Storage, qi::MapTypeInterface>
680673
std::advance(it, index);
681674
const auto key = ::py::reinterpret_borrow<::py::object>(it->first);
682675
const auto element = ::py::reinterpret_borrow<::py::object>(it->second);
683-
const auto keyElementPair = std::make_pair(key, element);
684-
auto ref = AnyReference::from(keyElementPair).clone();
676+
auto keyRef = AnyReference::from(key);
677+
auto elementRef = AnyReference::from(element);
678+
auto pairRef = makeGenericTuple({keyRef, elementRef});
685679
// Store the disowned reference with the list as a context instead of the
686680
// iterator because the reference might outlive the iterator.
687-
storeDisownedReference(dictStorage, ref);
688-
return ref;
681+
storeDisownedReference(dictStorage, pairRef);
682+
return pairRef;
689683
}
690684

691685
void next(void** storage) override { ++asIter(storage).second; }
692686
bool equals(void* s1, void* s2) override { return asIter(&s1) == asIter(&s2); }
693687

694688
using DefaultImpl = DefaultTypeImplMethods<Iterator, TypeByPointerPOD<Iterator>>;
695689

696-
void* initializeStorage(void* ptr = nullptr) override
697-
{
698-
return DefaultImpl::initializeStorage(ptr);
699-
}
700-
690+
void* initializeStorage(void* ptr = nullptr) override { return DefaultImpl::initializeStorage(ptr); }
701691
void* clone(void* storage) override { return DefaultImpl::clone(storage); }
702-
void destroy(void* storage) override
703-
{
704-
destroyDisownedReferences(storage);
705-
return DefaultImpl::destroy(storage);
706-
}
707-
692+
void destroy(void* storage) override { return DefaultImpl::destroy(storage); }
708693
const TypeInfo& info() override { return DefaultImpl::info(); }
709694
void* ptrFromStorage(void** s) override { return DefaultImpl::ptrFromStorage(s); }
710695
bool less(void* a, void* b) override { return DefaultImpl::less(a, b); }
696+
711697
Iterator* asIterPtr(void** storage) { return static_cast<Iterator*>(ptrFromStorage(storage)); }
712698
Iterator& asIter(void** storage) { return *asIterPtr(storage); }
713699
};

tests/test_types.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -387,20 +387,40 @@ TEST_F(TypePassing, Recursive)
387387
}
388388
}
389389

390+
TEST_F(TypePassing, ReverseList)
391+
{
392+
exec(
393+
"class TestService:\n"
394+
" def func(self, list):\n"
395+
// Test the iterator interface.
396+
" for value in list:\n"
397+
" assert(isinstance(value, str))\n"
398+
" assert(list == ['hello', 'world'])\n"
399+
);
400+
registerService();
401+
const std::vector<const char*> list {"hello", "world"};
402+
getService().call<void>("func", list);
403+
}
404+
405+
390406
TEST_F(TypePassing, ReverseDict)
391407
{
392408
exec(
393409
"class TestService:\n"
394410
" def func(self, dict):\n"
395-
" return dict == {'one' : 1, 'two' : 2, 'three' : 3}\n"
411+
// Test the iterator interface.
412+
" for key, value in dict.items():\n"
413+
" assert(isinstance(key, str))\n"
414+
" assert(isinstance(value, int))\n"
415+
" assert(dict == {'one' : 1, 'two' : 2, 'three' : 3})\n"
396416
);
397417
registerService();
398-
const std::map<std::string, int> expected {
418+
const std::map<std::string, int> dict {
399419
{"one", 1},
400420
{"two", 2},
401421
{"three", 3},
402422
};
403-
EXPECT_TRUE(getService().call<bool>("func", expected));
423+
getService().call<void>("func", dict);
404424
}
405425

406426
TEST_F(TypePassing, LogLevel)

0 commit comments

Comments
 (0)