ADJOIN shouldn't constant fold.
authorStas Boukarev <stassats@gmail.com>
Mon, 23 Sep 2013 17:25:51 +0000 (21:25 +0400)
committerStas Boukarev <stassats@gmail.com>
Mon, 23 Sep 2013 17:25:51 +0000 (21:25 +0400)
ADJOIN creates new lists, so it shouldn't be constant folded. The
problem materialized when more %adjoin-* helper functions received an
fndb entry with foldable attribute copied, causing more cases to be
folded.

Reported by Eric Marsden.

src/compiler/fndb.lisp
tests/list.pure.lisp

index b25fe32..bb39bc4 100644 (file)
 
 (defknown adjoin (t list &key (:key callable) (:test callable)
                     (:test-not callable))
-  cons (foldable flushable call))
+  cons (flushable call))
 
 (defknown (union intersection set-difference set-exclusive-or)
   (list list &key (:key callable) (:test callable) (:test-not callable))
   function
   (flushable foldable))
 
-(defknown (%adjoin %adjoin-eq %member %member-eq
+(defknown (%adjoin %adjoin-eq)
+    (t list)
+    list
+    (explicit-check flushable))
+
+(defknown (%member %member-eq
            %assoc %assoc-eq %rassoc %rassoc-eq)
     (t list)
     list
     (explicit-check foldable flushable))
 
-(defknown (%adjoin-key %adjoin-key-eq %member-key %member-key-eq
+(defknown (%adjoin-key %adjoin-key-eq)
+    (t list function)
+    list
+    (explicit-check flushable call))
+
+(defknown (%member-key %member-key-eq
            %assoc-key %assoc-key-eq %rassoc-key %rassoc-key-eq)
   (t list function)
   list
   list
   (explicit-check foldable flushable call))
 
-(defknown (%adjoin-test %adjoin-test-not
-           %member-test %member-test-not
+(defknown (%adjoin-test %adjoin-test-not)
+    (t list function)
+    list
+    (explicit-check flushable call))
+
+(defknown (%member-test %member-test-not
            %assoc-test %assoc-test-not
            %rassoc-test %rassoc-test-not)
     (t list function)
     list
     (explicit-check foldable flushable call))
 
-(defknown (%adjoin-key-test %adjoin-key-test-not
-           %member-key-test %member-key-test-not
+(defknown (%adjoin-key-test %adjoin-key-test-not)
+    (t list function function)
+    list
+    (explicit-check flushable call))
+
+(defknown (%member-key-test %member-key-test-not
            %assoc-key-test %assoc-key-test-not
            %rassoc-key-test %rassoc-key-test-not)
     (t list function function)
index 431275b..7ccdf3c 100644 (file)
 
 ;;; FIND on lists should not call key outside the specified subsquence.
 (assert (not (find :a '(0 (:c) 1) :start 1 :end 2 :key #'car)))
+
+(with-test (:name :adjoin-folding)
+  (flet ((%f () (adjoin 'x '(a b))))
+    (assert (not (eq (%f) (%f))))))