The following expressions evaluates to boolean values, in Saxon 8.6:
(1, error()) instance of empty-sequence()
(1, 1, error()) instance of xs:integer
(1, error()) = 1
And so do my implementation. And boy, I wish it is correct to do so and it can stay that way, but I doubt it.
In the 'instance of' case, what Saxon does here(from my quick look) is a sensible optimization: if the cardinality is wrong, it doesn't evaluate the whole sequence. This in turn means the error() function is never executed, which I think this is inconsistent with the specification; it is an optimization which changes program behavior. Am I looking at it the right way?
Does the following apply for the general comparison case? "[...] an implementation may return true as soon as it finds an item in the first operand and an item in the second operand that have the required magnitude relationship. [...] As a result of these rules, the result of a general comparison is not deterministic in the presence of errors." I think there's a difference between dynamic, unpredictable errors and errors/behavior which the user have explicitly asked for. I think the quote refers to the former.
It will be interesting to see whether this will lead to a discussion about changtes to the specifications, but I doubt it.
Assuming my observation is correct, that the optimizations are not conformant, one can start thinking about how to fix it. First of all, the early-exit optimization is very valuable and one wants to keep it. Perhaps the fix is to let:
1. The AST node for the error() call signal "I must be evaluated". In my implementation, it would be one of the OR'd values among an Expression's properties.
2. The 'instance of' implementation does at compile time cache in a boolean whether its child(or any of the child's children, etc) needs to be fully evaluted.
3. At runtime choose between two code paths, one which is the fast one, and one which must evaluate the child fully, depending on what that cached value says.
And I guess one would have to do the same with general comparisons. Are there any more cases where one would typically find this error()+exit-early dilemma?