X Tutup
Skip to content

Reorder registration of types, to register supertypes before subtypes.#111431

Merged
Repiteo merged 1 commit intogodotengine:masterfrom
Ivorforce:registration-order-3
Oct 9, 2025
Merged

Reorder registration of types, to register supertypes before subtypes.#111431
Repiteo merged 1 commit intogodotengine:masterfrom
Ivorforce:registration-order-3

Conversation

@Ivorforce
Copy link
Member

@Ivorforce Ivorforce commented Oct 8, 2025

This PR addresses various inconsistencies around registration order, where subtypes are registered before their respective supertypes.

My strategy:

  • "Fundamental" types (like Texture) that are referenced in many of the blocks are registered at the top.
  • Other supertypes are placed above the respective subtypes, if it fits the respective block. Most move only a few lines.
  • The exception is CanvasItem which is moved from the 2D nodes to the Control nodes (since they're registered above 2D, and also inherit from CanvasItem).
  • The optional "XR" block is not depended on and moves to the bottom of the #ifdef.

I think that covers everything. I worked entirely with cut-paste; no registrations were modified, added or removed.

About the docs change

The docs instantiate classes automatically to infer default values of properties. Abstract classes cannot be instantiated. To infer default values in abstract classes, the docs will try to instantiate a subclass.
This PR triggered a re-order, which made CanvasItem's 'designated subclass' be Control instead of Node2D. This caused physics_interpolation_mode to be changed, since Node2D has a different default from Control and CanvasItem.

I fixed the problem by supplying a default directly in CanvasItem explicitly. This required adding an explicit path for 'non-instantiatable objects that supply their own defaults', which was previously not supported.

Another solution would have been to check the superclass has the same property, and use the same default. However, this may not catch if the subtype changes the default. But, this could be added in a future PR. Even so, to respect ADD_PROPERTY_DEFAULT would be a prerequisite, because otherwise incorrect values may appear. So I think adding support for ADD_PROPERTY_DEFAULT in abstract classes is the best way to fix this, for now.

@Ivorforce Ivorforce added this to the 4.x milestone Oct 8, 2025
@Ivorforce Ivorforce requested a review from a team as a code owner October 8, 2025 20:44
@Ivorforce Ivorforce force-pushed the registration-order-3 branch from e86b89c to f8ab3b3 Compare October 8, 2025 21:22
@Ivorforce Ivorforce requested a review from a team as a code owner October 8, 2025 21:22
@Ivorforce Ivorforce force-pushed the registration-order-3 branch 2 times, most recently from aa48ded to c886394 Compare October 8, 2025 22:30
Copy link
Member

@aaronfranke aaronfranke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Indeed, we should register types at a minimum in order of inheritance, and maybe in order of dependency too when appropriate.

Fun fact, with GDExtension C++, you MUST register types in order of inheritance, or else the extension breaks. But it seems doing this in engine code has been unhelpfully flexible so far, so I agree we should make it more strict to ensure things are registered in order (this PR then PR #106873).

@akien-mga
Copy link
Member

The docs instantiate classes automatically to infer default values of properties. Abstract classes cannot be instantiated. To infer default values in abstract classes, the docs will try to instantiate a subclass. This PR triggered a re-order, which made CanvasItem's 'designated subclass' be Control instead of Node2D. This caused physics_interpolation_mode to be changed, since Node2D has a different default from Control and CanvasItem.

I fixed the problem by supplying a default directly in CanvasItem explicitly. This required adding an explicit path for 'non-instantiatable objects that supply their own defaults', which was previously not supported.

I wonder if we could allow instantiating abstract classes only for doctool, to retrieve the default values properly. The current behavior of inferring it from a subclass is pretty iffy as we see here.

Otherwise yes, we'd have to sprinkle some ADD_PROPERTY_DEFAULT as needed, like we already do for some platform-specific APIs.

@akien-mga
Copy link
Member

akien-mga commented Oct 9, 2025

I support reordering registrations to be in the correct inheritance order, but I wonder: is there any actual problem caused by the existing out-of-order registrations? What are we solving exactly besides making things "correct"?

@Ivorforce
Copy link
Member Author

Ivorforce commented Oct 9, 2025

I wonder if we could allow instantiating abstract classes only for doctool, to retrieve the default values properly. The current behavior of inferring it from a subclass is pretty iffy as we see here.

Unless the class is also C++-abstract, it should be possible.

I support reordering registrations to be in the correct inheritance order, but I wonder: is there any actual problem caused by the existing out-of-order registrations? What are we solving exactly besides making things "correct"?

Yes, two problems are addressed with these changes:

  • We currently have some classes with inconsistent state (e.g. using GDCLASS even though they're never explicitly registered). They often end up being registered automatically through subclasses. This can lead to unexpected behavior when querying ClassDB about these classes, or when asking them about their class name (which might not be the name of a registered class). By enforcing expected registration behavior, we can catch these problems early, which is what the eventual follow-up implements: Warn when classes are registered out of order #106873
  • For performance purposes, we should start creating certain caches for Object types. The best time to create a cache is when the class is finalized. Unfortunately, some classes are registered before their superclasses, so they can't be easily finalized. I ran into this issue when creating property caches, so I had to work around the improper registration order by updating subclass caches when the super type finalizes. This will not work for every type of cache. See PR Optimize property access for Object subtypes #106646

@Ivorforce Ivorforce force-pushed the registration-order-3 branch from c886394 to 9843a01 Compare October 9, 2025 09:50
@akien-mga akien-mga modified the milestones: 4.x, 4.6 Oct 9, 2025
@Repiteo Repiteo merged commit 5913469 into godotengine:master Oct 9, 2025
20 checks passed
@Repiteo
Copy link
Contributor

Repiteo commented Oct 9, 2025

Thanks!

@Ivorforce Ivorforce deleted the registration-order-3 branch October 9, 2025 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

X Tutup