0.8.12.10: Fix bug 338: "MOP specializers as type specifiers"
[sbcl.git] / BUGS
diff --git a/BUGS b/BUGS
index 175889a..51587c4 100644 (file)
--- a/BUGS
+++ b/BUGS
@@ -89,15 +89,6 @@ WORKAROUND:
   Perhaps any number of such consecutive lines ought to turn into a
   single "compiling top-level forms:" line.
 
-11:
-  It would be nice if the
-       caught ERROR:
-         (during macroexpansion)
-  said what macroexpansion was at fault, e.g.
-       caught ERROR:
-         (during macroexpansion of IN-PACKAGE,
-         during macroexpansion of DEFFOO)
-
 19:
   (I *think* this is a bug. It certainly seems like strange behavior. But
   the ANSI spec is scary, dark, and deep.. -- WHN)
@@ -165,25 +156,6 @@ WORKAROUND:
   so they could be supported after all. Very likely 
   SIGCONTEXT-FLOATING-POINT-MODES could now be supported, too.
 
-45:
-  a slew of floating-point-related errors reported by Peter Van Eynde
-  on July 25, 2000:
-       c: Many expressions generate floating infinity on x86/Linux:
-               (/ 1 0.0)
-               (/ 1 0.0d0)
-               (EXPT 10.0 1000)
-               (EXPT 10.0d0 1000)
-          PVE's regression tests want them to raise errors. sbcl-0.7.0.5
-          on x86/Linux generates the infinities instead. That might or
-          might not be conforming behavior, but it's also inconsistent,
-           which is almost certainly wrong. (Inconsistency: (/ 1 0.0)
-          should give the same result as (/ 1.0 0.0), but instead (/ 1 0.0)
-          generates SINGLE-FLOAT-POSITIVE-INFINITY and (/ 1.0 0.0)
-          signals an error.
-       d: (in section12.erg) various forms a la 
-               (FLOAT 1 DOUBLE-FLOAT-EPSILON)
-          don't give the right behavior.
-
 60:
   The debugger LIST-LOCATIONS command doesn't work properly.
   (How should it work properly?)
@@ -368,34 +340,6 @@ WORKAROUND:
 
   (see also bug 279)
 
-118:
-   as reported by Eric Marsden on cmucl-imp@cons.org 2001-08-14:
-     (= (FLOAT 1 DOUBLE-FLOAT-EPSILON)
-        (+ (FLOAT 1 DOUBLE-FLOAT-EPSILON) DOUBLE-FLOAT-EPSILON)) => T
-   when of course it should be NIL. (He says it only fails for X86,
-   not SPARC; dunno about Alpha.)
-
-   Also, "the same problem exists for LONG-FLOAT-EPSILON,
-   DOUBLE-FLOAT-NEGATIVE-EPSILON, LONG-FLOAT-NEGATIVE-EPSILON (though
-   for the -negative- the + is replaced by a - in the test)."
-
-   Raymond Toy comments that this is tricky on the X86 since its FPU
-   uses 80-bit precision internally.
-
-   Bruno Haible comments:
-     The values are those that are expected for an IEEE double-float
-     arithmetic. The problem appears to be that the rounding is not
-     IEEE on x86 compliant: namely, values are first rounded to 64
-     bits mantissa precision, then only to 53 bits mantissa
-     precision. This gives different results than rounding to 53 bits
-     mantissa precision in a single step.
-
-     The quick "fix", to permanently change the FPU control word from
-     0x037f to 0x027f, will give problems with the fdlibm code that is
-     used for computing transcendental functions like sinh() etc.
-   so maybe we need to change the FPU control word to that for Lisp
-   code, and adjust it to the safe 0x037f for calls to C?
-
 124:
    As of version 0.pre7.14, SBCL's implementation of MACROLET makes
    the entire lexical environment at the point of MACROLET available
@@ -470,15 +414,6 @@ WORKAROUND:
   forever, even when it is uninterned and all other references to it
   are lost.
 
-141: "pretty printing and backquote"
-  a.
-    * '``(FOO ,@',@S)
-    ``(FOO SB-IMPL::BACKQ-COMMA-AT S)
-
-  c. (reported by Paul F. Dietz)
-     * '`(lambda ,x)
-     `(LAMBDA (SB-IMPL::BACKQ-COMMA X))
-
 143:
   (reported by Jesse Bouwman 2001-10-24 through the unfortunately
   prominent SourceForge web/db bug tracking system, which is 
@@ -861,18 +796,6 @@ WORKAROUND:
     ; compilation unit finished
     ;   printed 1 note
 
-241: "DEFCLASS mysteriously remembers uninterned accessor names."
-  (from tonyms on #lisp IRC 2003-02-25)
-  In sbcl-0.7.12.55, typing
-    (defclass foo () ((bar :accessor foo-bar)))
-    (profile foo-bar)
-    (unintern 'foo-bar)
-    (defclass foo () ((bar :accessor foo-bar)))
-  gives the error message
-    "#:FOO-BAR already names an ordinary function or a macro."
-  So it's somehow checking the uninterned old accessor name instead
-  of the new requested accessor name, which seems broken to me (WHN).
-
 242: "WRITE-SEQUENCE suboptimality"
   (observed from clx performance)
   In sbcl-0.7.13, WRITE-SEQUENCE of a sequence of type 
@@ -1042,14 +965,6 @@ WORKAROUND:
 
   (fixed in 0.8.2.51, but a test case would be good)
 
-276:
-    (defmethod fee ((x fixnum))
-      (setq x (/ x 2))
-      x)
-    (fee 1) => type error
-
-  (taken from CLOCC)
-
 278:
   a.
     (defun foo ()
@@ -1086,39 +1001,6 @@ WORKAROUND:
 
  (see also bug 117)
 
-280: bogus WARNING about duplicate function definition 
-  In sbcl-0.8.3 and sbcl-0.8.1.47, if BS.MIN is defined inline,
-  e.g. by 
-     (declaim (inline bs.min))
-     (defun bs.min (bases) nil)
-  before compiling the file below, the compiler warns
-     Duplicate definition for BS.MIN found in one static
-     unit (usually a file).
-  when compiling 
-    (declaim (special *minus* *plus* *stagnant*))
-    (defun b.*.min (&optional (x () xp) (y () yp) &rest rest)
-      (bs.min avec))
-    (define-compiler-macro b.*.min (&rest rest)
-      `(bs.min ,@rest))
-    (defun afish-d-rbd (pd)
-      (if *stagnant* 
-          (b.*.min (foo-d-rbd *stagnant*))
-          (multiple-value-bind (reduce-fn initial-value)
-              (etypecase pd
-                (list (values #'bs.min 0))
-                (vector (values #'bs.min *plus*)))
-            (let ((cv-ks (cv (kpd.ks pd))))
-              (funcall reduce-fn d-rbds)))))
-    (defun bfish-d-rbd (pd)
-      (if *stagnant* 
-          (b.*.min (foo-d-rbd *stagnant*))
-          (multiple-value-bind (reduce-fn initial-value)
-              (etypecase pd
-                (list (values #'bs.min *minus*))
-                (vector (values #'bs.min 0)))
-            (let ((cv-ks (cv (kpd.ks pd))))
-              (funcall reduce-fn d-rbds)))))
-
 281: COMPUTE-EFFECTIVE-METHOD error signalling.
   (slightly obscured by a non-0 default value for
    SB-PCL::*MAX-EMF-PRECOMPUTE-METHODS*)
@@ -1330,18 +1212,6 @@ WORKAROUND:
   spurious errors should two threads attempt to tokenise at the same
   time.
 
-312:
-  (reported by Jon Dyte)
-  SBCL issues a warning "Duplicate definition of FOO" compiling
-
-    (declaim (inline foo))
-    (defun foo (x)
-      (1+ x))
-    (defun bar (y)
-      (list (foo y) (if (> y 1) (funcall (if (> y 0) #'foo #'identity) y))))
-
-  (probably related to the bug 280.)
-
 314: "LOOP :INITIALLY clauses and scope of initializers"
   reported by Bruno Haible sbcl-devel "various SBCL bugs" from CLISP
   test suite, originally by Thomas F. Burdick.
@@ -1359,23 +1229,6 @@ WORKAROUND:
     Expected: (2 6 15 38)
     Got:      ERROR
 
-315: "no bounds check for access to displaced array"
-  reported by Bruno Haible sbcl-devel "various SBCL bugs" from CLISP
-  test suite.
-    (locally (declare (optimize (safety 3) (speed 0)))
-      (let* ((x (make-array 10 :fill-pointer 4 :element-type 'character
-                               :initial-element #\space :adjustable t))
-             (y (make-array 10 :fill-pointer 4 :element-type 'character
-                               :displaced-to x)))
-        (adjust-array x '(5))
-        (char y 5)))
-
-  SBCL 0.8.10 elides the bounds check somewhere along the line, and
-  returns #\Nul (where an error would be much preferable, since a test
-  of that form but with (setf (char y 5) #\Space) potentially corrupts
-  the heap and certainly confuses the world if that string is used by
-  C code.
-
 317: "FORMAT of floating point numbers"
   reported by Bruno Haible sbcl-devel "various SBCL bugs" from CLISP
   test suite.
@@ -1407,22 +1260,6 @@ WORKAROUND:
     #(1 2 ((SB-IMPL::|,|) + 2 2) 4)
   which probably isn't intentional.
 
-321: "DEFINE-METHOD-COMBINATION lambda list parsing"
-  reported by Bruno Haible sbcl-devel "various SBCL bugs" from CLISP
-  test suite.
-    (define-method-combination w-args ()
-      ((method-list *))
-      (:arguments arg1 arg2 &aux (extra :extra))
-     `(progn ,@(mapcar (lambda (method) `(call-method ,method)) method-list)))
-  gives a (caught) compile-time error, which can be exposed by
-    (defgeneric mc-test-w-args (p1 p2 s)
-      (:method-combination w-args)
-      (:method ((p1 number) (p2 t) s)
-        (vector-push-extend (list 'number p1 p2) s))
-      (:method ((p1 string) (p2 t) s)
-        (vector-push-extend (list 'string p1 p2) s))
-      (:method ((p1 t) (p2 t) s) (vector-push-extend (list t p1 p2) s)))
-
 323: "REPLACE, BIT-BASH and large strings"
   The transform for REPLACE on simple-base-strings uses BIT-BASH, which
   at present has an upper limit in size.  Consequently, in sbcl-0.8.10
@@ -1443,3 +1280,310 @@ WORKAROUND:
   to about 1024 (and similarly for signed-byte), so
     (open "/dev/zero" :element-type '(unsigned-byte 1025))
   gives an error in sbcl-0.8.10.
+
+325: "CLOSE :ABORT T on supeseding streams"
+  Closing a stream opened with :IF-EXISTS :SUPERSEDE with :ABORT T leaves no
+  file on disk, even if one existed before opening.
+
+  The illegality of this is not crystal clear, as the ANSI dictionary
+  entry for CLOSE says that when :ABORT is T superseded files are not
+  superseded (ie. the original should be restored), whereas the OPEN
+  entry says about :IF-EXISTS :SUPERSEDE "If possible, the
+  implementation should not destroy the old file until the new stream
+  is closed." -- implying that even though undesirable, early deletion
+  is legal. Restoring the original would none the less be the polite
+  thing to do.
+
+326: "*PRINT-CIRCLE* crosstalk between streams"
+  In sbcl-0.8.10.48 it's possible for *PRINT-CIRCLE* references to be
+  mixed between streams when output operations are intermingled closely
+  enough (as by doing output on S2 from within (PRINT-OBJECT X S1) in the
+  test case below), so that e.g. the references #2# appears on a stream
+  with no preceding #2= on that stream to define it (because the #2= was
+  sent to another stream).
+    (cl:in-package :cl-user)
+    (defstruct foo index)
+    (defparameter *foo* (make-foo :index 4))
+    (defstruct bar)
+    (defparameter *bar* (make-bar))
+    (defparameter *tangle* (list *foo* *bar* *foo*))
+    (defmethod print-object ((foo foo) stream)
+      (let ((index (foo-index foo)))
+        (format *trace-output*
+           "~&-$- emitting FOO ~D, ambient *BAR*=~S~%"
+           index *bar*)
+        (format stream "[FOO ~D]" index))
+      foo)
+    (let ((tsos (make-string-output-stream))
+          (ssos (make-string-output-stream)))
+      (let ((*print-circle* t)
+           (*trace-output* tsos)
+           (*standard-output* ssos))
+        (prin1 *tangle* *standard-output*))
+      (let ((string (get-output-stream-string ssos)))
+        (unless (string= string "(#1=[FOO 4] #S(BAR) #1#)")
+          ;; In sbcl-0.8.10.48 STRING was "(#1=[FOO 4] #2# #1#)".:-(
+          (error "oops: ~S" string)))))
+  It might be straightforward to fix this by turning the
+  *CIRCULARITY-HASH-TABLE* and *CIRCULARITY-COUNTER* variables into
+  per-stream slots, but (1) it would probably be sort of messy faking
+  up the special variable binding semantics using UNWIND-PROTECT and
+  (2) it might be sort of a pain to test that no other bugs had been
+  introduced. 
+
+328: "Profiling generic functions", transplanted from #241
+  (from tonyms on #lisp IRC 2003-02-25)
+  In sbcl-0.7.12.55, typing
+    (defclass foo () ((bar :accessor foo-bar)))
+    (profile foo-bar)
+    (unintern 'foo-bar)
+    (defclass foo () ((bar :accessor foo-bar)))
+  gives the error message
+    "#:FOO-BAR already names an ordinary function or a macro."
+
+  Problem: when a generic function is profiled, it appears as an ordinary
+  function to PCL. (Remembering the uninterned accessor is OK, as the
+  redefinition must be able to remove old accessors from their generic
+  functions.)
+
+329: "Sequential class redefinition"
+  reported by Bruno Haible:
+   (defclass reactor () ((max-temp :initform 10000000)))
+   (defvar *r1* (make-instance 'reactor))
+   (defvar *r2* (make-instance 'reactor))
+   (slot-value *r1* 'max-temp)
+   (slot-value *r2* 'max-temp)
+   (defclass reactor () ((uptime :initform 0)))
+   (slot-value *r1* 'uptime)
+   (defclass reactor () ((uptime :initform 0) (max-temp :initform 10000)))
+   (slot-value *r1* 'max-temp) ; => 10000
+   (slot-value *r2* 'max-temp) ; => 10000000 oops...
+
+  Possible solution: 
+   The method effective when the wrapper is obsoleted can be saved
+     in the wrapper, and then to update the instance just run through
+     all the old wrappers in order from oldest to newest.
+
+331: "lazy creation of CLOS classes for user-defined conditions"
+    (defstruct foo)
+    (defstruct (bar (:include foo)))
+    (sb-mop:class-direct-subclasses (find-class 'foo))
+  returns NIL, rather than a singleton list containing the BAR class.
+
+332: "fasl stack inconsistency in structure redefinition"
+  (reported by Tim Daly Jr sbcl-devel 2004-05-06)
+  Even though structure redefinition is undefined by the standard, the
+  following behaviour is suboptimal: running
+    (defun stimulate-sbcl ()
+      (let ((filename (format nil "/tmp/~A.lisp" (gensym))))
+        ;;create a file which redefines a structure incompatibly
+        (with-open-file (f filename :direction :output :if-exists :supersede)
+          (print '(defstruct astruct foo) f)
+          (print '(defstruct astruct foo bar) f))
+        ;;compile and load the file, then invoke the continue restart on
+        ;;the structure redefinition error
+        (handler-bind ((error (lambda (c) (continue c))))
+          (load (compile-file filename)))))
+    (stimulate-sbcl)
+  and choosing the CONTINUE restart yields the message
+    debugger invoked on a SB-INT:BUG in thread 27726:
+      fasl stack not empty when it should be
+
+334: "COMPUTE-SLOTS used to add slots to classes"
+  (reported by Bruno Haible sbcl-devel 2004-06-01)
+  a. Adding a local slot does not work:
+    (use-package "SB-PCL")
+    (defclass b (a) ())
+    (defmethod compute-slots ((class (eql (find-class 'b))))
+      (append (call-next-method)
+              (list (make-instance 'standard-effective-slot-definition
+                      :name 'y
+                      :allocation :instance))))
+    (defclass a () ((x :allocation :class)))
+    ;; A should now have a shared slot, X, and a local slot, Y.
+    (mapcar #'slot-definition-location (class-slots (find-class 'b)))
+  yields
+    There is no applicable method for the generic function
+      #<STANDARD-GENERIC-FUNCTION CLASS-SLOTS (3)>
+    when called with arguments
+      (NIL).
+
+  b. Adding a class slot does not work:
+    (use-package "SB-PCL")
+    (defclass b (a) ())
+    (defmethod compute-slots ((class (eql (find-class 'b))))
+      (append (call-next-method)
+              (list (make-instance 'standard-effective-slot-definition
+                      :name 'y
+                      :allocation :class))))
+    (defclass a () ((x :allocation :class)))
+    ;; A should now have two shared slots, X and Y.
+    (mapcar #'slot-definition-location (class-slots (find-class 'b)))
+  yields
+    There is no applicable method for the generic function
+      #<STANDARD-GENERIC-FUNCTION SB-PCL::CLASS-SLOT-CELLS (1)>
+    when called with arguments
+      (NIL).
+   
+336: "slot-definitions must retain the generic functions of accessors"
+  reported by Tony Martinez:
+    (defclass foo () ((bar :reader foo-bar)))
+    (defun foo-bar (x) x)
+    (defclass foo () ((bar :reader get-bar))) ; => error, should work
+
+  Note: just punting the accessor removal if the fdefinition
+  is not a generic function is not enough:
+
+   (defclass foo () ((bar :reader foo-bar)))
+   (defvar *reader* #'foo-bar)
+   (defun foo-bar (x) x)
+   (defclass foo () ((bar :initform 'ok :reader get-bar)))
+   (funcall *reader* (make-instance 'foo)) ; should be an error, since
+                                           ; the method must be removed
+                                           ; by the class redefinition
+
+  Fixing this should also fix a subset of #328 -- update the
+  description with a new test-case then.
+
+337: MAKE-METHOD and user-defined method classes
+  (reported by Bruno Haible sbcl-devel 2004-06-11)
+
+  In the presence of  
+
+(defclass user-method (standard-method) (myslot))
+(defmacro def-user-method (name &rest rest)
+  (let* ((lambdalist-position (position-if #'listp rest))
+         (qualifiers (subseq rest 0 lambdalist-position))
+         (lambdalist (elt rest lambdalist-position))
+         (body (subseq rest (+ lambdalist-position 1)))
+         (required-part 
+          (subseq lambdalist 0 (or 
+                                (position-if 
+                                 (lambda (x) (member x lambda-list-keywords))
+                                 lambdalist)
+                                (length lambdalist))))
+         (specializers (mapcar #'find-class 
+                               (mapcar (lambda (x) (if (consp x) (second x) t))
+                                       required-part)))
+         (unspecialized-required-part 
+          (mapcar (lambda (x) (if (consp x) (first x) x)) required-part))
+         (unspecialized-lambdalist 
+          (append unspecialized-required-part 
+           (subseq lambdalist (length required-part)))))
+    `(PROGN
+       (ADD-METHOD #',name
+         (MAKE-INSTANCE 'USER-METHOD
+          :QUALIFIERS ',qualifiers
+          :LAMBDA-LIST ',unspecialized-lambdalist
+          :SPECIALIZERS ',specializers
+          :FUNCTION
+          (LAMBDA (ARGUMENTS NEXT-METHODS-LIST)
+            (FLET ((NEXT-METHOD-P () NEXT-METHODS-LIST)
+                   (CALL-NEXT-METHOD (&REST NEW-ARGUMENTS)
+                     (UNLESS NEW-ARGUMENTS (SETQ NEW-ARGUMENTS ARGUMENTS))
+                     (IF (NULL NEXT-METHODS-LIST)
+                         (ERROR "no next method for arguments ~:S" ARGUMENTS)
+                         (FUNCALL (SB-PCL:METHOD-FUNCTION 
+                                   (FIRST NEXT-METHODS-LIST))
+                                  NEW-ARGUMENTS (REST NEXT-METHODS-LIST)))))
+              (APPLY #'(LAMBDA ,unspecialized-lambdalist ,@body) ARGUMENTS)))))
+       ',name)))
+
+  (progn
+    (defgeneric test-um03 (x))
+    (defmethod test-um03 ((x integer))
+      (list* 'integer x (not (null (next-method-p))) (call-next-method)))
+    (def-user-method test-um03 ((x rational))
+      (list* 'rational x (not (null (next-method-p))) (call-next-method)))
+    (defmethod test-um03 ((x real))
+      (list 'real x (not (null (next-method-p)))))
+    (test-um03 17))
+  works, but
+
+  a.(progn
+      (defgeneric test-um10 (x))
+      (defmethod test-um10 ((x integer))
+        (list* 'integer x (not (null (next-method-p))) (call-next-method)))
+      (defmethod test-um10 ((x rational))
+        (list* 'rational x (not (null (next-method-p))) (call-next-method)))
+      (defmethod test-um10 ((x real))
+        (list 'real x (not (null (next-method-p)))))
+      (defmethod test-um10 :after ((x real)))
+      (def-user-method test-um10 :around ((x integer))
+        (list* 'around-integer x 
+         (not (null (next-method-p))) (call-next-method)))
+      (defmethod test-um10 :around ((x rational))
+        (list* 'around-rational x 
+         (not (null (next-method-p))) (call-next-method)))
+      (defmethod test-um10 :around ((x real))
+        (list* 'around-real x (not (null (next-method-p))) (call-next-method)))
+      (test-um10 17))
+    fails with a type error, and
+
+  b.(progn
+      (defgeneric test-um12 (x))
+      (defmethod test-um12 ((x integer))
+        (list* 'integer x (not (null (next-method-p))) (call-next-method)))
+      (defmethod test-um12 ((x rational))
+        (list* 'rational x (not (null (next-method-p))) (call-next-method)))
+      (defmethod test-um12 ((x real))
+        (list 'real x (not (null (next-method-p)))))
+      (defmethod test-um12 :after ((x real)))
+      (defmethod test-um12 :around ((x integer))
+        (list* 'around-integer x 
+         (not (null (next-method-p))) (call-next-method)))
+      (defmethod test-um12 :around ((x rational))
+        (list* 'around-rational x 
+         (not (null (next-method-p))) (call-next-method)))
+      (def-user-method test-um12 :around ((x real))
+        (list* 'around-real x (not (null (next-method-p))) (call-next-method)))
+      (test-um12 17))
+    fails with NO-APPLICABLE-METHOD.
+
+339: "DEFINE-METHOD-COMBINATION bugs"
+  (reported by Bruno Haible via the clisp test suite)
+
+  a. Syntax checking laxity (should produce errors):
+     i. (define-method-combination foo :documentation :operator)
+    ii. (define-method-combination foo :documentation nil)
+   iii. (define-method-combination foo nil)
+    iv. (define-method-combination foo nil nil
+         (:arguments order &aux &key))
+     v. (define-method-combination foo nil nil (:arguments &whole))
+    vi. (define-method-combination foo nil nil (:generic-function))
+   vii. (define-method-combination foo nil nil (:generic-function bar baz))
+  viii. (define-method-combination foo nil nil (:generic-function (bar)))
+    ix. (define-method-combination foo nil ((3)))
+     x. (define-method-combination foo nil ((a)))
+
+  b. define-method-combination arguments lambda list badness
+     i. &aux args are currently unsupported;
+    ii. default values of &optional and &key arguments are ignored;
+   iii. supplied-p variables for &optional and &key arguments are not
+        bound.
+
+  c. qualifier matching incorrect
+  (progn
+    (define-method-combination mc27 () 
+        ((normal ()) 
+         (ignored (:ignore :unused)))
+      `(list 'result 
+             ,@(mapcar #'(lambda (method) `(call-method ,method)) normal)))
+    (defgeneric test-mc27 (x)
+      (:method-combination mc27)
+      (:method :ignore ((x number)) (/ 0)))
+    (test-mc27 7))
+
+  should signal an invalid-method-error, as the :IGNORE (NUMBER)
+  method is applicable, and yet matches neither of the method group
+  qualifier patterns.
+
+340: SETF of VALUES using too many values
+  (reported by Kalle Olavi Niemetalo via the Debian bug system, with
+  bug id #256764)
+
+    (let ((a t) (b t) (c t) (d t))
+      (setf (values (values a b) (values c d)) (values 1 2 3 4))
+      (list a b c d))
+  should return (1 NIL 2 NIL), but under sbcl-0.8.12.x returns 
+  (1 2 3 4) instead.