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 4378 - error in K2-NodeTest-21
Summary: error in K2-NodeTest-21
Status: RESOLVED WORKSFORME
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XQuery 3.1 (show other bugs)
Version: Proposed Recommendation
Hardware: PC Windows XP
: P2 normal
Target Milestone: ---
Assignee: Oliver Hallam
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-03-07 21:29 UTC by Andrew Eisenberg
Modified: 2015-11-12 10:34 UTC (History)
6 users (show)

See Also:


Attachments

Description Andrew Eisenberg 2007-03-07 21:29:00 UTC
Test case K2-NodeTest-21 contains an expression in the function definition that will cause a dynamic error. The query body, however, is just 1. Was an invocation of the function intended?
Comment 1 Frans Englich 2007-03-09 14:04:54 UTC
Yes, a fix is attempted in CVS.
Comment 2 Josh Spiegel 2009-08-20 01:05:47 UTC
Where was the fix for this made?  In the version I have checked out, it seems the query body is still 1.  

http://dev.w3.org/cvsweb/2006/xquery-test-suite/TestSuiteStagingArea/Queries/XQuery/PathExpr/Steps/NodeTestSection/NodeTest/K2-NodeTest-21.xq

Thanks,
Josh
Comment 3 Frans Englich 2009-10-14 12:51:42 UTC
Wait, no invocation was intended. That would result in XPDY0002. The test simply "Ensure 'element(local:ncname)' is parsed correctly when inside document-node()."
Comment 4 Andrew Eisenberg 2009-11-20 16:26:45 UTC
Ok. I understand that 1 is the correct result for this test case.

I see that err:XPDY0002 is also an expected result. Since the function is never invoked, I believe that this error should be dropped.
Comment 5 Frans Englich 2010-03-15 09:47:59 UTC
Removed XPDY0002 baseline in CVS.
Comment 6 Michael Kay 2010-03-25 09:17:20 UTC
I disagree with the opinion in comment #4 and with the way the test has been changed. I believe it is legitimate to throw XPDY0002.

We say "A dynamic error is an error that must be detected during the dynamic evaluation phase and may be detected during the static analysis phase". If there was ever a candidate for detecting a dynamic error during the static analysis phase, this is one. Calling the function can never succeed.

Further, we never say that because the query contains no call on this function, the function must not be evaluated. The function has no arguments and does not depend in any way on input data, so pre-evaluating it at compile time is a perfectly reasonable strategy, and is entirely permissible according to our rules. We do prescribe some conditions under which expressions must not be evaluated (for example branches of a conditional), and this is not one of them.

Comment 7 Andrew Eisenberg 2010-04-22 22:25:46 UTC
I agree with Mike's comments and retract what I said in comment #4.

I believe that XPDY0002 should be added back as an expected result for this test case.
Comment 8 Oliver Hallam 2010-06-08 10:09:17 UTC
I have made this change.
Comment 9 Josh Spiegel 2015-09-25 17:57:52 UTC
I think an implementation should also be allowed to raise XPST0005. 

"During the analysis phase, it is a static error if the static type assigned to an expression other than the expression () or data(()) is empty-sequence()."

Consider the function:

  declare function local:userFunction()
  {
    document-node(element(local:ncname))
  };

The context item is unbound and has the static type item().  An implementation should be able to tell that the static type of the function body is empty.
Comment 10 Tim Mills 2015-09-28 11:09:04 UTC
(In reply to Josh Spiegel from comment #9)

> The context item is unbound and has the static type item().  An
> implementation should be able to tell that the static type of the function
> body is empty.

In XQ30 4.18 Function Declaration, we read

[Definition: User defined functions are functions that contain a function body, which provides the implementation of the function as an XQuery expression.] The static context for a function body includes all functions, variables, and namespaces that are declared or imported anywhere in the Prolog, including the function being declared. Its in-scope variables component also includes the parameters of the function being declared. However, its context item static type component is absent[DM30].

So in the scope of the function body, the context item static type is absent, not item().  

One might argue that XPTY0004 would be permissible as a static error, since if the context item static type component is absent how can one successfully type check the expression?

Perhaps it would have been better to say the the context item static type would be "none" (from XQ10 Formal Semantics), or "xs:error" (which behaves in an identical way to "none").

If you treat the context item as type none/xs:error, then the type of

 document-node(element(local:ncname))

is none?/xs:error? which is the same as empty-sequence().  On that basis, XPST0005 should be permissible.

I'm of the opinion that whenever the compiler comes across something of the form

if (condition)
then fn:error()
else ()

it's probably unwise to treat this as empty-sequence() without issuing a warning to the user.  That said, the specification regarding xs:error states:

"xs:error? and xs:error* are identical to empty-sequence()."
Comment 11 Michael Kay 2015-09-28 11:48:37 UTC
It's always struck me as a complete absurdity that using the context item where there isn't one isn't regarded as a type error. We seem to be piling angels on pinheads in a desperate attempt to work around that issue. Why not just nail it head-on?
Comment 12 Josh Spiegel 2015-10-01 19:33:11 UTC
Thanks for the clarification Tim.  I agree that none isn't ideal because it leaves the possibility that static analysis and optimizations hide the error condition. Since it never makes sense to use the context item of the function body, why not raise a static error when an expression depends on it?

While playing around with this idea, I noticed tests try-016 and try-017:
https://github.com/LeoWoerteler/QT3TS/blob/a2a6b9dc40fbcd5db7a41f927c038b1b1880c489/prod/TryCatchExpr.xml#L215

Wouldn't a static error be more helpful to the user in both these cases?  It would be a backwards compatibility issue to force it at this point, but allowing it might be nice...
Comment 13 Tim Mills 2015-10-02 09:14:51 UTC
(In reply to Josh Spiegel from comment #12)
> Thanks for the clarification Tim.  I agree that none isn't ideal because it
> leaves the possibility that static analysis and optimizations hide the error
> condition. Since it never makes sense to use the context item of the
> function body, why not raise a static error when an expression depends on it?
> 
> While playing around with this idea, I noticed tests try-016 and try-017:
> https://github.com/LeoWoerteler/QT3TS/blob/
> a2a6b9dc40fbcd5db7a41f927c038b1b1880c489/prod/TryCatchExpr.xml#L215

One could certainly argue that both of these tests should accept XPTY0004, on the grounds that the static type of "." is absent.

> Wouldn't a static error be more helpful to the user in both these cases?  It
> would be a backwards compatibility issue to force it at this point, but
> allowing it might be nice...

Yes.  Formal semantics normalized "." to a variable reference $fs:dot.  A reference to an out-of-scope variable would raise static error [err:XPST0008].  Perhaps this error could or should have also applied in this case.  I can't think of an example where it wouldn't have been helpful to the programmer to point out the error early.

Consider:

declare function local:use-dot($yes) { if ($yes) then . else "not dot" };

On invocation of local:use-dot,

- If use of out-of-scope "." were a static error S, all implementations would raise S.

- If use of out-of-scope "." were a type check error T:
  * implementations performing pessimistic static type checking would raise T.
  * implementations performing optimistic type checking or dynamic type checking would raise T in the event that $yes is true.

-  If use of out-of-scope "." is not a type check error, but XPDY0002 (the status quo), implementations would only raise XPDY0002 at run time when $yes is true.



To be honest, I don't understand the reason for the restriction anyway.  Consider why 

declare function local:use-dot() { . };

local:use-dot()

is bad, but

declare variable $dot := .;

declare function local:use-dot() { $dot };

local:use-dot()

is fine.
Comment 14 Josh Spiegel 2015-10-02 15:22:43 UTC
> To be honest, I don't understand the reason for the restriction anyway.

I don't understand either and, I agree, it appears inconsistent.  I am changing this to an XQuery 3.1 bug.  

A simple fix would be something like this in 4.18 Function Declaration:

"Its in-scope variables component also includes the parameters of the function being declared. However, its context item static type component is absent and an implementation SHOULD raise a static error [err:XPST0008] if an expression depends on the context item."

This is technically a backwards-incompatible change since raising the error could cause currently valid XQuery 3.0 queries to fail in corner cases.  For example, requiring the error would change the result of try-016 and try-017.  This is why I suggest "SHOULD".  However, I would also be comfortable removing SHOULD since it seems the error always indicates the user has made a mistake.

Alternatively, we could also discuss removing the restriction completely (i.e. the initial context item is accessible from a function body).  Maybe someone in the working group knows why it was added...
Comment 15 Josh Spiegel 2015-10-02 16:15:26 UTC
Maybe the restriction was added so users don't try something like this:

  declare local:foo() {
     ./bar/bat
  };

  ./zip/foo()

And expect the context item of the function call to be used in the function body. This type of ambiguity doesn't apply to global variables.
Comment 16 Michael Kay 2015-10-02 16:25:38 UTC
I would definitely not want to change the rule that function bodies are executed with an absent focus. (One reason is that many users, especially those used to XSLT named templates, would expect the focus to be that of the caller, rather than the initial focus).

I think that when expressions depend on the focus and there is no focus, that should be a type error rather than a dynamic error, and this change would be sufficient to allow processors (at their discretion) to raise the error statically. We should simply recategorize XPDY0002 as a type error.
Comment 17 Josh Spiegel 2015-10-02 16:45:43 UTC
> I would definitely not want to change the rule that function bodies are executed with an absent focus. 

OK

> We should simply recategorize XPDY0002 as a type error.

Why?  Can you give an example of where it makes sense or is necessary to detect this condition at runtime?  

I think this error condition is analogous to detecting that a variable reference is not in scope and likewise should be a static error.
Comment 18 Michael Kay 2015-10-02 17:52:50 UTC
In XSLT it is not always possible to detect statically whether or not the focus will be defined: for example in a named template, the focus or absence of a focus depends on the caller (and we can't resolve calls statically across package boundaries).

This is also true for the top-level expression in XQuery in the absence of a context item declaration.
Comment 19 Josh Spiegel 2015-10-02 18:47:11 UTC
> In XSLT it is not always possible to detect statically

This change is only relevant to function declarations so I don't see why it should impact XPath or XSLT.

> This is also true for the top-level expression in XQuery in the absence of a context item declaration.

This situation is a bit different though.  In the case of the initial context item it (1) has a static type and (2) may or may not be bound at runtime.  In the case of the function body context item (1) there is no static type (it is defined to be absent) and (2) it is impossible for it to be bound at runtime.

Does Saxon infer static types?  If so, what static type do you infer for "." in a function body?
Comment 20 Michael Kay 2015-10-02 19:46:07 UTC
Saxon in effect rewrites "." within a function body as fn:error("XPDY0002"), and outputs a warning. Saxon's type inference for fn:error() is item()?, to prevent any spurious static type errors (item()? has an intersection with every SequenceType).
Comment 21 Michael Kay 2015-10-02 19:50:10 UTC
"This change is only relevant to function declarations so I don't see why it
should impact XPath or XSLT."

When "." is executed and there is no context item, we don't want to handle the error differently depending on whether or not the reason for the absence of a context item is that we're in an XQuery function.
Comment 22 Tim Mills 2015-10-05 10:00:39 UTC
I think there are two issues becoming confused here.

Firstly, we have the case of using the context item when it is not in scope.

e.g. 

declare local:func() { . }
local:func()

This is analogous to any "normal" referenced variable being out of scope.


Secondly, we have the case of using the context item when it is in scope but not bound to a value, which as Mike has pointed out, can happen in XSLT.

This is analogous to use of any "normal" optional template parameter to which a value has not been bound.  In XQuery, this is similar to use of an external variable for which a value has not been supplied e.g.

declare variable $unbound external;
declare local:fun() { $unbound }
local:func()

I believe that the first case should ideally be a static error (but I could live with a type check error), and the second a dynamic error.
Comment 23 Michael Kay 2015-10-05 10:29:41 UTC
We could introduce the idea of a binding to the context item having static scope, but there's no such concept in the current spec. All the prose talks of it being bound dynamically, reflecting the XSLT 1.0 history.

I think that making it a static error would be a fairly disruptive change, both in terms of the effect on the spec, and in terms of backwards compatibility. Making XPDY0002 into a type error is a much "gentler" change, because it's a very small change to the spec, and because implementations have more discretion, so they can make their own choices about how to manage the backwards compatibility issue. In addition it works much better for XPath, where it's the host language that knows whether or not a context item is defined for the XPath expression.
Comment 24 Tim Mills 2015-10-05 10:55:50 UTC
If only because XPDY0002 doesn't have "TY" in it, I'd rather just leave XPDY0002 as is and permit XPTY0004.  This should not be seen as a backwards compatibility issue, because it's (a) not a new error code, and (b) is perfectly reasonable given the static typing rules.
Comment 25 Josh Spiegel 2015-10-05 11:40:31 UTC
I agree with Tim that using the function body context item should be a static error.  

Mike, I don't understand why allowing a static error in this case would be a "fairly disruptive change".  For example, you said "Saxon in effect rewrites "." within a function body as fn:error("XPDY0002")".  It isn't clear to me why you can't simply raise a static error at this point instead.  

But yes, whether it is a static error or a type error that can be raised statically, implementations should not be forced to make any incompatible changes.
Comment 26 Michael Kay 2015-10-05 12:03:19 UTC
I didn't say it would be disruptive for the implementation, I said it would be disruptive for the spec. That's because we need to introduce a new component to the static context (e.g. "has-defined-focus"), define how it is initialized, define what constructs change it, and so on.

It does become disruptive for the implementation as well if the implementation needs to distinguish places where it is allowed to raise a static error (e.g. within xsl:function or within XPath inline functions) from places where it isn't allowed to do so (e.g. within a named template after inlining), or if we have a different error code for absent focus within a function versus absent focus in the top-level XPath expression.

Existing applications that call XPath from say Java might be testing for an XPDY0002 error code and would be affected if we change it to XPTY0004.

Many test cases would be affected by a change of error code.
Comment 27 Tim Mills 2015-10-05 12:13:37 UTC
(In reply to Michael Kay from comment #26)

> Existing applications that call XPath from say Java might be testing for an
> XPDY0002 error code and would be affected if we change it to XPTY0004.

I'd not have much sympathy with this.  Even if the test suite doesn't include it, I assert that XPTY0004 should always have been permissible.
Comment 28 Michael Kay 2015-10-05 14:23:04 UTC
>I assert that XPTY0004 should always have been permissible

Perhaps it should have been, but sadly, it wasn't. The spec is absolutely clear:

If the context item is absent, a context item expression raises a dynamic error [err:XPDY0002].
Comment 29 Tim Mills 2015-10-05 14:41:35 UTC
(In reply to Michael Kay from comment #28)
> >I assert that XPTY0004 should always have been permissible
> 
> Perhaps it should have been, but sadly, it wasn't. The spec is absolutely
> clear:
> 
> If the context item is absent, a context item expression raises a dynamic
> error [err:XPDY0002].

But

"The dynamic evaluation phase can occur only if no errors were detected during the static analysis phase. If the Static Typing Feature is in effect, all type errors are detected during static analysis and serve to inhibit the dynamic evaluation phase."

and there are no static typing rules which give a type to an out-of-scope context item.  If the processor supports the Static Typing Feature, it MUST report the static type error, and if it does not support the Static Typing Feature, it MAY still do so.
Comment 30 Abel Braaksma 2015-11-11 04:03:34 UTC
There's another implementation issue that perhaps should be looked into when considering requiring a static error when a context item is referenced:

<xsl:function name="f:run">
    <xsl:param name="fun" />
    <xsl:value-of select="$fun()" />
</xsl:function>

<xsl:template match="/">
    <xsl:value-of select="f:run(node-name#0)" />
    <xsl:value-of select="f:run(position#0)" />
    <xsl:value-of select="f:run(function-lookup('node-name', 0))" />
</xsl:template>

We apply function rewriting and inlining in this case *after* the static analysis phase. During static analysis, we do not detect this as an error case. The rewrites result in the whole body being replaced with a single call to some version of fn:error('xyz').

If the context item should be statically detected as being absent, I don't think that is trivial in the above example, though possible because all calls are static. But even if you do see this as an error case, it should still be dynamic because we cannot know beforehand whether the template is matched.

1) in the above example I think it should clearly be a dynamic error, even though proposals below suggests this should be statically detected.

2) the inlining removes the knowledge of being inside a function, the inlining happens after the static error checking phase. We currently apply the same strategy for other places where the context item can be absent and treat them all as dynamic errors. Turning this around is not trivial, I think (but by no means impossible).
Comment 31 Michael Kay 2015-11-11 11:33:45 UTC
Abel, I may have missed something, but I don't see wny your example is an error at all. An expression like node-name#0 creates a function whose closure captures the context item at the point where the expression "node-name#0" is evaluated; a context item exists at this point, so there is no error.
Comment 32 Andrew Coleman 2015-11-11 15:35:33 UTC
At the teleconference on 2015-11-10, the WG decided to keep the status quo and resolve this bug as 'works for me'
Comment 33 Josh Spiegel 2015-11-11 18:22:29 UTC
Sounds more like a "WONTFIX" to me but I had to leave early and wasn't there for the decision.  In any case, I am including the minutes from the previous meetings below.  

Here are the minutes from meeting 622:

§§ Action A-620-01 has been completed, so this is up for discussion.

§§ JR reported that he has done essentially what is described in comment
§§ 14 of bug 4378.  The text of 4.18 Function Declaration now reads in
§§ part:

§§   [Definition: User defined functions are functions that contain a
§§   function body, which provides the implementation of the function
§§   as an XQuery expression.] The static context for a function body
§§   includes all functions, variables, and namespaces that are
§§   declared or imported anywhere in the Prolog, including the
§§   function being declared. Its in-scope variables component also
§§   includes the parameters of the function being declared. However,
§§   its context item static type component is absentDM31, and an
§§   implementation should raise a static error [err:XPST0008] if an
§§   expression depends on the context item.

§§ We discussed at some length.

§§ Among the points raised:

§§ - MD suggested that "if an expression depends on the context item" 
§§   was a bit fuzzy as regards the phrase "an expression".
§§ - MK suggested the "depends on the context item" also leaves a
§§   great deal of work to the reader.
§§ - TM argued that the correct error to raise here is a type error.
§§   He has found some places where we talk about an item's typed value
§§   being absent, but not (so far) places where we talk about its
§§   type annotation being absent.
§§ - TM suggested that changing 2.2.3.1 Static Analysis Phase of XQuery
§§   might do the job; others were inclined to agree.

§§ It was felt that we needed a fuller discussion of the issues involved,
§§ in email.  AC suggested that the right way to launch such a discussion
§§ was with a concrete proposal.

§§ ACTION A-622-05: MK to propose a resolution to bug 4378 "error in
§§ K2-NodeTest-21" (dependency of function bodies on context item).

Here are the minutes from meeting 623:

§§ There was a lot more discussion (almost an hour), but we didn't make great progress.

§§ There seems some level of consensus: (a) we all want to be allowed to raise a static error when a context-dependent expression is used in a function body. (b) We think making it a type error might be an expedient way to achieve this.

§§ The disagreement is about how we need to define the static/dynamic context to make this possible.

§§ Also need machinery for describing how type errors are raised for things like name() where the reference to the context item is implicit. We can't raise type errors from within the F+O spec of the function, it has to be associated with the function call itself.

§§ Feeling that we want to progress and we may have to do so without making progress on this issue: i.e. decide to stick with the status quo.

§§ DECISION: close bug 4378 as "works for me".
Comment 34 Abel Braaksma 2015-11-12 10:34:33 UTC
FYI (no reopen request)

(In reply to Michael Kay from comment #31)
> Abel, I may have missed something, but I don't see wny your example is an
> error at all. An expression like node-name#0 creates a function whose
> closure captures the context item at the point where the expression
> "node-name#0" is evaluated; a context item exists at this point, so there is
> no error.

This has been taken on in bug 29277 and was caused by my misunderstanding of the spec. Indeed, my example in comment #30 should not throw an error.