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 6160 - [FS] 7.1.1 The fs:convert-operand function: incorrect type rules
Summary: [FS] 7.1.1 The fs:convert-operand function: incorrect type rules
Status: CLOSED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: Formal Semantics 1.0 (show other bugs)
Version: Recommendation
Hardware: All All
: P2 normal
Target Milestone: ---
Assignee: Michael Dyck
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-10-13 21:16 UTC by Michael Dyck
Modified: 2009-02-16 01:06 UTC (History)
1 user (show)

See Also:


Attachments

Description Michael Dyck 2008-10-13 21:16:58 UTC
(This bug is extracted from Bug 5915 comment #2, where it's secondary to
that bug's main point.)

Consider the query:

    let $x := if (1) then text{"42"} else 3.14
    return -$x

which normalizes to something like:

    let $x := if (1) then text{"42"} else 3.14
    return fs:unary-minus( fs:convert-operand( fn:data($x), 1.0E0 ) )
    
We can infer the following static types:

    text{"42"}                        : text?
    3.14                              : xs:decimal
    if (1) then text{"42"} else 3.14  : text? | xs:decimal
    $x                                : text? | xs:decimal
    fn:data($x)                       : (xs:untypedAtomic | xs:decimal)?

The last of these types becomes 'Type1' in the Static Type Analysis rules
for fs:convert-operand (FS 7.1.1). Note that
    Type1 <: xs:untypedAtomic?
does not hold (because of the presence of xs:decimal in Type1), and so
only the first of the four rules applies:

    statEnv |- not(Type1 <: xs:untypedAtomic?)
    ------------------------------------------------------------
    statEnv |- (FS-URI,"convert-operand")( Type1, Type2) : Type1

Thus the static type of the call to fs:convert-operand is also inferred to
be:
    (xs:untypedAtomic | xs:decimal)?
    
On the other hand, we know that dynamically:
    $x is bound to a text node,
    fn:data($x) yields "42" as an xs:untypedAtomic, and
    fs:convert-operand returns that value cast to xs:double.

Since the value of the call does not belong to the static type for
the call, this is a violation of type soundness. The rules for
fs:convert-operand need to be changed to properly handle such cases.
Comment 1 Michael Dyck 2008-10-14 00:02:58 UTC
I propose to replace the rules in 7.1.1 / STA with the following rules.
(Note that the second through fifth are minor reworkings of the existing
four rules.)


statEnv |- Type0 <: xs:anyAtomicType?
statEnv |- TypeE <: xs:anyAtomicType
prime(Type0) = AtomicTypeName1 | ... | AtomicTypeNameN
statEnv |- convert_operand AtomicTypeName1 against TypeE is AtomicTypeName1'
...
statEnv |- convert_operand AtomicTypeNameN against TypeE is AtomicTypeNameN'
AtomicTypeName1' | ... | AtomicTypeNameN' = TypeR
-----------------------------------------------------
statEnv |- (FS-URI,"convert-operand")(Type0, TypeE) :
               TypeR . quantifier(Type0)


statEnv |- not(AtomicTypeName <: xs:untypedAtomic)
-------------------------------------------------------
statEnv |- convert_operand AtomicTypeName against TypeE is AtomicTypeName


statEnv |- AtomicTypeName <: xs:untypedAtomic
statEnv |- TypeE <: xs:untypedAtomic | xs:string
-------------------------------------------------------
statEnv |- convert_operand AtomicTypeName against TypeE is xs:string


statEnv |- AtomicTypeName <: xs:untypedAtomic
statEnv |- TypeE <: fs:numeric
-------------------------------------------------------
statEnv |- convert_operand AtomicTypeName against TypeE is xs:double


statEnv |- AtomicTypeName <: xs:untypedAtomic
statEnv |- not(TypeE <: xs:untypedAtomic | xs:string | fs:numeric)
-------------------------------------------------------
statEnv |- convert_operand AtomicTypeName against TypeE is TypeE
Comment 2 Tim Mills 2008-10-24 10:28:15 UTC
While we agree that the new rules you have proposed are correct,
recalling your comment from Bug 5915

"The new rules will probably change the static type of
    fs:convert-operand(data(()), 1)
to 'empty'"

they are not the most precise.

Under your new rules, I think

    fs:convert-operand(data(()), 1)

will come out as xs:double?, rather than the more precise type 'empty'.

statEnv |- none <: xs:untypedAtomic
statEnv |- xs:double <: fs:numeric
-------------------------------------------------------
statEnv |- convert_operand none against xs:double is xs:double


statEnv |- empty <: xs:anyAtomicType?
statEnv |- xs:double<: xs:anyAtomicType
prime(empty) = none
statEnv |- convert_operand none against xs:double is AtomicTypeName1'
-----------------------------------------------------
statEnv |- (FS-URI,"convert-operand")(empty, xs:double) :
               xs:double . quantifier(empty) = xs:dobule?

Comment 3 Michael Dyck 2008-10-24 18:39:17 UTC
My proposed new rule has the premise
    prime(Type0) = AtomicTypeName1 | ... | AtomicTypeNameN
and in your second inference above, when Type0 is bound to 'empty', you've
used the fact (from FS 8.4) that
    prime(empty) = none
to bind N to 1 and AtomicTypeName1 to 'none'.

However, the thing to note is that 'none' isn't an AtomicTypeName, rather
it's a concrete way of denoting "a choice with zero alternatives". So the
proper way to use
    prime(empty) = none
to satisfy the given premise is to bind N to 0. Whereupon:
 -- the "convert_operand against" premises disappear,
 -- TypeR is bound to 'none', and
 -- the type inferred for the convert-operand() call is
        none . quantifier(empty)
     =  none . ?
     =  empty
Comment 4 Tim Mills 2008-10-27 08:10:23 UTC
Good point.  We hadn't spotted that.  

It might be worth a note in the erratum to avoid misinterpretation.
Comment 5 Michael Dyck 2008-11-11 06:14:10 UTC
> It might be worth a note in the erratum to avoid misinterpretation.

I'm thinking of adding a Note immediately after the definition of prime(), conveying something like the point of comment #3. 

Comment 6 Michael Dyck 2008-11-11 06:21:26 UTC
At its meeting on 2008-10-27, the XQuery WG accepted the proposal in
comment #1. Consequently, I'm marking this bug resolved-fixed. If you
agree with this resolution, please mark the bug closed.
Comment 7 Tim Mills 2008-11-11 08:41:12 UTC
Great, thanks.
Comment 8 Michael Dyck 2009-02-16 01:06:20 UTC
This issue has been entered as FS erratum E057, and the proposed fixes have
been committed to the source files for the next edition of the FS document.

Actually, while working on the erratum, it occurred to me the that same
problem can occur with the second argument's type, so I modified the fix
to handle that too.

Consequently, I'm marking this issue CLOSED.