Project

Profile

Help

Bug #6313

closed

Static type error from fn:remove()

Added by Debbie Lockett 4 months ago. Updated 3 months ago.

Status:
Resolved
Priority:
Normal
Assignee:
Category:
XPath conformance
Sprint/Milestone:
-
Start date:
2024-01-09
Due date:
% Done:

0%

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

Description

I've discovered a weird bug when using fn:remove(); e.g.

<xsl:variable name="result" select="remove( (xs:integer('100'), xs:string('abc')), 1)"/>

Running the attached stylesheet (e.g. from the command line with net.sf.saxon.Transform -xsl:removeBug.xsl -it:main) produces a static type error:

Error at char 21 in xsl:variable/@select on line 9 column 70 of removeBug.xsl:
  XPTY0004  Required cardinality of value of variable $result is code 40960; supplied value
  has cardinality exactly one
Errors were reported during stylesheet compilation

It appears that the cardinality checking wrongly produces an error. Also note that the error message is rather mysterious and unhelpful - what is "cardinality of value of variable $result is code 40960" supposed to mean??

I see this error running Saxon 9.9 onwards; but not with Saxon 9.8.


Files

removeBug.xsl (449 Bytes) removeBug.xsl Debbie Lockett, 2024-01-09 12:35
Actions #1

Updated by Debbie Lockett 4 months ago

Same bug using fn:subsequence():

<xsl:variable name="result" select="subsequence((1, 2, 3.1, 'four'), 4)"/>

The problem seems to be to do with a sequence of length exactly one being accepted where a sequence of length zero or more is expected. This is not restricted to fn:remove().

Actions #2

Updated by Michael Kay 3 months ago

Note that the cardinality code 40960 means "allows 0 and allows many (but does not allow one)". This presumably results from some incorrect static cardinality inference (which may or may not be relevant to the problem). In the error message, if the cardinality code does not correspond to one of the standard occurrence indicators, we output the numeric value of the code.

Actions #3

Updated by Michael Kay 3 months ago

The cardinality of the expression remove( (xs:integer('100'), xs:string('abc')), 1) is calculated as follows: the expression compiles to tail((100, 'abc')). The cardinality of (100, 'abc') is "many", and the cardinality of tail() is the cardinality of its argument or zero; so we get "many or zero"; which (incorrectly) excludes the possibility of "one".

Note at this point of processing, we haven't yet reduced this expression to a literal.

I think the solution is slightly smarter logic in TailExpression.computeCardinality().

This fixes both cases. The subsequence() case also compiles to a TailExpression, which is used to return the tail of a sequence starting at any position, not just position 2.

The critical factor in both cases is doing subsequence selection on an expression whose cardinality is statically known.

Actions #4

Updated by Michael Kay 3 months ago

  • Status changed from New to Resolved
  • Assignee set to Michael Kay
  • Fix Committed on Branch 10, 11, 12, trunk added
  • Platforms .NET, Java added

Please register to edit this issue

Also available in: Atom PDF