From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.devel Subject: Re: Can the byte-compiler check whether functions passed by name are defined? Date: Wed, 07 Aug 2013 13:34:41 -0400 Message-ID: References: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1375896896 13982 80.91.229.3 (7 Aug 2013 17:34:56 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 7 Aug 2013 17:34:56 +0000 (UTC) Cc: Sebastian Wiesner , emacs-devel@gnu.org To: Klaus-Dieter Bauer Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Aug 07 19:34:57 2013 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1V77dQ-0005tC-J9 for ged-emacs-devel@m.gmane.org; Wed, 07 Aug 2013 19:34:56 +0200 Original-Received: from localhost ([::1]:43539 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V77dQ-0003Il-6q for ged-emacs-devel@m.gmane.org; Wed, 07 Aug 2013 13:34:56 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:59551) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V77dI-0003Hj-C8 for emacs-devel@gnu.org; Wed, 07 Aug 2013 13:34:53 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1V77dD-0008Ar-74 for emacs-devel@gnu.org; Wed, 07 Aug 2013 13:34:48 -0400 Original-Received: from ironport2-out.teksavvy.com ([206.248.154.182]:42233) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V77dD-0008Am-1k for emacs-devel@gnu.org; Wed, 07 Aug 2013 13:34:43 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Av4EABK/CFFLd/Nq/2dsb2JhbABEvw4Xc4IeAQEEAVYjBQsLNBIUGA0kE4gLBsEtkQoDklqSIIFegxM X-IPAS-Result: Av4EABK/CFFLd/Nq/2dsb2JhbABEvw4Xc4IeAQEEAVYjBQsLNBIUGA0kE4gLBsEtkQoDklqSIIFegxM X-IronPort-AV: E=Sophos;i="4.84,565,1355115600"; d="scan'208";a="20861448" Original-Received: from 75-119-243-106.dsl.teksavvy.com (HELO pastel.home) ([75.119.243.106]) by ironport2-out.teksavvy.com with ESMTP/TLS/ADH-AES256-SHA; 07 Aug 2013 13:34:35 -0400 Original-Received: by pastel.home (Postfix, from userid 20848) id E95BF66AF2; Wed, 7 Aug 2013 13:34:41 -0400 (EDT) In-Reply-To: (Stefan Monnier's message of "Wed, 07 Aug 2013 11:21:16 -0400") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (gnu/linux) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 206.248.154.182 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:162468 Archived-At: >>>>> "Stefan" == Stefan Monnier writes: >> The patch only adds a single line of code to byte-compile-normal-call >> which calls defun byte-compile--higher-order--check-arguments. > But there's no normal call in (if a #'foo1 #'foo2), so how can this work? > Stefan I installed the patch below which checks that #'foo refers to a function that will exist. Stefan === modified file 'lisp/ChangeLog' --- lisp/ChangeLog 2013-08-07 16:37:04 +0000 +++ lisp/ChangeLog 2013-08-07 17:33:11 +0000 @@ -1,3 +1,11 @@ +2013-08-07 Stefan Monnier + + * emacs-lisp/bytecomp.el: Check existence of f in #'f. + (byte-compile-callargs-warn): Use `push'. + (byte-compile-arglist-warn): Ignore higher-order "calls". + (byte-compile-file-form-autoload): Use `pcase'. + (byte-compile-function-form): If quoting a symbol, check that it exists. + 2013-08-07 Eli Zaretskii * progmodes/dos.el (dos-font-lock-keywords): Rename LINUX to UNIX === modified file 'lisp/emacs-lisp/bytecomp.el' --- lisp/emacs-lisp/bytecomp.el 2013-06-19 07:35:00 +0000 +++ lisp/emacs-lisp/bytecomp.el 2013-08-07 17:20:38 +0000 @@ -1364,7 +1364,10 @@ ;; This is the first definition. See if previous calls are compatible. (let ((calls (assq name byte-compile-unresolved-functions)) nums sig min max) - (when calls + (setq byte-compile-unresolved-functions + (delq calls byte-compile-unresolved-functions)) + (setq calls (delq t calls)) ;Ignore higher-order uses of the function. + (when (cdr calls) (when (and (symbolp name) (eq (function-get name 'byte-optimizer) 'byte-compile-inline-expand)) @@ -1382,10 +1385,7 @@ name (byte-compile-arglist-signature-string sig) (if (equal sig '(1 . 1)) " arg" " args") - (byte-compile-arglist-signature-string (cons min max)))) - - (setq byte-compile-unresolved-functions - (delq calls byte-compile-unresolved-functions))))))) + (byte-compile-arglist-signature-string (cons min max))))))))) (defvar byte-compile-cl-functions nil "List of functions defined in CL.") @@ -3574,9 +3570,31 @@ ;; and (funcall (function foo)) will lose with autoloads. (defun byte-compile-function-form (form) - (byte-compile-constant (if (eq 'lambda (car-safe (nth 1 form))) - (byte-compile-lambda (nth 1 form)) - (nth 1 form)))) + (let ((f (nth 1 form))) + (when (and (symbolp f) + (byte-compile-warning-enabled-p 'callargs)) + (when (get f 'byte-obsolete-info) + (byte-compile-warn-obsolete (car form))) + + ;; Check to see if the function will be available at runtime + ;; and/or remember its arity if it's unknown. + (or (and (or (fboundp f) ; Might be a subr or autoload. + (byte-compile-fdefinition (car form) nil)) + (not (memq f byte-compile-noruntime-functions))) + (eq f byte-compile-current-form) ; ## This doesn't work + ; with recursion. + ;; It's a currently-undefined function. + ;; Remember number of args in call. + (let ((cons (assq f byte-compile-unresolved-functions))) + (if cons + (or (memq t (cdr cons)) + (push t (cdr cons))) + (push (list f t) + byte-compile-unresolved-functions))))) + + (byte-compile-constant (if (eq 'lambda (car-safe f)) + (byte-compile-lambda f) + f)))) (defun byte-compile-indent-to (form) (let ((len (length form)))