(unless (info :function :kind name)
(setf (info :function :kind name) :function)
(setf (info :function :where-from name) :assumed))
-
(let ((where (info :function :where-from name)))
(when (and (eq where :assumed)
;; In the ordinary target Lisp, it's silly to report
(collect ((res nil cons))
(dolist (name names)
(when (fboundp name)
- (compiler-assert-symbol-home-package-unlocked name
- "declaring the ftype of ~A"))
- (let ((found (find name fvars
- :key #'leaf-source-name
- :test #'equal)))
+ (compiler-assert-symbol-home-package-unlocked
+ name "declaring the ftype of ~A"))
+ (let ((found (find name fvars :key #'leaf-source-name :test #'equal)))
(cond
(found
(setf (leaf-type found) type)
res)))
;;; Return a DEFINED-FUN which copies a GLOBAL-VAR but for its INLINEP
-;;; (and TYPE if notinline).
-(defun make-new-inlinep (var inlinep)
+;;; (and TYPE if notinline), plus type-restrictions from the lexenv.
+(defun make-new-inlinep (var inlinep local-type)
(declare (type global-var var) (type inlinep inlinep))
- (let ((res (make-defined-fun
- :%source-name (leaf-source-name var)
- :where-from (leaf-where-from var)
- :type (if (and (eq inlinep :notinline)
- (not (eq (leaf-where-from var) :declared)))
- (specifier-type 'function)
- (leaf-type var))
- :inlinep inlinep)))
+ (let* ((type (if (and (eq inlinep :notinline)
+ (not (eq (leaf-where-from var) :declared)))
+ (specifier-type 'function)
+ (leaf-type var)))
+ (res (make-defined-fun
+ :%source-name (leaf-source-name var)
+ :where-from (leaf-where-from var)
+ :type (if local-type
+ (type-intersection local-type type)
+ type)
+ :inlinep inlinep)))
(when (defined-fun-p var)
(setf (defined-fun-inline-expansion res)
(defined-fun-inline-expansion var))
(let ((sense (cdr (assoc (first spec) *inlinep-translations* :test #'eq)))
(new-fenv ()))
(dolist (name (rest spec))
- (let ((fvar (find name fvars
- :key #'leaf-source-name
- :test #'equal)))
+ (let ((fvar (find name fvars :key #'leaf-source-name :test #'equal)))
(if fvar
(setf (functional-inlinep fvar) sense)
- (let ((found
- (find-lexically-apparent-fun
- name "in an inline or notinline declaration")))
+ (let ((found (find-lexically-apparent-fun
+ name "in an inline or notinline declaration")))
(etypecase found
(functional
(when (policy *lexenv* (>= speed inhibit-warnings))
definition of local function:~% ~S"
sense name)))
(global-var
- (push (cons name (make-new-inlinep found sense))
- new-fenv)))))))
-
+ (let ((type
+ (cdr (assoc found (lexenv-type-restrictions res)))))
+ (push (cons name (make-new-inlinep found sense type))
+ new-fenv))))))))
(if new-fenv
(make-lexenv :default res :funs new-fenv)
res)))
(print output)
(assert (zerop (length output))))
+;;;; bug 305: INLINE/NOTINLINE causing local ftype to be lost
+
+(define-condition optimization-error (error) ())
+
+(labels ((compile-lambda (type sense)
+ (handler-bind ((compiler-note (lambda (_)
+ (declare (ignore _))
+ (error 'optimization-error))))
+ (values
+ (compile
+ nil
+ `(lambda ()
+ (declare
+ ,@(when type '((ftype (function () (integer 0 10)) bug-305)))
+ (,sense bug-305)
+ (optimize speed))
+ (1+ (bug-305))))
+ nil)))
+ (expect-error (sense)
+ (multiple-value-bind (f e) (ignore-errors (compile-lambda nil sense))
+ (assert (not f))
+ (assert (typep e 'optimization-error))))
+ (expect-pass (sense)
+ (multiple-value-bind (f e) (ignore-errors (compile-lambda t sense))
+ (assert f)
+ (assert (not e)))))
+ (expect-error 'inline)
+ (expect-error 'notinline)
+ (expect-pass 'inline)
+ (expect-pass 'notinline))
+
;;; success
(quit :unix-status 104)