ACTION A-642-06 on Bug 29586

(:
   ACTION A-642-06 on Bug 29586

   Recall that function coercion occurs to convert an argument value or 
a return
   value to its expected TypedFunctionTest type.  Function coercion wraps a
   function in a new function with signature the same as the expected type.
   This function has the same name as the function it wraps.

   The specification notes that static typing will often be able to 
reduce the
   number of places where this is actually necessary.  However, 
FunctionTest
   matching is described in terms of checking its function signature and
   annotations.  This means that the static type of a function item is 
entirely
   dependent on its signature and annotations, and not on, for example, the
   static type of the function body.

   For example, while

   function() as xs:integer { 1 } instance of function() as xs:integer

   is true.

   function() { 1 } instance of function() as xs:integer

   is false.

   For comparison, it is implementation defined whether or not

   (1.2 + 0.8) instance of xs:integer

   is true.

   This has the consequence that an implementation may be forced to perform
   unnecessary function coercion.
:)

(: The following function declarations differ only in their names and
    signatures.  The function bodies are identical.
  :)

declare function local:items-to-items($arg)
{
   xs:long(
     typeswitch ($arg)
        case xs:long return 1
        case xs:integer return 2
        default return 3)
};

declare function local:anyAtomic-to-items($arg)
{
   xs:long(
     typeswitch ($arg)
        case xs:long return 1
        case xs:integer return 2
        default return 3)
};

declare function local:items-to-integer($arg) as xs:integer
{
   xs:long(
     typeswitch ($arg)
        case xs:long return 1
        case xs:integer return 2
        default return 3)
};

declare function local:integer-to-items($arg as xs:integer)
{
   xs:long(
     typeswitch ($arg)
        case xs:long return 1
        case xs:integer return 2
        default return 3)
};

declare function local:integer-to-integer($arg as xs:integer) as xs:integer
{
   xs:long(
     typeswitch ($arg)
        case xs:long return 1
        case xs:integer return 2
        default return 3)
};

declare function local:integer-to-long($arg as xs:integer) as xs:long
{
   xs:long(
     typeswitch ($arg)
        case xs:long return 1
        case xs:integer return 2
        default return 3)
};

declare function local:invoke($arg as function(xs:integer) as xs:integer)
   as xs:integer
{
   $arg(1)
};

(
   (: Case 1: local:integer-to-integer#1 is exactly the expected type
      * return type xs:integer is exactly the expected xs:integer
      * expected xs:integer is exactly the argument type xs:integer

      Function coercion can be eliminated.
    :)
   local:invoke(local:integer-to-integer#1),


   (: Case 2: local:integer-to-long#1, more specific return type
      * return type xs:long is subtype of expected xs:integer
      * expected xs:integer is exactly the argument type xs:integer

      Function coercion can be eliminated.
    :)
   local:invoke(local:integer-to-long#1),


   (: Case 3: local:items-to-integer#1, less specific argument type
      * return type xs:integer is exactly the expected xs:integer
      * expected xs:integer is a subtype of argument type item()*

      Function coercion can be eliminated.
    :)
   local:invoke(local:items-to-integer#1),


   (: Case 4: local:integer-to-items#1, less specific return type
      * return type item()* is NOT a subtype of expected xs:integer
      * expected xs:integer is exactly the argument type xs:integer

      Function coercion cannot (currently) be eliminated.
    :)
   local:invoke(local:integer-to-items#1),


   (: Case 5: local:anyAtomic-to-items#1, less specific return type
      * return type item()* is NOT a subtype of expected xs:integer
      * expected xs:integer is a subtype of the argument type 
xs:anyAtomicType

      Function coercion cannot (currently) be eliminated.
    :)

   local:invoke(local:integer-to-items#1),


   (: Case 6: local:items-to-items#1, less speific argument and return 
type.
      * return type item()* is NOT a subtype of expected xs:integer
      * expected xs:integer is a subtype of argument type item()*

      Function coercion cannot (currently) be eliminated.
    :)
   local:invoke(local:items-to-items#1),

   (: Case 7: [2, 2, 2] matches function(xs:integer) as item()*,
              (like Case 4)
      * return type item()* is NOT a subtype of expected xs:integer
      * expected xs:integer is exactly the argument type xs:integer

      Function coercion cannot (currently) be eliminated.

     Propose that array(V) should match function(xs:integer) as V.

    :)
   local:invoke([2, 2, 2]),

   (: Case 8: map { 1 : 2, 2 : 2} matches function(xs:anyAtomicType) as 
item()*.
              (like Case 5)
      * return type item()* is NOT a subtype of expected xs:integer
      * expected xs:integer is a subtype of the argument type 
xs:anyAtomicType

      Function coercion cannot (currently) be eliminated.

     Propose that map(K, V) should match function(xs:anyAtomicType) as V.

    :)
   local:invoke(map { 1 : 2, 2 : 2 } )

)

Received on Tuesday, 10 May 2016 10:34:06 UTC