From: Adam Warner
Subject: DECLARE FTYPE
Date: 
Message-ID: <pan.2003.12.13.08.20.31.702469@consulting.net.nz>
Hi all,

Should a FTYPE declaration for a global function be recognised within
the function's declaration block? For example:

(defun test (df)
  (declare (ftype (function (double-float) double-float) test))
  df)

Currently SBCL ignores the declaration:

* (describe 'test)
...
Its defined argument types are:
  (t)
Its result type is:
  *

For the type declarations to be recognised I have to place them in a
DECLAIM statement:

(declaim (ftype (function (double-float) double-float) test))
(defun test (df)
  df)

(Which also exposes an issue with the assertion checker:)

* (defun test (df) df)
; in: lambda nil
;     (SB-INT:NAMED-LAMBDA TEST (DF) (BLOCK TEST DF))
; ==>
;   #'(SB-INT:NAMED-LAMBDA TEST (DF) (BLOCK TEST DF))
; 
; note: type assertion too complex to check:
;  (values double-float &rest t).

* (test 1d0)

1.0
* (test 1)

debugger invoked on a TYPE-ERROR in thread 2672:
  The value 1 is not of type DOUBLE-FLOAT.

(describe 'test)
Its declared argument types are:
  (double-float)
Its result type is:
  (values double-float &rest t)

From the CLHS: "If one of the functions mentioned has a lexically apparent
local definition (as made by flet or labels), then the declaration applies
to that local definition and not to the global function definition." As
there is no lexically apparent local definition as made by flet or labels
it appears the declaration should apply to the global function definition.

It also doesn't appear to be recognised for labels either:
(labels ((test (df)
           (declare (ftype (function (double-float) double-float) test))
           df))
   (test 1)) => 1

(labels ((test (df) df))
  (declare (ftype (function (double-float) double-float) test))
  (test 1)) => 1

I need to resolve this issue to determine whether a global DEFUN to local
LABELS form of block compilation can have consistent type semantics.

Thanks,
Adam

From: Kalle Olavi Niemitalo
Subject: Re: DECLARE FTYPE
Date: 
Message-ID: <87vfol839d.fsf@Astalo.kon.iki.fi>
Adam Warner <······@consulting.net.nz> writes:

> (defun test (df)
>   (declare (ftype (function (double-float) double-float) test))
>   df)

Because this FTYPE declaration does not appear immediately before
the body of a FLET or LABELS form, it is a free declaration.  It
affects references to the global function TEST, but only when
those references are within the body of TEST itself.  See 3.3.4.

In particular, if you defined

  (defun test (&optional (df (test 'foo)))
    (declare (ftype (function (double-float) double-float) test))
    df)

then the FTYPE declaration would not affect the (test 'foo) form
in the lambda list.

> (labels ((test (df) df))
>   (declare (ftype (function (double-float) double-float) test))
>   (test 1)) => 1

In CMUCL:

* (defun outer (df)
    (labels ((test (df) df))
      (declare (ftype (function (double-float) double-float) test))
      (test df)))

OUTER
* (outer 1)

1
* (compile 'outer)
; Compiling LAMBDA (DF): 
; Compiling Top-Level Form: 

OUTER
NIL
NIL
* (outer 1)


Type-error in KERNEL::OBJECT-NOT-DOUBLE-FLOAT-ERROR-HANDLER:
   1 is not of type DOUBLE-FLOAT

Restarts:
  0: [ABORT] Return to Top-Level.

Debug  (type H for help)

(OUTER 1)
Source: (TEST DF)
0] 
From: Adam Warner
Subject: Re: DECLARE FTYPE
Date: 
Message-ID: <pan.2003.12.13.10.37.42.969447@consulting.net.nz>
Hi Kalle Olavi Niemitalo,

> Because this FTYPE declaration does not appear immediately before
> the body of a FLET or LABELS form, it is a free declaration.  It
> affects references to the global function TEST, but only when
> those references are within the body of TEST itself.  See 3.3.4.

Ah! Many thanks Kalle.

Regards,
Adam