master: Fix the SYMBOL restart for missing packages

stassats via Sbcl-commits <[email protected]> Tue, 19 May 2026 00:27:58 +0000
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  93b87fc504b7bb1eaf0ce5c273a59e48605067a2 (commit)
      from  5b647a0f634241ccb96b5aca635e28103581b5bc (commit)

- Log -----------------------------------------------------------------
commit 93b87fc504b7bb1eaf0ce5c273a59e48605067a2
Author: Stas Boukarev <[email protected]>
Date:   Tue May 19 03:21:48 2026 +0300

    Fix the SYMBOL restart for missing packages
    
    Fixes lp#2153092
---
 src/code/reader.lisp            | 66 ++++++++++++++++++++++-------------------
 src/code/target-extensions.lisp |  2 +-
 tests/reader.pure.lisp          |  6 ++++
 3 files changed, 42 insertions(+), 32 deletions(-)

diff --git a/src/code/reader.lisp b/src/code/reader.lisp
index ce5840ed9..777a1d862 100644
--- a/src/code/reader.lisp
+++ b/src/code/reader.lisp
@@ -1572,37 +1572,41 @@ extended <package-name>::<form-in-package> syntax."
             (if package-designator
                 (reader-find-package package-designator stream t)
                 (or *reader-package* (sane-package)))
-          (if (eq restart-kind :uninterned)
-              (return (make-symbol (copy-token-buf-string buf)))
-              (let* ((intern-p (or (/= colons 1)
-                                   (eq pkg *keyword-package*)
-                                   (eq restart-kind :current))))
-                (unless intern-p        ; Try %FIND-SYMBOL
-                  (multiple-value-bind (symbol accessibility)
-                      (%find-symbol (token-buf-string buf) (token-buf-fill-ptr buf) pkg)
-                    (when (eq accessibility :external) (return symbol))
-                    (when (and accessibility
-                               (check-deprecated-export pkg symbol))
-                      (return symbol))
-                    (with-simple-restart (continue "Use symbol anyway.")
-                      (error 'simple-reader-package-error
-                             :package pkg
-                             :stream stream
-                             :format-arguments
-                             (list (copy-token-buf-string buf) (package-name pkg))
-                             :format-control
-                             (if accessibility
-                                 "The symbol ~S is not external in the ~A package."
-                                 "Symbol ~S not found in the ~A package.")))))
-                (return (%intern (token-buf-string buf)
-                                 (token-buf-fill-ptr buf)
-                                 pkg
-                                 (if (token-buf-only-base-chars buf)
-                                     (%readtable-symbol-preference rt)
-                                     'character)
-                                 ;; reader-package behaves as if *package* were that package.
-                                 ;; Hence it should be allowed to create new symbols.
-                                 (eq pkg *reader-package*))))))))))
+          (case restart-kind
+            (:uninterned
+             (return (make-symbol (copy-token-buf-string buf))))
+            (:symbol
+             (return pkg))
+            (t
+             (let ((intern-p (or (/= colons 1)
+                                 (eq pkg *keyword-package*)
+                                 (eq restart-kind :current))))
+               (unless intern-p         ; Try %FIND-SYMBOL
+                 (multiple-value-bind (symbol accessibility)
+                     (%find-symbol (token-buf-string buf) (token-buf-fill-ptr buf) pkg)
+                   (when (eq accessibility :external) (return symbol))
+                   (when (and accessibility
+                              (check-deprecated-export pkg symbol))
+                     (return symbol))
+                   (with-simple-restart (continue "Use symbol anyway.")
+                     (error 'simple-reader-package-error
+                            :package pkg
+                            :stream stream
+                            :format-arguments
+                            (list (copy-token-buf-string buf) (package-name pkg))
+                            :format-control
+                            (if accessibility
+                                "The symbol ~S is not external in the ~A package."
+                                "Symbol ~S not found in the ~A package.")))))
+               (return (%intern (token-buf-string buf)
+                                (token-buf-fill-ptr buf)
+                                pkg
+                                (if (token-buf-only-base-chars buf)
+                                    (%readtable-symbol-preference rt)
+                                    'character)
+                                ;; reader-package behaves as if *package* were that package.
+                                ;; Hence it should be allowed to create new symbols.
+                                (eq pkg *reader-package*)))))))))))
 
 ;;; For semi-external use: Return 3 values: the token-buf,
 ;;; a flag for whether there was an escape char, and the position of
diff --git a/src/code/target-extensions.lisp b/src/code/target-extensions.lisp
index eb90042ad..165d20469 100644
--- a/src/code/target-extensions.lisp
+++ b/src/code/target-extensions.lisp
@@ -203,7 +203,7 @@ unspecified."
                        :interactive
                        (lambda ()
                          (read-evaluated-form-of-type 'symbol))
-                       (values value :symbol)))))
+                       (return (values value :symbol))))))
        (go retry))))
 
 ;;;; Deprecating stuff
diff --git a/tests/reader.pure.lisp b/tests/reader.pure.lisp
index e990275ee..1c3b000d2 100644
--- a/tests/reader.pure.lisp
+++ b/tests/reader.pure.lisp
@@ -641,3 +641,9 @@
   ;; constituent when not a dot by itself (or all dots). And #\( terminates a token.
   ;; The token "#." is then ignored by *read-suppress*
   (assert (equal (read-from-string "#+notfeat #o#.(progn wat)") '(progn wat))))
+
+(with-test (:name :missing-package-restarts)
+  (handler-bind ((reader-error
+                   (lambda (c)
+                     (invoke-restart (find-restart 'symbol c) 'pi))))
+    (assert (eq (read-from-string "missing-package::symbol") 'pi))))

-----------------------------------------------------------------------


hooks/post-receive
-- 
SBCL