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

Autocomplete doesn't correctly work on implicitly casted variables #86513

Closed
jjaxu opened this issue Dec 26, 2023 · 2 comments · Fixed by #85224
Closed

Autocomplete doesn't correctly work on implicitly casted variables #86513

jjaxu opened this issue Dec 26, 2023 · 2 comments · Fixed by #85224

Comments

@jjaxu
Copy link

jjaxu commented Dec 26, 2023

Tested versions

Experienced in 4.1 and 4.2 stable versions.

System information

Godot v4.2.1.stable - Windows 10.0.22621 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 4080 (NVIDIA; 31.0.15.4601) - AMD Ryzen 9 7900X 12-Core Processor (24 Threads)

Issue description

This issue is on the autocomplete features of using static types in GDScript, and not the actual execution behaviour. The actual execution behaviour works as expected.

In GDscript, there are two ways to assign variables with a specific type, they are the following, with an example:

  1. var result := foo() as Array (explicit cast using the as keyword)
  2. var result: Array = foo() (implicit cast using static typing : <TypeName>operator)

One benefit of static typing is that it provides useful autocomplete suggestions when interacting with the variable. For example, the above result is of type Array, so autocomplete correctly shows methods associated with the array class:
image

This works all and well until the assignment is the value of a function call that returns a Variant type such as .get on a dictionary or any user-defined function like this simple example:

func arr_or_dict(x: int) -> Variant:
    if x == 0:
        return []
    return {}

The above example returns a Variant type of either Array or Dictionary. When casted using method 1 (as keyword`), the autocomplete works correctly, displaying the attributes associated with the casted type:

func explicit_cast():
    var result := arr_or_dict(0) as Array

image

The problem occurs when using method 2 to implicitly cast the return value - It appears that the autocomplete suggestions are incorrectly showing the methods associated with Dictionary, despite it being statically declared as type Array (and the actual type is Array as 0 is the parameter, triggering the first return [] statement:

func implict_cast():
    var result: Array = arr_or_dict(0)
	

image

After testing it a bit more, it seems like the editor will always show options associated with the type of the variable of the last return statement of the function and ignore the declared type. In the example given, it is Dictionary from the last line return {}. If I switch [] and {} and cast result into Dictionary, it will show array methods because the type of the last return statement will be Array.

The expected behaviour should be that the autocomplete suggestions always show the methods declared by the static type Array, exactly like the behaviour of explicitly using as keyword to cast.

Despite the autocomplete showing incorrect options, the execution behaviour is still correct, result is still of type Array, and calling dictionary methods given by the faulty autocomplete will still throw an error.

Steps to reproduce

  1. Attach empty script to any node in any scene
  2. Paste in the MRP
  3. Uncomment the result. lines
  4. In the Godot editor, trigger the autocomplete associated with the above line and observe the incorrect suggestions of implict_cast compared to the correct explicit_cast

Minimal reproduction project (MRP)

(Code is below, will also include a zipped project on Godot 4.2.1: godot-autocomplete-bug-mrp.zip)

extends Node2D

func arr_or_dict(x: int) -> Variant:
	if x == 0:
		return []
	return {}

# explicit cast (correct)
func explicit_cast():
	var result := arr_or_dict(0) as Array
	# autocomplete works correctly when using `result.`
	# result.

# implicit cast (incorrect)
func implict_cast():
	var result: Array = arr_or_dict(0)
	# when using `result.`, autocomplete shows suggestions associated with the type of the LAST return value (dict in this case)
	# result.

Tasks

No tasks being tracked yet.
@HolonProduction
Copy link
Member

HolonProduction commented Dec 26, 2023

Duplicate of #78820 but we can keep this one open, since it adds the additional detail of the interfered type being Dictionary (although that's not really bug).

@Phoebus
Copy link

Phoebus commented Jan 7, 2024

I don't know how useful it is, but I came across the same problem without the use of "return" though.

I am learning to code a finite state machine and in the process I created a custom class named "state" that has the following code.

class_name state
extends Node

signal Transitioned

func Enter() -> void:
	
	pass

func Exit() -> void:
	
	pass

func Update(_delta: float) -> void:
	
	pass

func Physics_Update(_delta: float) -> void:
	
	pass

There is also a StateMachine that contains a function that is called when a transition between two states happens. Inside this function there is a "new_state" variable that is casted as a "state" type.

func StateTransition(curr_state: state, next_state_name: String) -> void:
	
	if current_state != curr_state:
		
		return
	
	var new_state: state = states.get(next_state_name.to_lower())
	if !new_state:
		
		return
	
	if current_state:
		
		current_state.Exit()
	
	new_state.Enter()
	
	current_state = new_state

What is supposed to happen, is that autocomplete needs to suggest me the functions that "state" defines when accessing the variable "new_state" but autocomplete doesn't work...

Desktop Screenshot 2024 01 06 - 22 50 29 53

However, when I use the "as state" method of casting, autocomplete DOES work.

Desktop Screenshot 2024 01 07 - 12 05 00 45

Why is Godot acting differently? Aren't these two situations basically the same exact thing?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants