@@ -33,7 +33,25 @@ impl<'e> Value<'e> {
3333 /// ```
3434 ///
3535 /// [`IntoLisp`]: trait.IntoLisp.html
36+ #[ inline]
3637 pub fn call < A > ( self , args : A ) -> Result < Value < ' e > > where A : IntoLispArgs < ' e > {
38+ // Safety: The returned value is explicitly protected.
39+ unsafe { self . call_unprotected ( args) . map ( |v| v. protect ( ) ) }
40+ }
41+
42+ /// Like [`call`], except that the returned `Value` is not protected against
43+ /// Emacs GC's [bug #31238], which caused [issue #2].
44+ ///
45+ /// # Safety
46+ ///
47+ /// This can be used as an optimization, in situations when the returned `Value` is unused,
48+ /// or when its usage is shorter than the lifespan of the underlying Lisp object.
49+ ///
50+ /// [`call`]: #method.call
51+ /// [bug #31238]: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=31238
52+ /// [issue #2]: https://github.com/ubolonton/emacs-module-rs/issues/2
53+ #[ allow( unused_unsafe) ]
54+ pub unsafe fn call_unprotected < A > ( self , args : A ) -> Result < Value < ' e > > where A : IntoLispArgs < ' e > {
3755 let env = self . env ;
3856 let mut lisp_args = args. into_lisp_args ( env) ?;
3957 let lisp_args: & mut [ emacs_value ] = lisp_args. borrow_mut ( ) ;
@@ -42,7 +60,7 @@ impl<'e> Value<'e> {
4260 // Safety:
4361 // - ptr comes from a locally-owned value.
4462 // - length is ensured to be valid by IntoLispArgs implementation.
45- unsafe_raw_call_value ! ( env, funcall, self . raw, length, ptr)
63+ unsafe_raw_call_value_unprotected ! ( env, funcall, self . raw, length, ptr)
4664 }
4765}
4866
@@ -78,12 +96,33 @@ impl Env {
7896 /// [`IntoLisp`]: trait.IntoLisp.html
7997 #[ inline]
8098 pub fn call < ' e , F , A > ( & ' e self , func : F , args : A ) -> Result < Value < ' _ > >
81- where
82- F : IntoLispCallable < ' e > ,
83- A : IntoLispArgs < ' e > ,
99+ where
100+ F : IntoLispCallable < ' e > ,
101+ A : IntoLispArgs < ' e > ,
84102 {
85103 func. into_lisp_callable ( self ) ?. call ( args)
86104 }
105+
106+ /// Like [`call`], except that the returned [`Value`] is not protected against
107+ /// Emacs GC's [bug #31238], which caused [issue #2].
108+ ///
109+ /// # Safety
110+ ///
111+ /// This can be used as an optimization, in situations when the returned [`Value`] is unused,
112+ /// or when its usage is shorter than the lifespan of the underlying Lisp object.
113+ ///
114+ /// [`call`]: #method.call
115+ /// [`Value`]: struct.Value.html
116+ /// [bug #31238]: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=31238
117+ /// [issue #2]: https://github.com/ubolonton/emacs-module-rs/issues/2
118+ #[ inline]
119+ pub unsafe fn call_unprotected < ' e , F , A > ( & ' e self , func : F , args : A ) -> Result < Value < ' _ > >
120+ where
121+ F : IntoLispCallable < ' e > ,
122+ A : IntoLispArgs < ' e > ,
123+ {
124+ func. into_lisp_callable ( self ) ?. call_unprotected ( args)
125+ }
87126}
88127
89128impl GlobalRef {
@@ -101,6 +140,26 @@ impl GlobalRef {
101140 {
102141 self . bind ( env) . call ( args)
103142 }
143+
144+ /// Like [`call`], except that the returned [`Value`] is not protected against
145+ /// Emacs GC's [bug #31238], which caused [issue #2].
146+ ///
147+ /// # Safety
148+ ///
149+ /// This can be used as an optimization, in situations when the returned [`Value`] is unused,
150+ /// or when its usage is shorter than the lifespan of the underlying Lisp object.
151+ ///
152+ /// [`call`]: #method.call
153+ /// [`Value`]: struct.Value.html
154+ /// [bug #31238]: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=31238
155+ /// [issue #2]: https://github.com/ubolonton/emacs-module-rs/issues/2
156+ #[ inline]
157+ pub unsafe fn call_unprotected < ' e , A > ( & ' e self , env : & ' e Env , args : A ) -> Result < Value < ' _ > >
158+ where
159+ A : IntoLispArgs < ' e > ,
160+ {
161+ self . bind ( env) . call_unprotected ( args)
162+ }
104163}
105164
106165// We can implement IntoLispArgs for IntoLisp types (after breaking up this implementation).
0 commit comments