Skip to content

Keep declared and refined function return types separate in FuncType#2716

Merged
ChristianGruen merged 2 commits into
BaseXdb:mainfrom
GuntherRademacher:refined-function-type
Jul 8, 2026
Merged

Keep declared and refined function return types separate in FuncType#2716
ChristianGruen merged 2 commits into
BaseXdb:mainfrom
GuntherRademacher:refined-function-type

Conversation

@GuntherRademacher

Copy link
Copy Markdown
Member

The function return type in the FuncType of a function item may currently be affected by the type of the function body. This may be helpful for enabling optimizations based on a narrower type, but it makes instance of tests go wrong, as in the following, returning true, where the correct result is false:

fn() {42} instance of fn() as xs:integer

The changes here attempt to achieve both, optimization and correctness of instance of, by keeping the refined type in addition to the declared type in FuncType. The eq and instanceOf methods still stick to the declared type, while consumers with optimization in mind now refer to the refined type.

As instance of now observes the declared type rather than the inferred body type, the same holds for the type reported by inspect:function/inspect:type and by adaptive/BaseX serialization: an inline function without a declared return type is now shown as fn() as item()* instead of by its body type. This keeps the displayed type consistent with what instance of checks.

This also uncovered a different bug: both Closure and Var are normalizing types to null when they are eq(ITEM_ZM). This held for unresolved type references, because such a reference - a forward reference, e.g. to a recursive record type like fn:schema-type-record - dereferences to item() until it has been resolved. Since SeqType.eq dereferences before comparing, the reference compared equal to item()* and its declared type was dropped. Once dropped it was never restored, so the declared type was effectively never enforced (e.g. let $x as fn:schema-type-record* := 1 was silently accepted). As a collateral fix, this is solved by having SeqType.eq compare unresolved TypeRefs by object identity. This also keeps built-in-record-type-305 passing, which would otherwise have regressed.

Regression tests have been added for all changes. QT4 test cases built-in-record-type-303 and built-in-record-type-304 also now pass.

@ChristianGruen ChristianGruen merged commit b98a08f into BaseXdb:main Jul 8, 2026
1 check passed
@ChristianGruen ChristianGruen deleted the refined-function-type branch July 8, 2026 17:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants