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 30399 - [XSLT30] unclear how modes can be exposed unless xsl:mode is in effect
Summary: [XSLT30] unclear how modes can be exposed unless xsl:mode is in effect
Status: NEW
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XSLT 3.0 (show other bugs)
Version: 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: 2019-02-19 18:01 UTC by Abel Braaksma
Modified: 2019-02-21 13:56 UTC (History)
0 users

See Also:


Attachments

Description Abel Braaksma 2019-02-19 18:01:34 UTC
When looking up the implicit package definition, it points to the transformation (bottom of section 3.5), which exposes modes as public. The text explains this in reference to backwards compatibility.

When looking up xsl:template, it explicitly states that visibility cannot be used on modes.

When looking up xsl:mode, it has a visibility attribute.

Section 3.5.4 explicitly states: "A named mode may be declared in an xsl:mode declaration as being either public, private, or final. The values of the visibility attribute are interpreted as follows: " 

Finally, section 3.5.3.1 on Visibility of Components states: "The visibility of a named template, function, variable, attribute set, or mode declared within a package is the first of the following that applies, ..."

---

I interpret the combination of these texts as that an implicit mode (one not defined by xsl:mode) can never have its visibility set by xsl:expose, stays private in an implicit package and is therefor never eligible as a component for xsl:override or xsl:accept.

However, I think the same text can be interpreted differently (that is: that xsl:expose can be used to expose implicit modes). 

I've created a few tests package-001f-j that try my interpretation.
Comment 1 Abel Braaksma 2019-02-19 19:12:50 UTC
Thinking about this a little more, the mention of "for backwards compatibility reasons" in section 3.5, and the formal stylesheet given, suggests that implicit modes can be made public/final/private (never abstract) by virtue of xsl:expose.

However, if that stylesheet is the only reference of such rule, I think we ought to make this more explicit.

And considering xsl:override, you cannot change the visibility of a mode there, and an xsl:override plus xsl:accept that matches the same name is forbidden, which makes it impossible (or at least non-trivial) to override a mode *and* make it anything else but private (default visibility of components from a used package is private).

I may be missing the obvious here, in which case I apologize, but I cannot find it yet.
Comment 2 Abel Braaksma 2019-02-19 19:25:21 UTC
And I found this:

"The xsl:expose and xsl:accept elements may be used to reduce the visibility of a mode in a using package; the same rules apply in general, though some of the rules are not applicable because, for example, modes cannot be abstract. "

This seems at odds with other parts of the text because:

- a non-matching component becomes private, so xsl:accept can only be used to rise the original visibility

- same is true for xsl:expose, as the default visibility, if the visibility attribute is absent, is private, and otherwise, it must be consistent

- this text appears under the section on overriding templates rules, but combining xsl:accept and xsl:override + xsl:template/@mode is not possible (though the rules here are fuzzy again):

[ERR XTSE3051] It is a static error if a token in the names attribute of xsl:accept, other than a wildcard, matches the symbolic name of a component declared within an xsl:override child of the same xsl:use-package element. 


Also, in the same section, about component compatibility, the text says "Modes are not overridable, so the xsl:mode declaration cannot appear as a child of xsl:override. ". But later, the text explains how you can augment or override public, used modes. The rules for compatibility should apply for <xsl:template mode="X" />, if it appears as child of xsl:override.
Comment 3 Michael Kay 2019-02-20 09:25:59 UTC
As far as I can see, there is only one thing we need to fix. In 6.6.1, where it says:

Similarly, if there is a mode that is named in an xsl:template or xsl:apply-templates element, or in the [xsl:]default-mode attribute of a containing element, and the stylesheet does not contain a declaration of that mode, then a declaration is implied comprising an xsl:mode element with a name attribute equal to that mode name, plus the attribute visibility="private".

we should change "plus the attribute visibility="private"" to say "with no visibility attribute". The visibility defaults to private, but specifying private explicitly is not the same as omitting the attribute, because if the attribute is explicitly present, then the component cannot be made public using xsl:expose, whereas if visibility is absent, then it can.

With this change, a "legacy" stylesheet that uses named modes without declaring them effectively exposes those modes as public by virtue of the xsl:expose declarations added by the "packagizing" stylesheet in 3.5.

