DOLIST macro expansion can't handled type declaration properly.
How to reproduce the issue
Type 1
> (compile nil
(lambda ()
(dolist (s '("foo" "bar" "baz"))
(declare (type string s))
(check-type s string))))
;;; Warning: In LET* body, the type of the form S is SYMBOL, not STRING.
#<compiled-function 000000000394e630>
T
T
> (macroexpand
'(dolist (s '("foo" "bar" "baz"))
(declare (type string s))
(check-type s string)))
(BLOCK NIL
(LET* ((SI::%DOLIST-VAR '("foo" "bar" "baz"))
S ;; <==== initialized by NIL
)
(DECLARE (TYPE STRING S))
(SI:WHILE SI::%DOLIST-VAR
(SETQ S (FIRST SI::%DOLIST-VAR))
(CHECK-TYPE S STRING)
(SETQ SI::%DOLIST-VAR (REST SI::%DOLIST-VAR)))
NIL))
T
Type 2
> (compile nil
(lambda ()
(dolist (s '("foo" "bar" "baz") s)
(declare (type string s))
(check-type s string))))
;;; Warning: Type mismatch between S and NIL.
#<compiled-function 7ff51fe16f30>
T
T
> (macroexpand
'(dolist (s '("foo" "bar" "baz") s)
(declare (type string s))
(check-type s string)))
(BLOCK NIL
(LET* ((SI::%DOLIST-VAR '("foo" "bar" "baz")) S)
(DECLARE (TYPE STRING S))
(SI:WHILE SI::%DOLIST-VAR
(SETQ S (FIRST SI::%DOLIST-VAR))
(CHECK-TYPE S STRING)
(SETQ SI::%DOLIST-VAR (REST SI::%DOLIST-VAR)))
(SETQ S NIL) ;; <=== SETQ by NIL
S))
How to fix this issue (in my opinion)
I also reported this bug to the ECL team.
https://gitlab.com/embeddable-common-lisp/ecl/issues/348