Subject: bug#44103: 28.0.50; [feature/native-comp] let-bound dynamic variables are optimized away

From: Kisaragi Hiu <[email-masked]>
Date: Wed, 21 Oct 2020 03:29:35 +0900

--text follows this line--

Some functions use a dynamic (special, marked with defvar) variable to 
change their behaviors. In a lexically bound file, those dynamic 
variable bindings are currently optimized away.

# Reproduction

Run this function with the interpreter:

```elisp
(defun k/test ()
   (with-current-buffer (get-buffer-create "testing")
     (erase-buffer)
     (let ((data '((a . "b") (c . "b")))
           (json-encoding-pretty-print t))
       (insert (json-encode data)))))
```

the contents of #<buffer "testing"> after running `(k/test)` should be

```
{
   "a": "b",
   "c": "b"
}
```

whereas if you native-compile the code, the contents would become

```
{"a":"b","c":"b"}
```

because `json-encoding-pretty-print` is optimized away (I think).

# Potential fix

Maybe it's possible to check if a variable is dynamic (special / defined 
with defvar) and don't optimize them away?

# Related

This is also the core issue behind #43536.

In #43536, the reason the infinite recursion happened is because 
`org-roam-db-build-cache` prevents it by let-binding `org-mode-hook` to 
nil. Doing so, it ensures it's not called again recursively in 
`org-mode-hook` even if a user misconfigures Org-roam.

In GNU Emacs 28.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 
3.24.23, cairo version 1.17.3)
  of 2020-10-20 built on MF-PC
Repository revision: d5791ba5feeb5500433ca43506dda13c7c67ce14
Repository branch: makepkg
Windowing system distributor 'The X.Org Foundation', version 11.0.12009000
System Description: Arch Linux

Configured using:
  'configure --prefix=/usr --sysconfdir=/etc --libexecdir=/usr/lib
  --localstatedir=/var --mandir=/usr/share/man --with-gameuser=:games
  --with-sound=alsa --with-modules --without-gconf --without-gsettings
  --with-nativecomp --with-x-toolkit=gtk3 --without-xaw3d
  --without-m17n-flt --with-cairo --without-compress-install
  'CFLAGS=-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -g
  -fuse-ld=gold' CPPFLAGS=-D_FORTIFY_SOURCE=2
  LDFLAGS=-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now'

Configured features:
XPM JPEG TIFF GIF PNG RSVG CAIRO SOUND GPM DBUS GLIB NOTIFY INOTIFY ACL
GNUTLS LIBXML2 FREETYPE HARFBUZZ LIBOTF ZLIB TOOLKIT_SCROLL_BARS GTK3
X11 XDBE XIM MODULES NATIVE_COMP THREADS LIBSYSTEMD JSON PDUMPER LCMS2

Important settings:
   value of $LANG: ja_JP.UTF-8
   value of $XMODIFIERS: @im=fcitx
   locale-coding-system: utf-8-unix

Major mode: Magit

Minor modes in effect:
   lisp-extra-font-lock-global-mode: t
   org-roam-bibtex-mode: t
   yas-global-mode: t
   yas-minor-mode: t
   pyvenv-mode: t
   dired-async-mode: t
   org-super-agenda-mode: t
   kisaragi-org-ret-create-new-link-mode: t
   magit-todos-mode: t
   global-git-gutter-mode: t
   kisaragi/auto-save-visited-mode: t
   global-magit-file-mode: t
   magit-auto-revert-mode: t
   global-git-commit-mode: t
   global-atomic-chrome-edit-mode: t
   rainbow-parinfer-mode: t
   smartparens-global-mode: t
   global-anzu-mode: t
   anzu-mode: t
   kisaragi/show-trailing-whitespace-mode: t
   global-whitespace-mode: t
   show-paren-mode: t
   global-so-long-mode: t
   savehist-mode: t
   minibuffer-depth-indicate-mode: t
   recentf-mode: t
   global-page-break-lines-mode: t
   didyoumean-mode: t
   editorconfig-mode: t
   which-key-mode: t
   global-evil-surround-mode: t
   evil-surround-mode: t
   evil-commentary-mode: t
   evil-goggles-mode: t
   global-evil-collection-unimpaired-mode: t
   evil-collection-unimpaired-mode: t
   global-undo-tree-mode: t
   shell-dirtrack-mode: t
   evil-mode: t
   evil-local-mode: t
   global-company-mode: t
   company-mode: t
   global-flycheck-mode: t
   counsel-projectile-mode: t
   projectile-mode: t
   ivy-rich-mode: t
   ivy-prescient-mode: t
   prescient-persist-mode: t
   counsel-mode: t
   ivy-mode: t
   delete-selection-mode: t
   el-patch-use-package-mode: t
   general-override-mode: t
   async-bytecomp-package-mode: t
   leaf-key-override-global-mode: t
   override-global-mode: t
   straight-use-package-mode: t
   straight-package-neutering-mode: t
   tooltip-mode: t
   global-eldoc-mode: t
   electric-indent-mode: t
   mouse-wheel-mode: t
   file-name-shadow-mode: t
   global-font-lock-mode: t
   font-lock-mode: t
   auto-composition-mode: t
   auto-encryption-mode: t
   auto-compression-mode: t
   buffer-read-only: t
   column-number-mode: t
   line-number-mode: t
   transient-mark-mode: t

