Project

Profile

Help

Bug #6271

closed

In 4.0, reduced-arity coercion fails when target function has optional parameters

Added by Michael Kay 5 months ago. Updated 5 months ago.

Status:
Resolved
Priority:
Low
Assignee:
Category:
Features new in 4.0
Sprint/Milestone:
-
Start date:
2023-12-01
Due date:
% Done:

0%

Estimated time:
Legacy ID:
Applies to branch:
12, trunk
Fix Committed on Branch:
12, trunk
Fixed in Maintenance Release:
Platforms:
.NET, Java

Description

See QT3 test case FunctionCall-417

         declare function local:f($x as xs:string, $y as xs:string, $z as xs:string := '1900-01-01') as xs:string {
           concat($x, '-', $y, ' on ', $z)
         };
         declare function local:g($x as xs:string, $z as function(xs:string, xs:string, xs:integer) as xs:string) {
           $z($x, $x, 22)
         };  
         local:g("ABC", local:f#2)

The function local:f#2 should be equivalent to fn($x, $y){concat($x, '-', $y, ' on ', '1900-01-01'); the call on $z should accept this arity-2 function by virtue of reduced-arity coercion, and the third argument (22) should be ignored. In fact we get a run-time type error because local:f expects a string, not an integer, as its third argument.

The effect is more noticeable when we supply something like deep-equal#2 as an argument to for-each-pair. Now that for-each-pair accepts an arity-3 callback, with the third argument being an integer position, we get a spurious failure because deep-equal has an arity-3 variant that expects a string as the third argument. (But this manifestation is not present in 12.4, because that does not yet implement the arity-3 callback on for-each-pair).

Actions #1

Updated by Michael Kay 5 months ago

  • Description updated (diff)
Actions #2

Updated by Michael Kay 5 months ago

  • Description updated (diff)
Actions #3

Updated by Michael Kay 5 months ago

  • Status changed from New to In Progress

To get this example working I made the following changes:

  1. In UserFunction, add a method to get the function item type for a specific arity within the function's arity range. The current getFunctionItemType() method gets the maximum-arity type.

  2. In UserFunctionReference, if the target function is a user function, call the new method in (1) in getFunctionItemType()

  3. Change CoercedFunction.getArity() to get the arity of the function after coercion, rather than the arity of the target function.

  4. Change UserFunctionReference.copy() to call the two-argument constructor, needed to avoid changing the arity.

So far so good but I'm not sure item (2) is enough for the general case; it only handles the case where the target is a UserFunction. (The class UserFunctionReference is misnamed; it can also be used where the target is a context-dependent system function reference).

Actions #4

Updated by Michael Kay 5 months ago

As suspected, a further fix was needed to handle references to system functions: change SystemFunction.getFunctionItemType() to return only as many argument types as appropriate for the value of getArity().

Actions #5

Updated by Michael Kay 5 months ago

  • Category set to Features new in 4.0
  • Status changed from In Progress to Resolved
  • Applies to branch 12, trunk added
  • Fix Committed on Branch 12, trunk added
  • Platforms .NET, Java added

Please register to edit this issue

Also available in: Atom PDF