LOOP fails to catch the duplicate variables bindings in some cases

Bug #645534 reported by Roman Marynchak
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
Fix Released
Low
Unassigned

Bug Description

The slightly modified example from CLHS demonstrates the problem in SBCL 1.0.42:

 (loop with (a b) of-type float = '(1.0 2.0)
          and (c a) of-type float = '(3.0 4.0)
       return (list a b c))

CLISP and Lispworks do not have this issue - they both say about the duplicate binding in LOOP and throw the error.

But in SBCL's REPL it yields:

* (loop with (a b) of-type float = '(1.0 2.0)
          and (c a) of-type float = '(3.0 4.0)
       return (list a b c))
; in: LAMBDA NIL
; (SB-LOOP::LOOP-DESTRUCTURING-BIND (C A) #:LOOP-DESTRUCTURE-604
; (SB-LOOP::LOOP-DESTRUCTURING-BIND (A B)
; #:LOOP-DESTRUCTURE-603
; (DECLARE
; (TYPE
; FLOAT
; A)
; (TYPE
; FLOAT
; C)
; (TYPE
; FLOAT
; B)
; (TYPE
; FLOAT
; A))
; (SB-LOOP::LOOP-BODY
; NIL NIL
; ((RETURN-FROM
; NIL
; #))
; NIL
; NIL)))
; --> DESTRUCTURING-BIND LET LET*
; ==>
; (LET* ((C (CAR #:WHOLE1))
; (A (CAR (CDR #:WHOLE1)))
; (#:LOOP-IGNORED-VAR-0 (CDR (CDR #:WHOLE1))))
; (DECLARE (IGNORE #:LOOP-IGNORED-VAR-0))
; (SB-LOOP::LOOP-DESTRUCTURING-BIND (A B) #:LOOP-DESTRUCTURE-603
; (DECLARE (TYPE FLOAT A)
; (TYPE FLOAT C)
; (TYPE FLOAT B)
; (TYPE FLOAT A))
; (SB-LOOP::LOOP-BODY NIL NIL
; ((RETURN-FROM NIL #))
; NIL NIL)))
;
; caught STYLE-WARNING:
; The variable A is defined but never used.
;
; compilation unit finished
; caught 1 STYLE-WARNING condition

(1.0 2.0 3.0)
*

The right behavior here is to signal the error. CLHS (section 6.1.1.7) says that "An error of type program-error is signaled (at macro expansion time) if the same variable is bound twice in any variable-binding clause of a single loop expression. Such variables include local variables, iteration control variables, and variables found by destructuring."

Tags: loop
Changed in sbcl:
importance: Undecided → Low
status: New → Triaged
Changed in sbcl:
assignee: nobody → Roman Marynchak (roman-marynchak)
status: Triaged → In Progress
Revision history for this message
Roman Marynchak (roman-marynchak) wrote :

There is a simple patch. Before declaring a variable, we check whether its name is already used within the loop. To do that, we analyze *loop-declarations* list contents. Variables which are initialized by destructuring are described by the sublists in that list. Every sublist has a variable name as a last element.

The regression tests is coming soon. Current behavior with the fix:

* (loop with (a b) of-type float = '(1.0 2.0)
          and (c a) of-type float = '(3.0 4.0)
       return (list a b c))

debugger invoked on a SB-INT:SIMPLE-PROGRAM-ERROR in thread #<THREAD
                                                              "initial thread" RUNNING
                                                              {A9E6861}>:
  duplicated variable A in a LOOP binding
current LOOP context: WITH (A B) OF-TYPE FLOAT = '(1.0 2.0) AND (C
                                                                 A) OF-TYPE FLOAT = '(3.0
                                                                                      4.0) RETURN.

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

Revision history for this message
Roman Marynchak (roman-marynchak) wrote :

The attachment contains a regression test. Note that a 'successful' variant of the similar example (where A is not duplicated) is already present in loop.pure.lisp.

tags: added: loop review
Revision history for this message
Roman Marynchak (roman-marynchak) wrote :

I have just found that this patch is not applicable on the current LOOP, so I'm removing the review tag. But I will try to find the acceptable solution later.

tags: removed: review
Paul Khuong (pvk)
Changed in sbcl:
assignee: Roman Marynchak (roman-marynchak) → nobody
status: In Progress → Triaged
Revision history for this message
Stas Boukarev (stassats) wrote :

FIxed in a42a2c6f6dd93b31ef8a6ba7f6457d024972a4ac.

Changed in sbcl:
status: Triaged → Fix Committed
Changed in sbcl:
status: Fix Committed → Fix Released
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.