non-standard attempts to evaluate declarations

Bug #573747 reported by Roman Marynchak on 2010-05-02
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
Status tracked in Trunk
Trunk
Wishlist
Unassigned

Bug Description

CLHS says that "The consequences of attempting to evaluate a declare expression are undefined. In situations where such expressions can appear, explicit checks are made for their presence and they are never actually evaluated". But SBCL evaluates them, at least it tries. For example, entering this code

(declare (print "I am going to be evaluated by SBCL"))

yields the next output:

"I am going to be evaluated by SBCL"
debugger invoked on a UNDEFINED-FUNCTION in thread #<THREAD
                                                     "initial thread" RUNNING
                                                     {1002ABEEF1}>:
  The function DECLARE is undefined.

Note that at least partial evaluation of the declaration occurs - the string is printed. Also, the error message is confusing - it seems that the evaluation wants to go further and fails on #'declare being undefined.

CLISP and Lispworks do not have this bug. For example, in CLISP:

(declare (print "I am going to be evaluated by CLISP"))

*** - declarations ((PRINT "I am going to be evaluated by CLISP")) are not
      allowed here
The following restarts are available:
ABORT :R1 Abort main loop
Break 1 [4]>

The error message is also clear.

Regards,
Roman

Zach Beane (xach) wrote :

"For example, entering this code..."

Entering it where? A place where such an expression can occur?

I entered this code in REPL. Sorry, forgot to mention in the description.

Regards,
Roman

Print is there only to show the evaluation. It looks like non-sense, but shows what is going on. Other clauses, like (inline foo) are also evaluated, and we will get error about INLINE function absence.

Zach Beane (xach) wrote :

It seems to me like you entered a declare expression in a place where it's not allowed, so the result is undefined. I agree that it would be nice to have better error, but I don't think this can be called a bug.

You are right, I have entered that garbage in REPL intentionally, because I saw in compiler sources (src/code/eval.lisp) this code

(defun %simple-eval (expr lexenv)
  (let* (;; why PROGN? So that attempts to eval free declarations
         ;; signal errors rather than return NIL. -- CSR, 2007-05-01
         (lambda `(lambda ()
                    (declare (muffle-conditions compiler-note))
                    (progn ,expr)))
         (fun (sb!c:compile-in-lexenv nil lambda lexenv)))
    (funcall fun)))

This trick is not CLHS-compliant. Just because "In situations where such expressions can appear, explicit checks are made for their presence and they are never actually evaluated". There is no check, and the evaluation proceeds at least partially. The string from my example should never be printed, and the error about invalid declaration attempt should be signalled. So, I am inclined to call this a bug :)

The fix is really trivial - just to add two lines to the evaluator code is enough.

SBCL behaviour after the fix:

* (declare (print "I am going to be evaluated by SBCL"))

debugger invoked on a SIMPLE-ERROR in thread #<THREAD "initial thread" RUNNING
                                               {A9EB801}>:
  Declarations are not allowed here: (DECLARE
                                      (PRINT
                                       "I am going to be evaluated by SBCL"))

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

(SB-INT:SIMPLE-EVAL-IN-LEXENV
 (DECLARE (PRINT "I am going to be evaluated by SBCL"))
 #<NULL-LEXENV>)
0]

Notice that the string is not printed - so, the evaluation does not occur even partially, and the error message is clear.

Regards,
Roman

 status confirmed
 importance wishlist

Roman Marynchak <email address hidden> writes:

> You are right, I have entered that garbage in REPL intentionally,
> because I saw in compiler sources (src/code/eval.lisp) this code
>
> (defun %simple-eval (expr lexenv)
> (let* (;; why PROGN? So that attempts to eval free declarations
> ;; signal errors rather than return NIL. -- CSR, 2007-05-01
> (lambda `(lambda ()
> (declare (muffle-conditions compiler-note))
> (progn ,expr)))
> (fun (sb!c:compile-in-lexenv nil lambda lexenv)))
> (funcall fun)))
>
> This trick is not CLHS-compliant.

Yes it is.

> Just because "In situations where such expressions can appear,
> explicit checks are made for their presence and they are never
> actually evaluated".

Within a PROGN, or at the REPL, is not a situation where such (DECLARE)
expressions can appear. A better error message in situations where
declare expressions are not legal might be desireable, but sbcl's
current behaviour on free declarations is allowed by the standard.

Christophe

Changed in sbcl:
importance: Undecided → Wishlist
status: New → Confirmed
Changed in sbcl:
assignee: nobody → Roman Marynchak (roman-marynchak)
status: Confirmed → In Progress
tags: added: review
Nikodemus Siivola (nikodemus) wrote :

Sorry about the following fussiness -- but when this is fixed, I think it's better to fix it properly:

* The error should be a PROGRAM-ERROR, and preferably a REFERENCE-CONDITION.

* Need to make the compiler behave equivalently: the current WARNING for a misplaced DECLARE should probably be changed into a a COMPILER-ERROR -> PROGRAM-ERROR, and the expressions nested inside the DECLARE should not be compiled.

* Test-cases.

tags: removed: review
tags: added: compiler-ir1 eval

Thank you for the code review and for the reasonable remarks. I will finish this fix when I am back from my vacation.

Note: signal plain ERROR in SB-IMPL::SIMPLE-EVAL-IN-LEXENV, because other parts of this function signal plain errors as well. So, keep the style solid.

Other requirements seem to be satisfied.

tags: added: review

commit d9fae7311cb25912664399cef0abec5388a61701
Author: Christophe Rhodes <email address hidden>
Date: Wed Jun 11 13:26:24 2014 +0100

    Fix #lp573747

    Handle misplaced DECLAREs in the compiler earlier. This takes care
    of compiled code, and of evaluated code under :COMPILE evaluator-mode
    add a test too for :INTERPRET evaluator-mode (though the current
    behaviour is correct).

    Based on the patch by Roman Marynchak.

tags: removed: review
Changed in sbcl:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers