DECLAIM FTYPE: invalid suggestion to use &OPTIONAL in place of &REST

Bug #1904766 reported by Michał "phoe" Herda on 2020-11-18
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
Undecided
Unassigned

Bug Description

SBCL 2.0.10 on Linux amd64.

(in-package #:cl-user)

(defstruct (foo
            (:constructor %make-foo))
  (type nil :type symbol))

(defstruct (bar
            (:constructor %make-bar)
            (:include foo)))

(declaim (ftype (function (symbol &rest t) foo) make-foo))
(defun make-foo (type &rest args)
  (if (subtypep type 'foo)
      (apply (alexandria:symbolicate '#:%make- type) :type type args)
      (error "~s is not defined." type)))

; note: Type assertion too complex to check:
; (VALUES COMMON-LISP-USER::FOO &REST T).
; It allows an unknown number of values, consider using
; (VALUES COMMON-LISP-USER::FOO &OPTIONAL).

I will gladly learn how I can pass an unknown number of values (which is fully intentional here, the arguments get passed to another constructor function via APPLY) by using &OPTIONAL, as SBCL suggests.

"Michał \"phoe\" Herda" <email address hidden> writes:

> (declaim (ftype (function (symbol &rest t) foo) make-foo))
> (defun make-foo (type &rest args)
> (if (subtypep type 'foo)
> (apply (alexandria:symbolicate '#:%make- type) :type type args)
> (error "~s is not defined." type)))
>
> ; note: Type assertion too complex to check:
> ; (VALUES COMMON-LISP-USER::FOO &REST T).
> ; It allows an unknown number of values, consider using
> ; (VALUES COMMON-LISP-USER::FOO &OPTIONAL).
>
> I will gladly learn how I can pass an unknown number of values (which is
> fully intentional here, the arguments get passed to another constructor
> function via APPLY) by using &OPTIONAL, as SBCL suggests.

SBCL is not suggesting that the arguments part of the FTYPE declaration
is changed.

The declamation

    (ftype (function (symbol &rest t) foo) make-foo)

means "this function MAKE-FOO, when it's called, will always take a
symbol as its first argument, and any number of other arguments; its
primary return value will be a FOO". It's equivalent to

    (ftype (function (symbol &rest t) (values foo &rest t)) make-foo)

SBCL's optimization note is that that is too complex a restriction for
the normal declarations-are-assertions to apply. Why? Because as well
as the primary return value, the function could return an arbitrary
number of other values, and inserting code for checking just the first
while preserving all the others is a bit horrible. The note is
suggesting to you that if you changed the declamation to

    (ftype (function (symbol &rest t) (values foo &optional)) make-foo)

then you would be declaring that make-foo always returned precisely one
value, a FOO, which is more amenable to checking and/or derivation.

I hope that helps clarify things.

Stas Boukarev (stassats) wrote :

That's not for passing, but for returning.

Changed in sbcl:
status: New → Invalid
Michał "phoe" Herda (phoe-krk) wrote :

OK - I misread the output; thank you for the clarification.

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers