Subject: Re: 25.0.95; Regression in handling error caused by (string-match-p "." nil)

From: Stefan Monnier <[email-masked]>
Date: Wed, 13 Jul 2016 10:48:15 -0400

> Dynamically binding variables around some expression is standard Emacs
> Lisp programming technique, used all over the place.

For sure.  But it's risky and does cause problems in lots of corner
cases (which luckily for us are very rarely triggered).

E.g. we often use re-search-forward or string-match without binding
case-fold-search explicitly, so we depend on the particular setting it
happens to have.  In some cases it truly doesn't matter, while in others
it happens to work because in 99% of the cases the code is run with the
right setting.

Same for completion-ignore-case, completion-regexp-list,
inhibit-read-only, ...

That's just part of life in Elisp.
And I'm not sure what a real "fix" would look like.  E.g. for
minibuffer-setup-hook, we have minibuffer-with-setup-hook but it's
pretty hackish.

Instead, we just live with it and fix the corner cases that we actually
bump into.

> I also think that the "breaks a lot of Elisp code" part is at least a
> tad exaggerated.

Binding inhibit-changing-match-data to t will pretty much break any
function that uses match-beginning or match-end.  I think that counts as
"a lot of Elisp code".  Of course, we currently don't have any code that
binds inhibit-changing-match-data to t around calls to those functions,
except when the calls happen via the debugger.  But it could rear its
ugly head in other cases, e.g. if/when we make it possible for the
regexp-engine to run Elisp code (there can be various reasons to do
that.  Such as to setup the syntax-table property lazily, or to allow
the regexp primitives to be expanded in Elisp [I've a long term desire
to do so for the zero-length primitives such as \< ]) or to pause and
run timers or process filters.

> (defsubst string-match-p (regexp string &optional start)
>   "\
> Same as `string-match' except this function does not change the match data."
>   (condition-case err
>       (let ((inhibit-changing-match-data t))
> 	(string-match regexp string start))
>     (error (signal (car err) (cdr err)))))

That will still cause the same problems when debug-on-signal is non-nil.

        Stefan