#:g1: バグ報告: LispWorks/システム関数の型宣言が合ってない

Posted 2017-01-23 20:28:36 GMT

パッケージ名を短かく表示する自作ユーティリティをLispWorksに移植してみていて、妙なエラーに遭遇

(proclaim '(optimize (debug 3) (safety 3)))

(defun foo (string package) (system::find-external-symbol String Package))

のようなものをコンパイルして呼び出すと

(foo "PROGN" (find-package :cl))
⊳ Error: The results of SYSTEM::FIND-EXTERNAL-SYMBOL, (PROGN 403), do not satisfy the ftype specifier (VALUES SYMBOL SYMBOL).

とエラーになってしまう。

system::find-external-symbolの型を確認してみると、

(function-information 'system::find-external-symbol)
→ :function 
   nil 
   ((ftype function (simple-string package) (values symbol symbol))) 

となっているが、実際に呼び出してみると

(system::find-external-symbol "PROGN" (find-package :cl))
→ progn 
   403

(system::find-external-symbol "PROGZ" (find-package :cl)) → 0 nil

となっているので返り値の型宣言である(values symbol symbol)とは不整合があるのが問題のようだ。

またコンパイラの設定にも依存していて、safety 3でないとチェックには引っ掛からない。

回避方法

(defun foo (string package)
  (declare (ftype (function (simple-string package)
                            (values (or symbol fixnum) (or symbol fixnum)))
                  system::find-external-symbol))
  (system::find-external-symbol String Package))

こんな感じに宣言をシャドウ?してやれば通る。
また、グローバルにproclaimとかファイルローカルにdeclaimとかしても良いっぽい。

(proclaim '(ftype (function (simple-string package)
                            (values (or symbol fixnum) (or symbol fixnum)))
                  system::find-external-symbol))

報告と回答

どうでも良さそうなバグだけど一応報告してみた。
回答は、内部シンボルは使わないで、ということで終了。

結局、LispWorksの内部的に型宣言は合っているのか、それとも間違っているのかは不明なままだった。

コンパイラのセッティングで無視するなら、(values t t)にでもしちゃえば良いのにね、と思ったり。

むすび

(proclaim '(optimize (debug 3) (safety 3)))しておくと、コンパイラが型宣言の間違いを発見してくれることが多いのでお勧め。
自作のライブラリを公開する時にも、(optimize (debug 3) (safety 3)))で一度通るか確認してから、出荷設定でビルドするのが良いと思う。

ちなみに、パッケージ名を短かく表示する自作ユーティリティとは、こちら

端的に言ってしまうと処理系の改造なのでLispWorksのような商用処理系で試すのはお勧めしない(ソースが公開されている処理系でもお勧めはしないが)
一応LispWorksでも動くようになったので使ってみている。


HTML generated by 3bmd in LispWorks 7.0.0

comments powered by Disqus