@@ -161,7 +161,11 @@ std::string MutuallyRecursiveTypeGroup::repr(bool deep) {
161161
162162 std::string levelPrefix (level, ' ' );
163163
164- s << levelPrefix << " group with hash " << group->hash ().digestAsHexString () << " :\n " ;
164+ if (group->mIsCurrentlyHashing ) {
165+ s << levelPrefix << " hashing group @ " << (void *)group << " \n " ;
166+ } else {
167+ s << levelPrefix << " group with hash " << group->hash ().digestAsHexString () << " :\n " ;
168+ }
165169
166170 // sort lexically and then by level, so that
167171 // we can tell what's going on when we have a discrepancy
@@ -188,16 +192,25 @@ std::string MutuallyRecursiveTypeGroup::repr(bool deep) {
188192 subgroup = v.typeOrPyobjAsType ()->getRecursiveTypeGroup ();
189193 ixInSubgroup = v.typeOrPyobjAsType ()->getRecursiveTypeGroupIndex ();
190194 } else {
191- std::tie (subgroup, ixInSubgroup) = MutuallyRecursiveTypeGroup::pyObjectGroupHeadAndIndex (
192- v.typeOrPyobjAsObject ()
193- );
195+ std::tie (subgroup, ixInSubgroup) =
196+ MutuallyRecursiveTypeGroup::pyObjectGroupHeadAndIndex (
197+ v.typeOrPyobjAsObject ()
198+ );
194199 }
195200
196201 if (seen.find (subgroup) == seen.end ()) {
197202 dump (subgroup, level + 2 );
198203 } else {
199- s << levelPrefix << " " << " group with hash " << group->hash ().digestAsHexString ()
200- << " item " << ixInSubgroup << " \n " ;
204+ if (group->mIsCurrentlyHashing ) {
205+ s << levelPrefix << " "
206+ << " hashing group @ " << (void *)group
207+ << " item " << ixInSubgroup << " \n " ;
208+ } else {
209+ s << levelPrefix << " "
210+ << " group with hash "
211+ << group->hash ().digestAsHexString ()
212+ << " item " << ixInSubgroup << " \n " ;
213+ }
201214 }
202215 }
203216 }
@@ -465,19 +478,34 @@ void MutuallyRecursiveTypeGroup::computeHash() {
465478 return ;
466479 }
467480
468- if (mIsCurrentlyHashing ) {
481+ PyEnsureGilAcquired getTheGil;
482+
483+ thread_local static std::unordered_set<MutuallyRecursiveTypeGroup*> hashingGroupsSet;
484+ thread_local static std::vector<MutuallyRecursiveTypeGroup*> hashingGroups;
485+
486+ if (hashingGroupsSet.find (this ) != hashingGroupsSet.end ()) {
469487 CompilerVisibleObjectVisitor::singleton ().checkForInstability ();
470488
471- throw std::runtime_error (
472- " Somehow we are already computing the hash of this MRTG. "
489+ std::ostringstream errMsg;
490+
491+ errMsg << " Somehow we are already computing the hash of this MRTG. "
473492 " This means that when we computed the group's constituents, we missed "
474- " a link between elements of this group and elements of a calling group."
475- );
493+ " a link between elements of this group and elements of a calling group.\n\n " ;
494+
495+ for (auto group: hashingGroups) {
496+ errMsg << group->repr (false ) << " \n\n " ;
497+ }
498+
499+ errMsg << this ->repr (false ) << " \n " ;
500+
501+ throw std::runtime_error (errMsg.str ());
476502 }
477503
478504 try {
479505 // mark that we're currently hashing.
480506 mIsCurrentlyHashing = true ;
507+ hashingGroups.push_back (this );
508+ hashingGroupsSet.insert (this );
481509
482510 // we are a recursive group head. We want to compute the hash
483511 // of all of our constituents where, when each of them looks at
@@ -504,13 +532,16 @@ void MutuallyRecursiveTypeGroup::computeHash() {
504532 mHash = wholeGroupHash;
505533 mIsCurrentlyHashing = false ;
506534
507- PyEnsureGilAcquired getTheGil;
535+ hashingGroups.pop_back ();
536+ hashingGroupsSet.erase (this );
508537
509538 if (mHashToGroup .find (mHash ) == mHashToGroup .end ()) {
510539 mHashToGroup [mHash ] = this ;
511540 }
512541 } catch (...) {
513542 mIsCurrentlyHashing = false ;
543+ hashingGroups.pop_back ();
544+ hashingGroupsSet.erase (this );
514545 throw ;
515546 }
516547}
0 commit comments