-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Loop for by should only allow a positive number #300
Comments
SBCL and CCL share the same loop ancestry so I thought it should be possible to port the fix. However it doesn't appear to be the case. Although maybe I'm not rebuilding CCL properly? The way SBCL prevents is the issue is by adding a
I've tried adding that to the loop code in ? (macroexpand ' (loop :for i :from 0 :upto 10 :by 0))
; Warning: The form 0 evaluated to 0, which was not of the anticipated type (AND NUMBER (REAL (0))).
; Current LOOP context: :FOR I :FROM 0 :UPTO 10 :BY 0.
; While executing: ANSI-LOOP::LOOP-WARN, in process listener(1).
(BLOCK NIL (LET ((I 0) (#:LOOP-STEP-BY-6 0)) (DECLARE (TYPE (AND NUMBER (REAL (0))) #:LOOP-STEP-BY-6) (TYPE NUMBER I)) (ANSI-LOOP::LOOP-BODY NIL (NIL NIL (WHEN (> I '10) (GO ANSI-LOOP::END-LOOP)) NIL) NIL (NIL (ANSI-LOOP::LOOP-REALLY-DESETQ I (+ I #:LOOP-STEP-BY-6)) (WHEN (> I '10) (GO ANSI-LOOP::END-LOOP)) NIL) NIL)))
diff --git a/library/loop.lisp b/library/loop.lisp
index 946bfce7..bf4cbe39 100644
--- a/library/loop.lisp
+++ b/library/loop.lisp
@@ -1851,17 +1851,17 @@ (defun loop-sequencer (indexv indexv-type indexv-user-specified-p
(loop-constant-fold-if-possible form indexv-type))
(setq endform (if limit-constantp
`',limit-value
(loop-make-variable
(loop-gentemp 'loop-limit-) form indexv-type))))
(:by
(multiple-value-setq (form stepby-constantp stepby)
- (loop-constant-fold-if-possible form indexv-type))
+ (loop-constant-fold-if-possible form `(and ,indexv-type (real (0)))))
(unless stepby-constantp
- (loop-make-variable (setq stepby (loop-gentemp 'loop-step-by-)) form indexv-type)))
+ (loop-make-variable (setq stepby (loop-gentemp 'loop-step-by-)) form `(and ,indexv-type (real (0))))))
(t (loop-error
"~S invalid preposition in sequencing or sequence path.~@
Invalid prepositions specified in iteration path descriptor or something?"
prep)))
(when (and odir dir (not (eq dir odir)))
(loop-error "Conflicting stepping directions in LOOP sequencing path"))
(setq odir dir))
|
Hello, loop-constant-fold-if-possible simply warns and does not error. Even in sbcl you can I believe the type-error is produced by the more aggressive sbcl compiler, but this I have to check. |
I believe a good explanation is the following: (defun test ()
(let ((var 0))
(declare (type (and number (real (0))) var))
(+ 23 var))) in ccl this compiles fine and returns 23 ; SLIME 2.24; compiling file "/Users/karstenpoeck/lisp/compiler/clasp/test-declarations.lisp" (written 25 APR 2020 03:40:09 PM):
; file: /Users/karstenpoeck/lisp/compiler/clasp/test-declarations.lisp
; in: DEFUN TEST
; (LET ((VAR 0))
; (DECLARE (TYPE (AND NUMBER (REAL #)) VAR))
; (+ 23 VAR))
;
; note: deleting unreachable code
;
; caught WARNING:
; Constant
; 0 conflicts with its asserted type
; (OR (SINGLE-FLOAT (0.0)) (DOUBLE-FLOAT (0.0d0)) (RATIONAL (0))).
; See also:
; The SBCL Manual, Node "Handling of Types"
;
; compilation unit finished
; caught 1 WARNING condition
; printed 1 note
; wrote /Users/karstenpoeck/lisp/compiler/clasp/test-declarations.fasl
; compilation finished in 0:00:00.011
CL-USER> (test)
; Evaluation aborted on #<SIMPLE-TYPE-ERROR expected-type:
(OR (SINGLE-FLOAT (0.0)) (DOUBLE-FLOAT (0.0d0)) (RATIONAL (0)))
datum: 0>. |
In summary i believe your fix is correct, It just doesn't create the type-error you expected |
(defun test ()
(let ((var 0))
(declare (type (and number (real (0))) var))
(+ 23 var))) This is undefined behaviour. You tell the compiler that the value CL-USER> (typep 0 '(real (0)))
NIL |
@phoe I knew all that. I tried to make a connection to the loop problem with the
which is precisely what I explained here. so while your answer is correct,I believe I failed to properly explain the context, which you did not take into account |
Thank you. If I understand this context correctly now, CCL |
I think you missed the beginning:
|
OK, thanks. Sorry, I shouldn't perhaps post when exhausted. This is not a spec bug in CCL per se, because the code wasn't conforming in the beginning. If anything, a sane thing for CCL to do would be to signal a compile-time error and/or warning, but it's not a spec conformance error. SBCL treats declarations as assertions by default, which is why the error is signaled in SBCL. This is why the SBCL fix won't work in CCL. If I read the LOOP code correctly, a possible fix would be to edit the following line: Line 1883 in 3ebeace
It checks if the step is |
If a macroexpansion-time error is kosher, perhaps we it is easier to change |
That's a question to @xrme - we are already in undefined behaviour territory, so CCL is free to do whatever it wants to. The question is what would be consistent. |
@PuercoPop @digikar99 @phoe |
@kpoeck Thanks for the fix! Would you also mind submitting a matching regression test case to https://github.com/Clozure/ccl-tests/ that shows that the bug has been fixed? |
don't mind, will do |
@phoe, did that in Clozure/ccl-tests#5 |
Matt Kaufmann reports that 7d0657e broke his code. Specifically,
Prior to 7d0657e this merely caused a compiler warning, which wasn't a problem for Matt. But the underlying issue seems to be that the :BY variable is paying literal attention to the type of x, and it obviously should not do so when the type of x has high and/or low bounds. The :BY variable should probably only pay attention to the numeric-ctype-class of the type of x and ignore any high or low bounds. Note that SBCL makes this same mistake, although it merely throws a warning rather than an error. Lispworks quietly compiles and executes the code without errors or warnings, which I think is as it should be. Finally, another, related issue that seems to catch both CCL and SBCL is that the loop terminal value of 20 causes its own type warning in both SBCL and CCL and throws an error when (bar) is run in SBCL. When the loop variable is declared to be a type with bounds, the terminal value of that variable should probably be ignored for purposes of type checking in loop forms where that value will never be used, as in the above code. Again, Lispworks seems to get this right. In summary, are at least 3 subtly different issues at play here:
|
The |
#300 (comment) All 21911 current tests succeed.
The following works in CCL but not in SBCL:
On mentioning it over at SBCL Bugs mailing list, I learnt that this is against the standard: http://www.lispworks.com/documentation/lw51/CLHS/Body/06_abaa.htm and only positive numbers are allowed for the by clause.
As of 1.11.5, CCL also allows negative numbers.
The text was updated successfully, but these errors were encountered: