aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
authorStefan Monnier2020-11-25 14:49:55 -0500
committerStefan Monnier2020-11-25 14:49:55 -0500
commit1eb168fa9765ff62361b279a480388674e1b9745 (patch)
treeaeaef63ff37bcb083cc8d5d30a82c06225f21c88 /src/eval.c
parentd148d0259a4d3ad3da2f5bdf121e1f5836b3522b (diff)
downloademacs-1eb168fa9765ff62361b279a480388674e1b9745.tar.gz
emacs-1eb168fa9765ff62361b279a480388674e1b9745.zip
(defvar): Detect defining a variable currently lexically bound
* src/eval.c (lexbound_p): New function. (Finternal__define_uninitialized_variable): Use it.
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/eval.c b/src/eval.c
index 76708e6e7e2..3f9dcf6be6d 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -691,6 +691,45 @@ default_toplevel_binding (Lisp_Object symbol)
691 return binding; 691 return binding;
692} 692}
693 693
694/* Look for a lexical-binding of SYMBOL somewhere up the stack.
695 This will only find bindings created with interpreted code, since once
696 compiled names of lexical variables are basically gone anyway. */
697static bool
698lexbound_p (Lisp_Object symbol)
699{
700 union specbinding *pdl = specpdl_ptr;
701 while (pdl > specpdl)
702 {
703 switch ((--pdl)->kind)
704 {
705 case SPECPDL_LET_DEFAULT:
706 case SPECPDL_LET:
707 if (EQ (specpdl_symbol (pdl), Qinternal_interpreter_environment))
708 {
709 Lisp_Object env = specpdl_old_value (pdl);
710 if (CONSP (env) && !NILP (Fassq (symbol, env)))
711 return true;
712 }
713 break;
714
715 case SPECPDL_UNWIND:
716 case SPECPDL_UNWIND_ARRAY:
717 case SPECPDL_UNWIND_PTR:
718 case SPECPDL_UNWIND_INT:
719 case SPECPDL_UNWIND_INTMAX:
720 case SPECPDL_UNWIND_EXCURSION:
721 case SPECPDL_UNWIND_VOID:
722 case SPECPDL_BACKTRACE:
723 case SPECPDL_LET_LOCAL:
724 break;
725
726 default:
727 emacs_abort ();
728 }
729 }
730 return false;
731}
732
694DEFUN ("default-toplevel-value", Fdefault_toplevel_value, Sdefault_toplevel_value, 1, 1, 0, 733DEFUN ("default-toplevel-value", Fdefault_toplevel_value, Sdefault_toplevel_value, 1, 1, 0,
695 doc: /* Return SYMBOL's toplevel default value. 734 doc: /* Return SYMBOL's toplevel default value.
696"Toplevel" means outside of any let binding. */) 735"Toplevel" means outside of any let binding. */)
@@ -726,6 +765,15 @@ This is like `defvar' and `defconst' but without affecting the variable's
726value. */) 765value. */)
727 (Lisp_Object symbol, Lisp_Object doc) 766 (Lisp_Object symbol, Lisp_Object doc)
728{ 767{
768 if (!XSYMBOL (symbol)->u.s.declared_special
769 && lexbound_p (symbol))
770 /* This test tries to catch the situation where we do
771 (let ((<foo-var> ...)) ...(<foo-function> ...)....)
772 and where the `foo` package only gets loaded when <foo-function>
773 is called, so the outer `let` incorrectly made the binding lexical
774 because the <foo-var> wasn't yet declared as dynamic at that point. */
775 error ("Defining as dynamic an already lexical var");
776
729 XSYMBOL (symbol)->u.s.declared_special = true; 777 XSYMBOL (symbol)->u.s.declared_special = true;
730 if (!NILP (doc)) 778 if (!NILP (doc))
731 { 779 {