-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ANSI-TEST SUBTYPEP.CONS.43 fails #249
Comments
Looks like the issue is in the type translator for CL-USER> (funcall (ccl::info-type-translator 'not)
`(NOT (OR (NOT CONS)
(CONS (INTEGER 0 0)
(OR (NOT INTEGER)
(INTEGER * -1)
(REAL (-3.926510009989861D+7))
(REAL * (-3.926510009989861D+7))))
(CONS (OR (NOT INTEGER)
(INTEGER * -1)
(INTEGER 1))
T)))
(ccl::new-lexical-environment))
#<NAMED-CTYPE NIL> |
Some more digging, following the logic in CCL> (defparameter *type* `(OR (NOT CONS)
(CONS (INTEGER 0 0)
(OR (NOT INTEGER)
(INTEGER * -1)
(REAL (-3.926510009989861D+7))
(REAL * (-3.926510009989861D+7))))
(CONS (OR (NOT INTEGER)
(INTEGER * -1)
(INTEGER 1))
T)))
*TYPE*
CCL> (defparameter *ctype* (ccl::specifier-type *type*))
*CTYPE*
CCL> (union-ctype-types *ctype*)
(#<NEGATION-CTYPE (NOT CONS)> #<CONS-CTYPE (CONS (INTEGER 0 0) (OR (NOT INTEGER) (INTEGER * -1) (REAL (-3.926510009989861D+7)) (REAL * (-3.926510009989861D+7))))> #<CONS-CTYPE (CONS (OR (NOT INTEGER) (INTEGER * -1) (INTEGER 1)) T)>)
CCL> (second *)
#<CONS-CTYPE (CONS (INTEGER 0 0) (OR (NOT INTEGER) (INTEGER * -1) (REAL (-3.926510009989861D+7)) (REAL * (-3.926510009989861D+7))))>
CCL> (funcall #'(lambda (x) (specifier-type `(not ,(type-specifier x)))) *)
#<UNION-CTYPE (OR (NOT CONS) (CONS (OR (NOT INTEGER) (INTEGER * -1) (INTEGER 1)) T))> In particular, we see that the negation of: #<CONS-CTYPE
(CONS (INTEGER 0 0)
(OR (NOT INTEGER)
(INTEGER * -1)
(REAL (-3.926510009989861D+7))
(REAL * (-3.926510009989861D+7))))> is #<UNION-CTYPE
(OR (NOT CONS)
(CONS (OR (NOT INTEGER)
(INTEGER * -1)
(INTEGER 1))
T))> E.g. the information about |
EDIT: Sorry, I was wrong in this comment. This type: (OR (NOT INTEGER)
(INTEGER * -1)
(REAL (-3.926510009989861D+7))
(REAL * (-3.926510009989861D+7))) is actually This means that the original type: CCL> (defparameter *type* `(OR (NOT CONS)
(CONS (INTEGER 0 0)
(OR (NOT INTEGER)
(INTEGER * -1)
(REAL (-3.926510009989861D+7))
(REAL * (-3.926510009989861D+7))))
(CONS (OR (NOT INTEGER)
(INTEGER * -1)
(INTEGER 1))
T))) Is actually: CCL> (defparameter *type* `(OR (NOT CONS)
(CONS (INTEGER 0 0)
T)
(CONS (OR (NOT INTEGER)
(INTEGER * -1)
(INTEGER 1))
T))) Which in turn is actually: CCL> (defparameter *type* `(OR (NOT CONS)
(CONS T T))) Which is also |
OK. We therefore need to go into the other branch of the test. CCL is sure that (NOT (CONS FLOAT T)) is NOT a subtype of (OR (NOT (CONS (EQL 0)
(REAL -3.926510009989861D+7 -3.926510009989861D+7)))
(NOT (CONS T (EQL 0)))) Even though the latter type is equivalent to |
I've traced it down to: (let* ((t1 '(not (cons float t)))
(t2 `(or (not (cons (eql 0) (real #1=-3.5d0 #1#)))
(not (cons t (eql 0)))))
(c1 (ccl::specifier-type t1))
(c2 (ccl::specifier-type t2)))
(defparameter *type1* c1)
(defparameter *type2* c2))
CCL> (union-simple-subtypep *type1* *type2*)
NIL
T More digging required. |
More digging: I have reduced the first type to CCL> (csubtypep (specifier-type '(CONS (NOT FLOAT) T))
(specifier-type `(OR (CONS (INTEGER 0 0)
(OR (REAL * (-3.5D0))
(NOT INTEGER)
(INTEGER * -1)
(REAL (-3.5D0))))
(CONS (OR (NOT INTEGER)
(INTEGER * -1)
(INTEGER 1))
T)))) |
I have dug my way all through CCL is sure that these two are not the same type, which is an error. CCL> (type= (specifier-type
`(OR (CONS (INTEGER 0 0)
(OR (REAL * (-3.5D0))
(NOT INTEGER)
(INTEGER * -1)
(REAL (-3.5D0))))
(CONS (OR (AND (NOT FLOAT) (NOT INTEGER))
(INTEGER * -1)
(INTEGER 1))
T)))
(specifier-type
`(CONS (NOT FLOAT) T)))
NIL
T This is because of how the type method (let ((type2 (specifier-type
`(OR (CONS (INTEGER 0 0)
(OR (REAL * (-3.5D0))
(NOT INTEGER)
(INTEGER * -1)
(REAL (-3.5D0))))
(CONS (OR (AND (NOT FLOAT) (NOT INTEGER))
(INTEGER * -1)
(INTEGER 1))
T)))))
(if (some #'type-might-contain-other-types-p
(union-ctype-types type2))
(values nil nil)
(values nil t)))
NIL
T So we check if any of the types of the union ctype might contain another type. We do it like this: (defun type-might-contain-other-types-p (type)
(or (hairy-ctype-p type)
(negation-ctype-p type)
(union-ctype-p type)
(intersection-ctype-p type))) This list has no cons type, BUT, as we can see, the following type is a union type containing (OR (CONS (INTEGER 0 0)
(OR (REAL * (-3.5D0))
(NOT INTEGER)
(INTEGER * -1)
(REAL (-3.5D0))))
(CONS (OR (NOT INTEGER)
(INTEGER * -1)
(INTEGER 1))
T)) Therefore we have a bug in our implementation - CCL> (let* ((t1 '(not (cons float t)))
(t2 `(or (not (cons (eql 0) (real #1=-3.5d0 #1#)))
(not (cons t (eql 0)))))
(c1 (ccl::specifier-type t1))
(c2 (ccl::specifier-type t2)))
(union-simple-subtypep c1 c2))
NIL
NIL Which is not the best that we can do, but, at least, it is correct. |
Fixed at phoe-trash@ba28152 |
Actually NOT fixed properly - the aforementioned commit might cause |
Hairy cons types are affected as well - @Bike found this on CCL> (subtypep `(or (cons (satisfies foo)
(satisfies foo2))
(cons (satisfies bar)
(satisfies bar2)))
`(cons (not float)))
NIL
T |
Union types go out of the window, cons types are just as affected. CCL> (subtypep `(cons (satisfies foo) (satisfies foo2))
`(cons (not float) t))
NIL
T |
Here is what I believe is going on with the "go out the window" example. Since both types are cons types, the simple subtypep method is used, that is https://github.com/Clozure/ccl/blob/master/level-1/l1-typesys.lisp#L3333-L3341 This method computes the subtypep of the cars and the subtypep of the cdrs. It gets NIL NIL for the cars and T T for the second. So far so good. Then it merges these (on 3339-3341), and does so incorrectly: It decides that since it's certain that The following truth table is ideal, I think, where T(ruth) = T T, F(alsity) = NIL T, and M(aybe) = NIL NIL:
whereas what's done now is
|
And I think the issue with the example I found is the same as the one with the range types, to be clear - the union type is all cons types, and those "never contain other types", so the complex-= method for unions erroneously concludes that the types are not equal. |
I can't really think of a nice way to rewrite that erroneous if. the best i got is |
The body of the failing test:
We are only interested in a part of this test. After simplifying:
This evaluates to
(VALUES NIL T)
, even thought2
is equivalent toT
and therefore the valid results are(VALUES T T)
and(VALUES NIL NIL)
.The text was updated successfully, but these errors were encountered: