GDScript: Unify StringName and String
this change aims to fix #64171 by letting String and StringName be used nearly interchangeably in GDScript
registers all string methods to StringName in variant_call.cpp
-- So String methods can be used on StringNames ('&"stringname".has("str")' and vice versa)
fills in the gaps between String and StringName in variant_op.cpp
-- So '"str" in &"stringname"' works and among others
Array will silently coerce Strings and StringNames into each other when typed in any method that takes a variant input -- So Array acts like they are almost the same type, but silently converts if inserted or anything into a typed Array -- fixes #63965, all 4 tests return true
other functions in untyped Array will also compare Strings and StringNames -- fixes #68918
Dictionary now compares String and StringName keys -- which fixes #62957
lastly, the analyzer will do the same -- So it doesn't tell you you can't assign Array[String] to Array[StringName] and the compiler will make an exception in match statements for String and StringName, allowing comparisons -- which fixes #60145
also added a check for StringName in a couple places (regex.cpp and scene_rpc_interface.cpp)
Notes and things to discuss:
- Array ==, <, >, etc. still do not compare Strings and StringNames as equal, not sure if this is desired?
- Dictionary ==, <, >, still DO compare String and StringName keys as equal, but only because StringNames are converted to Strings on insertion, does that make it different from Array?
- Strings and StringNames still cannot be compared using <, >, etc. in GDScript, should this be allowed?
- Variant could benefit from an
is_string()method..
I've found no functionality regression.
As one would expect, has() and in are slower (in the ballpark of 2x as slow), insofar as arrays are concerned (and not only Array[StringName] or Array[String].) To get these results, I compared the Linux Mono editor artifact with beta 5, running lots of loops on GDScript and timing it with the Time singleton.
@MewPurPur that performance diff shouldn't be the case, although i did push a new version since you tested i think maybe the artifacts aren't production builds? i got similar performance running this test on a production build vs master: test_unify.zip
In order for the last check to pass, https://github.com/godotengine/godot-cpp/pull/930 needs to be merged to solve ambiguous overload errors
Fait critique, the benchmarks need something to compare to.
I tested this pr and it seems to 'fix' the match statement, in gd3 this worked
match node.get_name():
"test1":
pass
_:
pass
And this PR makes this code work again ( Need to do StringName("test1") for the match to work, or String(node.get_name()) without this PR)
I didn't test, but looking at the code it also fixes #68834
Thanks!
I'm not sure if it belongs here, in a separate bug report, or in a feature request, but int lacks a StringName constructor and will give "Invalid type in 'int' constructor. Cannot convert argument 1 from StringName to String." if you try to do say int(some_node.name).
To me that feels logically related to the unification of StringName and String.
Also not sure if this belongs here, but: funcs that take String like load() need something like this:
var a = ProjectSettings.get_global_class_list()
var find = a.filter(func(d): return &"ResourcePrinterPlants" in d["class"])
var c = load(str(find[0].path)).new()
It took me ages to think of using str()
Also not sure if this belongs here, but: funcs that take String like load() need something like this:
#77164 fixes this.
Also not sure if this belongs here, but: funcs that take String like load() need something like this:
#77164 fixes this.
Had a look, but don't quickly see how.