* Don't bind constants in PROGV.
* Check variable types before binding / assignment.
* When un-binding, PROGV doesn't temporarily bind a variable to NIL
anymore, but directly to the unbound marker, so that an interrupt
handler cannot see a bogus value.
* Based on patch by Richard Kreuter.
Halik)
* bug fix: non-local exit from a WITH-ALIEN form no longer causes
alien-stack leakage. (reported by Andy Hefner)
+ * bug fix: PROGV signals an error when an attempt to violate declared
+ type of a variable or bind a constant is made.
+ * bug fix: SET signals an error when an attempt to violate declared
+ type of a variable is made.
changes in sbcl-1.0.19 relative to 1.0.18:
* new feature: user-customizable variable SB-EXT:*MUFFLED-WARNINGS*;
;;; foo => 13, (constantp 'foo) => t
;;;
;;; ...in which case you frankly deserve to lose.
-(defun about-to-modify-symbol-value (symbol action)
+(defun about-to-modify-symbol-value (symbol action &optional (new-value nil valuep))
(declare (symbol symbol))
(multiple-value-bind (what continue)
(when (eq :constant (info :variable :kind symbol))
(when what
(if continue
(cerror "Modify the constant." what action symbol)
- (error what action symbol))))
+ (error what action symbol)))
+ (when valuep
+ ;; :VARIABLE :TYPE is in the db only if it is declared, so no need to
+ ;; check.
+ (let ((type (info :variable :type symbol)))
+ (unless (sb!kernel::%%typep new-value type)
+ (let ((spec (type-specifier type)))
+ (error 'simple-type-error
+ :format-control "Cannot ~@? to ~S (not of type ~S.)"
+ :format-arguments (list action symbol new-value spec)
+ :datum new-value
+ :expected-type spec))))))
(values))
;;; If COLD-FSET occurs not at top level, just treat it as an ordinary
#!+sb-doc
"Set SYMBOL's value cell to NEW-VALUE."
(declare (type symbol symbol))
- (about-to-modify-symbol-value symbol "set SYMBOL-VALUE of ~S")
+ (about-to-modify-symbol-value symbol "set SYMBOL-VALUE of ~S" new-value)
(%set-symbol-value symbol new-value))
(defun %set-symbol-value (symbol new-value)
(progn
(labels ((,unbind (vars)
(declare (optimize (speed 2) (debug 0)))
- (dolist (var vars)
- (%primitive bind nil var)
- (makunbound var)))
+ (let ((unbound-marker (%primitive make-other-immediate-type
+ 0 sb!vm:unbound-marker-widetag)))
+ (dolist (var vars)
+ ;; CLHS says "bound and then made to have no value" -- user
+ ;; should not be able to tell the difference between that and this.
+ (about-to-modify-symbol-value var "bind ~S")
+ (%primitive bind unbound-marker var))))
(,bind (vars vals)
(declare (optimize (speed 2) (debug 0)))
(cond ((null vars))
((null vals) (,unbind vars))
- (t (%primitive bind
- (car vals)
- (car vars))
- (,bind (cdr vars) (cdr vals))))))
+ (t
+ (let ((val (car vals))
+ (var (car vars)))
+ (about-to-modify-symbol-value var "bind ~S" val)
+ (%primitive bind val var))
+ (,bind (cdr vars) (cdr vals))))))
(,bind ,vars ,vals))
nil
,@body)
(eval '(labels ((%f (&key x) x)) (%f nil nil)))
(error (c) :good)
(:no-error (val) (error "no error: ~S" val)))
+
+;;; PROGV must not bind constants, or violate declared types -- ditto for SET.
+(assert (raises-error? (set pi 3)))
+(assert (raises-error? (progv '(pi s) '(3 pi) (symbol-value x))))
+(declaim (cons *special-cons*))
+(assert (raises-error? (set '*special-cons* "nope") type-error))
+(assert (raises-error? (progv '(*special-cons*) '("no hope") (car *special-cons*)) type-error))
\f
;;;; tests not in the problem domain, but of the consistency of the
;;;; compiler machinery itself
;;; 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.19.2"
+"1.0.19.3"