> > I have found some odd subtypep behavior on function type.
> >
> > CLUSER> (subtypep '(function (fixnum) fixnum) '(function (fixnum) integer))
> > T
> > T
> > CLUSER> (subtypep '(function (fixnum) fixnum) '(function (integer) integer))
> > T
> > T
> > CLUSER> (subtypep '(function (fixnum) fixnum) '(function (bit) integer))
> > NIL
> > T
> >
> > As you may know, function parameters should be contravariant, meaning if we have a>b <: a'>b, then a' <: a must hold. So last two statement could be said wrong, or at least the second value should be false.
>
> I don't follow. In CL, and SBCL specifically covariance seems exactly
> right to me. Can you unpack your reasoning a little?
OK, let me explain my concern with a working example.
Here, we have two functions: one takes an argument of type fixnum and another takes an argument of type bit.
(declaim (type (function (fixnum) t) functionwithfixnumboundary))
(defparameter functionwithfixnumboundary
(lambda (index)
(declare (type fixnum index)
(optimize (safety 0)))
(format t "~D must be a type of fixnum~%" index)))
(declaim (type (function (bit) t) functionwithbitboundary))
(defparameter functionwithbitboundary
(lambda (index)
(declare (type bit index)
(optimize (safety 0)))
(format t "~D must be a type of bit~%" index)))
Both of functions are unsafe, meaning the type of the argument wouldn't be typechecked.
Then, let's update the function reference carefully like:
(defun variabletype (name)
(cdr (assoc 'type (nthvalue 2 (sbcltl2:variableinformation name)))))
(when (equal (multiplevaluelist
(subtypep (variabletype 'functionwithbitboundary)
(variabletype 'functionwithfixnumboundary)))
'(t t))
(setq functionwithfixnumboundary functionwithbitboundary))
The above assignment will be evaluated because (function (bit) t) <: (function (fixnum) t) is valid in SBCL.
Now, call the function like (note that this function call should be valid):
(funcall functionwithfixnumboundary 10)
Then, we will get the following message.
10 must be a type of bit
In a real world program, such a illegal function call might cause the program SEGV.
The problem is that the subtypep states (function (bit) t) is subtype of (function (fixnum) t), though actually (function (bit) t) is NOT subtype of (function (fixnum) t), in a meaning of that a value of the subtype can be used as a value of supertype.
That's what I wanted to explain.

Tomohiro Matsuyama <tomo@...>
