Summary
Compiled scripts currently do not have a clear, stable contract for redundant same-type int(...) construction.
A shape as simple as int(value) where value is already statically int should behave like a trivial identity / normalization step, but the current pipeline does not define an obvious compile-ready route for that case.
Earlier investigation briefly misframed this as a c_int_to_int or int(float) issue. After narrowing the source shape, the real unresolved surface is repeated construction of already-int values.
Background
This surfaced during benchmark work while restoring and adjusting container-heavy benchmark scripts.
To keep compilation moving, the offending redundant int(...) shape had to be removed instead of relying on it as a harmless source-level normalization.
Although the original investigation started near quadtree benchmark work, this is not a quadtree-specific problem. It is a broader compile-surface contract gap around repeated builtin int construction.
Observed Behavior
A redundant source form like this is not clearly treated as a compile-surface no-op:
func keep(value: int) -> int:
return int(value)
From code inspection, the current pipeline does not model this as a dedicated identity path. Instead, bare int(...) is handled as builtin constructor resolution, which means the result depends on constructor metadata and boundary compatibility rules rather than a simple same-type roundtrip rule.
The practical consequence is that source authors cannot safely assume that redundant int(...) around already-int values is compile-ready, even though the source-level intent is trivial.
Minimal Reproduction
class_name RedundantIntConstructor
extends Node
func keep(value: int) -> int:
return int(value)
This issue is about the redundant same-type constructor itself. It is intentionally narrower than unrelated numeric routes such as int(float_value).
Cause Chain
-
Frontend expression typing treats bare int(...) as a builtin type-meta constructor call, not as an identity operation.
FrontendExpressionSemanticSupport.resolveCallExpressionType(...)
FrontendExpressionSemanticSupport.resolveBareTypeMetaConstructorCallExpression(...)
-
Builtin constructor applicability is then decided through constructor metadata and callable-argument matching.
FrontendConstructorResolutionSupport.resolveBuiltinConstructor(...)
FrontendConstructorResolutionSupport.matchesCallableArguments(...)
-
The boundary-compatibility layer defines special routes such as ALLOW_WITH_PACK and ALLOW_WITH_INTRINSIC_CAST, but it does not expose a dedicated redundant same-type int -> int identity contract.
FrontendVariantBoundaryCompatibility.classify(...)
-
Non-Variant builtin constructor calls lower through the ordinary constructor path rather than a no-op/self-roundtrip path.
FrontendSequenceItemInsnLoweringProcessors.lowerConstructorCall(...)
-
Backend regular builtin construction expects exact constructor metadata or a supported helper-backed constructor surface.
CBuiltinBuilder.constructRegularBuiltin(...)
-
The generated builtin constructor surface exposes entries such as:
godot_new_int_with_Variant
godot_new_int_with_String
-
There is no obvious corresponding godot_new_int_with_int self-constructor surface in the generated builtin header, so redundant int(int_value) does not have a clearly defined backend-ready route.
-
The result is a compile-surface gap: repeated int(...) over an already-int value is not modeled as a guaranteed safe identity operation, and benchmark/script work has to remove that source shape instead of relying on it.
Expected Behavior
GDCC should make the contract for redundant same-type int(...) explicit.
The most natural behavior is:
int(value) where value is already statically int should compile successfully.
- The route should lower either as a no-op / slot reuse or as another clearly defined backend-safe identity form.
If the project intentionally does not want to support redundant builtin self-construction, then the compiler should reject it at one clear frontend boundary with a targeted diagnostic.
What should not happen is leaving the source form in a compile-blocking gray area where it is semantically trivial but not actually compile-ready.
Scope
This issue is about redundant same-type int(...) construction in compiled scripts.
It is not primarily:
- a
c_int_to_int intrinsic generation issue,
- a
c_int_to_float issue,
- the broader
int(float_value) route,
- a quadtree algorithm bug,
- the existing
int(Variant) special constructor path.
The benchmark work only exposed the gap; it is not the root cause.
Relevant Implementation Points
src/main/java/gd/script/gdcc/frontend/sema/analyzer/support/FrontendExpressionSemanticSupport.java
resolveCallExpressionType(...)
resolveBareTypeMetaConstructorCallExpression(...)
src/main/java/gd/script/gdcc/frontend/sema/analyzer/support/FrontendConstructorResolutionSupport.java
resolveBuiltinConstructor(...)
matchesCallableArguments(...)
src/main/java/gd/script/gdcc/frontend/sema/analyzer/support/FrontendVariantBoundaryCompatibility.java
src/main/java/gd/script/gdcc/frontend/lowering/pass/body/FrontendSequenceItemInsnLoweringProcessors.java
lowerConstructorCall(...)
src/main/java/gd/script/gdcc/backend/c/gen/CBuiltinBuilder.java
constructRegularBuiltin(...)
src/test/java/gd/script/gdcc/backend/c/gen/CConstructInsnGenTest.java
constructBuiltinShouldRejectVariantOperandWithoutExactMetadata()
src/main/c/codegen/include_451/godot/godot_builtin.h
- current
godot_new_int_with_* constructor surface
doc/module_impl/frontend/frontend_builtin_constructor_variant_argument_plan.md
Suggested Acceptance Coverage
Add focused coverage for redundant same-type int(...):
- frontend semantic coverage for
return int(value) where value: int,
- lowering coverage proving the accepted form does not depend on a nonexistent self-constructor surface,
- backend/codegen coverage proving the route either:
- compiles as an identity/no-op contract, or
- fails immediately with one intentional, explicit diagnostic,
- regression coverage from a real compiled script fixture so benchmark and container-heavy scripts can rely on the chosen contract consistently.
Notes
This issue replaces the earlier, narrower misread that focused on c_int_to_int / int(float) during benchmark investigation.
The corrected scope is simpler: repeated int(...) over already-int values should not be an accidental compile blocker.
Summary
Compiled scripts currently do not have a clear, stable contract for redundant same-type
int(...)construction.A shape as simple as
int(value)wherevalueis already staticallyintshould behave like a trivial identity / normalization step, but the current pipeline does not define an obvious compile-ready route for that case.Earlier investigation briefly misframed this as a
c_int_to_intorint(float)issue. After narrowing the source shape, the real unresolved surface is repeated construction of already-intvalues.Background
This surfaced during benchmark work while restoring and adjusting container-heavy benchmark scripts.
To keep compilation moving, the offending redundant
int(...)shape had to be removed instead of relying on it as a harmless source-level normalization.Although the original investigation started near quadtree benchmark work, this is not a quadtree-specific problem. It is a broader compile-surface contract gap around repeated builtin
intconstruction.Observed Behavior
A redundant source form like this is not clearly treated as a compile-surface no-op:
From code inspection, the current pipeline does not model this as a dedicated identity path. Instead, bare
int(...)is handled as builtin constructor resolution, which means the result depends on constructor metadata and boundary compatibility rules rather than a simple same-type roundtrip rule.The practical consequence is that source authors cannot safely assume that redundant
int(...)around already-intvalues is compile-ready, even though the source-level intent is trivial.Minimal Reproduction
This issue is about the redundant same-type constructor itself. It is intentionally narrower than unrelated numeric routes such as
int(float_value).Cause Chain
Frontend expression typing treats bare
int(...)as a builtin type-meta constructor call, not as an identity operation.FrontendExpressionSemanticSupport.resolveCallExpressionType(...)FrontendExpressionSemanticSupport.resolveBareTypeMetaConstructorCallExpression(...)Builtin constructor applicability is then decided through constructor metadata and callable-argument matching.
FrontendConstructorResolutionSupport.resolveBuiltinConstructor(...)FrontendConstructorResolutionSupport.matchesCallableArguments(...)The boundary-compatibility layer defines special routes such as
ALLOW_WITH_PACKandALLOW_WITH_INTRINSIC_CAST, but it does not expose a dedicated redundant same-typeint -> intidentity contract.FrontendVariantBoundaryCompatibility.classify(...)Non-
Variantbuiltin constructor calls lower through the ordinary constructor path rather than a no-op/self-roundtrip path.FrontendSequenceItemInsnLoweringProcessors.lowerConstructorCall(...)Backend regular builtin construction expects exact constructor metadata or a supported helper-backed constructor surface.
CBuiltinBuilder.constructRegularBuiltin(...)The generated builtin constructor surface exposes entries such as:
godot_new_int_with_Variantgodot_new_int_with_StringThere is no obvious corresponding
godot_new_int_with_intself-constructor surface in the generated builtin header, so redundantint(int_value)does not have a clearly defined backend-ready route.The result is a compile-surface gap: repeated
int(...)over an already-intvalue is not modeled as a guaranteed safe identity operation, and benchmark/script work has to remove that source shape instead of relying on it.Expected Behavior
GDCC should make the contract for redundant same-type
int(...)explicit.The most natural behavior is:
int(value)wherevalueis already staticallyintshould compile successfully.If the project intentionally does not want to support redundant builtin self-construction, then the compiler should reject it at one clear frontend boundary with a targeted diagnostic.
What should not happen is leaving the source form in a compile-blocking gray area where it is semantically trivial but not actually compile-ready.
Scope
This issue is about redundant same-type
int(...)construction in compiled scripts.It is not primarily:
c_int_to_intintrinsic generation issue,c_int_to_floatissue,int(float_value)route,int(Variant)special constructor path.The benchmark work only exposed the gap; it is not the root cause.
Relevant Implementation Points
src/main/java/gd/script/gdcc/frontend/sema/analyzer/support/FrontendExpressionSemanticSupport.javaresolveCallExpressionType(...)resolveBareTypeMetaConstructorCallExpression(...)src/main/java/gd/script/gdcc/frontend/sema/analyzer/support/FrontendConstructorResolutionSupport.javaresolveBuiltinConstructor(...)matchesCallableArguments(...)src/main/java/gd/script/gdcc/frontend/sema/analyzer/support/FrontendVariantBoundaryCompatibility.javasrc/main/java/gd/script/gdcc/frontend/lowering/pass/body/FrontendSequenceItemInsnLoweringProcessors.javalowerConstructorCall(...)src/main/java/gd/script/gdcc/backend/c/gen/CBuiltinBuilder.javaconstructRegularBuiltin(...)src/test/java/gd/script/gdcc/backend/c/gen/CConstructInsnGenTest.javaconstructBuiltinShouldRejectVariantOperandWithoutExactMetadata()src/main/c/codegen/include_451/godot/godot_builtin.hgodot_new_int_with_*constructor surfacedoc/module_impl/frontend/frontend_builtin_constructor_variant_argument_plan.mdSuggested Acceptance Coverage
Add focused coverage for redundant same-type
int(...):return int(value)wherevalue: int,Notes
This issue replaces the earlier, narrower misread that focused on
c_int_to_int/int(float)during benchmark investigation.The corrected scope is simpler: repeated
int(...)over already-intvalues should not be an accidental compile blocker.