FTYPE declaration badness
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
Confirmed
|
Medium
|
Unassigned |
Bug Description
The compiler assumes that any time a function of declared FTYPE
doesn't signal an error, its arguments were of the declared type.
E.g. compiling and loading
(DECLAIM (OPTIMIZE (SAFETY 3)))
(DEFUN FACTORIAL (X) (GAMMA (1+ X)))
(DEFUN GAMMA (X) X)
(DECLAIM (FTYPE (FUNCTION (UNSIGNED-BYTE)) FACTORIAL))
(DEFUN FOO (X)
(COND ((> (FACTORIAL X) 1.0E6)
(T
then executing
(FOO 1.5)
will cause the INTEGERP case to be selected, giving bogus output a la
exactly 2.5
This violates the "declarations are assertions" principle.
According to the ANSI spec, in the section "System Class FUNCTION",
this is a case of "lying to the compiler", but the lying is done
by the code which calls FACTORIAL with non-UNSIGNED-BYTE arguments,
not by the unexpectedly general definition of FACTORIAL. In any case,
"declarations are assertions" means that lying to the compiler should
cause an error to be signalled, and should not cause a bogus
result to be returned. Thus, the compiler should not assume
that arbitrary functions check their argument types. (It might
make sense to add another flag (CHECKED?) to DEFKNOWN to
identify functions which *do* check their argument types.)
(Also, verify that the compiler handles declared function
return types as assertions.)
Changed in sbcl: | |
importance: | Undecided → Medium |
status: | New → Confirmed |
I'm inclined to think that the correct solution would be to add :TRUSTED as a :WHERE-FROM type to globaldb, and trust only those.
After a function has been compiled, any :DECLARED type it had can be upgraded to :TRUSTED.