This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 29499 - [XSLT30] Global xsl:variable/xsl:param not in streamability rules
Summary: [XSLT30] Global xsl:variable/xsl:param not in streamability rules
Status: CLOSED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XSLT 3.0 (show other bugs)
Version: Candidate Recommendation
Hardware: PC Windows NT
: P2 normal
Target Milestone: ---
Assignee: Michael Kay
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-02-22 12:48 UTC by Abel Braaksma
Modified: 2016-10-06 18:42 UTC (History)
0 users

See Also:


Attachments

Description Abel Braaksma 2016-02-22 12:48:10 UTC
I'm not sure, but I couldn't find it. We have section "19.8.4.41 Streamability of xsl:variable" which deals with the *instruction* xsl:variable, but not with the declaration.

I vaguely remember we have had discussions concluding that a global variable declared with xsl:param and xsl:variable is allowed to access a streamable global context item (either because the stylesheet is executed with a default mode set to a streamable mode or the xsl:global-context-item is set to streamable), but only if motionless and grounded.

If we do have these rules in place, I wonder where they went. If we don't I think we should add them.

The same seems true for xsl:key.

As an aside, I wouldn't oppose to — in fact, I'd welcome — a section under "19 Streaming" that is called something like "Classifying declarations" and point from there to the relevant section in the rest of the prose, and any declaration not yet in the prose and that is not allowed to access the global context item could be mentioned there (currently, a back-reference is placed in the opening section of section "19 Streaming", while this helps, it could be more prominent with its own section).
Comment 1 Michael Kay 2016-02-22 14:20:03 UTC
We only evaluate posture and sweep for constructs that can be evaluated to return a value. Declarations are not evaluated. If they had a posture and sweep, how would we use it?

We do have a rule in 3.5.6:

If the streamable attribute [of xsl:global-context-item] is present with the value yes, then the select expression or contained sequence constructor of every global xsl:variable and xsl:param declaration in the containing package must be grounded and motionless, when assessed with a context posture of striding, and a context item type based on the declared type of the global context item. The consequences of violating this rule depend on the conformance level of the processor, as described in 19.10 Streamability Guarantees.
Comment 2 Abel Braaksma 2016-02-22 16:02:03 UTC
I didn't find that rule previously, thanks.

I see a few caveats and I'm not sure we handle / guard them well. 

Situation 1: request streamed processing with initial match selection as a streamed node.

a) xsl:key, through the key-function can be non-motionless. I think this is guarded by fn:key(A, A, N), which effectively makes *any* use of keys roaming/free-ranging.

b) xsl:variable/param are not in effect, they do not access the initial match selection.

Situation 2: request streamed processing with global context item (not xsl:global-context-item) set to a streamed node, I believe this is allowed and supported.

a) xsl:variable can access the streamed global context item, i.e. <xsl:variable name="n" select="." />

b) xsl:param can also access it, but this can be overridden by a supplied parameter, which the API may set to something unstreamed, but that can only be detected *after* the static phase, at the priming phase.

Situation 3: streamed variables that are not used, may they be ignored? We don't allow this with xsl:variable instructions, though it makes sense to allow it with either, but as an implementation-defined leniency towards the "must throw an error if not guaranteed streamable" rule.

Situation 4: import-precedence kicking in, i.e. a variable that would be illegal at lower precedence, but legal through a higher-precedence override. Same may be true for xsl:function and xsl:accumulator, I didn't check what we say about this.
Comment 3 Michael Kay 2016-05-12 11:23:59 UTC
Addressing comment #2:

Situation 1: request streamed processing with initial match selection as a streamed node.

a) xsl:key, through the key-function can be non-motionless. I think this is guarded by fn:key(A, A, N), which effectively makes *any* use of keys roaming/free-ranging.

Yes.

b) xsl:variable/param are not in effect, they do not access the initial match selection.

I don't understand what you mean by "not in effect". I don't think there is a problem here.

Situation 2: request streamed processing with global context item (not xsl:global-context-item) set to a streamed node, I believe this is allowed and supported.

a) xsl:variable can access the streamed global context item, i.e. <xsl:variable name="n" select="." />

3.5.6 says: If the [xsl:global-context-item/@streamable] attribute is absent or has the value no, or if there is no xsl:global-context-item declaration, then when the transformation is primed, the item supplied as the global context item cannot be a node in a streamed document (the transformation API may handle this either by disallowing such an input, or by building the corresponding tree in memory and supplying the global context item as an unstreamed node.)

So xsl:variable can access the streamed global context item only if xsl:global-context-item/@streamable = 'yes', and in that case the variable must be grounded an motionless, so in effect it can inspect the global context item but cannot consume it.

b) xsl:param can also access it, but this can be overridden by a supplied parameter, which the API may set to something unstreamed, but that can only be detected *after* the static phase, at the priming phase.

