ubolonton / emacs-module-rs Goto Github PK
View Code? Open in Web Editor NEWRust binding and tools for Emacs's dynamic modules
Rust binding and tools for Emacs's dynamic modules
👋 I saw that there was a new release (thanks!) but I don't think it picked up the bindgen
upgrade because the version of emacs_module
wasn't bumped from 0.12.0
. I think a bump to 0.12.1
in emacs_module
, and then for emacs
to 0.16.2
should get the fix released.
I'm curious if someone has made a Serde like serializer/deserializer for emacs-module-rs or if that's something that might be possible to implement?
I just ran through the hello, Emacs! tutorial and I have to say, I am blown away by how easy that was. Thanks so much for making what I was sure was going to be a hellish experience so effortless.
There're no LICENSE file.
It seems this repository is published under BSD-3-Clause.
Line 13 in 9a29b07
Please add LICENSE file to clarify the repository license.
I am just getting started with rust and since I am coming from elisp I figured this would be a good place to get started. Unfortunately I am not even able to begin building the greeting
example, things already fail when trying to build emacs
:
$ cargo build
Compiling emacs v0.12.3
error[E0425]: cannot find function `type_name` in module `any`
--> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/types/us er_ptr.rs:52:14
|
52 | any::type_name::<Self>()
| ^^^^^^^^^ not found in `any`
help: possible candidates are found in other modules, you can import them into scope
|
1 | use core::intrinsics::type_name;
|
1 | use std::intrinsics::type_name;
|
error[E0658]: use of unstable library feature 'maybe_uninit' (see issue #53491)
--> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs: 4:5
|
4 | use std::mem::MaybeUninit;
| ^^^^^^^^^^^^^^^^^^^^^
error[E0658]: use of unstable library feature 'maybe_uninit' (see issue #53491)
--> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.r s:111:26
|
111 | let mut symbol = MaybeUninit::uninit();
| ^^^^^^^^^^^^^^^^^^^
error[E0658]: use of unstable library feature 'maybe_uninit' (see issue #53491)
--> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.r s:112:24
|
112 | let mut data = MaybeUninit::uninit();
| ^^^^^^^^^^^^^^^^^^^
error[E0658]: use of unstable library feature 'maybe_uninit' (see issue #53491)
--> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.r s:218:22
|
218 | symbol: &mut MaybeUninit<emacs_value>,
| ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0658]: use of unstable library feature 'maybe_uninit' (see issue #53491)
--> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.r s:219:20
|
219 | data: &mut MaybeUninit<emacs_value>,
| ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0599]: no function or associated item named `uninit` found for type `std::mem::Maybe Uninit<_>` in the current scope
--> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.r s:111:39
|
111 | let mut symbol = MaybeUninit::uninit();
| -------------^^^^^^
| |
| function or associated item not found in `std::mem::MaybeUninit<_>`
error[E0599]: no function or associated item named `uninit` found for type `std::mem::MaybeUninit<_>` in the current scope
--> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:112:37
|
112 | let mut data = MaybeUninit::uninit();
| -------------^^^^^^
| |
| function or associated item not found in `std::mem::MaybeUninit<_>`
error[E0599]: no method named `assume_init` found for type `std::mem::MaybeUninit<*mut emacs_module::emacs_value_tag>` in the current scope
--> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:120:60
|
120 | symbol: unsafe { TempValue::new(symbol.assume_init()) },
| ^^^^^^^^^^^
error[E0599]: no method named `assume_init` found for type `std::mem::MaybeUninit<*mut emacs_module::emacs_value_tag>` in the current scope
--> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:121:56
|
121 | data: unsafe { TempValue::new(data.assume_init()) },
| ^^^^^^^^^^^
error[E0599]: no method named `assume_init` found for type `std::mem::MaybeUninit<*mut emacs_module::emacs_value_tag>` in the current scope
--> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:128:54
|
128 | tag: unsafe { TempValue::new(tag.assume_init()) },
| ^^^^^^^^^^^
error[E0599]: no method named `assume_init` found for type `std::mem::MaybeUninit<*mut emacs_module::emacs_value_tag>` in the current scope
--> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:129:58
|
129 | value: unsafe { TempValue::new(value.assume_init()) },
| ^^^^^^^^^^^
error[E0658]: use of unstable library feature 'maybe_uninit' (see issue #53491)
--> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:222:67
|
222 | unsafe_raw_call_no_exit!(self, non_local_exit_get, symbol.as_mut_ptr(), data.as_mut_ptr())
| ^^^^^^^^^^
error[E0658]: use of unstable library feature 'maybe_uninit' (see issue #53491)
--> /home/jonas/.cargo/registry/src/github.com-1ecc6299db9ec823/emacs-0.12.3/src/error.rs:222:86
|
222 | unsafe_raw_call_no_exit!(self, non_local_exit_get, symbol.as_mut_ptr(), data.as_mut_ptr())
| ^^^^^^^^^^
error: aborting due to 14 previous errors
Some errors occurred: E0425, E0599, E0658.
For more information about an error, try `rustc --explain E0425`.
error: Could not compile `emacs`.
To learn more, run the command again with --verbose.
I am such a beginner I have no idea yet how to proceed. Could you please help me out?
If I try to build the emacs-module-rs
directly I get the same errors, prefixed with some warnings:
$ bin/build
warning: couldn't execute `llvm-config --prefix` (error: No such file or directory (os error 2))
warning: set the LLVM_CONFIG_PATH environment variable to a valid `llvm-config` executable
Compiling emacs v0.12.3 (/home/jonas/git/pep/emacs-module/emacs-module-rs)
error[E0425]: cannot find function `type_name` in module `any`
--> src/types/user_ptr.rs:52:14
...
Some time I found it's usual to convert a Vec of type implemented IntoLisp
(e.g. Vec<String>
) trait to a Lisp list.
But env.list
just accept a type implemented IntoLispArgs
, so only AsRef<[Value]>
or tuple of type implemented IntoLisp
can be used.
I have to convert a Vec<String>
to Vec<Value>
and map
can't be used here since into_lisp
return a Result<Value>
.
Can you consider impl IntoLispArgs for AsRef<[T]>
where T: IntoLisp?
In the readme it says:
Note: This doesn't work on macOS 10.13+ (High Sierra and up). See Rust's issue #28794.
This seems outdated though, as the linked issue is already resolved.
Hi there, this is a really cool library and I'm excited to speed up my Emacs with Rust.
I'm having trouble figuring out how to send Elisp lists to my Rust functions. Something like this doesn't seem to compile:
#[emacs::defun]
fn mean(items: Vec<f64>) -> emacs::Result<f64> { ... }
as it complains that Vec
is missing a FromLisp
instance. I see that Elisp Vector
s are supported, but lists aren't the same. Am I missing something really basic?
Please and thanks.
I wannt to start a new thread and then call Elisp functions within that thread, but I found that Env does not implement Sync or Send. So is there anyway to archive my goal? Thanks.
More information about my use case:
I'd like to start a subprocess and read repeatedly its output in a loop in a thread, after reading in some data, I'll call a Elisp function to tell Emacs.
Writing a module still involves many ad-hoc scripts (test.sh
, load.sh
) and manual steps (e.g. renaming files).
There should be a cargo's subcommand that supports at least the following:
new
: Create a new module.test
: Run integration (ert
) tests.load
: Load the module into a running Emacs daemon. Reload if it's already loaded.package
: Create a correctly-named file that can be dropped into a directory in load-path
.I can't reconcile what was said on the mailing list about unloading leaving old functions laying around. The reloading here just loads the new module without unloading the old one, correct?
Perhaps the old module just needs to move itself out of the way and then call a closure that loads the new module, which can then patch itself in. This wouldn't require a shim module.
It seems the bash script integration can be done just as well from Elisp, without a script.
Edit: Issue mentioned in reloading was closed, though nobody linked to the details of what "fixed on MacOS" means
Hi, I'm trying to write some elisp bindings to a rust library and would like to benefit from live reloading.
Looking at the workflow shown in magit-libgit2, I've:
bin/load.sh
and modified the file names for my projectemacs-rs-module
to my dev dependenciescargo-watch
as shown in the aforementioned project's readmeBut it doesn't seem to work - find "$root" -iname "*emacs_rs_module*.$ext"
returns nothing.
Furthermore, I can't find any file that looks like *emacs_rs_module*.so
anywhere in my project (after a build of course).
Is this workflow just broken at the moment?
Maybe some build script machinery could be used to have a more ergonomic workflow?
I'm not sure I know enough about how emacs (and linux I guess) loads dynamic libraries to work on it myself, but I feel like it could possibly make this a bit more ergonomic (e.g. automate the whole .so
/.dylib
symlinking thing, generate elisp files that modify the load path and require the module).
It's mostly about generating a useful type name, for error reporting. Using typename crate is one option.
Hello,
Thanks for this project, I wanted to try a first FFI project so I wrote small bindings, and I was wondering how a more fleshed out implementation would look with macros and all so that's nice.
I'm currently wondering why you brought in source the emacs-module.h header ( here ) and only took the 25 version of it. It seems that it prevents users from using Emacs 26+ API.
The "naive" way I used was to use bindgen
with a simple wrapper.h
that is only
#include <emacs-module.h>
This way the build step automatically fetches and updates bindings for the currently included emacs header, and the compilation of the module will fail if the code uses an API that is absent on their system (emacs_env
gets aliased to the most recent emacs_env
type). What are the inconvenients of using such a method ?
I am using a plugin for nvim that leverages this library. When I try to run cargo build --release
, it fails on the emacs_module
build step:
Compiling emacs_module v0.10.0
error: unexpected close delimiter: `]`
--> <...>/.local/share/nvim/plugged/parinfer-rust/target/release/build/emacs_module-9fb3f11fcc6e3c12/out/emacs_module.rs:112:40
|
112 | # [ derive ( Copy , Clone ) ]; 16usize ] , }# [ test ]
| ^ unexpected close delimiter
error: aborting due to previous error
error: Could not compile `emacs_module`.
warning: build failed, waiting for other jobs to finish...
error: build failed
Looking at the library cargo.toml
file, it looks like the latest version is supplied:
emacs = "0.11.0"
I haven't seen any other issues about this, so I am wondering if there is some problem specific to my setup?
I should probably get off my butt and try implementing some of these myself eh? Haha. Anyway, this seems like another logical instance to have. Off the top of my head, it should be rendered into a Lisp cons-cell (i.e. (a . b)
).
Thanks again for the cool library. General question: should into_rust::<f64>()
succeed for non-float literals like 1
? Currently it fails, but I'm not sure what users should expect in general here.
Thoughts? Thanks you kindly.
ARG1
, ARG2
, like currently. This can be done by either:
advertised-signature-table
.usage:
to the end of the docstring.find-function
should be able to find the correct location in Rust source.
tar
archive).I followed the user guide and when try to (require 'greeting), the following message showed
ad-Advice-require: Loading file /home/hekinami/.emacs.d/elpa/helm-20180222.2124/helm-command.elc failed to provide feature ‘greeting’
And failed to require.
I tried to (load "greeting"), it returned t, but I cannot use the feature written in the modlue.
Thanks for your work on this package!
I am working on lsp-mode which at this stage of the project has issues with the performance of json parsing and I am investigating what are the options to implement it as a Rust emacs module and the potential optimization effect. I am rust beginner and in general, I do not have a lot of low-level programming knowledge and I have few questions regarding whether the whole approach will make sense.
Generally, do you think this approach is feasible? I know that the json parsing will be very fast in rust, but what about the code that will convert from rust data structures to emacs one? Do you think that running it in a separate thread and then reporting it to the emacs-lsp thread will work in case we want to parse several responses in parallel (e. g. using a thread pool to create async parse json function)?
I am playing around with exposing some of Rust's rayon
crate to Emacs. I've started with attempting to implement join
:
#[emacs::defun]
fn join<'a>(env: &Env, fa: Value<'a>, fb: Value<'a>) -> emacs::Result<()> {
env.message("racing: Entered join.")?;
let la = Lambda::new(fa);
let lb = Lambda::new(fb);
let a = || la.call();
let b = || lb.call();
env.message("racing: Invoking rayon...")?;
let (ra, rb) = rayon::join(a, b);
env.message(format!("ra: {}", ra.is_ok()))?;
env.message(format!("rb: {}", rb.is_ok()))?;
Ok(())
}
Ignoring the return type for the moment. After building and loading, I invoke it like this:
(racing-join (lambda () (message "Call from first lambda within Elisp!"))
(lambda () (message "Call from second lambda within Elisp!")))
Here, Lambda
is a wrapper type I've introduced to allow these evil trait instances:
unsafe impl<'a> Send for Lambda<'a> {}
unsafe impl<'a> Sync for Lambda<'a> {}
Otherwise the compiler complains of raw pointers (within Env
) being unSend
able.
My join
function "works" only if I replace b
with something that doesn't call lb
, the second lambda. Otherwise Emacs complete freezes as soon as I invoke the Lisp shown above. Poking around in the source code of your library, I suspect it has something to do with Env
. Having these unsafe
trait instances as I do might just be impossible.
Do you have any ideas as to why Emacs would entirely freeze (as opposed to just erroring) when I invoke racing-join
? Is Env
entirely thread-unsafe?
Thank you kindly.
A "String" in Elisp VM can be used to present a byte slice Vec<u8>
, not only a regular string. We can enable this conversion for the convenience. And we can deprecate utf-8-validation
flag because user should use Vec<u8>
to access a byte-slice and a string should always be valid utf-8.
This is useful to check if the user pressed C-g during a long running computation. From the documentation:
If your module includes potentially long-running code, it is a good
idea to check from time to time in that code whether the user wants to
quit, e.g., by typing ‘C-g’ (*note Quitting::). The following function,
which is available since Emacs 26.1, is provided for that purpose.-- Function: bool should_quit (emacs_env *ENV)
This function returns ‘true’ if the user wants to quit. In that
case, we recommend that your module function aborts any on-going
processing and returns as soon as possible.
Notice that this is only available since Emacs 26.1, so some runtime check for the Emacs version would probably be needed.
For instance, in this example
// Define a function callable by Lisp code.
#[defun]
fn say_hello(env: &Env, name: String) -> Result<Value<'_>> {
env.message(&format!("Hello, {}!", name))
}
I'd like to be able to run this code in Emacs with a highlighted region used as the value of name
. Is this possible?
There are other functions defined in emacs-module.h
such as vec_get
vec_size
. How to call these method?
Or would you like to impl trait FromLisp
for Vec?
IMO it's a good way to iterate a lisp vector in Rust. Would this cause any UB?
Hi,
I'm using emacs-module-rs
in some of my projects. I just made a small module that convert a json string to a lisp object.
You can see the code here, it's very small.
When a big json object is returned, it makes emacs crash. It doesn't happen with small objects.
It seems that the lisp object is not valid:
0 in terminate_due_to_signal of ../../src/emacs.c:369
1 in die of ../../src/alloc.c:7434
2 in XSTRING of ../../src/lisp.h:1395
3 in SDATA of ../../src/lisp.h:1446
4 in print_object of ../../src/print.c:1930
5 in print_vectorlike of ../../src/print.c:1713
6 in print_object of ../../src/print.c:2104
7 in print of ../../src/print.c:1150
8 in Fprin1 of ../../src/print.c:648
9 in print_error_message of ../../src/print.c:964
10 in Fcommand_error_default_function of ../../src/keyboard.c:1049
11 in funcall_subr of ../../src/eval.c:2901
12 in Ffuncall of ../../src/eval.c:2821
13 in call3 of ../../src/eval.c:2688
14 in cmd_error_internal of ../../src/keyboard.c:1004
15 in read_process_output_error_handler of ../../src/process.c:5803
16 in internal_condition_case_1 of ../../src/eval.c:1352
17 in read_and_dispose_of_process_output of ../../src/process.c:6008
18 in read_process_output of ../../src/process.c:5919
19 in wait_reading_process_output of ../../src/process.c:5616
20 in kbd_buffer_get_event of ../../src/keyboard.c:3822
21 in read_event_from_main_queue of ../../src/keyboard.c:2157
22 in read_decoded_event_from_main_queue of ../../src/keyboard.c:2221
23 in read_char of ../../src/keyboard.c:2808
24 in read_filtered_event of ../../src/lread.c:674
25 in Fread_event of ../../src/lread.c:786
26 in funcall_subr of ../../src/eval.c:2901
27 in Ffuncall of ../../src/eval.c:2821
28 in exec_byte_code of ../../src/bytecode.c:632
29 in funcall_lambda of ../../src/eval.c:3022
30 in Ffuncall of ../../src/eval.c:2823
31 in exec_byte_code of ../../src/bytecode.c:632
32 in funcall_lambda of ../../src/eval.c:3022
33 in Ffuncall of ../../src/eval.c:2823
34 in exec_byte_code of ../../src/bytecode.c:632
35 in funcall_lambda of ../../src/eval.c:3022
36 in Ffuncall of ../../src/eval.c:2823
37 in exec_byte_code of ../../src/bytecode.c:632
38 in funcall_lambda of ../../src/eval.c:3022
39 in Ffuncall of ../../src/eval.c:2823
40 in exec_byte_code of ../../src/bytecode.c:632
41 in funcall_lambda of ../../src/eval.c:3022
42 in Ffuncall of ../../src/eval.c:2823
43 in exec_byte_code of ../../src/bytecode.c:632
44 in funcall_lambda of ../../src/eval.c:3022
45 in Ffuncall of ../../src/eval.c:2823
46 in exec_byte_code of ../../src/bytecode.c:632
47 in funcall_lambda of ../../src/eval.c:3022
48 in Ffuncall of ../../src/eval.c:2823
49 in Fapply of ../../src/eval.c:2441
50 in funcall_subr of ../../src/eval.c:2876
51 in Ffuncall of ../../src/eval.c:2821
52 in exec_byte_code of ../../src/bytecode.c:632
53 in funcall_lambda of ../../src/eval.c:3022
54 in Ffuncall of ../../src/eval.c:2823
55 in call1 of ../../src/eval.c:2672
56 in timer_check_2 of ../../src/keyboard.c:4333
57 in timer_check of ../../src/keyboard.c:4395
58 in readable_events of ../../src/keyboard.c:3352
59 in get_input_pending of ../../src/keyboard.c:6808
60 in swallow_events of ../../src/keyboard.c:4135
61 in sit_for of ../../src/dispnew.c:5783
62 in read_char of ../../src/keyboard.c:2723
63 in read_key_sequence of ../../src/keyboard.c:9150
64 in command_loop_1 of ../../src/keyboard.c:1370
65 in internal_condition_case of ../../src/eval.c:1332
66 in command_loop_2 of ../../src/keyboard.c:1111
67 in internal_catch of ../../src/eval.c:1097
68 in command_loop of ../../src/keyboard.c:1090
69 in recursive_edit_1 of ../../src/keyboard.c:696
70 in Frecursive_edit of ../../src/keyboard.c:767
71 in main of ../../src/emacs.c:1720
0 in terminate_due_to_signal of ../../src/emacs.c:369
1 in emacs_abort of ../../src/sysdep.c:2426
2 in print_vectorlike of ../../src/print.c:1759
3 in print_object of ../../src/print.c:2104
4 in print of ../../src/print.c:1150
5 in Fprin1 of ../../src/print.c:648
6 in print_error_message of ../../src/print.c:964
7 in Fcommand_error_default_function of ../../src/keyboard.c:1049
8 in funcall_subr of ../../src/eval.c:2901
9 in Ffuncall of ../../src/eval.c:2821
10 in call3 of ../../src/eval.c:2688
11 in cmd_error_internal of ../../src/keyboard.c:1004
12 in read_process_output_error_handler of ../../src/process.c:5803
13 in internal_condition_case_1 of ../../src/eval.c:1352
14 in read_and_dispose_of_process_output of ../../src/process.c:6008
15 in read_process_output of ../../src/process.c:5919
16 in wait_reading_process_output of ../../src/process.c:5616
17 in sit_for of ../../src/dispnew.c:5824
18 in read_char of ../../src/keyboard.c:2723
19 in read_key_sequence of ../../src/keyboard.c:9150
20 in command_loop_1 of ../../src/keyboard.c:1370
21 in internal_condition_case of ../../src/eval.c:1332
22 in command_loop_2 of ../../src/keyboard.c:1111
23 in internal_catch of ../../src/eval.c:1097
24 in command_loop of ../../src/keyboard.c:1090
25 in recursive_edit_1 of ../../src/keyboard.c:696
26 in Frecursive_edit of ../../src/keyboard.c:767
27 in main of ../../src/emacs.c:1720
Am I doing something wrong in my code ?
Is it the conversion from rust to emacs that fails somewhere ?
Or do you think it's a bug in emacs ?
Note that git-tube also makes crash my emacs when the buffer contains lots of diffs
Consider the following code(it does not compile).
#[defun]
fn demo_func(env: &Env) {
let mut vec : Vec<Value<'_>> = Vec::with_capacity(1);
let xx = "xx".into_lisp(env).unwrap();
vec.push(xx);
return env.call("list", &vec);
}
I am a bit new to rust, but don't we need the following:
(or changing the defun
to handle that case).
impl <'e> IntoLisp<'e> for Result<Value<'e>>
{
fn into_lisp(self, env: &Env) -> Result<Value<'e>> {
return self;
}
}
Could we get #[defun]
to be able to take parameters to annotate for 'pure
and 'side-effect-free
? This can help the byte-compiler to make some optimizations. So something like:
#[defun(pure = true, side_effect_free = true)]
fn my_json_parsing(str: String) -> ... {
...
}
Often time, there's no initialization logic needed. Modules should be able to put #![emacs::module]
at the root of the crate, instead of this:
// So much boilerplate!
#[emacs::module]
fn init(_: &Env) -> Result<()> {
Ok(())
}
This needs to wait for Rust's issue #54726.
I'm trying to convert a rust library to be able to run in Emacs but I've run into an issue when trying to upgrade from 0.9.0
to 0.10.0+
. I get an error about rust being able to infer appropriate lifetimes for a struct. This code compiles perfectly fine in 0.9.0, but once you added the static lifetimes requirement to
user_ptrin
0.10.0`, Rust has refused to compile. Unfortunately, I haven't been able to figure out a work around and I was wondering if you had any suggestions for how I could resolve or work around this issue.
If you would like to see where this is happening in my code, you can find it here. But I've created a minimal program that recreates the same error message. Which can be found below:
I think the issue is because I've got a struct that has an explicit lifetime 'a
, and it's getting this lifetime from another user_ptr being passed into the function and rust is getting confused about how to ensure that the struct with lifetime 'a
has a static lifetime.
#[macro_use]
extern crate emacs;
use emacs::{Result};
use std::borrow::Cow;
struct Foo{
string: String
}
struct Bar <'a>{
sub_str: Cow<'a, str>,
}
#[defun(user_ptr)]
fn run_function(foo: &Foo)-> Result<Bar>{
Ok(Bar{
sub_str: Cow::from(foo.string),
})
}
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:15:17
|
15 | fn run_function(foo: &Foo)-> Result{
| ^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 14:1...
--> src/main.rs:14:1
|
14 | #[defun(user_ptr)]
| ^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:15:17
|
15 | fn run_function(foo: &Foo)-> Result{
| ^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the typeBar<'_>
will meet its required lifetime bounds
--> src/main.rs:15:30
|
15 | fn run_function(foo: &Foo)-> Result{
Most improvements from failure
are now incorporated into std::error::Error
.
thiserror
. This should be used to defined core error types.anyhow
. This is what modules should use.This is also the chance to drop the Send + Sync
requirement on core error types, and therefore the clunky TempValue
type.
See also:
The Emacs commit that fixes the issue is emacs-mirror/emacs@09d746dad3, which is not in 26.2. After it is released:
See #2 and https://debbugs.gnu.org/cgi/bugreport.cgi?bug=31238.
cargo build
Updating `git://mirrors.ustc.edu.cn/crates.io-index` index
Blocking waiting for file lock on package cache lock
Blocking waiting for file lock on package cache lock
Compiling emacs v0.10.1
error[E0658]: use of unstable library feature 'maybe_uninit'
--> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:4:5
|
4 | use std::mem::MaybeUninit;
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/53491
= help: add #![feature(maybe_uninit)] to the crate attributes to enable
error[E0658]: use of unstable library feature 'maybe_uninit'
--> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:111:26
|
111 | let mut symbol = MaybeUninit::uninit();
| ^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/53491
= help: add #![feature(maybe_uninit)] to the crate attributes to enable
error[E0658]: use of unstable library feature 'maybe_uninit'
--> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:112:24
|
112 | let mut data = MaybeUninit::uninit();
| ^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/53491
= help: add #![feature(maybe_uninit)] to the crate attributes to enable
error[E0658]: use of unstable library feature 'maybe_uninit'
--> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:213:22
|
213 | symbol: &mut MaybeUninit<emacs_value>,
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/53491
= help: add #![feature(maybe_uninit)] to the crate attributes to enable
error[E0658]: use of unstable library feature 'maybe_uninit'
--> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:214:20
|
214 | data: &mut MaybeUninit<emacs_value>,
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/53491
= help: add #![feature(maybe_uninit)] to the crate attributes to enable
error[E0658]: use of unstable library feature 'maybe_uninit'
--> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:120:60
|
120 | symbol: unsafe { TempValue::new(symbol.assume_init()) },
| ^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/53491
= help: add #![feature(maybe_uninit)] to the crate attributes to enable
error[E0658]: use of unstable library feature 'maybe_uninit'
--> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:121:56
|
121 | data: unsafe { TempValue::new(data.assume_init()) },
| ^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/53491
= help: add #![feature(maybe_uninit)] to the crate attributes to enable
error[E0658]: use of unstable library feature 'maybe_uninit'
--> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:128:54
|
128 | tag: unsafe { TempValue::new(tag.assume_init()) },
| ^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/53491
= help: add #![feature(maybe_uninit)] to the crate attributes to enable
error[E0658]: use of unstable library feature 'maybe_uninit'
--> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:129:58
|
129 | value: unsafe { TempValue::new(value.assume_init()) },
| ^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/53491
= help: add #![feature(maybe_uninit)] to the crate attributes to enable
error[E0658]: use of unstable library feature 'maybe_uninit'
--> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:216:60
|
216 | raw_call_no_exit!(self, non_local_exit_get, symbol.as_mut_ptr(), data.as_mut_ptr())
| ^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/53491
= help: add #![feature(maybe_uninit)] to the crate attributes to enable
error[E0658]: use of unstable library feature 'maybe_uninit'
--> /home/chino/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/emacs-0.10.1/src/error.rs:216:79
|
216 | raw_call_no_exit!(self, non_local_exit_get, symbol.as_mut_ptr(), data.as_mut_ptr())
| ^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/53491
= help: add #![feature(maybe_uninit)] to the crate attributes to enable
error: aborting due to 11 previous errors
intern
calls into the Lisp runtime. We can have emacs::sym::nil
, emacs::sym::t
. Modules will also be able to declare symbols they often use.unsafe
(even though the safety requirement is almost trivial currently).The biggest problem with this is that free_global_ref()
requires an emacs_env
, thus cannot be used directly in GlobalValue::drop()
(this is likely a mis-design in emacs-module
(BEAM's enif_release_resource doesn't need an env, for example)). There are 2 potential ways to solve this:
fn free(self, env: &Env)
, and just leak on normal drops. They are supposed to be long-lived anyway.Env::drop()
, once in a while.Currently Lisp functions are called using Env::call
. This has 2 drawbacks:
Value
. This requires a lot of .into_lisp(env)?
and .into_rust()
boilerplate.emacs_value
arguments, while most of the time the number of arguments is statically known.These can be solved by a macro. A basic version already exists as an internal macro: call_lisp!
.
According to https://rust-lang.github.io/api-guidelines/naming.html. I think we'd better to rename make_global_ref
to to_global_ref
to help user discover this API. What's your opinion?
mod_in_name
doesn't seem to have any effect, neither as parameter to #[module]
nor [defun]
, unless I'm misunderstanding its purpose.
E.g. a rust function
#[emacs::defun(mod_in_name = false)]
fn foo(_env: &emacs::Env, n: i64) -> emacs::Result<i64> {
Ok(n)
}
is defined in elisp as module-name-foo
instead of just foo
.
Notice that this is also true for the test cases of this project. See e.g. vec_size
in test-module/src/test_vector.rs
, which is called from elisp as t/vec-size
I'm working on a package that's passing a hashmap serialized as JSON back and forth between my rust library and Emacs. Unfortunately, this can be a pretty slow processes on large JSON objects. I was wondering if it's possible to pass in and return an Emacs hashmap directly?
Or are there alternative approaches for emulating a hashmap? Should I do something akin to this: https://github.com/ubolonton/emacs-module-rs/blob/master/test-module/src/hash_map.rs
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.