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

Incorrect array element type error for arg when method is called on non-typed class property with non-typed arg #86963

Closed
moritztim opened this issue Jan 8, 2024 · 5 comments

Comments

@moritztim
Copy link

moritztim commented Jan 8, 2024

Tested versions

  • Reproducible in v4.2.1.stable.arch_linux

System information

Arch Linux

Issue description

A class has a method (some_method) that accepts an Array[String].
some_method is called with an array containing a constant.
If the class instance is stored as a non-typed property (of another class) and the method is called with an identical array, the engine raises a type error.

Steps to reproduce

Code:

extends Object

var prop
var typed_prop: C

class C:
	func trouble_maker(_a: Array[String]): return

func bug():
	var local = C.new()
	local.trouble_maker([""])
	print("local works")
	
	typed_prop = C.new()
	typed_prop.trouble_maker([""])
	print("typed_prop works")

	var arg: Array[String] = [""]
	prop = C.new()
	prop.trouble_maker(arg)
	print("prop with typed arg works")

	prop = C.new()
	prop.trouble_maker([""])
	print("prop with expression arg works")

Output:

local works
typed_prop works
prop with typed arg works

Error:

Invalid type in function 'trouble_maker' in base 'RefCounted (C)'. The array of argument 1 (Array) does not have the same element type as the expected type array argument.

Minimal reproduction project (MRP)

mrp.zip

Minimal reproduction script

extends Object
var prop
class C: func m(_a: Array[String]): return
func f():
 prop = C.new()
 prop.m([""])

to get the error, run f()

moritztim added a commit to moritztim/Godot-Form that referenced this issue Jan 8, 2024
@moritztim moritztim changed the title Array element type error when array element is class constant and instance is property Array element type error when array element is constant and instance is non-typed class property Jan 8, 2024
@moritztim moritztim changed the title Array element type error when array element is constant and instance is non-typed class property Incorrect argument array element type error when argument is a constant in an array and the instance is stored in a non-typed class property Jan 8, 2024
@moritztim moritztim changed the title Incorrect argument array element type error when argument is a constant in an array and the instance is stored in a non-typed class property Incorrect method argument array element type error when instance is stored in a non-typed class property Jan 8, 2024
@moritztim moritztim changed the title Incorrect method argument array element type error when instance is stored in a non-typed class property Incorrect array element type error for arg when method is called on non-typed class property with non-typed arg Jan 8, 2024
@dalexeev
Copy link
Member

dalexeev commented Jan 8, 2024

This is expected behavior, although not obvious. An array literal ([]) is implicitly made typed only in a context where a typed array is expected (you can find the list in the discussion). In an untyped context, the literal remains untyped.

This will be fixed when we add a typed array constructor (Array[int]([])). Currently you can use a type cast ([] as Array[int]), however note that this only works with array literals, not arbitrary expressions (array as Array[int]).

@moritztim
Copy link
Author

Alright, makes sense. Doesn't that make the error message technically incorrect tho?

The array of argument 1 (Array) does not have the same element type as the expected type array argument.

Shouldn't it be something like

The array of argument 1 (Array) cannot be verified to have the same element type as the expected type array argument.

@moritztim
Copy link
Author

I don't get why this works tho:

var local = C.new()
	local.trouble_maker([""])
	print("local works")

@dalexeev
Copy link
Member

dalexeev commented Jan 9, 2024

Doesn't that make the error message technically incorrect tho?

The array of argument 1 (Array) does not have the same element type as the expected type array argument.

Shouldn't it be something like

The array of argument 1 (Array) cannot be verified to have the same element type as the expected type array argument.

By default, GDScript produces no errors/warnings if the source's static type is a supertype of the target's type (in other words, wider than expected). GDScript generates static errors only if it's guaranteed that the code is incorrect, otherwise static analyzer leaves this check for runtime. At runtime, we know the exact types, so "cannot be verified" is incorrect.

I don't get why this works tho:

var local = C.new()
	local.trouble_maker([""])
	print("local works")

There is some inconsistency in how weak type inference works for local variables. The type of initializer expression of a local variable is used as its type, if you don't explicitly specify type and even don't use :=. So it looks like a bug similar to the one fixed in #81332.

Note: In theory, unless you assign a local variable to something else, it cannot change its type (unlike a member variable, which can be changed "between the lines"), so GDScript could treat the variable as if it were explicitly declared statically typed (but in practice, the GDScript compiler is not so smart and does not currently use SSA optimizations).

@moritztim
Copy link
Author

Ok that all makes a lot of sense! Thanks for taking the time to explain :)

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

No branches or pull requests

2 participants