Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GDScript: Fix non-static call is allowed in static var lambda body #83486

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 27 additions & 15 deletions modules/gdscript/gdscript_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1585,7 +1585,13 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
GDScriptParser::FunctionNode *previous_function = parser->current_function;
parser->current_function = p_function;
bool previous_static_context = static_context;
static_context = p_function->is_static;
if (p_is_lambda) {
// For lambdas this is determined from the context, the `static` keyword is not allowed.
p_function->is_static = static_context;
} else {
// For normal functions, this is determined in the parser by the `static` keyword.
static_context = p_function->is_static;
}

GDScriptParser::DataType prev_datatype = p_function->get_datatype();

Expand Down Expand Up @@ -3317,15 +3323,16 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
}

if (is_self && static_context && !method_flags.has_flag(METHOD_FLAG_STATIC)) {
if (parser->current_function) {
// Get the parent function above any lambda.
GDScriptParser::FunctionNode *parent_function = parser->current_function;
while (parent_function->source_lambda) {
parent_function = parent_function->source_lambda->parent_function;
}
// Get the parent function above any lambda.
GDScriptParser::FunctionNode *parent_function = parser->current_function;
while (parent_function && parent_function->source_lambda) {
parent_function = parent_function->source_lambda->parent_function;
}

if (parent_function) {
push_error(vformat(R"*(Cannot call non-static function "%s()" from static function "%s()".)*", p_call->function_name, parent_function->identifier->name), p_call);
} else {
push_error(vformat(R"*(Cannot call non-static function "%s()" for static variable initializer.)*", p_call->function_name), p_call);
push_error(vformat(R"*(Cannot call non-static function "%s()" from a static variable initializer.)*", p_call->function_name), p_call);
}
} else if (!is_self && base_type.is_meta_type && !method_flags.has_flag(METHOD_FLAG_STATIC)) {
base_type.is_meta_type = false; // For `to_string()`.
Expand Down Expand Up @@ -3908,15 +3915,16 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
bool source_is_variable = p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_VARIABLE || p_identifier->source == GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
bool source_is_signal = p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_SIGNAL;
if ((source_is_variable || source_is_signal) && static_context) {
if (parser->current_function) {
// Get the parent function above any lambda.
GDScriptParser::FunctionNode *parent_function = parser->current_function;
while (parent_function->source_lambda) {
parent_function = parent_function->source_lambda->parent_function;
}
// Get the parent function above any lambda.
GDScriptParser::FunctionNode *parent_function = parser->current_function;
while (parent_function && parent_function->source_lambda) {
parent_function = parent_function->source_lambda->parent_function;
}

if (parent_function) {
push_error(vformat(R"*(Cannot access %s "%s" from the static function "%s()".)*", source_is_signal ? "signal" : "instance variable", p_identifier->name, parent_function->identifier->name), p_identifier);
} else {
push_error(vformat(R"*(Cannot access %s "%s" for a static variable initializer.)*", source_is_signal ? "signal" : "instance variable", p_identifier->name), p_identifier);
push_error(vformat(R"*(Cannot access %s "%s" from a static variable initializer.)*", source_is_signal ? "signal" : "instance variable", p_identifier->name), p_identifier);
}
}

Expand Down Expand Up @@ -5459,12 +5467,15 @@ void GDScriptAnalyzer::resolve_pending_lambda_bodies() {
}

GDScriptParser::LambdaNode *previous_lambda = current_lambda;
bool previous_static_context = static_context;

List<GDScriptParser::LambdaNode *> lambdas = pending_body_resolution_lambdas;
pending_body_resolution_lambdas.clear();

for (GDScriptParser::LambdaNode *lambda : lambdas) {
current_lambda = lambda;
static_context = lambda->function->is_static;

resolve_function_body(lambda->function, true);

int captures_amount = lambda->captures.size();
Expand Down Expand Up @@ -5493,6 +5504,7 @@ void GDScriptAnalyzer::resolve_pending_lambda_bodies() {
}

current_lambda = previous_lambda;
static_context = previous_static_context;
}

bool GDScriptAnalyzer::class_exists(const StringName &p_class) const {
Expand Down
2 changes: 1 addition & 1 deletion modules/gdscript/gdscript_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -838,7 +838,7 @@ class GDScriptParser {
HashMap<StringName, int> parameters_indices;
TypeNode *return_type = nullptr;
SuiteNode *body = nullptr;
bool is_static = false;
bool is_static = false; // For lambdas it's determined in the analyzer.
bool is_coroutine = false;
Variant rpc_config;
MethodInfo info;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# GH-83468

func non_static_func():
pass

static func static_func():
var f := func ():
var g := func ():
non_static_func()
g.call()
f.call()

func test():
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot call non-static function "non_static_func()" from static function "static_func()".
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# GH-83468

func non_static_func():
pass

static func static_func(
f := func ():
var g := func ():
non_static_func()
g.call()
):
f.call()

func test():
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot call non-static function "non_static_func()" from static function "static_func()".
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# GH-83468

func non_static_func():
pass

static var static_var = func ():
var f := func ():
var g := func ():
non_static_func()
g.call()
f.call()

func test():
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot call non-static function "non_static_func()" from a static variable initializer.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# GH-83468

func non_static_func():
pass

static var static_var:
set(_value):
var f := func ():
var g := func ():
non_static_func()
g.call()
f.call()

func test():
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot call non-static function "non_static_func()" from static function "@static_var_setter()".
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot call non-static function "non_static()" for static variable initializer.
Cannot call non-static function "non_static()" from a static variable initializer.
Loading