Unused lexical functions not (DECLARE IGNORE)'d don't report a STYLE-WARNING as for variables.

Bug #841260 reported by Jean-Philippe Paradis
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
Triaged
Wishlist
Unassigned

Bug Description

What I do:
(flet ((foo ())))
=> NIL

What happens:
Compilation and evaluation proceed without a STYLE-WARNING.

What I expected to happen:
I expected a STYLE-WARNING.

Analysis:
It's already well-established that an unused LET binding results in a STYLE-WARNING unless it's been (DECLARE IGNORE)'d. The above situation is exactly analogous except it takes place in the function namespace, so the same behavior should apply.

If we look at CLHS IGNORE we see it's indeed possible to (DECLARE IGNORE) (or IGNORABLE) a function, reinforcing the idea that the same behavior (a STYLE-WARNING) should apply.

SBCL version: 1.0.51
uname -a: Linux dynamorph 2.6.32-33-generic #72-Ubuntu SMP Fri Jul 29 21:08:37 UTC 2011 i686 GNU/Linux

*features*:
(:SWANK :QUICKLISP :SB-BSD-SOCKETS-ADDRINFO :ASDF2 :ASDF :ASDF-UNIX :ANSI-CL
 :COMMON-LISP :SBCL :SB-DOC :SB-TEST :SB-LDB :SB-PACKAGE-LOCKS :SB-UNICODE
 :SB-EVAL :SB-SOURCE-LOCATIONS :IEEE-FLOATING-POINT :X86 :UNIX :ELF :LINUX
 :SB-THREAD :LARGEFILE :GENCGC :STACK-GROWS-DOWNWARD-NOT-UPWARD
 :C-STACK-IS-CONTROL-STACK :COMPARE-AND-SWAP-VOPS :UNWIND-TO-FRAME-AND-CALL-VOP
 :RAW-INSTANCE-INIT-VOPS :STACK-ALLOCATABLE-CLOSURES :STACK-ALLOCATABLE-VECTORS
 :STACK-ALLOCATABLE-LISTS :STACK-ALLOCATABLE-FIXED-OBJECTS :ALIEN-CALLBACKS
 :CYCLE-COUNTER :INLINE-CONSTANTS :MEMORY-BARRIER-VOPS :MULTIPLY-HIGH-VOPS
 :LINKAGE-TABLE :OS-PROVIDES-DLOPEN :OS-PROVIDES-DLADDR :OS-PROVIDES-PUTWC
 :OS-PROVIDES-SUSECONDS-T :OS-PROVIDES-GETPROTOBY-R :OS-PROVIDES-POLL)

Revision history for this message
Nikodemus Siivola (nikodemus) wrote :

They are reported. What you're experiencing is the either *evalutor-mode* :interpret, or EVAL muffling of style-warnings from compiling the toplevel form prior to its execution.

CL-USER> (compile nil '(lambda () (flet ((foo () ())))))
; in: LAMBDA ()
; (FLET ((FOO NIL NIL)))
;
; note: deleting unused function
; (FLET FOO)
;
; compilation unit finished
; printed 1 note
#<FUNCTION (LAMBDA ()) {10030DE0D9}>
NIL
NIL

Changed in sbcl:
status: New → Invalid
Revision history for this message
Jean-Philippe Paradis (hexstream) wrote :

I didn't go out of my way to change *EVALUATOR-MODE* to :interpret and I verified that it's indeed set to :compile.

As for "EVAL muffling of style-warnings from compiling the toplevel form prior to its execution", I'm not sure exactly what that means, but given that entering (let ((foo nil))) in the REPL produces a "STYLE-WARNING: The variable FOO is defined but never used", I'm positive that entering (flet ((foo ()))) in the REPL ought to produce a "STYLE-WARNING: The function FOO is defined but never used" since these are completely analogous situations in all relevant respects (the only difference being that one binding is happening in the variable namespace while the other happens in the function namespace).

I understand that there might be technical/historical reasons why the behaviors differ, but from a user's perspective, I don't see how the discrepancy might be justified.

(And btw I consider a NOTE to be quite different than a STYLE-WARNING.)

Revision history for this message
Nikodemus Siivola (nikodemus) wrote :

On reflection, I don't see why functions and variables should no be treated equivalently. Would need to double-check CLHS, though.

Changed in sbcl:
importance: Undecided → Wishlist
status: Invalid → Triaged
tags: added: compiler-ir1 easy
Revision history for this message
Douglas Katzman (dougk) wrote :

re. "I'm positive that entering (flet ((foo ()))) in the REPL ought to produce a "STYLE-WARNING"

No, the REPL expressly avoids printing anything from the compiler to the extent possible.

If you explicitly ask to produce a compiled function, which can be done with COMPILE or COMPILE-FILE, then you get warnings. A lazy evaluation model (in forms are eval'ed only as reached) will never pre-scan a lambda to figure out what to warn about.

The bug here is actually the opposite of the problem as stated: the REPL warns when it should not.
(setq fred 5) ; no defvar on this gets a warning
Most other implementations will *not* print "undefined variable", and it's wrong that we do.

Revision history for this message
Jean-Philippe Paradis (hexstream) wrote :

"No, the REPL expressly avoids printing anything from the compiler to the extent possible."

Uh?!? To me, this seems like a strictly counter-productive policy.

1. Any gratuitous differences between evaluation in the REPL and other contexts are likely to lead to unnecessary surprises (for me and/or other people) later. If I'm testing code in the REPL, often with the view of copy/pasting that code in some other context when I'm satisfied, it's much better if the code behaves exactly the same in other contexts, to the extent possible.

2. The REPL is the perfect time to throw warnings at me, as I can trivially ignore them if I don't care about them.

"(setq fred 5) ; no defvar on this gets a warning
Most other implementations will *not* print "undefined variable", and it's wrong that we do."

What?!?

1. I don't know that anyone should ever use SETQ when SETF would do, which is virtually always.

2. I don't even know what "(setq fred 5)" even means if the "fred" binding has not yet been defined. Isn't that undefined or unspecified behavior or something like that? Is "fred" then a special variable without earmuffs?? Seems like a bad idea all around.

3. It seems to me to be a particularly good idea to throw a warning in this case, as SETQ (or SETF) on undefined bindings seems to be used almost exclusively by confused newbies, who should learn about properly defining bindings as quickly as possible. Properly using DEFVAR, DEFPARAMETER or LET has never seemed like a burden to me...

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.