From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Stephen Berman Newsgroups: gmane.emacs.bugs Subject: bug#12952: 24.3.50; Buggy handling of dependencies between customized variables Date: Wed, 21 Nov 2012 15:36:33 +0100 Message-ID: <87r4nnggzy.fsf@rosalinde.fritz.box> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1353508685 10594 80.91.229.3 (21 Nov 2012 14:38:05 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 21 Nov 2012 14:38:05 +0000 (UTC) To: 12952@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Wed Nov 21 15:38:14 2012 Return-path: Envelope-to: geb-bug-gnu-emacs@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 1TbBRL-0006P8-Gx for geb-bug-gnu-emacs@m.gmane.org; Wed, 21 Nov 2012 15:38:11 +0100 Original-Received: from localhost ([::1]:52901 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TbBRB-0004Pb-44 for geb-bug-gnu-emacs@m.gmane.org; Wed, 21 Nov 2012 09:38:01 -0500 Original-Received: from eggs.gnu.org ([208.118.235.92]:52942) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TbBQz-0004PQ-HI for bug-gnu-emacs@gnu.org; Wed, 21 Nov 2012 09:37:59 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TbBQy-0007Og-09 for bug-gnu-emacs@gnu.org; Wed, 21 Nov 2012 09:37:49 -0500 Original-Received: from debbugs.gnu.org ([140.186.70.43]:48205) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TbBQx-0007Oc-Sj for bug-gnu-emacs@gnu.org; Wed, 21 Nov 2012 09:37:47 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.72) (envelope-from ) id 1TbBSA-00037j-At for bug-gnu-emacs@gnu.org; Wed, 21 Nov 2012 09:39:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Stephen Berman Original-Sender: debbugs-submit-bounces@debbugs.gnu.org Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 21 Nov 2012 14:39:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 12952 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.135350869611948 (code B ref -1); Wed, 21 Nov 2012 14:39:01 +0000 Original-Received: (at submit) by debbugs.gnu.org; 21 Nov 2012 14:38:16 +0000 Original-Received: from localhost ([127.0.0.1]:58456 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.72) (envelope-from ) id 1TbBRP-00036d-7B for submit@debbugs.gnu.org; Wed, 21 Nov 2012 09:38:16 -0500 Original-Received: from eggs.gnu.org ([208.118.235.92]:49346) by debbugs.gnu.org with esmtp (Exim 4.72) (envelope-from ) id 1TbBRJ-00036O-RJ for submit@debbugs.gnu.org; Wed, 21 Nov 2012 09:38:12 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TbBQ0-0007GJ-GE for submit@debbugs.gnu.org; Wed, 21 Nov 2012 09:36:54 -0500 Original-Received: from lists.gnu.org ([208.118.235.17]:33252) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TbBQ0-0007GD-CO for submit@debbugs.gnu.org; Wed, 21 Nov 2012 09:36:48 -0500 Original-Received: from eggs.gnu.org ([208.118.235.92]:52760) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TbBPv-0003qV-Ei for bug-gnu-emacs@gnu.org; Wed, 21 Nov 2012 09:36:48 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TbBPt-0007F2-S5 for bug-gnu-emacs@gnu.org; Wed, 21 Nov 2012 09:36:43 -0500 Original-Received: from mailout-de.gmx.net ([213.165.64.23]:49221) by eggs.gnu.org with smtp (Exim 4.71) (envelope-from ) id 1TbBPt-0007Eg-Hj for bug-gnu-emacs@gnu.org; Wed, 21 Nov 2012 09:36:41 -0500 Original-Received: (qmail invoked by alias); 21 Nov 2012 14:36:38 -0000 Original-Received: from i59F5654F.versanet.de (EHLO rosalinde.fritz.box) [89.245.101.79] by mail.gmx.net (mp019) with SMTP; 21 Nov 2012 15:36:38 +0100 X-Authenticated: #20778731 X-Provags-ID: V01U2FsdGVkX1/+iBUEzRv+cAVeLe3TfRr/3D0obEXJTNgxViokLF UYAxvVOlsjRpAG User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (gnu/linux) X-Y-GMX-Trusted: 0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.13 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 140.186.70.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:67269 Archived-At: There's a bug in the handling of :set-after dependencies between customized variables; details below. But first, here's a recipe showing how the bug can have annoying side effects: 0. Ensure that ~/.emacs and ~/.emacs.d/ do not exist or are empty. 1. Start Emacs (*without* -Q or -q). 2. Type `M-x customize-create-theme RET', then create a theme, give it a name and save it (it is helpful if the theme is readily recognizable when enabled, e.g., default face with the strike-through attribute in red). 3. Type `M-x customize-option RET custom-file RET', change the Value Menu from `Your Emacs init file' to `File', type a file name in the editable field (choosing `~/.emacs' as the value, though rather perverse, also triggers the bug), then select the State `Save for Future Sessions'. 4. Type `M-x customize-themes RET', click the check-box next to the name of the theme created in step 2, then click the button 'Save Theme Settings'. Now the file named in step 3 should look like this (modulo the values): (custom-set-variables ;; custom-set-variables was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. '(custom-enabled-themes (quote (srb-test))) '(custom-file "~/.emacs-custom.el") '(custom-safe-themes (quote ("c0e0b5618faae142b2a62d45174f9a0db392ee7ca12accd705a3a524e3490adf" default)))) (custom-set-faces ;; custom-set-faces was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. ) 5. If you gave custom-file a different name than `~/.emacs' in step 3, now type `C-x C-f ~/.emacs RET' and insert this line: (load "~/.emacs-custom.el") where the file to be loaded is the one named in step 3, then save ~/.emacs. 6. Kill Emacs, then start it again (as in step 1). => The frame is split, with the *scratch* buffer above, the buffer *Custom Theme* below, containing the code of the theme created in step 2, and this is in the Minibuffer: "Loading a theme can run Lisp code. Really load? (y or n) ". If you type `y', you should see the theme created in step 2, and this in the Minibuffer: "Treat this theme as safe in future sessions? (y or n) ". Even if you answer `y', the next time you start Emacs (with the customizations made above), the same thing happens again, and every subsequent time. In other words, even though you tell Emacs to save the theme as safe, Emacs does not treat it as safe the next time it starts. The patch below fixes at least this specific problem, and I think it will work in most cases likely the arise in practice. To motivate it, here's my analysis of the bug's cause and this particular side effect: The sort predicate in custom-theme-set-variables, which checks for custom-dependencies between pairs of variables in the alphabetical list of customized variables, returns nil if there is no dependency, so the sort function leaves the order of such variables unchanged. Now sort assumes (as documented in the manual) that if a relation holds between two variables, it is transitive; this allows saving come computations. Thus, when the sort predicate etablishes that Rab and Rbc hold, it does not check Rac, but assumes it holds. However, while the variable-setting dependency relation is transitive, its dual is not: if var1 does not depend on var2 and var2 does not depend on var3, it does not follow that var1 does not depend on var3. Since the predicate checking is short-circuited, a dependency relation may be missed and the needed reordering of variables for setting omitted. AFAICT, that is what happens in the above case. Specifically, custom-enabled-themes depends on custom-safe-themes, but neither enters into a dependency relation with custom-file. Now the sort predicate checks this alphabetical list pairwise from the end: it finds no dependency between custom-safe-themes and custom-file, nor between custom-file and custom-enabled-themes, and assuming transitivity, does not check the relation between custom-safe-themes and custom-enabled-themes, missing their dependency and leaving them to be set in alphabetical order. Thus, when custom-enabled-themes is set, it calls load-theme, which checks whether srb-test is safe, but since custom-safe-themes has not yet been set, the check fails, resulting in the theme not being enabled and the Minibuffer questions being asked. If both questions are affirmed, srb-theme is enabled and added to custom-safe-themes (by customize-push-and-save) and both this and custom-enabled-themes are written to custom-file, which has already been set (in step 3 of the above recipe). Thus the customized variables are set correctly anew. But the next time Emacs is started the same steps are repeated, and so on, ad infinitum. I suspect a general solution to this problem would need to check all pairs of variables for dependencies in arbitrarily long lists, effectively circumventing sort's assumption of transivity; maybe it would be better not to use sort in that case. Anyway, I couldn't figure out a general solution, but I did come up with a simple fix that at least solves the case which prompted this bug report, by reordering pairs of variables, neither of which depends on the other. This makes the sort predicate continue checking, until it finds a dependency or exhausts the list. I haven't tried to test if this approach will works if there are dependency chains with more than one link, but I think such cases are unlikely in practice, so until a better solution is found, I think this fix improves on the current status. This bug also exists on the emacs-24 branch, but I guess it's been around since the Custom facility has recognized dependencies (but customizations that result in noticeable bad side effects, like the one reported here, are evidently quite rare). In GNU Emacs 24.3.50.4 (x86_64-suse-linux-gnu, GTK+ Version 3.4.4) of 2012-11-21 on rosalinde Bzr revision: 110970 rgm@gnu.org-20121121111740-z7q5jq8dmyh328a6 Windowing system distributor `The X.Org Foundation', version 11.0.11203000 System Description: openSUSE 12.2 (x86_64) Configured using: `configure '--without-toolkit-scroll-bars' 'CFLAGS=-g3 -O0'' 2012-11-21 Stephen Berman * custom.el (custom-theme-set-variables): Reorder variables if neither is a dependency of the other, in order to circumvent sort's assumption of transitivity, which may wrongly short-circuit the dependency check (bug#xxxx). === modified file 'lisp/custom.el' *** lisp/custom.el 2012-09-28 12:18:38 +0000 --- lisp/custom.el 2012-11-21 13:52:42 +0000 *************** *** 970,976 **** (cond ((and 1-then-2 2-then-1) (error "Circular custom dependency between `%s' and `%s'" sym1 sym2)) ! (2-then-1 nil) ;; 1 is a dependency of 2, so needs to be set first. (1-then-2) ;; Put minor modes and symbols with :require last. --- 970,980 ---- (cond ((and 1-then-2 2-then-1) (error "Circular custom dependency between `%s' and `%s'" sym1 sym2)) ! ;; Reorder 1 and 2 if neither is a dependency of the ! ;; other, in order to circumvent sort's assumption of ! ;; transitivity, which may wrongly short-circuit the ! ;; dependency check (bug#xxxx). ! ((not (or 1-then-2 2-then-1)) t) ;; 1 is a dependency of 2, so needs to be set first. (1-then-2) ;; Put minor modes and symbols with :require last.