diff --git a/core/variant/dictionary.cpp b/core/variant/dictionary.cpp index f2522a4545cd..025f82a393e3 100644 --- a/core/variant/dictionary.cpp +++ b/core/variant/dictionary.cpp @@ -84,16 +84,25 @@ Variant Dictionary::get_value_at_index(int p_index) const { } Variant &Dictionary::operator[](const Variant &p_key) { - if (unlikely(_p->read_only)) { - if (likely(_p->variant_map.has(p_key))) { - *_p->read_only = _p->variant_map[p_key]; + Variant key = p_key; + if (unlikely(!_p->typed_key.validate(key))) { + if (_p->typed_fallback == nullptr) { + _p->typed_fallback = memnew(Variant); + } else { + *_p->typed_fallback = Variant(); + } + + return *_p->typed_fallback; + } else if (unlikely(_p->read_only)) { + if (likely(_p->variant_map.has(key))) { + *_p->read_only = _p->variant_map[key]; } else { *_p->read_only = Variant(); } return *_p->read_only; } else { - return _p->variant_map[p_key]; + return _p->variant_map[key]; } } diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assign_differently_typed_key.gd b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assign_differently_typed_key.gd new file mode 100644 index 000000000000..531bb751b281 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assign_differently_typed_key.gd @@ -0,0 +1,7 @@ +func get_key(): + return "key" + +func test(): + var typed: Dictionary[int, int] + typed[get_key()] = 0 + print('not ok') diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assign_differently_typed_key.out b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assign_differently_typed_key.out new file mode 100644 index 000000000000..d04f127a5c59 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assign_differently_typed_key.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Invalid index type "String" for a base of type "Dictionary[int, int]". diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_dictionary_assign_differently_typed_key.gd b/modules/gdscript/tests/scripts/runtime/errors/typed_dictionary_assign_differently_typed_key.gd new file mode 100644 index 000000000000..2f0b3bd0ebfa --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/typed_dictionary_assign_differently_typed_key.gd @@ -0,0 +1,7 @@ +func get_key() -> Variant: + return "key" + +func test(): + var typed: Dictionary[int, int] + typed[get_key()] = 0 + print('not ok') diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_dictionary_assign_differently_typed_key.out b/modules/gdscript/tests/scripts/runtime/errors/typed_dictionary_assign_differently_typed_key.out new file mode 100644 index 000000000000..44f5957556f5 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/typed_dictionary_assign_differently_typed_key.out @@ -0,0 +1,5 @@ +GDTEST_RUNTIME_ERROR +>> ERROR +>> Method/function failed. Returning: false +>> Attempted to use a variable of type 'String' into a TypedDictionary.Key of type 'int'. +not ok diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_dictionary_assign_differently_typed_value.gd b/modules/gdscript/tests/scripts/runtime/errors/typed_dictionary_assign_differently_typed_value.gd new file mode 100644 index 000000000000..607cd1a0016a --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/typed_dictionary_assign_differently_typed_value.gd @@ -0,0 +1,16 @@ +func get_value() -> Variant: + return "value" + +func test(): + var typed: Dictionary[int, int] + + # TODO: This SHOULD fail, but the assignment operator detaches the value. + typed[0] = get_value() + + # Won't fail, as the key is valid and present; value argument skips check entirely. + typed.get_or_add(0, get_value()) + + # Will fail. + typed.get_or_add(123, get_value()) + + print("not ok") diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_dictionary_assign_differently_typed_value.out b/modules/gdscript/tests/scripts/runtime/errors/typed_dictionary_assign_differently_typed_value.out new file mode 100644 index 000000000000..4bbfe1810bdd --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/typed_dictionary_assign_differently_typed_value.out @@ -0,0 +1,4 @@ +GDTEST_RUNTIME_ERROR +>> ERROR +>> Condition "!_p->typed_value.validate(value, "add")" is true. Returning: value +not ok