godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91.02k stars 21.17k forks source link

[GDScript] Godot allows to run game with non-existing constant value. Error comes only after executing the line. #89201

Open neomonkey opened 8 months ago

neomonkey commented 8 months ago

Tested versions

Godot 4.2.1.

System information

Windows 10, Godot 4.2.1, Forward+

Issue description

When executing a game which has a scene, which uses constants from another scene, the Godot lets you build the game and run it normally. Game executes normally until Godot hits the certain line which has the non-existing const value, then game crashes and throws an error. This is problematic because if the game won't hit the certain line, it will execute normamally until then. Although you can clear this error with unit testing, it is problematic because you can ship a software with and error which is not found in compile.

Steps to reproduce

Make a scene which has const values. Make other scene which uses the const values from other scene. The game builds without and runs without any errors until the non-existing const line is reached in execution.

Minimal reproduction project (MRP)

bugtest.zip

Mickeon commented 8 months ago

This is one of the scripts in the provided MRP. Glob is a Global autoload.

extends Node2D

@onready var testNode = preload("res://testScene.tscn")
var mynode

# Called when the node enters the scene tree for the first time.
func _ready():
    mynode = testNode.instantiate()
    add_child(mynode)
    testfunc()

func testfunc():
    var test = 5

    if test == mynode.MYVAL:
        print("MYVAL ok")

    if test == mynode.MYNEWVAL:
        print("MYNEWVAL ok")

    if test == Glob.GLOB_EXISTS:
        print("GLOB WORKS")

    if test == Glob.GLOB_COMMENTED_OUT:
        print("Glob commented ok")

    if test == mynode.COMMENTED_OUT:
        print("commented ok")

    print("END no errors")

With only this context, because GDScript by a dynamic language, there's no way it would ever know that those are constants at runtime. They could also be dynamic properties. They may, or may not even exist. You may notice that in the Script Editor itself, some line numbers are grayed out because of this.

You can always enforce safe access by enabling the debug/gdscript/warnings/unsafe_property_access warning in the Project Setting.

dalexeev commented 8 months ago
neomonkey commented 8 months ago

This is one of the scripts in the provided MRP. Glob is a Global autoload.

extends Node2D

@onready var testNode = preload("res://testScene.tscn")
var mynode

# Called when the node enters the scene tree for the first time.
func _ready():
  mynode = testNode.instantiate()
  add_child(mynode)
  testfunc()

func testfunc():
  var test = 5

  if test == mynode.MYVAL:
      print("MYVAL ok")

  if test == mynode.MYNEWVAL:
      print("MYNEWVAL ok")

  if test == Glob.GLOB_EXISTS:
      print("GLOB WORKS")

  if test == Glob.GLOB_COMMENTED_OUT:
      print("Glob commented ok")

  if test == mynode.COMMENTED_OUT:
      print("commented ok")

  print("END no errors")

With only this context, because GDScript by a dynamic language, there's no way it would ever know that those are constants at runtime. They could also be dynamic properties. They may, or may not even exist. You may notice that in the Script Editor itself, some line numbers are grayed out because of this.

You can always enforce safe access by enabling the debug/gdscript/warnings/unsafe_property_access warning in the Project Setting.

Thank you this helped. I missed the "advanced" button so I didn't locate this set of options. I think that there could be a small text about the const not showing any error in the documentation. After making unsafe property access to warning I found few extra ones hiding in the code, so thumbs up.