Maintenance: Planio will be observing a scheduled maintenance window this Tuesday, November 5, 2024 from 03:00 UTC until 06:30 UTC to perform urgent network maintenance in our primary data center. Your Planio account will be unavailable during this maintenance window.
Bug #6313
closedStatic type error from fn:remove()
100%
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
Updated by Debbie Lockett 10 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()
.
Updated by Michael Kay 10 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.
Updated by Michael Kay 10 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.
Updated by Michael Kay 10 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
Updated by O'Neil Delpratt 4 months ago
- % Done changed from 0 to 100
- Fixed in Maintenance Release 12.5 added
Bug fix applied in the Saxon 12.5 Maintenance release. Not marking this closed until patched in older releases (i.e 11.x).
Please register to edit this issue