diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index fb321ea24..1b3e0c723 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2142,9 +2142,10 @@ TypeResult StructType::interfaceType(bool _inLibrary) const if (!_inLibrary && m_interfaceType.is_initialized()) return *m_interfaceType; - bool recursion = false; TypeResult result{TypePointer{}}; + m_recursive = false; + auto visitor = [&]( StructDefinition const& _struct, CycleDetector& _cycleDetector, @@ -2175,7 +2176,7 @@ TypeResult StructType::interfaceType(bool _inLibrary) const _cycleDetector.run(innerStruct->structDefinition()) ) { - recursion = true; + m_recursive = true; if (_inLibrary && location() == DataLocation::Storage) continue; else @@ -2195,7 +2196,7 @@ TypeResult StructType::interfaceType(bool _inLibrary) const } }; - recursion = recursion || (CycleDetector(visitor).run(structDefinition()) != nullptr); + m_recursive = m_recursive.get() || (CycleDetector(visitor).run(structDefinition()) != nullptr); std::string const recursiveErrMsg = "Recursive type not allowed for public or external contract functions."; @@ -2208,13 +2209,13 @@ TypeResult StructType::interfaceType(bool _inLibrary) const else m_interfaceType_library = copyForLocation(DataLocation::Memory, true); - if (recursion) + if (m_recursive.get()) m_interfaceType = TypeResult::err(recursiveErrMsg); return *m_interfaceType_library; } - if (recursion) + if (m_recursive.get()) m_interfaceType = TypeResult::err(recursiveErrMsg); else if (!result.message().empty()) m_interfaceType = result; diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index c2445fc4c..86ae52ff4 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -844,6 +844,16 @@ public: } TypeResult interfaceType(bool _inLibrary) const override; + bool recursive() const + { + if (m_recursive.is_initialized()) + return m_recursive.get(); + + interfaceType(false); + + return m_recursive.get(); + } + TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override; std::string canonicalName() const override; @@ -868,6 +878,7 @@ private: // Caches for interfaceType(bool) mutable boost::optional m_interfaceType; mutable boost::optional m_interfaceType_library; + mutable boost::optional m_recursive; }; /**