The rule for xsl:param is exactly the same as xsl:variable.

Situation 3: streamed variables that are not used, may they be ignored? We don't allow this with xsl:variable instructions, though it makes sense to allow it with either, but as an implementation-defined leniency towards the "must throw an error if not guaranteed streamable" rule.

The rules in 3.5.6 as written apply to all global variables/params whether they are referenced or not. I would prefer not to make the rules more complicated without a compelling use case.

Situation 4: import-precedence kicking in, i.e. a variable that would be illegal at lower precedence, but legal through a higher-precedence override. Same may be true for xsl:function and xsl:accumulator, I didn't check what we say about this.

Again, the rules in 3.5.6 as written apply to all global variables/params whether they are overridden or not. I can see a use-case here which is that you might want to override a non-streamable variable declaration with a streamable one.
Comment 4 Abel Braaksma 2016-05-12 12:53:52 UTC
> I don't understand what you mean by "not in effect".
It meant that there was no problem there ;).

> The rules in 3.5.6 as written apply to all global variables/params whether 
> they are referenced or not. I would prefer not to make the rules more 
> complicated without a compelling use case.
I agree, but it conflicts with the rule that we do not need to raise an error in a global variable if it is not used. And perhaps more importantly, if variables are inlined, the may escape the analysis.

There's two other forces at play here: (1) streamability is (largely) a static process. And (2) processors should *not* inline before doing this static analysis.

> I can see a use-case here which is that you might want to override a 
> non-streamable variable declaration with a streamable one.
I wonder if this may already be captured by the fact that a declaration at higher import-precedence supersedes one at a lower import-precedence. But that only hides dynamic errors, not static ones and therefor has the same problem as the previous point.

All in all I agree with your comment 3, it looks like the rules that I thought were absent are somewhere around in sections I missed.

Whether or not we want to sharpen our pencils to elaborate on these rules and/or to add (for instance) a little table that explains the 8 invocation combinations I don't know.

----------

Additional scenario I just encountered: I added an option to our processor to allow the initial match selection to be a sequence of documents, and these documents can be streamable if the initial mode is streamable (which can be overridden on the commandline as well, forcing a streamable initial mode to be invoked with a grounded document node). I think the spec allows both these scenarios.
Comment 5 Michael Kay 2016-05-26 23:01:58 UTC
From the minutes of 12 May and 26 May:

 [XSLT30] Global xsl:variable/xsl:param not in streamability rules
    Summary from last meeting:
- We discussed situation 1, agreed there was no problem, but clarification
on xsl:key was considered helpful by means of a Note (no action item
assigned)
- We discussed situation 2 and agreed there was room for improvement, in
particular for error scenarios. The editor proposed to look for better
wording here (no action item assigned)
- We discussed situation 3, decided to leave it as is
- We discussed situation 4 and considered import-precedence should be taken
into account, but did not reach a full conclusion, though there was clear
sentiment towards making this change (note that currently the spec does not
say anything about it). Again, no action item was assigned, further
discussion needed.
- We DID NOT yet discuss the situation sketched in last para of comment 4.
- No formal DECISION was reached yet, but consensus was reached on points
mentioned above

MK said there are two situations where a variable declaration is not
used: (a) when there is no reference to it, and (b) when it is
overridden by a declaration with higher import precedence.  

In those situations, does it need to satisfy the streamability rules?

In the case of import precedence, it would be nice to say "no" -- one
could imagine a non-streamable library which is overridden precisely
to make it streamable. 

In the case of an unreferenced variable, MK felt the natural answer
was "no", since we have no distinctions anywhere in the spec between
declarations that are referenced and those that are not.

The same principles should apply to other global components for which
the same question arises.

Proposed resolution: to close issue 29499 as summarized in the minutes
of 12 May (extracted above), plus a resolution of situation 4 with two
parts: (a) error is raised for unreferenced global variables, and (b)
no error is raised for overridden global variable declarations. 

We were about to adopt this proposed resolution when it became clear
that 29499 also covers accumulators. ABr proposed that the same
principles will apply to (the initial value of) accumulators. MK felt
the need for more study of how these considerations apply to
accumulators. So we decided to separate accumulators from variables.
Comment 6 Michael Kay 2016-05-27 09:11:55 UTC
The agreed changes have been applied to the spec.
Comment 7 Abel Braaksma 2016-05-27 09:54:25 UTC
For reference only:

(In reply to Michael Kay from comment #5)
> We were about to adopt this proposed resolution when it became clear
> that 29499 also covers accumulators. ABr proposed that the same
> principles will apply to (the initial value of) accumulators. MK felt
> the need for more study of how these considerations apply to
> accumulators. So we decided to separate accumulators from variables.
See Bug 29670 for accumulators, where @initial-value can access the global context item.