diff --git a/src/Func.cc b/src/Func.cc index 319868395e..f24154d1a5 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -587,6 +587,11 @@ bool ScriptFunc::StrengthenClosureReference(Frame* f) return true; } +bool ScriptFunc::CopySemantics() const + { + return type->GetCaptures().has_value(); + } + void ScriptFunc::SetClosureFrame(Frame* f) { if ( closure ) diff --git a/src/Func.h b/src/Func.h index db15fde849..9729fbca1d 100644 --- a/src/Func.h +++ b/src/Func.h @@ -145,7 +145,7 @@ protected: namespace detail { -class ScriptFunc final : public Func { +class ScriptFunc : public Func { public: ScriptFunc(const IDPtr& id, StmtPtr body, const std::vector& inits, @@ -210,12 +210,17 @@ public: */ bool StrengthenClosureReference(Frame* f); + /** + * Whether the function's closure uses copy semantics. + */ + virtual bool CopySemantics() const; + /** * Serializes this function's closure or capture frame. * * @return a serialized version of the function's closure/capture frame. */ - broker::expected SerializeClosure() const; + virtual broker::expected SerializeClosure() const; /** * Sets the captures frame to one built from *data*. @@ -257,6 +262,7 @@ public: protected: ScriptFunc() : Func(SCRIPT_FUNC) {} + StmtPtr AddInits( StmtPtr body, const std::vector& inits); @@ -280,7 +286,7 @@ protected: * * @param f the frame holding the values of capture variables */ - void SetCaptures(Frame* f); + virtual void SetCaptures(Frame* f); private: size_t frame_size; diff --git a/src/broker/Data.cc b/src/broker/Data.cc index 2af93460bd..db372de6fe 100644 --- a/src/broker/Data.cc +++ b/src/broker/Data.cc @@ -392,6 +392,17 @@ struct val_converter { if ( a.size() == 2 ) // we have a closure/capture frame { + // Note, seems if we already have a separate + // instance of the same lambda, then unless + // we use a cloned value, we'll step on that + // one's captures, too. This is because + // the capture mapping lives with the Func + // object rather than the FuncVal. However, + // we can't readily Clone() here because + // rval is const (and, grrr, Clone() is not). + // -VP + // rval = rval->Clone(); + auto frame = broker::get_if(a[1]); if ( ! frame ) return nullptr; @@ -400,9 +411,7 @@ struct val_converter { if ( ! b ) return nullptr; - auto copy_semantics = b->GetType()->GetCaptures().has_value(); - - if ( copy_semantics ) + if ( b->CopySemantics() ) { if ( ! b->DeserializeCaptures(*frame) ) return nullptr;