I may have missed something here. For example, I'm not sure what you are referring to when you say "When looking up xsl:template, it explicitly states that visibility cannot be used on modes."
Comment 4 Abel Braaksma 2019-02-21 12:16:55 UTC
(In reply to Michael Kay from comment #3)
> [...] then a declaration is implied comprising an xsl:mode element with
> a name attribute equal to that mode name, plus the attribute
> visibility="private".
I missed this when trying to find the rules on implicit modes and exposing / accepting / overriding / visibility.

> we should change "plus the attribute visibility="private"" to say "with no
> visibility attribute". The visibility defaults to private, but specifying
> private explicitly is not the same as omitting the attribute, because if the
> attribute is explicitly present, then the component cannot be made public
> using xsl:expose, whereas if visibility is absent, then it can.
> 
> With this change, a "legacy" stylesheet that uses named modes without
> declaring them effectively exposes those modes as public by virtue of the
> xsl:expose declarations added by the "packagizing" stylesheet in 3.5.
This would definitely help a great way in making implicit modes eligible for exposing, and makes implicit packages have public modes.

> I may have missed something here. For example, I'm not sure what you are
> referring to when you say "When looking up xsl:template, it explicitly
> states that visibility cannot be used on modes."
Yes, my lengthy report got a bit messy. I'll try to recap, we still have:

* xsl:expose [...] may be used to reduce the visibility. --> should be: it can set the visibility, or reduce it if it is already present 

* xsl:accept [...] may be used to reduce the visibility. --> should be: the defaults without xsl:accept are private or hidden. Xsl:accept can be used solely for overriding this default behavior

* XTSE3051: we don't clearly say what happens with <xsl:accept component="mode" names="X"../> and <xsl:override> having <xsl:template mode="X" .../>. Though the covers this (by using the term "symbolic name"), I think it is hard to see this

* The sentence starting "Modes are not overridable..." is confusing and only partially correct, and it conflicts with the concept of compatibility

* It appears to me that it is not possible to write a package P that:
  a) uses a package Q with mode X
  b) exposes that mode publicly from P through an xsl:accept
  c) overrides that mode (by virtue of xsl:template)
  This is because XTSE3051 kicks in when both (b) and (c) are present

* Even after your proposed change, I think it is worthwhile to improve the sentence in 3.5.4: 

replace: "A named mode may be declared in an xsl:mode declaration as being either public, private, or final." 

with: "A named mode may be declared in an xsl:mode declaration as being either public, private, or final, or implicitly declared without a visibility attribute, defaulting to private for package and public for implicit packages." (or something along those lines)
Comment 5 Abel Braaksma 2019-02-21 12:24:01 UTC
Actually, thinking about the combination of a mode with xsl:accept and xsl:override combined, currently XTSE3051 will be thrown. But a few of the issues stated in comment#4 will be resolved by explicitly making XTSE3051 *not* apply to modes.

That way a programmer can use xsl:accept on a mode and keep it public, while at the same time using xsl:override to expand the mode. This would solve that loophole. 

Suggested fix for XTSE3051:

[ERR XTSE3051] It is a static error if a token in the names attribute of xsl:accept, other than a wildcard, matches the symbolic name of a component declared within an xsl:override child of the same xsl:use-package element, unless this component is a mode.
Comment 6 Michael Kay 2019-02-21 12:31:53 UTC
There seems to be confusion here about what it means to override a mode.

xsl:mode cannot appear as a child of xsl:override, so the proposed change to XTSE3051 doesn't make sense to me.

If a mode is public, however, then a using package can include new template rules for that mode. But those template rules are referencing the mode, they are not declaring it, so they can never trigger XTSE3051.
Comment 7 Abel Braaksma 2019-02-21 13:56:45 UTC
(In reply to Michael Kay from comment #6)
> There seems to be confusion here about what it means to override a mode.
> 
> xsl:mode cannot appear as a child of xsl:override, so the proposed change to
> XTSE3051 doesn't make sense to me.
> 
> If a mode is public, however, then a using package can include new template
> rules for that mode. But those template rules are referencing the mode, they
> are not declaring it, so they can never trigger XTSE3051.
I don't disagree with this notion, but we also talk of template *declarations*, and a mode can be implicitly declared without an xsl:mode present, so at best I'd say this notion is rather fuzzy.

Given your explanation and reading the current error XTSE3051 with that in mind, I agree that the error is not wrong. However, it is easy to misinterpret it and indeed I was writing tests to cover this error for modes (not submitted yet). 

So perhaps instead of 'fixing' the error (which I now see isn't wrong per se), we could add a Note underneath? Something like:

<proposal>
Note: this error does not extend to modes, since modes are not declared with xsl:template, and xsl:mode cannot appear as child of xsl:override.
</proposal>