-
Notifications
You must be signed in to change notification settings - Fork 42
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
PreparedGeometry lifetimes #177
Comments
Oof. It's pretty bad indeed. I think just holding the lifetime in a |
I might be wrong, but having lifetime of Let's say I'm writing some server and I need a component which tests if given point is inside a geometry and based on that it does something (and I want to encapsulate this implementation in a struct). With pub struct IsInsideTester {
// This fails because I need to provide lifetime.
prep: PreparedGeometry,
}
impl IsInsideTester {
pub fn new_from_wkt_file(path: &str) -> IsInsideTester {
let wkt = std::fs::read_to_string(path).unwrap();
let geom = Geometry::new_from_wkt(&wkt).unwrap();
let prep = PreparedGeometry::new(&geom).unwrap();
IsInsideTester { prep }
}
pub fn is_inside(&self, g: &Geometry) -> bool {
self.prep.contains(g).unwrap()
}
} But I can't do that. And I don't know how to work around this. Well, I do now, but it's something ugly and a bit dangerous too: pub struct IsInsideTester {
// `geom` must outlive `prep` !!!
geom: Geometry,
prep: PreparedGeometry<'static>,
}
impl IsInsideTester {
pub fn new_from_wkt_file(path: &str) -> IsInsideTester {
let wkt = std::fs::read_to_string(path).unwrap();
let geom = Geometry::new_from_wkt(&wkt).unwrap();
let prep: PreparedGeometry<'static> =
unsafe { std::mem::transmute(PreparedGeometry::new(&geom).unwrap()) };
IsInsideTester { geom, prep }
}
pub fn is_inside(&self, g: &Geometry) -> bool {
self.prep.contains(g).unwrap()
}
} With #176 I can do it easily because there are no lifetimes and pub struct IsInsideTester {
prep: PreparedGeometry,
}
impl IsInsideTester {
pub fn new_from_wkt_file(path: &str) -> IsInsideTester {
let wkt = std::fs::read_to_string(path).unwrap();
let geom = Geometry::new_from_wkt(&wkt).unwrap();
let prep = PreparedGeometry::new(geom).unwrap();
IsInsideTester { prep }
}
pub fn is_inside(&self, g: &Geometry) -> bool {
self.prep.contains(g).unwrap()
}
} With #175 (and the new pub struct IsInsideTester {
prep: PreparedGeometry<'static>,
}
impl IsInsideTester {
pub fn new_from_wkt_file(path: &str) -> IsInsideTester {
let wkt = std::fs::read_to_string(path).unwrap();
let geom = Geometry::new_from_wkt(&wkt).unwrap();
let prep = PreparedGeometry::new_owning(geom).unwrap();
IsInsideTester { prep }
}
pub fn is_inside(&self, g: &Geometry) -> bool {
self.prep.contains(g).unwrap()
}
} So this last solution is the most universal because it let me choose whether I want to be the owner of But the question is whether this complication in api is actually worth it. Someone needs to own the original |
I have noticed that lifetimes were removed from
PreparedGeometry
too, which is not correct becausePreparedGeometry
is holding a reference to the original non-prepared geometry.Test like this crashes with SIGSEGV:
There are actually tests testing this exact case. They are marked as
compile_fail
, but they are failing to compile for wrong reason (they use lifetimes, which were removed): https://github.com/georust/geos/blob/master/src/prepared_geometry.rs#L366-L410I'm not sure that the best solution is to introduce lifetime of
PreparedGeometry
again. The issue with such a lifetime is that it's impossible (AFAIK) to construct geometry and prepared geometry inside a function a return them both without using unsafe rust (which is not elegant and also is dangerous).I see 2 solutions to this problem:
Introduce lifetime of
PrepagedGeometry
again and addnew_owning
constructor which returnsPreparedGeometry<'static'>
so it can be moved around freely, if needed. (PreparedGeometry
is optionally owning the original geometry.) This is most universal but also least simple solution (lifetime + 2 different constructors). See PR fix: lifetime of geometry referenced by PreparedGeometry (version 1) #175Keep
PreparedGeometry
without a lifetime and make it always own the original geometry. It's unnecessarily cloning the geometry right now, but that could be improved. Overally I like this solution as it is simple. See PR fix: lifetime of geometry referenced by PreparedGeometry (version 2) #176 .Optionally I could keep the public api without any change and clone the geometry inside
PreparedGeometry
constructor.The text was updated successfully, but these errors were encountered: