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 29420 - [QT3] K2-SeqSUMFunc-4 and xs:unsignedShort vs xs:integer result
Summary: [QT3] K2-SeqSUMFunc-4 and xs:unsignedShort vs xs:integer result
Status: RESOLVED WORKSFORME
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XQuery 3 & XPath 3 Test Suite (show other bugs)
Version: Candidate Recommendation
Hardware: PC Windows NT
: P2 normal
Target Milestone: ---
Assignee: O'Neil Delpratt
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-02-05 15:05 UTC by Abel Braaksma
Modified: 2016-02-08 17:22 UTC (History)
1 user (show)

See Also:


Attachments

Description Abel Braaksma 2016-02-05 15:05:27 UTC
This test assumes that the fn:sum function retains type while in fact I think that the only requirement of the fn:sum function, which is defined in terms of the addition operator, is that the result is one of xs:double, xs:float, xs:decimal, xs:integer. I think that implementations are allowed leniency in optimizing more restrictive types away.

Hence the result is allowed to be false. I suggest an alternative result, or rewrite the test to:

sum(xs:unsignedShort("1")) instance of xs:unsignedShort or 
sum(xs:unsignedShort("1")) instance of xs:integer
Comment 1 Michael Kay 2016-02-05 15:23:41 UTC
Whether we like it or not, the spec says that the result of sum($c) is

if (fn:count($c) eq 0) then
    $zero
else if (fn:count($c) eq 1) then
    $c[1]
else
    $c[1] + fn:sum(subsequence($c, 2))

and on that basis the test is correct.

(Frans's tests are usually right, or at least they were right at the time they were written...)
Comment 2 Michael Kay 2016-02-05 16:09:17 UTC
But thanks for pointing it out: we were getting this wrong on one execution platform, and hadn't noticed. More seriously, I don't think there were any tests (there are now) that the second argument is ignored if the sequence is non-empty: we were returning 20 rather than 10 for sum((1 to 4), 10).
Comment 3 Michael Kay 2016-02-05 17:16:46 UTC
The test that does appear to be wrong here is fn-sum-10:

      <test>sum(xs:duration("P1Y1M1D"), xs:duration("PT0S"))</test>

This expects an error. But there should be no error - the specification says that the second argument is ignored if the first argument is a non-empty sequence.

Since this test has been around for nearly 6 years, it might suggest that many implementors are getting this wrong. However, given that the spec is completely unambiguous and has not changed since XPath 2.0/XQuery 1.0, I don't think we can consider changing the spec.
Comment 4 Abel Braaksma 2016-02-07 01:46:10 UTC
(In reply to Michael Kay from comment #1)
>     $c[1] + fn:sum(subsequence($c, 2))
> 
> and on that basis the test is correct.
I'm not sure it is. We say in 4.2 of FO31:

<quote>
In general the two-argument functions require that both arguments are of the same primitive type, and they return a value of this same type. 
</quote>

Then the text goes on and explains that the output is one of xs:integer, xs:float, xs:double, xs:decimal.

I think this makes sense, because otherwise fn:sum(xs:byte(127), xs:byte(127)) would overflow.

If I try it in Saxon, it returns xs:integer. And even when the values are in range, it still returns xs:integer and not xs:byte.

I would assume this to be the same for any other type: integers and derived types thereof become xs:integer etc etc.

(In reply to Michael Kay from comment #3)
> The test that does appear to be wrong here is fn-sum-10:
>
> This expects an error. But there should be no error - the specification says
> that the second argument is ignored if the first argument is a non-empty
> sequence.
The test is correct but for another reason: the first argument has an xs:duration with a Day facet, which is not allowed, it has no additive operand defined.

One could argue that it does not matter because of the normative function which, as written, would not call the additive operator. However, I think it makes sense to allow it to throw.

(In reply to Michael Kay from comment #2)
> were returning 20 rather than 10 for sum((1 to 4), 10).
Ouch, good catch ;).
Comment 5 Michael Kay 2016-02-07 13:19:15 UTC
The statement in 4.2 is clearly intended to apply only to the operators in the table immediately above, such as op:numeric-plus. It clearly doesn't apply to all two-arguments functions.
Comment 6 Abel Braaksma 2016-02-07 18:42:37 UTC
(In reply to Michael Kay from comment #5)
> The statement in 4.2 is clearly intended to apply only to the operators in
> the table immediately above, such as op:numeric-plus. It clearly doesn't
> apply to all two-arguments functions.
Then I'm lost, because fn:sum I believe is (normatively) defined in terms op op:numeric-plus, and as shown in the example, it seems that current practice of (some?) implementations is that derived types are unified into xs:integer if that is their common ancestor, even if the types of the sequence are all the same.

Personally, I do not see much use in fn:sum with xs:byte or xs:short to have to retain its type, if not only because of the possible overflow scenarios, which in turn are defined by that same section 4.2, adding to the confusion if that is supposed to be different.

Something can be said for positive-only types, or negative-only types to keep their type identity, but again, to me it makes sense if they would all simply return xs:integer for the sake of uniformity and principle of least surprise (but that is in the eye of the beholder, of course).

------------------------------

That said, I think I digressed in the direction of non-singleton sequences and forgot the point of the original bug report. I see now that it should return itself and it makes sense (to some extend at least) that is should retain its type, which means that fn:sum($somesingleton) is the same as $somesingleton.

However, the text here seems to contradict itself:

<quote>
For numeric values, the numeric promotion rules defined in 4.2 Arithmetic operators on numeric values are used to promote all values to a single common type. The sum of a sequence of integers will therefore be an integer, while the sum of a numeric sequence that includes at least one xs:double will be an xs:double.
</quote>

This is not in line with the given function body expression. I have reported this separately in Bug 29430.
Comment 7 Abel Braaksma 2016-02-07 19:07:48 UTC
After I fixed this special case in my code, I found that K-SeqSUMFunc-17 fails, it is defined as:

sum(xs:untypedAtomic("3")) instance of xs:double

Following your reasoning in comment#1, I think this test is incorrect. It should return xs:untypedAtomic: no conversion takes place because op:numeric-plus is not invoked.
Comment 8 Abel Braaksma 2016-02-07 19:10:13 UTC
(In reply to Abel Braaksma from comment #7)
> Following your reasoning in comment#1, I think this test is incorrect. It
> should return xs:untypedAtomic: no conversion takes place because
> op:numeric-plus is not invoked.
Oh crap, bad reading skills. The $c in the code snippet is the *converted sequence* and conversion takes place *prior* to op:numeric-plus being invoked, or not. So xs:double is correct (wish I could deleted my comment...)
Comment 9 Michael Kay 2016-02-08 10:20:11 UTC
>because fn:sum I believe is (normatively) defined in terms op op:numeric-plus

It only invokes op:numeric-plus if there are at least two items in the input sequence. The original bug is concerned with the sum of a singleton sequence.
Comment 10 Abel Braaksma 2016-02-08 17:22:27 UTC
(In reply to Michael Kay from comment #9)
> The original bug is concerned with the sum of a singleton sequence.
Yes indeed. Let's close this thread as WORKSFORME, I think we are in agreement. I already opened a spec-bug w.r.t. the other points: bug 29430.