1.0.37.36: revisit FIND/POSITION bounds checking on lists
authorNikodemus Siivola <nikodemus@random-state.net>
Sun, 4 Apr 2010 09:03:08 +0000 (09:03 +0000)
committerNikodemus Siivola <nikodemus@random-state.net>
Sun, 4 Apr 2010 09:03:08 +0000 (09:03 +0000)
  The spec doesn't actually /require/ us to signal an error if we
  are not in danger of running out of bounds as far as I can tell.

  So don't traverse the entire list during forward searches if we
  find what we are looking for before specified :END or the list end.

  Patch by Alec Berryman.

  This revisits lp#452008, and fixed lp#554385.

NEWS
src/compiler/seqtran.lisp
tests/seq.pure.lisp
version.lisp-expr

diff --git a/NEWS b/NEWS
index d0cd1d4..f6228a5 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,5 @@
 ;;;; -*- coding: utf-8; fill-column: 78 -*-
-changes relative to sbcl-1.0.36:
+changes relative to sbcl-1.0.37:
   * INCOMPATIBLE CHANGE: Thread names are now restricted to SIMPLE-STRINGs
     like for any other thread-related datastructure (MUTEX, etc.)
   * DEPRECATION: the SB-QUEUE contrib was merged into the SB-CONCURRENCY
@@ -48,6 +48,9 @@ changes relative to sbcl-1.0.36:
     CONDITION-NOTIFY on Linux. See threads "lost wakeup in condition-wait /
     condition-notify" (Feb 2010) and "Condition-Wait, Deadline handler, waking
     up itself" (March 2010) for further details.
+  * bug fix: allow forward FIND and POSITION on lists to elide checking :END
+    against length of the list if the element is found before the specified
+    END is reached. (thanks to Alec Berryman, lp#554385)
 
 changes in sbcl-1.0.37 relative to sbcl-1.0.36:
   * enhancement: Backtrace from THROW to uncaught tag on x86oids now shows
index 466496d..68aa5b3 100644 (file)
                                              (if from-end
                                                  (setf find element
                                                        position index)
-                                                 (unless find
-                                                   (setf find element
-                                                         position index)))))))))))))
+                                                 (return (values element index)))))))))))))
   (def %find-position-if when)
   (def %find-position-if-not unless))
 
index eb75013..2c1d638 100644 (file)
                            (second got) ',lambda)))))
     (test sb-kernel:bounding-indices-bad-error
           (lambda ()
-            (find :foo '(1 2 3 :foo) :start 1 :end 5)))
+            (find :foo '(1 2 3 :foo) :start 1 :end 5 :from-end t)))
     (test sb-kernel:bounding-indices-bad-error
           (lambda ()
-            (position :foo '(1 2 3 :foo) :start 1 :end 5)))
+            (position :foo '(1 2 3 :foo) :start 1 :end 5 :from-end t)))
     (test sb-kernel:bounding-indices-bad-error
           (lambda ()
-            (find :foo '(1 2 3 :foo) :start 3 :end 0)))
+            (find :foo '(1 2 3 :foo) :start 3 :end 0 :from-end t)))
     (test sb-kernel:bounding-indices-bad-error
           (lambda ()
-            (position :foo '(1 2 3 :foo) :start 3 :end 0)))
+            (position :foo '(1 2 3 :foo) :start 3 :end 0 :from-end t)))
     (test type-error
           (lambda ()
             (let ((list (list 1 2 3 :foo)))
           (lambda ()
             (let ((list (list 1 2 3 :foo)))
               (position :bar (nconc list list)))))))
+
+(with-test (:name :bug-554385)
+  ;; FIND-IF shouldn't look through the entire list.
+  (assert (= 2 (find-if #'evenp '(1 2 1 1 1 1 1 1 1 1 1 1 :foo))))
+  ;; Even though the end bounds are incorrect, the
+  ;; element is found before that's an issue.
+  (assert (eq :foo (find :foo '(1 2 3 :foo) :start 1 :end 5)))
+  (assert (= 3 (position :foo '(1 2 3 :foo) :start 1 :end 5))))
index 3441c01..ce63ee5 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.37.35"
+"1.0.37.36"