inline-expansion and type-inference
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
| SBCL |
Medium
|
Unassigned |
Bug Description
When the compiler inline expands functions, it may be that different
kinds of return values are generated from different code branches.
E.g. an inline expansion of POSITION generates integer results
from one branch, and NIL results from another. When that inline
expansion is used in a context where only one of those results
is acceptable, e.g.
(defun foo (x)
(aref *a1* (position x *a2*)))
and the compiler can't prove that the unacceptable branch is
never taken, then bogus type mismatch warnings can be generated.
If you need to suppress the type mismatch warnings, you can
suppress the inline expansion,
(defun foo (x)
#+sbcl (declare (notinline position)) ; to suppress bug 117 bogowarnings
(aref *a1* (position x *a2*)))
or, sometimes, suppress them by declaring the result to be of an
appropriate type,
(defun foo (x)
(aref *a1* (the integer (position x *a2*))))
This is not a new compiler problem in 0.7.0, but the new compiler
transforms for FIND, POSITION, FIND-IF, and POSITION-IF make it
more conspicuous. If you don't need performance from these functions,
and the bogus warnings are a nuisance for you, you can return to
your pre-0.7.0 state of grace with
#+sbcl (declaim (notinline find position find-if position-if)) ; bug 117..
See also bug #309113:
Changed in sbcl: | |
importance: | Undecided → Medium |
status: | New → Confirmed |
Nikodemus Siivola (nikodemus) wrote : | #1 |
Nikodemus Siivola (nikodemus) wrote : | #2 |
See also bug 750797.
Paul Khuong (pvk) wrote : | #3 |
I think most of this bug's instances now emit STYLE-WARNINGs instead of full WARNINGs, if any future reader is confused.
3b (00003b) wrote : | #4 |
some more possible examples with various warnings/style warnings in 1.2.6 (and 1.2.1)
(declaim (inline foo))
(defun foo (pointer)
(flet ((pointer-address (ptr)
(declare (type system-area-pointer ptr))
(if (sb-sys:
pointer)))
(defun bar ()
(unwind-protect
(foo 0)))
* ; in: DEFUN BAR
; (FOO 0)
; --> BLOCK FLET BLOCK
; ==>
; (SB-SYS:SAP-INT PTR)
;
; caught STYLE-WARNING:
; Lisp error during constant folding:
; The value 0 is not of type SYSTEM-
(DEFUN foo1 ()
(let ((type :float))
(the (unsigned-byte) (IF (KEYWORDP TYPE)
; in: DEFUN FOO1
; (THE (UNSIGNED-BYTE)
; (IF (KEYWORDP TYPE)
; 123
; TYPE))
;
; caught WARNING:
; Derived type of TYPE is
; (VALUES (MEMBER :FLOAT) &OPTIONAL),
; conflicting with its asserted type
; UNSIGNED-BYTE.
; See also:
; The SBCL Manual, Node "Handling of Types"
(DEFUN foo2 ()
(let ((type :float))
(let ((t2 (IF (KEYWORDP TYPE)
(declare (unsigned-byte t2) (ignore t2)))))
; in: DEFUN FOO2
; (IF (KEYWORDP TYPE)
; 123
; TYPE)
; ==>
; TYPE
;
; caught STYLE-WARNING:
; This is not a UNSIGNED-BYTE:
; :FLOAT
; See also:
; The SBCL Manual, Node "Handling of Types"
Stas Boukarev (stassats) wrote : | #5 |
Reduce test case for "The value 0 is not of type SYSTEM-
(declaim (inline foo))
(defun foo (x)
(flet ((c (ptr)
(declare (type cons ptr))
(car ptr)))
(and (consp x)
(c x))))
(defun bar ()
(block nil
(list (lambda () (return)))
(foo 0)))
Bug #309113 is an instance of this, and contains a nice small test-case.