Given Input Type | XQuery Expression | Expected Output Type |
<!ELEMENT r (b*,c?,d)> <!ELEMENT b EMPTY> <!ELEMENT c EMPTY> <!ELEMENT d EMPTY> |
<r>{for $y in child::* return <a>{$y}</a>}</r> |
<!ELEMENT r (a*)> <!ELEMENT a (b|d)> <!ELEMENT b EMPTY> <!ELEMENT d EMPTY> |
Explanation
The type-checker detects that: (1) an element "c" may occur as a child of root element "r" in the input, and that (2) for this element the expression will output an "a" element with an "c" child which is forbidden by the content model of "a" elements expected as output.
Full Trace
The full trace generated by the implementation for the example above:
Static type-checking 'sample.xq' with input type 'input.dtd' starting at 'r' and output type 'output.dtd' starting at 'r'... Read in sample.xq: <r>{for $y in child::* return <a>{$y}</a>}</r> Considered Input XQuery expression: element r {for $y in child::* return element a {$y } } Parsing tree grammar 'output.dtd'... CFT: 9 type variables, 9 production rules, 4 element names. Resulting CFT is: $Empty -> EMPTYSET $Epsilon -> () $Any -> () $PCData -> () $d -> d(()) $b -> b(()) $a -> a(($b | $d)) $1 -> ($a | ($a, $1)) $r -> r(($1 | ())) Start symbol is $r 9 type variables, 9 production rules, 4 element names. BTT: 8 type variables, 7 production rules, 5 element names. Resulting BTT is: $Epsilon -> EPSILON $Any -> *($Any, $Any) | EPSILON $Empty -> EMPTYSET $2 -> b($Epsilon, $Epsilon) | d($Epsilon, $Epsilon) $3 -> a($2, $Epsilon) | a($2, $3) $1 -> EPSILON | a($2, $Epsilon) | a($2, $3) $r -> r($1, $Epsilon) Start Symbol is $r 7 type variables, 7 production rules, 5 element names. Inferring Input Type... elem_elem element r {for $y in child::* return element a {$y } } , r($1, $Epsilon) expr_union for $y in child::* return element a {$y } , EPSILON | a($2, $Epsilon) | a($2, $3) for_empty for $y in child::* return element a {$y } , EPSILON child_empty: input root child::* , EPSILON child_empty returns (~<-2>T & ~<-1>T & ~<1>T) in_child for child::* in_child for child::* returns (mu X1.(<-2>X1 | <-1>(~<-2>T & ~<-1>T))) elem_empty returns: false for_empty: t1 is (~<-2>T & ~<-1>T & ~<1>T) for_empty: t is (mu X1.(<-2>X1 | <-1>(~<-2>T & ~<-1>T))) for_empty: t2 is F for_empty: t2subst F for_empty returns (~<-2>T & ~<-1>T & ~<1>T) expr_union for $y in child::* return element a {$y } , a($2, $Epsilon) | a($2, $3) for_elem for $y in child::* return element a {$y } , a($2, $Epsilon) elem_elem element a {$y } , a($2, $Epsilon) expr_union $y , b($Epsilon, $Epsilon) | d($Epsilon, $Epsilon) var_elem $y , b($Epsilon, $Epsilon) var_elem returns: (X2 & b & ~<1>T) var_elem $y , d($Epsilon, $Epsilon) var_elem returns: (X2 & d & ~<1>T) expr_union returns:((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) elem_elem returns: ((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) for_elem for $y in child::* return element a {$y } , a($2, $3) elem_elem element a {$y } , a($2, $3) elem_elem returns false elem_elem element a {$y } , a($2, $Epsilon) expr_union $y , b($Epsilon, $Epsilon) | d($Epsilon, $Epsilon) var_elem $y , b($Epsilon, $Epsilon) var_elem returns: (X2 & b & ~<1>T) var_elem $y , d($Epsilon, $Epsilon) var_elem returns: (X2 & d & ~<1>T) expr_union returns:((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) elem_elem returns: ((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) expr_union element a {$y } , a($2, $Epsilon) | a($2, $3) elem_elem element a {$y } , a($2, $Epsilon) expr_union $y , b($Epsilon, $Epsilon) | d($Epsilon, $Epsilon) var_elem $y , b($Epsilon, $Epsilon) var_elem returns: (X2 & b & ~<1>T) var_elem $y , d($Epsilon, $Epsilon) var_elem returns: (X2 & d & ~<1>T) expr_union returns:((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) elem_elem returns: ((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) elem_elem element a {$y } , a($2, $3) elem_elem returns false expr_union returns:((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) expr_union element a {$y } , a($2, $Epsilon) | a($2, $Epsilon) elem_elem element a {$y } , a($2, $Epsilon) expr_union $y , b($Epsilon, $Epsilon) | d($Epsilon, $Epsilon) var_elem $y , b($Epsilon, $Epsilon) var_elem returns: (X2 & b & ~<1>T) var_elem $y , d($Epsilon, $Epsilon) var_elem returns: (X2 & d & ~<1>T) expr_union returns:((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) elem_elem returns: ((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) elem_elem element a {$y } , a($2, $Epsilon) expr_union $y , b($Epsilon, $Epsilon) | d($Epsilon, $Epsilon) var_elem $y , b($Epsilon, $Epsilon) var_elem returns: (X2 & b & ~<1>T) var_elem $y , d($Epsilon, $Epsilon) var_elem returns: (X2 & d & ~<1>T) expr_union returns:((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) elem_elem returns: ((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) expr_union returns:((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) expr_union element a {$y } , a($2, $Epsilon) | a($2, $3) elem_elem element a {$y } , a($2, $Epsilon) expr_union $y , b($Epsilon, $Epsilon) | d($Epsilon, $Epsilon) var_elem $y , b($Epsilon, $Epsilon) var_elem returns: (X2 & b & ~<1>T) var_elem $y , d($Epsilon, $Epsilon) var_elem returns: (X2 & d & ~<1>T) expr_union returns:((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) elem_elem returns: ((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) elem_elem element a {$y } , a($2, $3) elem_elem returns false expr_union returns:((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) expr_union element a {$y } , a($2, $Epsilon) | a($2, $Epsilon) elem_elem element a {$y } , a($2, $Epsilon) expr_union $y , b($Epsilon, $Epsilon) | d($Epsilon, $Epsilon) var_elem $y , b($Epsilon, $Epsilon) var_elem returns: (X2 & b & ~<1>T) var_elem $y , d($Epsilon, $Epsilon) var_elem returns: (X2 & d & ~<1>T) expr_union returns:((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) elem_elem returns: ((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) elem_elem element a {$y } , a($2, $Epsilon) expr_union $y , b($Epsilon, $Epsilon) | d($Epsilon, $Epsilon) var_elem $y , b($Epsilon, $Epsilon) var_elem returns: (X2 & b & ~<1>T) var_elem $y , d($Epsilon, $Epsilon) var_elem returns: (X2 & d & ~<1>T) expr_union returns:((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) elem_elem returns: ((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) expr_union returns:((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) Recursive pattern detected, variable inserted: X3 Recursive pattern created: (mu X3.((((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) & <2>X3) | (~<2>T & ((X2 & d & ~<1>T) | (X2 & b & ~<1>T))))) Recursive pattern created: (mu X3.((((X2 & d & ~<1>T) | (X2 & b & ~<1>T)) & <2>X3) | (~<2>T & ((X2 & d & ~<1>T) | (X2 & b & ~<1>T))))) expr_union returns:((~<-2>T & <1>(((d & ~<1>T) | (b & ~<1>T)) & ~<2>T) & ~<-1>T) | (~<-2>T & ~<-1>T & <1>(((d & ~<1>T) | (b & ~<1>T)) & <2>(mu X4.((((d & ~<1>T) | (b & ~<1>T)) & ~<2>T) | (((d & ~<1>T) | (b & ~<1>T)) & <2>X4)))))) expr_union returns:((~<-2>T & <1>(((d & ~<1>T) | (b & ~<1>T)) & ~<2>T) & ~<-1>T) | (~<-2>T & ~<-1>T & <1>(((d & ~<1>T) | (b & ~<1>T)) & <2>(mu X4.((((d & ~<1>T) | (b & ~<1>T)) & ~<2>T) | (((d & ~<1>T) | (b & ~<1>T)) & <2>X4))))) | (~<-2>T & ~<-1>T & ~<1>T)) elem_elem returns: ((~<-2>T & <1>(((d & ~<1>T) | (b & ~<1>T)) & ~<2>T) & ~<-1>T) | (~<-2>T & ~<-1>T & <1>(((d & ~<1>T) | (b & ~<1>T)) & <2>(mu X4.((((d & ~<1>T) | (b & ~<1>T)) & ~<2>T) | (((d & ~<1>T) | (b & ~<1>T)) & <2>X4))))) | (~<-2>T & ~<-1>T & ~<1>T)) Inferred input type represented as a formula: ((~<-2>T & <1>(((d & ~<1>T) | (b & ~<1>T)) & ~<2>T) & ~<-1>T) | (~<-2>T & ~<-1>T & <1>(((d & ~<1>T) | (b & ~<1>T)) & <2>(mu X4.((((d & ~<1>T) | (b & ~<1>T)) & ~<2>T) | (((d & ~<1>T) | (b & ~<1>T)) & <2>X4))))) | (~<-2>T & ~<-1>T & ~<1>T)) Parsing and compiling input type 'input.dtd' starting at 'r'... Parsing tree grammar 'input.dtd'... CFT: 9 type variables, 9 production rules, 4 element names. Resulting CFT is: $Empty -> EMPTYSET $Epsilon -> () $Any -> () $PCData -> () $d -> d(()) $b -> b(()) $c -> c(()) $1 -> ($b | ($b, $1)) $r -> r(((($1 | ()), ($c | ())), $d)) Start symbol is $r 9 type variables, 9 production rules, 4 element names. BTT: 9 type variables, 8 production rules, 5 element names. Resulting BTT is: $Epsilon -> EPSILON $Any -> *($Any, $Any) | EPSILON $Empty -> EMPTYSET $3 -> d($Epsilon, $Epsilon) $2 -> c($Epsilon, $3) | d($Epsilon, $Epsilon) $4 -> b($Epsilon, $2) | b($Epsilon, $4) $1 -> b($Epsilon, $2) | b($Epsilon, $4) | c($Epsilon, $3) | d($Epsilon, $Epsilon) $r -> r($1, $Epsilon) Start Symbol is $r 8 type variables, 8 production rules, 5 element names. Converted tree grammar into BTT [3 ms]. Translated BTT into Tree Logic [8 ms]. input: (let X5=(r & ~<2>T & <1>X6), X6=((c & <2>X9 & ~<1>T) | (d & ~<2>T & ~<1>T) | (b & <2>X8 & ~<1>T) | (b & <2>X7 & ~<1>T)), X7=((c & <2>X9 & ~<1>T) | (d & ~<2>T & ~<1>T)), X8=((b & <2>X8 & ~<1>T) | (b & <2>X7 & ~<1>T)), X9=(d & ~<2>T & ~<1>T) in X5) neg_inferred: (<-1>T | (mu X11.((<-1>T | <-2>T | <1>(((<1>T | ~d) & (<1>T | ~b)) | ~<2>T | <2>(mu X12.((((<1>T | ~d) & (<1>T | ~b)) | ~<2>T | <2>X12) & (((<1>T | ~d) & (<1>T | ~b)) | <2>T)))) | ~<1>T) & (<-1>T | <1>T | <-2>T) & (<2>X11 | ~<2>T) & (<1>X11 | ~<1>T) & (<-1>T | <1>(((<1>T | ~d) & (<1>T | ~b)) | <2>T) | <-2>T | ~<1>T))) | <-2>T) Global formula contains the following total numbers of occurrences (including duplicates): 18 atomic propositions, 54 modalities, 13 variables, 3 fixpoint binder, 30 negations, 17 conjunctions, 21 disjunctions. Satisfiability Tested Formula: (mu X13.((~<-2>T & (<-1>T | (mu X11.((<-1>T | <-2>T | <1>(((<1>T | ~d) & (<1>T | ~b)) | ~<2>T | <2>(mu X12.((((<1>T | ~d) & (<1>T | ~b)) | ~<2>T | <2>X12) & (((<1>T | ~d) & (<1>T | ~b)) | <2>T)))) | ~<1>T) & (<-1>T | <1>T | <-2>T) & (<2>X11 | ~<2>T) & (<1>X11 | ~<1>T) & (<-1>T | <1>(((<1>T | ~d) & (<1>T | ~b)) | <2>T) | <-2>T | ~<1>T))) | <-2>T) & ~<2>T & ~<-1>T & (let X5=(r & ~<2>T & <1>X6), X6=((c & <2>X9 & ~<1>T) | (d & ~<2>T & ~<1>T) | (b & <2>X8 & ~<1>T) | (b & <2>X7 & ~<1>T)), X7=((c & <2>X9 & ~<1>T) | (d & ~<2>T & ~<1>T)), X8=((b & <2>X8 & ~<1>T) | (b & <2>X7 & ~<1>T)), X9=(d & ~<2>T & ~<1>T) in X5)) | <2>X13 | <1>X13)) Warning: no suitable native BDD library found. Falling back to the Java one. Computing Relevant Closure... Computed Relevant Closure [8 ms]. Computed Lean [1 ms]. Lean size is 21. It contains 15 eventualities and 6 symbols. Fixpoint Computation Initialized [15 ms]. Computing Fixpoint.....[24 ms]. Formula is satisfiable [total time: 54 ms]. A satisfying finite binary tree model is [7 ms]: r(c(#, d), #) In XML syntax: <r xmlns:solver="http://wam.inrialpes.fr/xml" solver:target="true"> <c/> <d/> </r> Static type checking failed. You can execute the program with the counter-example generated above as input and validate the result to see the error.