Bug #2545
closedInvalid slot number: local variables in match pattern with mode="#all"
100%
Description
Reported on the help forum:
Using: Saxon-EE 9.6.0.7
Input:
<?xml version="1.0" encoding="UTF-8"?>
<A/>
Stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
<xsl:template match="*[some $item in ('') satisfies $item eq local-name()]" mode="#all"/>
</xsl:stylesheet>
I've been able to isolate this issue to this very small subset of the stylesheet I encountered it in. Removing or changing the mode attribute avoids the error, as does rewriting the match pattern to *[local-name() = ('')]
. (The sequence being compared against was originally in a stylesheet variable and contained more than just an empty string.)
I'm stuck with version 9.6.0.7 for the time being, so my apologies if this issue has already been addressed.
Updated by Michael Kay almost 9 years ago
- Status changed from New to In Progress
The problem seems to be in XSLTemplate.allocatePatternSlots(). If a pattern declares local variables and the template has mode="#all", slots are allocated in the "omniMode" (which contains all template rules) but they need to be allocated to every individual named mode.
The same problem is present in the 9.7 code, but the bug is not manifested for this test case because the predicate in the match pattern is optimised to eliminate the local variable (the predicate is reduced to [not(local-name(.))]
.)
Updated by Michael Kay almost 9 years ago
- Status changed from In Progress to Resolved
- Applies to branch 9.7 added
- Fix Committed on Branch 9.6, 9.7 added
I reproduced the problem on the 9.7 branch by using a pattern that was less amenable to optimization:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
<xsl:param name="p" select="''"/>
<xsl:template match="*[some $item in $p satisfies $item eq local-name()]" mode="#all"/>
</xsl:stylesheet>
I have committed a patch on the 9.6 and 9.7 branches that solves this test case. Not yet regression-tested.
Updated by Michael Kay almost 9 years ago
- Subject changed from Invalid slot number using quantified expression within a match pattern to Invalid slot number: local variables in match pattern with mode="#all"
Updated by Michael Kay almost 9 years ago
- Status changed from Resolved to In Progress
Added a test case match-245 to do something similar, but a bit more complex. The test passed on 9.6, but on 9.7 it failed
java.lang.UnsupportedOperationException: Cannot copy a variable reference whose binding is unknown
at net.sf.saxon.expr.GlobalVariableReference.copy(GlobalVariableReference.java:42)
Updated by Michael Kay almost 9 years ago
- Status changed from In Progress to Resolved
Fixing this involved two main changes:
(a) global variable references are now bound to the compiled GlobalVariable object earlier, allowing the variable reference to be copied when a template with mode="#all" is copied.
(b) the copying of a template rule with mode="#all" is now done within the logic of XSLTemplate after calling RuleManager.setTemplateRule(), rather than from within the code of RuleManager.setTemplateRule(). This allows the variable compiledTemplateRules to contain a list of all copies of the template rules, so that when the time comes to allocate slots for local variables this is done for all copies.
A further change has been committed to the 9.7 branch.
Updated by Michael Kay almost 9 years ago
- Status changed from Resolved to In Progress
This patch appears to cause test case mode-1202 to fail.
Updated by Michael Kay almost 9 years ago
- Status changed from In Progress to Resolved
The new code was bypassing the code in RuleManager.setTemplateRule() which splits a union pattern and allocates a default priority. Test case mode-1202 is fixed by changing the call on Mode.addRule() to call RuleManager.setTemplateRule().
Looking at the code, I am also concerned that RuleManager.setTemplateRule(), when it breaks a union pattern into its separate sub-patterns, appears to allocate the same priority to each of them, whereas the whole point is that the subpatterns can have different default priorities. Exploring more closely with the debugger, it works by accident: UnionPattern.getDefaultPriority() returns NaN, and this means that the recursive call to register each subpattern makes a second call on getDefaultPriority() - the code which gets the default priority for the union pattern is redundant but not wrong. I have removed this code on the 9.7 branch, with no ill-effects.
Updated by O'Neil Delpratt almost 9 years ago
- % Done changed from 0 to 100
- Fixed in Maintenance Release 9.7.0.2 added
Bug fix applied in the Saxon 9.7.0.2 maintenance release
Updated by O'Neil Delpratt over 8 years ago
- Fixed in Maintenance Release 9.7.0.3 added
- Fixed in Maintenance Release deleted (
9.7.0.2)
Leave open until fix applied in the 9.6 branch
Updated by O'Neil Delpratt over 8 years ago
- Status changed from Resolved to Closed
- Fixed in Maintenance Release 9.6.0.9 added
- Fixed in Maintenance Release deleted (
9.7.0.3)
Bug fix applied in the Saxon 9.6.0.9 maintenance release.
Updated by O'Neil Delpratt over 8 years ago
- Sprint/Milestone set to 9.7.0.2
- Fixed in Maintenance Release 9.7.0.2 added
Please register to edit this issue