Project

Profile

Help

Bug #6239

closed

Function conversion rules: xs:anyURI to xs:string conversion

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

Status:
Closed
Priority:
Normal
Assignee:
Category:
XPath conformance
Sprint/Milestone:
-
Start date:
2023-11-04
Due date:
% Done:

100%

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

Description

The XPath 3.1 function conversion rules say that it should be possible to supply an item of type xs:anyURI where the required type is xs:string. This is only working in the case where the static type of the function argument is known to be xs:anyURI; it fails with a type error if the type is only discovered to be xs:anyURI at evaluation time.

Actions #1

Updated by Michael Kay 6 months ago

Demonstrated by QT4 test case function-call-promotion-405 run with -lang:XQ31.

Actions #2

Updated by Michael Kay 6 months ago

The test turned out to be incorrect. There is a problem, but it's quite hard to find a test case that reveals it.

The ItemChecker is letting an xs:anyURI through where an xs:string is expected, which means that a call that supplies an xs:anyURI to a function expecting an xs:string actually succeeds -- but it arrives as an xs:anyURI, not as an xs:string. How do we detect the difference? The obvious way is by using an "instance of" test, but this will be optimized away because we think we know the type of the value statically. Perhaps we should mix the supplied value into a sequence with other values and then do an instance-of test on a selected item from that sequence...?

I have revised the test function-call-promotion-405 so it now demonstrates the failure.

Actions #3

Updated by Michael Kay 6 months ago

Because the "treat as" expression is implemented using the ItemChecker class, and ItemChecker treats an xs:anyURI as an xs:string, the expression $x treat as xs:string* can succeed (incorrectly) when the sequence $x contains an xs:anyURI.

I have added QT3 test treat-as-26 to demonstrate this.

Actions #4

Updated by Michael Kay 6 months ago

  • Status changed from New to Resolved
  • Applies to branch deleted (11)
  • Fix Committed on Branch 12, trunk added

Fixed on the 12.x and main branches.

Although the bug is present in earlier releases, it has caused no trouble, so I shall refrain from fixing it unless it proves necessary. (The main changes needed are in ItemChecker and TypeChecker).

Actions #5

Updated by Michael Kay 6 months ago

  • Status changed from Resolved to In Progress

Reopening because there is a need to test that the new way of handling these promotions generates SEF files that existing SaxonJS releases will accept.

Actions #6

Updated by Michael Kay 6 months ago

I'm now looking at the SEF file output to ensure backwards compatibility in SaxonJS.

For this function (in test as-0152):

<xsl:function name="f:promote" as="xs:double">
      <xsl:param name="p"/>
      <xsl:sequence select="$p"/>
</xsl:function>

we are now generating:

<function name='Q{f}promote' line='10' module='file:/Users/mike/GitHub/xslt30-test/tests/attr/as/as-0152.xsl' flags='pU' as='1AO' slots='1'>
   <arg name='Q{}p' as='*'/>
   <check role='body' baseUri='file:/Users/mike/GitHub/xslt30-test/tests/attr/as/as-0152.xsl' ns='f=f xs=~ xsl=~' line='12' card='1' diag='5|0|XTTE0780|f:promote#1'>
    <convert from='A' to='AO' flags='p' diag='5|0|XTTE0780|f:promote#1'>
     <data diag='5|0|XTTE0780|f:promote#1'>
      <varRef name='Q{}p' slot='0'/>
     </data>
    </convert>
   </check>
  </function>

Specifcally, the varRef is wrapped in data (to do atomisation) then convert which now does both numeric type promotion and conversion from untyped atomic, and then check for a cardinality check.

Saxon 11 generated:

<function name='Q{f}promote' line='10' module='file:/Users/mike/GitHub/xslt30-test/tests/attr/as/as-0152.xsl' eval='16' flags='pU' as='1AO' slots='1'>
   <arg name='Q{}p' as='*'/>
   <check role='body' baseUri='file:/Users/mike/GitHub/xslt30-test/tests/attr/as/as-0152.xsl' ns='f=f xs=~ xsl=~' line='12' card='1' diag='5|0|XTTE0780|f:promote#1'>
    <convert from='A' to='AO' flags='p' diag='5|0|XTTE0780|f:promote#1'>
     <cvUntyped to='AO' diag='5|0|XTTE0780|f:promote#1'>
      <data diag='5|0|XTTE0780|f:promote#1'>
       <varRef name='Q{}p' slot='0'/>
      </data>
     </cvUntyped>
    </convert>
   </check>
  </function>

So the conversion was done in two steps: cvUntyped to convert untypedAtomic to double, and then convert to do promotion from decimal/float to double.

Attempting to run the SEF file from Saxon 12.x using SaxonJS 2.6 results in "Incompatible operands: xs:untypedAtomic (01.123) and xs:double". So we're going to need to adapt the SEF output from 12.x when target=JS.

Actions #7

Updated by Michael Kay 6 months ago

  • Status changed from In Progress to Resolved

This has been done. Marking as resolved.

Actions #8

Updated by O'Neil Delpratt 5 months ago

  • Status changed from Resolved to Closed
  • % Done changed from 0 to 100
  • Fixed in Maintenance Release 12.4 added

Bug fix applied in the Saxon 12.4 maintenance release

Please register to edit this issue

Also available in: Atom PDF