- From: <bugzilla@jessica.w3.org>
- Date: Thu, 04 Aug 2011 17:22:03 +0000
- To: public-qt-comments@w3.org
http://www.w3.org/Bugs/Public/show_bug.cgi?id=13674 Summary: [XQ30] schema-element() types behave differently in different modules. Product: XPath / XQuery / XSLT Version: Member-only Editors Drafts Platform: PC OS/Version: Windows NT Status: NEW Severity: normal Priority: P2 Component: XQuery 3.0 AssignedTo: jonathan.robie@gmail.com ReportedBy: oliver@cbcl.co.uk QAContact: public-qt-comments@w3.org I have been trying to modify our typing judgements to allow for separate compilation of modules (there were several places in the FS rules where this was not possible), and have run into the following issue with schema-element() types. Consider the following: 1. A schema with target namespace "urn:S1" which declares an element {urn:S1}E. 2. A schema with target namespace "urn:S2" which declares an element {urn:S2}E which substitutes for {urn:S1}E. Now, consider the module (urn:M1): declare module namespace m1="urn:M1"; import schema namespace s1="urn:S1"; declare function m1:function($x as schema-element(s1:E)) as xs:boolean { return $x instance of schema-element(s1:E); } The function m1:function accepts any element in the in-scope schema elements that substitutes for s1:E. In this case it only accepts elements named s1:E. Clearly this function should always return true. Consider the following query. import schema namespace s1="urn:S1"; import schema namespace s2="urn:S2"; import module namespace m1="urn:M1"; let $function := m1:function#1 as function(schema-element(s1:E)) as xs:boolean let $argument := validate { <s2:E /> } as schema-element(s1:E) return $function($argument) In this query the type schema-element(s1:E) also matches an s2:E element, as this is in the substitution group for s1:E. Following the rules given in the XQuery spec, both these type judgements are fine. Since the function takes a schema-element(s1:E) and we are passing it a schema-element(s1:E) no argument conversion takes place. However, the actual value of the function call is false, which indicates that something odd is going on, and the type system is not sound. I can see several ways of resolving this, none of which seem entirely satisfactory: 1. schema-element(E) matches any element that substitutes for E, regardless of whether this schema was imported in the current module. That is, when matching a schema-element(E) an implementation should use all the schema elements that it is aware of, and not just those that have been imported. 2. It is a static error if schema-element(E) is used ambiguously in different modules. If a module imports a schema which contains an element E' in namespace N' that substitutes for an element E in namespace N then it is a static error if any module contains a schema-element(E) without importing the namespace E', or more simply if any module imports N without importing N'. 3. schema-element(E) is shorthand for the union of matching element types. Specifically, schema-element(E) is expanded to the union of element types element (E', T') where E' and T' are the name and type respectively of an in-scope schema element that substitutes for E. 4. Importing a schema also imports any other namespaces the implementation is aware of that substitute elements in it. A few notes on each suggestion: 1: This agrees with the static typing rules given in FS. (FS apples all its type judgements based on the fact that it knows every type that can appear). When compiling modules seperately this hampers static analysis, as you cannot say anything about the name of an element that matches a type T without knowing which other schemas are available in other modules. Changing a schema import in one module could break another module. This may not be a problem in practice! 2: This is the simplest option to implement in the spec - just adding one more error condition. This prevents the following use case: * There is a simple schema S * There are two incompatible extensions to S, S1 and S2. * There are two queries Q1 and Q2 importing S1 and S2 which both use a common module M inporting S. Now, to use M in Q1 it must import S1. To use M in Q2 it must import S2. But it is an error if M imports both. Whilst the extra error may seem somewhat arbitrary to users, I suspect that it will very rarely be seen. 3: Painful to explain in the spec, as we don't have arbitrary union types This could lead to more costly type checking when calling functions in precompiled modules. The meaning of the type schema-element(E) would depend on its context. This would cause issues when exposing types to the outside world, and would hurt APIs. Potential for bugs. 4: Implementations are already allowed to do this since the schemas that are imported by a "schema import" are implementation defined. This is similar to option 1, but performs the same task by adding more types to the in-scope schema types. This can also be viewed as similar to option 2, but implicitly imports missing schemas rather than raising an error. This prevents a module from being compiled until all schemas are known. My opinion is that whilst option 3 seems cleanest in theory, it is probably the worst in practice! Option 1 seems nicest from a "no suprises" user perspective, but currently my preference would lie with option 2 as this allows the greatest flexibility to implementors. -- Configure bugmail: http://www.w3.org/Bugs/Public/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are the QA contact for the bug.
Received on Thursday, 4 August 2011 17:22:04 UTC