Subject: bug#39390: 28.0.50; prettify-symbols-mode confuses display when start/end faces are different

From: Raphael 'kena' Poss <[email-masked]>
Date: Sun, 2 Feb 2020 15:45:46 +0100

When I am using the following substitution with prettify-symbols-mode,
everything works fine and the word "err" is substituted with "⊙":

(add-hook 'go-mode-hook
 (lambda ()
   (push '("error" . ?⊙) prettify-symbols-alist)
   ;; (push '("err != nil" . "⊙?") prettify-symbols-alist)
 ))

However if I then uncomment the second substitution for "err != nil":
all hell breaks loose: moving the cursor up and down around a source
line containing this text will mess up the display of the lines that
follow in a way that is sometimes irrecoverable.

The display bug is exacerbated (and thus easier to recognize/reproduce)
when global-hl-line-mode is set.

I have traced this down to substitutions where the font-lock face at the
beginning and the end of the symbol composition is different:

- replacing "String" is OK, replacing ".String()" is not
- replacing "func" is OK, replacing "func(" is not
- replacing "Fatal" is OK, replacing "t.Fatal" is not

This probably needs to be fixed somehow, either by preventing the
problem or by documenting the pitfall.

I would like to know if a workaround is available?

In GNU Emacs 28.0.50 (build 1, amd64-portbld-freebsd13.0)
Repository revision: e31287e
Repository branch: master
System Description: 13.0-CURRENT

Recent messages:
For information about GNU Emacs and the GNU system, type C-h C-a.

Configured using:
 'configure --disable-build-details --localstatedir=/var --with-sound=no
 --with-x-toolkit=no --without-cairo --without-dbus --without-gconf
 --without-gif --without-gsettings --without-imagemagick --without-jpeg
 --without-lcms2 --without-libotf --without-m17n-flt --without-png
 --without-rsvg --without-tiff --without-toolkit-scroll-bars --without-x
 --without-xim --without-xpm --without-xwidgets --enable-acl
 --without-cairo --without-dbus --without-gconf --without-gif
 --with-gnutls --without-gsettings --without-harfbuzz --without-jpeg
 --with-json --with-file-notification=kqueue --without-lcms2
 --without-m17n-flt --without-imagemagick --with-mailutils
 --with-modules --without-libotf --without-png
 --without-toolkit-scroll-bars --without-rsvg --with-threads
 --without-tiff --without-xft --without-xim --with-xml2 --without-xpm
 --without-xwidgets --with-x-toolkit=no --prefix=/usr/local
 --mandir=/usr/local/man --disable-silent-rules
 --infodir=/usr/local/share/emacs/info/
 --build=amd64-portbld-freebsd13.0 'CFLAGS=-O2 -pipe
 -fstack-protector-strong -isystem /usr/local/include
 -fno-strict-aliasing ' 'CPPFLAGS=-isystem /usr/local/include' 'LDFLAGS=
 -fstack-protector-strong -L/usr/local/lib ''

Configured features:
NOTIFY KQUEUE ACL GNUTLS LIBXML2 ZLIB MODULES THREADS JSON PDUMPER GMP

Important settings:
  value of $LC_COLLATE: C
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Go

Minor modes in effect:
  lsp-ui-mode: t
  lsp-ui-doc-mode: t
  lsp-ui-sideline-mode: t
  global-pretty-mode: t
  global-hl-line-mode: t
  show-paren-mode: t
  electric-pair-mode: t
  go-guru-hl-identifier-mode: t
  lsp-managed-mode: t
  lsp-mode: t
  flymake-mode: t
  yas-global-mode: t
  yas-minor-mode: t
  company-mode: t
  helm-mode: t
  helm--remap-mouse-mode: t
  projectile-mode: t
  global-magit-file-mode: t
  magit-file-mode: t
  magit-auto-revert-mode: t
  auto-revert-mode: t
  global-git-commit-mode: t
  async-bytecomp-package-mode: t
  shell-dirtrack-mode: t
  global-flycheck-mode: t
  flycheck-mode: t
  global-whitespace-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  electric-indent-mode: t
  global-prettify-symbols-mode: t
  prettify-symbols-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
  column-number-mode: t
  line-number-mode: t
  global-visual-line-mode: t
  visual-line-mode: t
  transient-mark-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug sendmail winner helm-command helm-elisp
helm-eval edebug backtrace helm-info mule-util lsp-ui lsp-ui-flycheck
lsp-ui-doc goto-addr lsp-ui-imenu lsp-ui-peek lsp-ui-sideline view
lsp-clients lsp-eslint lsp-verilog lsp-json lsp-csharp gnutls lsp-pwsh
lsp-terraform lsp-yaml lsp-vhdl lsp-haxe lsp-erlang lsp-fsharp
lsp-metals lsp-elm lsp-dart lsp-clojure lsp-go lsp-xml lsp-css
lsp-intelephense lsp-vetur lsp-html lsp-solargraph lsp-rust lsp-pyls lsp
company-oddmuse company-keywords company-etags company-gtags
company-dabbrev-code company-dabbrev company-files company-cmake
company-xcode company-clang company-semantic company-eclim
company-template company-bbdb company-capf company-anaconda
anaconda-mode pythonic python tramp-sh tramp tramp-loaddefs trampver
tramp-integration files-x tramp-compat parse-time iso8601 ls-lisp
term/tmux term/xterm xterm pretty-mode cl swiper ivy flx delsel colir
ivy-overlay ido hl-line paren elec-pair go-projectile vc-git go-rename
go-guru go-eldoc go-mode url url-proxy url-privacy url-expand
url-methods url-history url-cookie url-domsuf mailcap find-file ffap
etags fileloop generator company-lsp lsp-mode xref url-util tree-widget
wid-edit spinner network-stream nsm markdown-mode color noutline outline
lv inline ht f s ewoc em-glob esh-util dash-functional bindat
flymake-proc flymake mwheel warnings project yasnippet-snippets
yasnippet company pcase helm-mode helm-projectile helm-files helm-tags
helm-buffers helm-occur helm-grep helm-regexp helm-utils helm-locate
helm-help helm-types helm-config helm-easymenu helm helm-source
eieio-compat helm-multi-match helm-lib edmacro kmacro projectile grep
compile ibuf-ext ibuffer ibuffer-loaddefs thingatpt 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 imenu magit-diff
smerge-mode diff diff-mode magit-core magit-autorevert autorevert
filenotify magit-margin magit-transient magit-process magit-mode
git-commit transient magit-git magit-section magit-utils crm log-edit
easy-mmode message rmc puny dired dired-loaddefs format-spec rfc822 mml
mml-sec epa derived epg epg-config gnus-util rmail rmail-loaddefs
text-property-search time-date mm-decode mm-bodies mm-encode mail-parse
rfc2231 rfc2047 rfc2045 mm-util ietf-drums mail-prsvr mailabbrev
mail-utils gmm-utils mailheader pcvs-util add-log with-editor cl-extra
async-bytecomp advice async shell pcomplete comint ring server flycheck
regexp-opt ansi-color find-func help-mode rx dash disp-table whitespace
info tool-bar package easymenu browse-url url-handlers url-parse
auth-source cl-seq eieio eieio-core cl-macs eieio-loaddefs
password-cache json subr-x map url-vars seq byte-opt gv bytecomp
byte-compile cconv cl-loaddefs cl-lib tooltip eldoc electric uniquify
ediff-hook vc-hooks lisp-float-type tabulated-list replace newcomment
text-mode elisp-mode lisp-mode prog-mode register page tab-bar menu-bar
rfn-eshadow isearch timer select 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 loaddefs button faces cus-face macroexp files
text-properties overlay sha1 md5 base64 format env code-pages mule
custom widget hashtable-print-readable backquote threads kqueue
multi-tty make-network-process emacs)

Memory information:
((conses 16 382129 48543)
 (symbols 48 30567 1)
 (strings 32 115055 9348)
 (string-bytes 1 3699508)
 (vectors 16 54044)
 (vector-slots 8 769489 36090)
 (floats 8 286 445)
 (intervals 56 16026 8087)
 (buffers 1000 20))

-- 
Raphael 'kena' Poss