Load-path shadows:
/home/kisaragi-hiu/.emacs.d/ext/company-org-block hides 
/home/kisaragi-hiu/.emacs.d/kisaragi/company-org-block
/home/kisaragi-hiu/.emacs.d/straight/build/map/map hides 
/usr/share/emacs/28.0.50/lisp/emacs-lisp/map
/home/kisaragi-hiu/.emacs.d/straight/build/let-alist/let-alist hides 
/usr/share/emacs/28.0.50/lisp/emacs-lisp/let-alist
/home/kisaragi-hiu/.emacs.d/straight/build/faceup/faceup hides 
/usr/share/emacs/28.0.50/lisp/emacs-lisp/faceup

Features:
(shadow sort mail-extr fix-ffap-on-iso8601 ffap emacsbug sendmail
kisaragi-log kisaragi-log-data kisaragi-log-vars vc-bzr vc-src vc-sccs
vc-svn vc-cvs vc-rcs vc vc-dispatcher bug-reference
evil-collection-helpful helpful trace info-look
evil-collection-elisp-refs elisp-refs loop mule-util typo
org-variable-pitch org-indent ol-eww ol-rmail ol-mhe ol-irc ol-info
ol-gnus nnselect nnir gnus-art mm-uu mml2015 mm-view mml-smime smime dig
gnus-sum gnus-group gnus-undo gnus-start gnus-dbus gnus-cloud nnimap
nnmail mail-source utf7 netrc nnoo gnus-spec gnus-int gnus-win
ol-docview evil-collection-doc-view doc-view jka-compr ol-bibtex ol-bbdb
ol-w3m mm-archive hideshow parinfer-ext highlight-numbers parent-mode
linum evil-collection-vc-git vc-git goto-addr magit-bookmark
evil-collection-bookmark bookmark pp kisaragi-preload-org-files
format-time-string-patch kisaragi-utau kisaragi-extra-functions
evil-collection-profiler profiler generic kisaragi-fcitx fcitx dbus
fcitx-autoloads kisaragi-desktop pollen-mode-autoloads
csharp-mode-autoloads plisp-mode-autoloads systemd-autoloads
csv-mode-autoloads ust-mode-autoloads ini-mode-autoloads
toml-mode-autoloads kisaragi-ledger ledger-mode ledger-check ledger-texi
ledger-test ledger-sort ledger-report ledger-reconcile ledger-occur
ledger-fonts ledger-fontify ledger-state ledger-complete ledger-schedule
ledger-init ledger-xact ledger-post ledger-exec ledger-navigate
ledger-context ledger-commodities ledger-regex evil-ledger-autoloads
flycheck-ledger flycheck-ledger-autoloads ledger-mode-autoloads
js2-mode-autoloads cakecrumbs cakecrumbs-autoloads lisp-extra-font-lock
lisp-extra-font-lock-autoloads bibtex-completion biblio biblio-download
biblio-dissemin biblio-ieee biblio-hal biblio-dblp biblio-crossref
biblio-arxiv timezone biblio-doi biblio-core hl-line parsebib
ivy-bibtex-autoloads org-ref-autoloads pdf-tools-autoloads
key-chord-autoloads hydra-autoloads lv-autoloads helm-bibtex-autoloads
htmlize-autoloads org-roam-bibtex orb-core orb-compat orb-utils
org-roam-bibtex-autoloads bibtex-completion-autoloads biblio-autoloads
biblio-core-autoloads parsebib-autoloads kisaragi-org-bibtex
yasnippet-snippets yasnippet highlight-indentation
evil-collection-flymake flymake-proc flymake help-fns elpy
find-file-in-project elpy-shell pyvenv evil-collection-eshell em-prompt
eshell elpy-profile elpy-django elpy-refactor ido evil-collection-custom
cus-edit cus-start cus-load elpy-autoloads pyvenv-autoloads
highlight-indentation-autoloads find-file-in-project-autoloads
web-mode-autoloads scribble-mode-autoloads racket-mode-autoloads
pos-tip-autoloads faceup-autoloads slime-autoloads macrostep-autoloads
janet-mode-autoloads flycheck-clj-kondo-autoloads cider-autoloads
sesman-autoloads queue-autoloads parseedn-autoloads parseclj-autoloads
clojure-mode-autoloads geiser-autoloads haskell-mode-autoloads
yaml-mode-autoloads vimrc-mode-autoloads meson-mode-autoloads
edit-indirect-autoloads fish-mode-autoloads company-shell-autoloads
audio-mode-autoloads mpv-autoloads git-modes gitignore-mode
gitconfig-mode conf-mode gitattributes-mode git-modes-autoloads
generic-x tup-mode-autoloads pacfiles-mode-autoloads awk-ward-autoloads
dired-show-readme-autoloads dired-collapse dired-collapse-autoloads
dired-narrow-autoloads dired-filter-autoloads peep-dired
peep-dired-autoloads diredfl-autoloads dired-open dired-hacks-utils
dired-x dired-open-autoloads dired-hacks-utils-autoloads
dired-git-info-autoloads dired-async dired-aux org-roam org-roam-link
org-roam-graph org-roam-doctor org-roam-db emacsql-sqlite3 emacsql
emacsql-compiler org-roam-dailies org-roam-capture org-roam-completion
org-roam-buffer org-roam-faces org-roam-macs org-roam-compat
org-roam-autoloads emacsql-sqlite3-autoloads emacsql-autoloads ox-reveal
ox-odt ox-latex ox-icalendar ox-html table ox-ascii ox-publish ox
ox-reveal-autoloads org-inline-video-thumbnails
org-inline-video-thumbnails-autoloads org-download org-attach org-id
org-download-autoloads ov org-super-agenda org-ql org-ql-autoloads
ov-autoloads org-super-agenda-autoloads org-msr-autoloads
org-variable-pitch-autoloads ob-shell ob-racket ob-lisp ob-python
smartparens-python evil-collection-python python tramp-sh docker-tramp
tramp-cache tramp tramp-loaddefs trampver tramp-integration files-x
tramp-compat ls-lisp ob-racket-autoloads
kisaragi-org-ret-create-new-link kisaragi-org-backlink org-capture
org-habit org-agenda org-refile kisaragi-org-link-photo dash-functional
kisaragi-org-link-diary company-org-block evil-org-agenda evil-org
org-element avl-tree evil-org-autoloads image-file image-converter
kisaragi-org evil-collection-magit-todos magit-todos pcre2el rxt
re-builder hl-todo smartparens-org org ob ob-tangle ob-ref ob-lob
ob-table ob-exp org-macro org-footnote org-src ob-comint org-pcomplete
org-list org-faces org-entities evil-collection-outline noutline outline
ob-emacs-lisp ob-core ob-eval org-table ol org-keys org-compat org-macs
org-loaddefs evil-collection-eww eww url-queue shr kinsoku svg xml
mm-url evil-collection-gnus gnus nnheader org-autoloads org-version
suggest-autoloads canrylog canrylog-evil canrylog-view canrylog-commands
canrylog-methods canrylog-metadata bibtex canrylog-read canrylog-parse
canrylog-file canrylog-types canrylog-cache canrylog-vars canrylog-utils
evil-collection-calendar cal-menu calendar cal-loaddefs
canrylog-autoloads trashed-autoloads vterm-toggle-autoloads
evil-collection-vterm vterm face-remap evil-collection-term term ehelp
vterm-module vterm-autoloads em-tramp em-smart esh-mode esh-cmd esh-ext
esh-opt esh-proc esh-io esh-arg esh-module esh-groups esh-util
magit-todos-autoloads pcre2el-autoloads hl-todo-autoloads git-gutter
git-gutter-autoloads evil-magit evil-magit-autoloads magit-libgit libgit
libegit2 magit-libgit-autoloads libgit-autoloads evil-collection-magit
magit-submodule magit-obsolete magit-blame magit-stash magit-reflog
magit-bisect magit-push magit-pull magit-fetch magit-clone magit-remote
magit-commit magit-sequence magit-notes magit-worktree magit-tag
magit-merge magit-branch magit-reset magit-files magit-refs magit-status
magit magit-repos magit-apply magit-wip magit-log which-func magit-diff
smerge-mode magit-core magit-autorevert autorevert filenotify
magit-margin magit-transient magit-process magit-mode git-commit
magit-git magit-section magit-utils crm evil-collection-log-edit
log-edit message rfc822 mml mml-sec evil-collection-epa epa gnus-util
rmail rmail-loaddefs mm-decode mm-bodies mm-encode mailabbrev gmm-utils
mailheader pcvs-util add-log with-editor server magit-autoloads
git-commit-autoloads with-editor-autoloads kisaragi-log-autoloads
docker-autoloads tablist-autoloads json-mode-autoloads
json-snatcher-autoloads json-reformat-autoloads docker-tramp-autoloads
speed-type-autoloads kisaragi-apps esup-autoloads buttercup-autoloads
atomic-chrome websocket bindat let-alist atomic-chrome-autoloads
websocket-autoloads rainbow-parinfer rainbow-delimiters
parinfer-autoloads parinfer evil-collection-ediff ediff ediff-merg
ediff-mult ediff-wind ediff-diff ediff-help ediff-init ediff-util
parinferlib names evil-collection-edebug edebug backtrace autoload
radix-tree smartparens-config smartparens-text smartparens-html
smartparens smartparens-autoloads helpful-autoloads elisp-refs-autoloads
loop-autoloads doom-monokai-pro-theme doom-themes doom-themes-base
doom-themes-ext-org doom-themes-autoloads spacemacs-theme-autoloads
monokai-theme-autoloads spaceline-config spaceline-segments spaceline
powerline powerline-separators powerline-themes spaceline-autoloads
powerline-autoloads evil-anzu anzu evil-anzu-autoloads anzu-autoloads
cangjie-autoloads yasearch-autoloads lacarte-autoloads
olivetti-autoloads typo-autoloads default-text-scale-autoloads
yasnippet-snippets-autoloads yasnippet-autoloads dumb-jump-autoloads
open-junk-file open-junk-file-autoloads mw-thesaurus-autoloads
define-word rng-nxml rng-valid rng-loc rng-uri rng-parse nxml-parse
rng-match rng-dt rng-util rng-pttrn nxml-ns nxml-mode nxml-outln
nxml-rap sgml-mode dom nxml-util nxml-enc xmltok define-word-autoloads
literate-calc-mode-autoloads disp-table whitespace paren
display-line-numbers so-long savehist mb-depth evil-collection-dashboard
dashboard dashboard-widgets time recentf tree-widget wid-edit
dashboard-autoloads page-break-lines page-break-lines-autoloads
link-hint-autoloads lsp-ui-autoloads lsp-mode-autoloads
markdown-mode-autoloads spinner-autoloads dash-functional-autoloads
migemo migemo-autoloads didyoumean didyoumean-autoloads editorconfig
editorconfig-autoloads which-key-replacements evil-collection-which-key
which-key which-key-autoloads format-all-autoloads
highlight-numbers-autoloads parent-mode-autoloads
multiple-cursors-autoloads rainbow-delimiters-autoloads
kisaragi-timestamp-highlight kisaragi-keybinds evil-textobj-line
evil-textobj-line-autoloads evil-textobj-syntax
evil-textobj-syntax-autoloads names-autoloads evil-numbers-autoloads
evil-easymotion evil-easymotion-autoloads avy-autoloads evil-surround
evil-surround-autoloads evil-commentary evil-commentary-integration
evil-commentary-autoloads evil-terminal-cursor-changer
evil-terminal-cursor-changer-autoloads evil-collection-diff-mode
diff-mode evil-goggles pulse evil-goggles-autoloads
evil-collection-unimpaired evil-collection-xref evil-collection-simple
evil-collection-package-menu evil-collection-occur
evil-collection-minibuffer evil-collection-ivy evil-collection-info
evil-collection-image image-mode exif evil-collection-ibuffer
evil-collection-help evil-collection-grep evil-collection-flycheck
evil-collection-elisp-mode evil-collection-dired evil-collection-compile
evil-collection-comint evil-collection-calc evil-collection-buff-menu
evil-collection annalist evil-collection-autoloads annalist-autoloads
evil evil-integration undo-tree diff evil-maps evil-commands reveal
flyspell evil-jumps evil-command-window evil-types evil-search evil-ex
shell pcomplete evil-macros evil-repeat evil-states evil-core
evil-common windmove rect evil-digraphs evil-vars evil-autoloads
goto-chg-autoloads undo-tree-autoloads company-prescient-autoloads
company-tng company-oddmuse company-keywords company-etags etags
fileloop generator company-gtags company-dabbrev-code company-dabbrev
company-files company-clang company-capf company-cmake company-semantic
company-template company-bbdb company company-autoloads flycheck-aspell
ispell flycheck-aspell-autoloads network-stream url-http mail-parse
rfc2231 rfc2047 rfc2045 mm-util ietf-drums mail-prsvr url-gw nsm rmc
url-cache url-auth epg epg-config flycheck-package package-lint imenu
finder lisp-mnt package browse-url url-handlers flycheck-jest flycheck
flycheck-jest-autoloads flycheck-package-autoloads
package-lint-autoloads flycheck-autoloads let-alist-autoloads
ag-autoloads counsel-projectile counsel-projectile-autoloads projectile
grep ibuf-ext ibuffer ibuffer-loaddefs thingatpt projectile-autoloads
pkg-info-autoloads epl-autoloads ivy-rich ivy-rich-autoloads
ivy-prescient ivy-prescient-autoloads prescient prescient-autoloads
counsel xref project dired dired-loaddefs compile text-property-search
comint ansi-color swiper ivy flx delsel ring ivy-overlay colir color
flx-autoloads counsel-autoloads swiper-autoloads ivy-autoloads
helm-autoloads helm-core-autoloads popup-autoloads handle
handle-autoloads edmacro kmacro el-patch el-patch-autoloads compdef
derived compdef-autoloads explain-pause-mode-autoloads opencc
opencc-autoloads kisaragi-constants kisaragi-helpers gnus-range uuidgen
calc-misc calc-ext calc calc-loaddefs calc-macs uuidgen-autoloads xmlgen
xmlgen-autoloads all-the-icons all-the-icons-faces data-material
data-weathericons data-octicons data-fileicons data-faicons
data-alltheicons memoize all-the-icons-autoloads memoize-autoloads
general general-autoloads xr xr-autoloads transient comp warnings rx
async-bytecomp advice format-spec transient-autoloads async
async-autoloads ts ts-autoloads request mail-utils url url-proxy
url-privacy url-expand url-methods url-history url-cookie url-domsuf
url-util url-parse auth-source eieio eieio-core eieio-loaddefs
password-cache json url-vars mailcap request-autoloads toml parse-time
iso8601 time-date toml-autoloads git git-autoloads edn peg edn-autoloads
peg-autoloads finder-inf ht ht-autoloads cl-seq f dash s f-autoloads
dash-autoloads s-autoloads a a-autoloads map loadhist map-autoloads
leaf-keywords leaf leaf-keywords-autoloads leaf-autoloads use-package
use-package-ensure use-package-delight use-package-diminish
use-package-bind-key bind-key easy-mmode use-package-core
use-package-autoloads bind-key-autoloads straight-x straight-autoloads
info cl-extra help-mode easymenu straight cl-macs gnutls puny
cl-loaddefs cl-lib mode-local find-func subr-x xdg seq byte-opt gv
bytecomp byte-compile cconv japan-util tooltip eldoc electric uniquify
ediff-hook vc-hooks lisp-float-type mwheel term/x-win x-win
term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode elisp-mode lisp-mode
prog-mode register page tab-bar menu-bar rfn-eshadow isearch timer
select scroll-bar mouse jit-lock font-lock syntax facemenu font-core
term/tty-colors frame minibuffer cl-generic cham georgian utf-8-lang
misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms
cp51932 hebrew greek romanian slovak czech european ethiopic indian
cyrillic chinese composite charscript charprop case-table epa-hook
jka-cmpr-hook help simple abbrev obarray cl-preloaded nadvice button
loaddefs faces cus-face pcase macroexp files window text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget
hashtable-print-readable backquote threads dbusbind inotify lcms2
dynamic-setting font-render-setting cairo move-toolbar gtk x-toolkit x
multi-tty make-network-process nativecomp emacs)

Memory information:
((conses 16 1200084 982251)
  (symbols 48 71635 46)
  (strings 32 297482 133418)
  (string-bytes 1 13024784)
  (vectors 16 132971)
  (vector-slots 8 3490498 997573)
  (floats 8 1596 3732)
  (intervals 56 12347 14133)
  (buffers 992 39))