Skip to content

Commit

Permalink
added section on common unsafe operations and their safe counterparts
Browse files Browse the repository at this point in the history
  • Loading branch information
AdriaandeJongh authored and Adriaan de Jongh committed Dec 29, 2023
1 parent 833e2c4 commit 4975792
Showing 1 changed file with 65 additions and 0 deletions.
65 changes: 65 additions & 0 deletions tutorials/scripting/gdscript/static_typing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,71 @@ if you prefer a more readable and reliable, but more verbose syntax.
``UNSAFE_*`` warnings make unsafe operations more noticeable, than unsafe lines.
Currently, ``UNSAFE_*`` warnings do not cover all cases that unsafe lines cover.

Common unsafe operations and their safe counterparts
----------------------------------------------------

Warnings: ``UNSAFE_PROPERTY_ACCESS`` and ``UNSAFE_METHOD_ACCESS``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In this example, we aim to set a property and call a method on an object
that has a script attached with ``class_name MyScript`` and that ``extends
Node2D``. If we have a reference to the object as a ``Node2D`` (for instance,
as it was passed to us by the physics system), we can first check if the
property and method exist and then set and call them if they do::
if "some_property" in node_2d:
node_2d.some_property = 20 # gives UNSAFE_PROPERTY_ACCESS warning
if node_2d.has_method("some_function"):
node_2d.some_function() # gives UNSAFE_METHOD_ACCESS warning

However, this code will return ``UNSAFE_PROPERTY_ACCESS`` and
``UNSAFE_METHOD_ACCESS`` warnings as the property and method are not present
in the referenced type - in this case a ``Node2D``. To make these operations
safe, you can first check if the object is of type ``MyScript`` using the
``is`` keyword and then declare a variable with the type ``MyScript`` on
which you can set its properties and call its methods::
if node_2d is MyScript:
var my_script: MyScript = node_2d
my_script.some_property = 20
my_script.some_function()


Warning: ``UNSAFE_CAST``
~~~~~~~~~~~~~~~~~~~~~~~~

In this example, we would like the label connected to an object entering our
collision area to show the area's name. Once the object enters the collision
area, the physics system sends a signal with a ``Node2D`` object, and the most
straightforward (but not statically typed) solution to do what we want could
be achieved like this::
func _on_body_entered(body: Node2D) -> void:
body.label.text = name # gives UNSAFE_PROPERTY_ACCESS warning

This piece of code gives a ``UNSAFE_PROPERTY_ACCESS`` warning because ``label``
is not defined in ``Node2D``. To solve this, we could first check if the
``label`` property exist and cast it to type ``Label`` before settings its text
property like so::

func _on_body_entered(body: Node2D) -> void:
if "label" in body:
(body.label as Label).text = name # gives UNSAFE_CAST warning

However, this gives an ``UNSAFE_CAST`` warning because ``body.label`` is of a
``Variant`` type. This operation can be made type safe using the
``Object.get()`` method that returns the property as a ``Variant`` (or
``null`` if the property doesn't exist), using the ``is`` keyword to determine
whether the property contains an object of the right type, and using a
variable declaration with a static type::

func _on_body_entered(body: Node2D) -> void:
var label_variant: Variant = body.get("label")
if label_variant is Label:
var label: Label = label_variant
label.text = name

Cases where you can't specify types
-----------------------------------

Expand Down

0 comments on commit 4975792

Please sign in to comment.