Don't disable argument checking with multiple callers.
[sbcl.git] / src / compiler / callable-args.lisp
blob7b4f55d0e7961bd2e584606ed37e806bc1e45cb9
1 ;;;; Type checking of higher order functions.
2 ;;;;
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
12 (in-package "SB-C")
14 (defun assert-function-designator (caller lvars lvar annotation policy)
15 (destructuring-bind (args &optional results &rest options) annotation
16 (declare (ignore options))
17 (multiple-value-bind (arg-specs result-specs deps)
18 (callable-dependant-lvars caller lvars args results)
19 (let* ((type (make-fun-type
20 :required
21 (make-list (+ (length arg-specs)
22 ;; Count ordinary types without annotations
23 (count-if #'atom args))
24 :initial-element *universal-type*)
25 :returns *wild-type*
26 :designator t))
27 (annotation (make-lvar-function-designator-annotation
28 :caller caller
29 :arg-specs arg-specs
30 :result-specs result-specs
31 :deps deps
32 :type type)))
33 (when (add-annotation lvar annotation)
34 (assert-lvar-type lvar
35 (specifier-type 'function-designator)
36 policy))))))
38 (defun fun-type-positional-count (fun-type)
39 (+ (length (fun-type-required fun-type))
40 (length (fun-type-optional fun-type))))
42 (defun callable-dependant-lvars (caller lvars args results)
43 (let ((fun-type (global-ftype caller)))
44 (collect ((lvars))
45 (let ((arg-position -1)
46 (optional-args (nthcdr (fun-type-positional-count fun-type) lvars)))
47 (labels ((record-lvar (lvar)
48 (lvars lvar)
49 (incf arg-position))
50 (handle-keys (options)
51 (loop for (key value*) on options by #'cddr
52 for value = (if (or (eq key :key)
53 (eq key :value))
54 (if (consp value*)
55 (let ((value-lvar (getf optional-args (car value*))))
56 (when value-lvar
57 (let ((if (getf optional-args (second value*))))
58 (cond (if
59 (list (record-lvar value-lvar)
60 (record-lvar if) (third value*)))
61 ((null (third value*))
62 (record-lvar value-lvar))))))
63 (let ((lvar (getf optional-args value*)))
64 (and lvar
65 (record-lvar lvar))))
66 value*)
67 when value
68 collect key
69 and
70 collect value))
71 (process-arg (arg)
72 (ecase (car arg)
73 (nth-arg
74 (list
75 (list* (record-lvar (nth (cadr arg) lvars))
76 (handle-keys (cddr arg)))))
77 (rest-args
78 (loop for lvar in optional-args
79 collect
80 (list* (record-lvar lvar)
81 (handle-keys (cdr arg)))))
82 (or
83 (list
84 (list* 'or (process-args (cdr arg)))))))
85 (process-args (args)
86 (loop for arg in args
87 when (consp arg)
88 nconc
89 (process-arg arg))))
90 (values (process-args args)
91 (and (consp results)
92 (car (process-arg results)))
93 (lvars)))))))
95 (defun map-key-lvars (function args type)
96 (when (fun-type-keyp type)
97 (let ((key-args (nthcdr (fun-type-positional-count type)
98 args))
99 (key-types (fun-type-keywords type))
100 seen
101 unknown)
102 (loop for (key lvar) on key-args by #'cddr
103 for key-value = (and (constant-lvar-p key)
104 (lvar-value key))
105 for key-info = (find key-value key-types :key #'key-info-name)
106 do (cond (key-info
107 (unless (memq key-value seen)
108 (funcall function key-value lvar)
109 (push key-value seen)))
110 ((eq key-value
111 :allow-other-keys))
113 (push key unknown))))
114 unknown)))
116 ;;; Turn constant LVARs in keyword arg positions to constants so that
117 ;;; they can be passed to FUN-INFO-CALLABLE-CHECK.
118 (defun resolve-key-args (args type)
119 (if (fun-type-keyp type)
120 (let ((non-key (fun-type-positional-count type)))
121 (if (> (length args) non-key)
122 (let* (key-arguments
123 (unknown (map-key-lvars (lambda (key value)
124 (push key key-arguments)
125 (push value key-arguments))
126 args
127 type)))
128 (values (nconc (subseq args 0 non-key)
129 (nreverse key-arguments))
130 unknown))
131 (values args nil)))
132 (values args nil)))
134 ;;; The function should accept
135 ;;; (lvar args results &key (unknown-keys boolean) (no-function-conversion boolean) (arg-lvars list-of-lvars))
136 (defun map-callable-arguments (function combination)
137 (let* ((combination-name (lvar-fun-name (combination-fun combination) t))
138 (type (global-ftype combination-name))
139 (info (info :function :info combination-name))
140 (annotation (fun-info-annotation info)))
141 (when annotation
142 (multiple-value-bind (arg-lvars unknown) (resolve-key-args (combination-args combination) type)
143 (flet ((call (lvar annotation)
144 (destructuring-bind (args &optional results . options) annotation
145 (apply function lvar
146 (loop for arg in args
147 if (typep arg '(cons (eql rest-args)))
148 nconc (loop repeat (- (length (combination-args combination))
149 (fun-type-positional-count type))
150 collect arg)
151 else
152 collect arg)
153 results
154 :arg-lvars arg-lvars
155 :unknown-keys unknown
156 options))))
157 (loop for (n kind . annotation) in (fun-type-annotation-positional annotation)
158 when (memq kind '(function function-designator))
160 (let ((arg (nth n arg-lvars)))
161 (when arg
162 (call arg annotation))))
163 (loop with keys = (nthcdr (fun-type-positional-count type)
164 arg-lvars)
165 for (key (kind . annotation)) on (fun-type-annotation-key annotation) by #'cddr
166 when (memq kind '(function function-designator))
168 (let ((lvar (getf keys key)))
169 (when lvar
170 (call lvar annotation)))))))))
172 ;; Handle #'function, 'function and (lambda (x y))
173 (defun node-fun-type (node &optional defined-here asserted-type)
174 (let* ((use node)
175 (lvar-type (single-value-type (node-derived-type use)))
176 (leaf (if (ref-p use)
177 (ref-leaf use)
178 (return-from node-fun-type
179 (values lvar-type
180 (node-source-form use)))))
181 (asserted t)
182 (defined-type (and (global-var-p leaf)
183 (case (leaf-where-from leaf)
184 (:declared
185 (leaf-type leaf))
186 (:defined
187 (cond ((or defined-here
188 asserted-type
189 (and (defined-fun-p leaf)
190 (eq (defined-fun-inlinep leaf) 'notinline))
191 (fun-lexically-notinline-p (leaf-%source-name leaf)
192 (node-lexenv (lvar-dest (node-lvar node)))))
193 (setf asserted nil)
194 lvar-type)
196 (global-ftype (leaf-%source-name leaf)))))
197 ((:defined-here :declared-verify)
198 (cond ((or (and (defined-fun-p leaf)
199 (eq (defined-fun-inlinep leaf) 'notinline))
200 (fun-lexically-notinline-p (leaf-%source-name leaf)
201 (node-lexenv (lvar-dest (node-lvar node)))))
202 lvar-type)
204 (global-ftype (leaf-%source-name leaf)))))
206 (global-var-defined-type leaf)))))
207 (entry-fun (if (and (functional-p leaf)
208 (functional-kind-eq leaf external))
209 (functional-entry-fun leaf)
210 leaf))
211 (lvar-type (cond ((and defined-type
212 (neq defined-type *universal-type*))
213 defined-type)
214 ((and (functional-p entry-fun)
215 (fun-type-p (functional-type entry-fun)))
216 (functional-type entry-fun))
217 ((and (not (fun-type-p lvar-type))
218 (lambda-p entry-fun)
219 (functional-kind-eq entry-fun nil)
220 (lambda-tail-set entry-fun))
221 (make-fun-type :wild-args t
222 :returns
223 (tail-set-type (lambda-tail-set entry-fun))))
224 ((and asserted-type
225 (not (constant-p leaf)))
226 (setf asserted nil)
227 ;; Don't trust FUNCTION type declarations,
228 ;; they perform no runtime assertions.
229 (specifier-type 'function))
231 (setf asserted nil)
232 lvar-type)))
233 (fun-name (cond ((or (fun-type-p lvar-type)
234 (functional-p leaf)
235 (global-var-p leaf))
236 (cond ((constant-p leaf)
237 (let ((value (constant-value leaf)))
238 (etypecase value
239 #-sb-xc-host
240 (function
241 (%fun-name value))
242 (symbol
243 value))))
244 ((and (lambda-p leaf)
245 (functional-kind-eq leaf external))
246 (leaf-debug-name (lambda-entry-fun leaf)))
248 (leaf-debug-name leaf))))
249 ((constant-p leaf)
250 (constant-value leaf))
252 (return-from node-fun-type lvar-type))))
253 (type (cond ((fun-type-p lvar-type)
254 lvar-type)
255 ((symbolp fun-name)
256 (if (or (fun-lexically-notinline-p fun-name
257 (node-lexenv (node-dest node)))
258 (and (or asserted-type
259 defined-here)
260 (neq (info :function :where-from fun-name) :declared)))
261 lvar-type
262 (global-ftype fun-name)))
263 ((functional-p leaf)
264 (let ((info (functional-info leaf)))
265 (if info
266 (specifier-type (entry-info-type info))
267 lvar-type)))
269 lvar-type))))
270 (values type fun-name leaf asserted)))
272 (defun lvar-fun-type (lvar &optional defined-here asserted-type)
273 (let* ((use (principal-lvar-use lvar))
274 (lvar-type (lvar-type lvar)))
275 (if (ref-p use)
276 (multiple-value-bind (type fun-name leaf asserted) (node-fun-type use defined-here asserted-type)
277 (let ((int (if (fun-type-p lvar-type)
278 ;; save the cast type
279 (type-intersection type lvar-type)
280 type)))
281 (values (if (neq int *empty-type*)
283 lvar-type)
284 fun-name leaf asserted)))
285 (values lvar-type
286 (typecase use
287 (node
288 (node-source-form use))
290 '.anonymous.))))))
292 (defun callable-argument-lossage-kind (fun-name leaf soft hard)
293 (if (or (not leaf)
294 (and (not (memq (leaf-where-from leaf) '(:defined-here :declared-verify)))
295 (not (and (functional-p leaf)
296 (or (lambda-p leaf)
297 (functional-kind-eq leaf toplevel-xep))))
298 (or (not fun-name)
299 (not (info :function :info fun-name)))))
300 soft
301 hard))
303 (defun validate-test-and-test-not (combination)
304 (let* ((combination-name (lvar-fun-name (combination-fun combination) t))
305 (info (info :function :info combination-name)))
306 (when (and info
307 (ir1-attributep (fun-info-attributes info) call))
308 (let (test
309 test-not
310 (null-type (specifier-type 'null)))
311 (map-key-lvars (lambda (key value)
312 (when (and (not test)
313 (eq key :test))
314 (setf test value))
315 (when (and (not test-not)
316 (eq key :test-not))
317 (setf test-not value)))
318 (combination-args combination)
319 (global-ftype combination-name))
320 (when (and test
321 test-not
322 (eq (type-intersection null-type (lvar-type test))
323 *empty-type*)
324 (eq (type-intersection null-type (lvar-type test-not))
325 *empty-type*))
326 (note-lossage "~s: can't specify both :TEST and :TEST-NOT"
327 combination-name))))))
329 (defun function-designator-lvar-types (annotation)
330 (labels ((arg-type (arg)
331 (if (lvar-p arg)
332 (lvar-type arg)
333 (leaf-type arg)))
334 (sequence-element-type (type)
335 (cond ((array-type-p type)
336 (let ((elt-type (array-type-element-type type)))
337 (if (eq elt-type *wild-type*)
338 *universal-type*
339 elt-type)))
340 ((csubtypep type (specifier-type 'string))
341 (specifier-type 'character))
343 *universal-type*))))
344 (let ((deps (lvar-function-designator-annotation-deps annotation))
345 (arg-specs (lvar-function-designator-annotation-arg-specs annotation))
346 (result-specs (lvar-function-designator-annotation-result-specs annotation)))
347 (labels ((%process-arg (spec)
348 (destructuring-bind (nth-arg . options) spec
349 (let* ((arg (nth nth-arg deps))
350 (value-nth (getf options :value))
351 (key-nth (getf options :key))
352 (value (and value-nth
353 (nth (if (consp value-nth)
354 (car value-nth)
355 value-nth)
356 deps)))
357 (key (and key-nth (nth key-nth deps)))
358 (key-return-type (cond ((not key)
359 nil)
360 ((lvar-p key)
361 (multiple-value-bind (type name) (lvar-fun-type key)
362 (cond ((eq name 'identity)
363 nil)
364 ((fun-type-p type)
365 (single-value-type (fun-type-returns type)))
367 *universal-type*))))
369 *universal-type*)))
370 (type (cond (key-return-type)
371 ((getf options :sequence)
372 (sequence-element-type (arg-type arg)))
373 ((getf options :sequence-type)
374 (or (let* ((value (cond ((constant-p arg)
375 (constant-value arg))
376 ((and (lvar-p arg)
377 (constant-lvar-p arg))
378 (lvar-value arg))))
379 (type (and value
380 (careful-specifier-type value))))
381 (and type
382 (sequence-element-type type)))
383 *universal-type*))
385 (arg-type arg)))))
386 (cond (value-nth
387 (if (consp value-nth)
388 (let* ((option (nth (second value-nth) deps))
389 (option-p (third value-nth))
390 (false (or (not option)
391 (csubtypep (lvar-type option) (specifier-type 'null))))
392 (true (and option
393 (csubtypep (lvar-type option) (specifier-type '(not null)))))
394 (unknown (not (or true false))))
395 (cond (unknown
396 (type-union (lvar-type value)
397 type))
398 ((and true option-p)
399 (lvar-type value))
400 ((and false (not option-p))
401 (lvar-type value))
403 type)))
404 (if (lvar-p value)
405 (lvar-type value)
406 *universal-type*)))
408 type)))))
409 (process-arg (spec)
410 (if (eq (car spec) 'or)
411 (cons 'or (mapcar #'%process-arg (cdr spec)))
412 (%process-arg spec))))
413 (values
414 (if arg-specs
415 (mapcar #'process-arg arg-specs)
416 (fun-type-required
417 (lvar-function-designator-annotation-type annotation)))
418 (if result-specs
419 (process-arg result-specs)
420 (fun-type-returns (lvar-function-designator-annotation-type annotation))))))))
422 ;;; Return MIN, MAX, whether it contaions &optional/&key/&rest
423 (defun fun-type-arg-limits (type)
424 (if (fun-type-wild-args type)
425 (values nil nil)
426 (let* ((min (length (fun-type-required type)))
427 (max (and (not (or (fun-type-rest type)
428 (fun-type-keyp type)))
429 (+ min
430 (length (fun-type-optional type))))))
431 (values min max (or (fun-type-rest type)
432 (fun-type-keyp type)
433 (fun-type-optional type))))))
435 ;;; Should have enough types for N
436 (defun fun-type-n-arg-types (n type)
437 (let (result)
438 (flet ((pick (types)
439 (loop for type in types
440 do (push type result)
441 while (plusp (decf n)))))
442 (pick (fun-type-required type))
443 (pick (fun-type-optional type))
444 (loop with rest = (or (fun-type-rest type)
445 *universal-type*)
446 repeat n
447 do (push rest result)))
448 (nreverse result)))
450 (defun report-arg-count-mismatch (fun caller type arg-count
451 condition-type
452 &optional lossage-fun name)
453 (flet ((lose (format-control &rest format-args)
454 (if lossage-fun
455 (apply lossage-fun format-control format-args)
456 (warn condition-type :format-control format-control
457 :format-arguments format-args))
459 (callee ()
460 (or name
461 (nth-value 1 (lvar-fun-type fun))))
462 (caller ()
463 (or caller
464 (loop for annotation in (lvar-annotations fun)
465 when (typep annotation 'lvar-function-designator-annotation)
466 do (setf *compiler-error-context* annotation)
467 (return (lvar-function-designator-annotation-caller annotation))))))
468 (multiple-value-bind (min max optional) (fun-type-arg-limits type)
470 (cond
471 ((and (not min) (not max))
472 nil)
473 ((not optional)
474 (when (/= arg-count min)
475 (lose
476 "The function ~S is called~@[ by ~S~] with ~R argument~:P, but wants exactly ~R."
477 (callee) (caller)
478 arg-count min)))
479 ((< arg-count min)
480 (lose
481 "The function ~S is called~@[ by ~S~] with ~R argument~:P, but wants at least ~R."
482 (callee) (caller)
483 arg-count min))
484 ((not max)
485 nil)
486 ((> arg-count max)
487 (lose
488 "The function ~S called~@[ by ~S~] with ~R argument~:P, but wants at most ~R."
489 (callee) (caller)
490 arg-count max)))
491 (let ((positional (fun-type-positional-count type)))
492 (when (and (fun-type-keyp type)
493 (> arg-count positional)
494 (oddp (- arg-count positional)))
495 (lose
496 "The function ~s is called with odd number of keyword arguments."
497 (callee))))))))
499 (defun disable-arg-count-checking (leaf type arg-count)
500 (when (lambda-p leaf)
501 (let ((once nil))
502 ;; TODO: what if all destinations can disable arg count checking.
503 (map-leaf-refs (lambda (dest)
504 (declare (ignore dest))
505 (when (shiftf once t)
506 (return-from disable-arg-count-checking)))
507 leaf))
508 (multiple-value-bind (min max) (fun-type-arg-limits type)
509 (when (and min
510 (if max
511 (<= min arg-count max)
512 (<= min arg-count)))
513 (setf (lambda-lexenv leaf)
514 (make-lexenv :default (lambda-lexenv leaf)
515 :policy (augment-policy verify-arg-count 0
516 (lexenv-policy (lambda-lexenv leaf)))))))))
518 ;;; This can provide better errors and better handle OR types than a
519 ;;; simple type intersection.
520 (defun check-function-designator-lvar (lvar annotation)
521 (map-all-uses
522 (lambda (node)
523 (multiple-value-bind (type name leaf) (node-fun-type node)
524 (cond
525 ((and name
526 (valid-function-name-p name)
527 (memq (info :function :kind name) '(:macro :special-form)))
528 (compiler-warn "~(~a~) ~s where a function is expected"
529 (info :function :kind name) name))
530 ((fun-type-p type)
531 ;; If the destination is a combination-fun that means the function
532 ;; is called here and not passed somewhere else, there's no longer a
533 ;; need to check the function type, the arguments to the call will
534 ;; do the same job.
535 (unless (let* ((dest (lvar-dest lvar)))
536 (and (basic-combination-p dest)
537 (eq (basic-combination-fun dest) lvar)))
538 (multiple-value-bind (args results)
539 (function-designator-lvar-types annotation)
540 (let* ((condition (if (consp (lvar-uses lvar))
541 'simple-style-warning
542 (callable-argument-lossage-kind name
543 leaf
544 'simple-style-warning
545 'simple-warning)))
546 (type-condition (case condition
547 (simple-style-warning
548 'type-style-warning)
550 'type-warning)))
551 (caller (lvar-function-designator-annotation-caller annotation))
552 (arg-count (length args)))
553 (or (report-arg-count-mismatch lvar caller
554 type
555 arg-count
556 condition
558 name)
559 (let ((param-types (fun-type-n-arg-types arg-count type)))
560 (unless (and (eq caller 'reduce)
561 (eql arg-count 2))
562 (disable-arg-count-checking leaf type arg-count))
563 (block nil
564 ;; Need to check each OR seperately, a UNION could
565 ;; intersect with the function parameters
566 (labels ((hide-ors (current-or or-part)
567 (loop for spec in args
568 collect (cond ((eq spec current-or)
569 or-part)
570 ((typep spec '(cons (eql or)))
571 (sb-kernel::%type-union (cdr spec)))
573 spec))))
574 (check (arg param &optional
575 current-spec)
576 (when (eq (type-intersection param arg) *empty-type*)
577 (warn type-condition
578 :format-control
579 "The function ~S is called by ~S with ~S but it accepts ~S."
580 :format-arguments
581 (list
582 name
583 caller
584 (mapcar #'type-specifier (hide-ors current-spec arg))
585 (mapcar #'type-specifier param-types)))
586 (return t))))
587 (loop for arg-type in args
588 for param-type in param-types
589 if (typep arg-type '(cons (eql or)))
590 do (loop for type in (cdr arg-type)
591 do (check type param-type arg-type))
592 else do (check arg-type param-type)))))
593 (let ((returns (single-value-type (fun-type-returns type))))
594 (when (and (neq returns *wild-type*)
595 (neq returns *empty-type*)
596 (neq results *wild-type*)
597 (eq (type-intersection returns results) *empty-type*))
598 (warn type-condition
599 :format-control
600 "The function ~S called by ~S returns ~S but ~S is expected"
601 :format-arguments
602 (list
603 name
604 caller
605 (type-specifier returns)
606 (type-specifier results)))))))))))))
607 lvar)
610 (defun check-function-lvar (lvar annotation)
611 (let ((atype (lvar-function-annotation-type annotation)))
612 (multiple-value-bind (type name leaf) (lvar-fun-type lvar)
613 (when (fun-type-p type)
614 (let ((condition (callable-argument-lossage-kind name
615 leaf
616 'type-style-warning
617 'type-warning)))
618 (if (eq (lvar-function-annotation-context annotation) :mv-call)
619 (let* ((*compiler-error-context* annotation)
620 (max-accepted (nth-value 1 (fun-type-nargs (lvar-fun-type lvar))))
621 (min-args (fun-type-nargs atype)))
622 (when (and max-accepted
623 (> min-args max-accepted))
624 (warn condition
625 :format-control
626 "~@<MULTIPLE-VALUE-CALL calls ~a with with at least ~R ~
627 values when it expects at most ~R.~@:>"
628 :format-arguments (list name min-args
629 max-accepted))))
630 (let ((int (type-intersection type atype)))
631 (when (or (memq *empty-type* (fun-type-required int))
632 (and (eq (fun-type-returns int) *empty-type*)
633 (neq (fun-type-returns type) *empty-type*)
634 (not (and (eq (fun-type-returns atype) *empty-type*)
635 (eq (fun-type-returns type) *wild-type*)))))
636 (%compile-time-type-error-warn annotation
637 (type-specifier atype)
638 (type-specifier type)
639 (list name)
640 :condition condition)))))))))