Skip to content

Commit

Permalink
Merge pull request #92241 from dalexeev/gds-fix-lambda-captures-non-l…
Browse files Browse the repository at this point in the history
…ocal-vars

GDScript: Fix lambdas capturing non-local variables
  • Loading branch information
akien-mga committed May 28, 2024
2 parents e408c77 + 4b69295 commit dbc6f2a
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 4 deletions.
21 changes: 17 additions & 4 deletions modules/gdscript/gdscript_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4061,10 +4061,23 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
mark_lambda_use_self();
return; // No need to capture.
}
// If the identifier is local, check if it's any kind of capture by comparing their source function.
// Only capture locals and enum values. Constants are still accessible from the lambda using the script reference. If not, this method is done.
if (p_identifier->source == GDScriptParser::IdentifierNode::UNDEFINED_SOURCE || p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_CONSTANT) {
return;

switch (p_identifier->source) {
case GDScriptParser::IdentifierNode::FUNCTION_PARAMETER:
case GDScriptParser::IdentifierNode::LOCAL_VARIABLE:
case GDScriptParser::IdentifierNode::LOCAL_ITERATOR:
case GDScriptParser::IdentifierNode::LOCAL_BIND:
break; // Need to capture.
case GDScriptParser::IdentifierNode::UNDEFINED_SOURCE: // A global.
case GDScriptParser::IdentifierNode::LOCAL_CONSTANT:
case GDScriptParser::IdentifierNode::MEMBER_VARIABLE:
case GDScriptParser::IdentifierNode::MEMBER_CONSTANT:
case GDScriptParser::IdentifierNode::MEMBER_FUNCTION:
case GDScriptParser::IdentifierNode::MEMBER_SIGNAL:
case GDScriptParser::IdentifierNode::MEMBER_CLASS:
case GDScriptParser::IdentifierNode::INHERITED_VARIABLE:
case GDScriptParser::IdentifierNode::STATIC_VARIABLE:
return; // No need to capture.
}

GDScriptParser::FunctionNode *function_test = current_lambda->function;
Expand Down
26 changes: 26 additions & 0 deletions modules/gdscript/tests/scripts/runtime/features/lambda_captures.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# GH-92217
# TODO: Add more tests.

static var static_var: int:
set(value):
prints("set static_var", value)
get:
print("get static_var")
return 0

var member_var: int:
set(value):
prints("set member_var", value)
get:
print("get member_var")
return 0

func test():
var lambda := func ():
var _tmp := static_var
_tmp = member_var

static_var = 1
member_var = 1

lambda.call()
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
GDTEST_OK
get static_var
get member_var
set static_var 1
set member_var 1

0 comments on commit dbc6f2a

Please sign in to comment.