-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to embed 2 types in user-ptr, when one of them is lifetime-constrained by the other? #21
Comments
user_ptr
causes issues on structs with lifetimes
The change was introduced in 0.10.0. Before that, the following code could be compiled, but would result in undefined behavior: struct Foo {
string: String,
}
struct Bar<'a> {
sub_str: Cow<'a, str>,
}
#[defun(user_ptr)]
fn make_foo(string: String) -> Result<Foo> {
Ok(Foo { string })
}
#[defun(user_ptr)]
fn make_bar(foo: &Foo) -> Result<Bar> {
Ok(Bar { sub_str: Cow::from(&foo.string) })
}
#[defun]
fn use_bar(bar: &Bar) -> Result<String> {
match bar.sub_str {
Cow::Borrowed(s) => Ok(s.to_owned()),
_ => unreachable!()
}
} The undefined behavior can be seen with something like the following: (let ((bar (let* ((foo (t/make-foo "abc abc"))
(bar-with-foo (t/make-bar foo)))
(message "before: %s" (t/use-bar bar-with-foo))
bar-with-foo)))
(garbage-collect)
(message "after : %s" (t/use-bar bar))) On my machine, it printed this: before: abc abc
after : < The problem is that It can show up more easily (with a segfault) if the type being referenced has more complex Making it work requires tracking the reference at run time, in a way that's visible to the GC. This can be done with an |
user_ptr
causes issues on structs with lifetimes
Awesome, this helped a lot. However, I have ran into one issue. I went with your first suggestion, using Rc, and I was able to make it a lot further! Rust was able to compile the library, but unfortunately when I tried to call my
type AliasedRequest<'a> = &'a SharedRequest;
#[defun(user_ptr, mod_in_name = false)]
fn execute(shared_request: AliasedRequest) -> Result<WrappedAnswer> {
let answer = parinfer::rc_process(&shared_request);
let wrapped_answer = unsafe{WrappedAnswer::new(shared_request.clone(), answer)};
Ok(wrapped_answer)
} I'm wondering if you have any ideas of why it's expecting an Rc and not getting one? Is it because it's a reference to an Rc and not an Rc in and of itself? If it helps, I was able to replicate this error here |
|
https://github.com/jpernst/rental is possibly a good option to avoid having to write |
That worked! Thank you so much for your patience in walking me through this. |
I tried out the The basic idea is similar to the #[macro_use]
extern crate rental;
#[derive(Debug, Clone)]
pub struct Foo {
string: String,
}
#[derive(Debug, Clone)]
pub struct Bar<'a> {
sub_str: Cow<'a, str>,
}
#[defun]
fn make_foo(string: String) -> Result<Rc<Foo>> {
Ok(Rc::new(Foo { string }))
}
rental! {
pub mod rental {
use std::rc::Rc;
#[rental(debug, clone, covariant)]
pub struct Bar {
foo: Rc<super::Foo>,
bar: super::Bar<'foo>,
}
}
}
#[defun(user_ptr)]
fn make_bar(foo: Value) -> Result<rental::Bar> {
let rc: &Rc<Foo> = foo.into_rust()?;
Ok(rental::Bar::new(
rc.clone(), |foo| Bar { sub_str: Cow::from(&foo.string) }
))
}
#[defun]
fn use_bar(bar: &rental::Bar) -> Result<String> {
match bar.suffix().sub_str {
Cow::Borrowed(s) => Ok(s.to_owned()),
_ => unreachable!()
}
} I'll update the guide with this soon. |
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
to0.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 withlifetime 'a
has a static lifetime.The text was updated successfully, but these errors were encountered: