* bug fix: several foreign functions accepting string also accepted NIL and
consequently caused a memory fault at 0 now signal a type-error instead.
(lp#721087)
+ * bug fix: under rare circumstances, constraint propagation could rewrite a
+ variable reference to refer to a variable not in scope, causing an error
+ during physical environment analysis when attempting to close over the
+ variable. (lp#551227)
changes in sbcl-1.0.46 relative to sbcl-1.0.45:
* enhancement: largefile support on Solaris.
(modified-numeric-type x :low new-bound)
(modified-numeric-type x :high new-bound)))))
+;;; Return true if LEAF is "visible" from NODE.
+(defun leaf-visible-from-node-p (leaf node)
+ (cond
+ ((lambda-var-p leaf)
+ ;; A LAMBDA-VAR is visible iif it is homed in a CLAMBDA that is an
+ ;; ancestor for NODE.
+ (let ((leaf-lambda (lambda-var-home leaf)))
+ (loop for lambda = (node-home-lambda node)
+ then (lambda-parent lambda)
+ while lambda
+ when (eq lambda leaf-lambda)
+ return t)))
+ ;; FIXME: Check on FUNCTIONALs (CLAMBDAs and OPTIONAL-DISPATCHes),
+ ;; not just LAMBDA-VARs.
+ (t
+ ;; Assume everything else is globally visible.
+ t)))
+
;;; Given the set of CONSTRAINTS for a variable and the current set of
;;; restrictions from flow analysis IN, set the type for REF
;;; accordingly.
(and (leaf-refs other) ; protect from
; deleted vars
(csubtypep other-type leaf-type)
- (not (type= other-type leaf-type))))
+ (not (type= other-type leaf-type))
+ ;; Don't change to a LEAF not visible here.
+ (leaf-visible-from-node-p other ref)))
(change-ref-leaf ref other)
(when (constant-p other) (return)))
(t
(handler-bind ((warning #'error))
(funcall (compile nil '(lambda () (directory "." :allow-other-keys t))))
(funcall (compile nil `(lambda () (directory "." :bar t :allow-other-keys t))))))
+
+(with-test (:name :bug-551227)
+ ;; This function causes constraint analysis to perform a
+ ;; ref-substitution that alters the A referred to in (G A) at in the
+ ;; consequent of the IF to refer to be NUMBER, from the
+ ;; LET-converted inline-expansion of MOD. This leads to attempting
+ ;; to CLOSE-OVER a variable that simply isn't in scope when it is
+ ;; referenced.
+ (compile nil '(lambda (a)
+ (if (let ((s a))
+ (block :block
+ (map nil
+ (lambda (e)
+ (return-from :block
+ (f (mod a e))))
+ s)))
+ (g a)))))
;;; 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.46.32"
+"1.0.46.33"