I have a mostly working implementation of a 2D grid in rust:
use itertools::Itertools;
#[derive(Debug)]
pub struct Grid<T> {
width: usize,
height: usize,
items: Vec<T>,
}
impl<T> Grid<T> {
pub fn new(width: usize, height: usize, initializer: impl Fn() -> T) -> Self {
Self {
width,
height,
items: (0..height * width).map(|_| initializer()).collect(),
}
}
pub fn width(&self) -> usize {
self.width
}
pub fn height(&self) -> usize {
self.height
}
pub fn size(&self) -> usize {
self.width * self.height
}
pub fn get(&self, x: usize, y: usize) -> Result<&T, &str> {
if self.on_grid(x as isize, y as isize) {
Ok(&self.items[self.coordinate_to_index(x, y)])
} else {
Err("coordinate not on grid")
}
}
pub fn get_mut(&mut self, x: usize, y: usize) -> Result<&mut T, &str> {
if self.on_grid(x as isize, y as isize) {
let index = self.coordinate_to_index(x, y);
Ok(&mut self.items[index])
} else {
Err("coordinate not on grid")
}
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.items.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
self.items.iter_mut()
}
pub fn enumerate(&self) -> impl Iterator<Item = (usize, usize, &T)> {
self.items.iter().enumerate().map(|(index, item)| {
let (x, y) = self.index_to_coordinate(index);
(x, y, item)
})
}
pub fn enumerate_mut(&mut self) -> impl Iterator<Item = (usize, usize, &mut T)> {
self.items.iter_mut().enumerate().map(move |(index, item)| {
let (x, y) = self.index_to_coordinate(index);
(x, y, item)
})
}
pub fn neighbors(&self, x: usize, y: usize) -> impl Iterator<Item = (usize, usize, &T)> {
self.neighbor_indices(x, y)
.map(|(x, y)| (x, y, &self.items[self.coordinate_to_index(x, y)]))
}
fn coordinate_to_index(&self, x: usize, y: usize) -> usize {
y * self.width + x
}
fn index_to_coordinate(&self, index: usize) -> (usize, usize) {
let x = index % self.width;
let y = (index - x) / self.width;
(x, y)
}
fn neighbor_indices(&self, x: usize, y: usize) -> impl Iterator<Item = (usize, usize)> + '_ {
neighbor_offsets(2)
.map(move |item| (x as isize + item[0], y as isize + item[1]))
.filter(|&(x, y)| self.on_grid(x, y))
.map(|(dx, dy)| (dx as usize, dy as usize))
}
fn on_grid(&self, x: isize, y: isize) -> bool {
0 <= x && x < self.width as isize && 0 <= y && y < self.height as isize
}
}
fn neighbor_offsets(dimension: usize) -> impl Iterator<Item = Vec<isize>> {
(-1..1)
.map(|index| index as isize)
.combinations_with_replacement(dimension)
// skip zero offset
.filter(|items| !items.iter().all(|&item| item == 0))
}
Cargo.toml
[package]
name = "grid"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
itertools = "*"
However, with enumerate_mut() the compilation currently fails with
$ cargo build
Compiling either v1.8.0
Compiling itertools v0.10.5
Compiling grid v0.1.0 (/home/neumann/Projekte/grid)
error[E0505]: cannot move out of `self` because it is borrowed
--> src/lib.rs:64:47
|
63 | pub fn enumerate_mut(&mut self) -> impl Iterator<Item = (usize, usize, &mut T)> {
| - let's call the lifetime of this reference `'1`
64 | self.items.iter_mut().enumerate().map(move |(index, item)| {
| --------------------- ^^^^^^^^^^^^^^^^^^^^ move out of `self` occurs here
| |
| _________borrow of `self.items` occurs here
| |
65 | | let (x, y) = self.index_to_coordinate(index);
| | ---- move occurs due to use in closure
66 | | (x, y, item)
67 | | })
| |__________- returning this value requires that `self.items` is borrowed for `'1`
For more information about this error, try `rustc --explain E0505`.
error: could not compile `grid` due to previous error
warning: build failed, waiting for other jobs to finish...
I know that I could write the method index_to_coordinate() as a pure function, but I would like a solution, that uses the member function similarly to enumerate().
Can this be done? If so, how?
I would like a solution, that uses the member function similarly to enumerate(). Can this be done? If so, how?
It cannot be done. You cannot borrow self while self.items is mutably borrowed. Full stop. Consider this formulation that does work without a member function:
pub fn enumerate_mut(&mut self) -> impl Iterator<Item = (usize, usize, &mut T)> {
self.items.iter_mut().enumerate().map(|(index, item)| {
let x = index % self.width;
let y = (index - x) / self.width;
(x, y, item)
})
}
The only way this works is because of disjoint borrows, i.e. the compiler knows that .width and .height are completely separate objects from .items (and actually this only works in 2021 edition since the disjoint borrows happen both inside and outside the closure). If you use a member of self though, the compiler has lost that knowledge and has to consider that self can access items within that member function, which wouldn't be allowed since the mutable borrow earlier must stay exclusive. Using the member function in the enumerate() method works since immutable borrows can be shared.
Function signatures are the contracts that borrow-checking, type-checking, and type-inference build off of. If the member function has access to self, it must be assumed that it will access all of self. There is no syntax for partial-borrows across a function interface.
It cannot be done at all? Even if I used unsafe?
Even with unsafe, you are not allowed to violate Rust's borrowing rules, so you can't have a &Self while its .items is mutably borrowed. You can access the .width and .height but it must be done via a pointer: *const Self. Here's what that'd look like (tested with Miri on the playground):
pub fn enumerate_mut(&mut self) -> impl Iterator<Item = (usize, usize, &mut T)> {
let this = self as *const Self;
self.items.iter_mut().enumerate().map(move |(index, item)| {
let (x, y) = unsafe { Self::index_to_coordinate(this, index) };
(x, y, item)
})
}
unsafe fn index_to_coordinate(this: *const Self, index: usize) -> (usize, usize) {
let width = *std::ptr::addr_of!((*this).width);
let height = *std::ptr::addr_of!((*this).height);
let x = index % width;
let y = (index - x) / width;
(x, y)
}
However, I hope we can agree that this wouldn't be a member function anymore since it is lacking the self.index_to_coordinate syntax. Of course I'm not advocating you use this at all, it's just a demonstration that even going to the absurd it is not possible.
Just use a free function. :)
Related
I am still quite new to the advanced topics in rust, but for context, I am trying to implement a generic quadtree in rust.
With the method find_mut(&mut self,x,y) I want to traverse the quadtree to find the lowermost subtree containing that coordinate and return a mutable reference of it.
Quadtree Struct
pub struct QuadTree<T> {
x: i32,
y: i32,
dx: i32,
dy: i32,
leaf: bool,
subtrees: [Option<Box<Self>>; 4],
value: Option<T>,
}
Methods and functions
fn find_mut(&mut self, x: i32, y: i32) -> Result<&mut Self, &mut Self> {
let mut current = self;
loop {
// If we've arrived at a leaf return it as Ok
if current.leaf { // First borrow occurs here for some reason
return Ok(current);
}
// Getting the subtree that contains our coordinate
match current.mut_subtree_at(x, y) {
// Go a level deeper
Some(child) => current = child,
// Return an Err containing the lowest subtree that is sadly not a leaf
None => return Err(current),
}
}
}
fn subtree_id<'a>(&'a self, x: i32, y: i32) -> usize {
let mut child_id = 0;
if x >= self.x {
child_id += 1;
}
if y >= self.y {
child_id += 2;
}
child_id
}
#[inline(always)]
fn mut_subtree_at(&mut self, x: i32, y: i32) -> Option<&mut Self> {
self.subtrees[self.subtree_id(x, y)].as_deref_mut()
}
Error
error[E0499]: cannot borrow `*current` as mutable more than once at a time
--> src/quadtree.rs:128:36
|
115 | fn find_mut(&mut self, x: i32, y: i32) -> Result<&mut Self, &mut Self> {
| - let's call the lifetime of this reference `'1`
...
121 | return Ok(current);
| ----------- returning this value requires that `*current` is borrowed for `'1`
...
124 | match current.mut_subtree_at(x, y) {
| ---------------------------- first mutable borrow occurs here
...
128 | None => return Err(current),
| ^^^^^^^ second mutable borrow occurs here
How would you approach this problem. I am missing something about the way borrowing mutable references and lifetimes work?
While not ideal, here is a recursive version that compiles, but requires querying mut_subtree_at twice:
pub struct QuadTree<T> {
x: i32,
y: i32,
dx: i32,
dy: i32,
leaf: bool,
subtrees: [Option<Box<Self>>; 4],
value: Option<T>,
}
impl<T> QuadTree<T> {
fn find_mut(&mut self, x: i32, y: i32) -> Result<&mut Self, &mut Self> {
if self.leaf {
Ok(self)
} else {
if self.mut_subtree_at(x, y).is_some() {
// Go a level deeper
self.mut_subtree_at(x, y).unwrap().find_mut(x, y)
} else {
// Return an Err containing the lowest subtree that is sadly not a leaf
Err(self)
}
}
}
fn subtree_id<'a>(&'a self, x: i32, y: i32) -> usize {
let mut child_id = 0;
if x >= self.x {
child_id += 1;
}
if y >= self.y {
child_id += 2;
}
child_id
}
#[inline(always)]
fn mut_subtree_at(&mut self, x: i32, y: i32) -> Option<&mut Self> {
self.subtrees[self.subtree_id(x, y)].as_deref_mut()
}
}
To my understanding this works because .is_some() returns a bool, which is an owned value and therefore Rust can prove that at the time of Err(self) no reference is held to self any more.
It seems that the same principle also works for the iterative solution:
pub struct QuadTree<T> {
x: i32,
y: i32,
dx: i32,
dy: i32,
leaf: bool,
subtrees: [Option<Box<Self>>; 4],
value: Option<T>,
}
impl<T> QuadTree<T> {
fn find_mut(&mut self, x: i32, y: i32) -> Result<&mut Self, &mut Self> {
let mut current = self;
loop {
// If we've arrived at a leaf return it as Ok
if current.leaf {
return Ok(current);
}
// Getting the subtree that contains our coordinate
if current.mut_subtree_at(x, y).is_some() {
// Go a level deeper
current = current.mut_subtree_at(x, y).unwrap()
} else {
// Return an Err containing the lowest subtree that is sadly not a leaf
return Err(current);
}
}
}
fn subtree_id<'a>(&'a self, x: i32, y: i32) -> usize {
let mut child_id = 0;
if x >= self.x {
child_id += 1;
}
if y >= self.y {
child_id += 2;
}
child_id
}
#[inline(always)]
fn mut_subtree_at(&mut self, x: i32, y: i32) -> Option<&mut Self> {
self.subtrees[self.subtree_id(x, y)].as_deref_mut()
}
}
For more performance (meaning, if you don't want to call mut_subtree_at twice), you would have to override the borrow checker as this is obviously a false positive.
Luckily, there is the polonius-the-crab crate that is written for specifically the problem you ran into and hides the unsafe code in a safe and reliable manner.
Here is my first working version using polonius-the-crab:
use ::polonius_the_crab::prelude::*;
use polonius_the_crab::WithLifetime;
pub struct QuadTree<T> {
x: i32,
y: i32,
dx: i32,
dy: i32,
leaf: bool,
subtrees: [Option<Box<Self>>; 4],
value: Option<T>,
}
impl<T> QuadTree<T> {
fn find_mut(&mut self, x: i32, y: i32) -> Result<&mut Self, &mut Self> {
type SelfRef<K> = dyn for<'lt> WithLifetime<'lt, T = &'lt mut QuadTree<K>>;
let mut current = self;
loop {
// If we've arrived at a leaf return it as Ok
if current.leaf {
return Ok(current);
}
// Getting the subtree that contains our coordinate
match polonius::<SelfRef<T>, _, _, _>(current, |current| {
current.mut_subtree_at(x, y).ok_or(())
}) {
Ok(child) => {
// Go a level deeper
current = child;
}
Err((current, ())) => {
// Return an Err containing the lowest subtree that is sadly not a leaf
return Err(current);
}
}
}
}
fn subtree_id<'a>(&'a self, x: i32, y: i32) -> usize {
let mut child_id = 0;
if x >= self.x {
child_id += 1;
}
if y >= self.y {
child_id += 2;
}
child_id
}
#[inline(always)]
fn mut_subtree_at(&mut self, x: i32, y: i32) -> Option<&mut Self> {
self.subtrees[self.subtree_id(x, y)].as_deref_mut()
}
}
or this version, which is a little easier to understand as it uses polonius' macros:
use ::polonius_the_crab::prelude::*;
pub struct QuadTree<T> {
x: i32,
y: i32,
dx: i32,
dy: i32,
leaf: bool,
subtrees: [Option<Box<Self>>; 4],
value: Option<T>,
}
impl<T> QuadTree<T> {
pub fn find_mut(&mut self, x: i32, y: i32) -> Result<&mut Self, &mut Self> {
let mut current = self;
while !current.leaf {
// Getting the subtree that contains our coordinate.
// If no subtree exists, return Err(current).
current = current.mut_subtree_at(x, y)?;
}
// If we are at a leaf node with the coordinate, success!
Ok(current)
}
fn subtree_id<'a>(&'a self, x: i32, y: i32) -> usize {
let mut child_id = 0;
if x >= self.x {
child_id += 1;
}
if y >= self.y {
child_id += 2;
}
child_id
}
#[inline(always)]
fn mut_subtree_at(&mut self, x: i32, y: i32) -> Result<&mut Self, &mut Self> {
let mut current = self;
polonius!(
|current| -> Result<&'polonius mut Self, &'polonius mut Self> {
if let Some(child) = current.subtrees[current.subtree_id(x, y)].as_deref_mut() {
polonius_return!(Ok(child))
}
}
);
// Return the ownership of `self` back through the `Err()` value.
// This in conjunction with the `polonius!()` macro resolves the
// ownership problem.
Err(current)
}
}
I am trying to implement a Rust iterator similar to the following Haskell code:
primes :: [Integer]
primes = nextPrime [2..]
where
nextPrime (x:xs) = x : nextPrime (filter (notDivBy x) xs)
notDivBy a x = a `mod` x /= 0
My attempt so far (playground):
// as pointed out in a comment this can simply return Primes and not use Box::new
fn primes() -> Box<dyn Iterator<Item = usize>> {
Box::new(Primes::new())
}
struct Primes {
nums: Box<dyn Iterator<Item = usize>>,
}
impl Primes {
fn new() -> Self {
Primes { nums : Box::new(2..) }
}
}
impl Iterator for Primes {
type Item = usize;
fn next(&mut self) -> Option<usize> {
let prime = self.nums.next().unwrap();
self.nums = Box::new(self.nums.filter(move |&n|!divides(prime, n)));
//use std::borrow::BorrowMut;
//*self.nums.borrow_mut() = self.nums.filter(move |&n|!divides(prime, n));
Some(prime)
}
}
pub fn divides(d: usize, n: usize) -> bool {
n % d == 0
}
Unfortunately this runs into:
error[E0507]: cannot move out of `self.nums` which is behind a mutable reference
--> src/lib.rs:22:30
|
22 | self.nums = Box::new(self.nums.filter(move |&n| !divides(prime, n)));
| ^^^^^^^^^ move occurs because `self.nums` has type `Box<dyn Iterator<Item = usize>>`, which does not implement the `Copy` trait
For more information about this error, try `rustc --explain E0507`.
Or if you uncomment the alternative borrow_mut code:
error[E0277]: the trait bound `Box<(dyn Iterator<Item = usize> + 'static)>: BorrowMut<Filter<Box<dyn Iterator<Item = usize>>, [closure#src/lib.rs:24:52: 24:79]>>` is not satisfied
--> src/lib.rs:24:20
|
24 | *self.nums.borrow_mut() = self.nums.filter(move |&n|!divides(prime, n));
| ^^^^^^^^^^ the trait `BorrowMut<Filter<Box<dyn Iterator<Item = usize>>, [closure#src/lib.rs:24:52: 24:79]>>` is not implemented for `Box<(dyn Iterator<Item = usize> + 'static)>`
|
= help: the following implementations were found:
<Box<T, A> as BorrowMut<T>>
Frankly I am not even sure which of these two is closer to working.
I think you can cache the discovered primes:
fn primes() -> Primes {
Primes::new()
}
struct Primes {
nums: Box<dyn Iterator<Item = usize>>,
cache: Vec<usize>,
}
impl Primes {
fn new() -> Self {
Primes {
nums: Box::new(2..),
cache: Vec::new(),
}
}
}
impl Iterator for Primes {
type Item = usize;
fn next(&mut self) -> Option<usize> {
loop {
let num = self.nums.next().unwrap();
if self
.cache
.iter()
.take_while(|&&n| n*n <= num)
.all(|&p| !divides(p, num))
{
// we found a prime!
self.cache.push(num);
return Some(num);
}
}
}
}
pub fn divides(d: usize, n: usize) -> bool {
n % d == 0
}
fn main() {
println!("Primes: {:?}", primes().take(10).collect::<Vec<_>>());
}
Playground
I'm not really expert in Rust, but one (ugly) option is to replace self.nums with a dummy iterator so to be able to move the previous value.
fn next(&mut self) -> Option<usize> {
let prime = self.nums.next().unwrap();
// Ugly replacement with a dummy iterator value
let rest = std::mem::replace(&mut self.nums, Box::new(0..));
self.nums = Box::new(rest.filter(move |&n|!divides(prime, n)));
Some(prime)
}
This could be cleaner if we used an Option wrapper so that we can use None as the dummy value.
I finally figured out (with the help of the other answers) how to fix cannot move out of self.nums which is behind a mutable reference. The trick is to use &mut self.nums (and get rid of the Box).
fn primes() -> Primes {
Primes::new()
}
pub struct Primes {
nums: std::ops::RangeFrom<usize>,
cache: Vec<usize>,
}
impl Primes {
fn new() -> Self {
Primes {
nums: 2..,
cache: Vec::new(),
}
}
}
impl Iterator for Primes {
type Item = usize;
fn next(&mut self) -> Option<usize> {
let next_prime = (&mut self.nums)
.filter(|&n| {
self.cache
.iter()
.take_while(|&p| p * p <= n)
.all(|&p| !divides(p, n))
})
.next()
.unwrap();
self.cache.push(next_prime);
return Some(next_prime);
}
}
pub fn divides(d: usize, n: usize) -> bool {
n % d == 0
}
fn main() {
println!("Primes: {:?}", primes().take(10).collect::<Vec<_>>());
}
playground
I am running into issues with the borrow checker. I have a trait (Physics) which has getters (e.g. velocity) and setters (e.g. velocity_mut). It also has default methods accelerate and apply_force which uses the getters and setters. Why is it not good to have multiple borrows and what are the ways around this? Here's an error message:
13:18 rustc error cannot borrow `*self` as immutable because it is also borrowed as mutable
immutable borrow occurs here
12:11 rustc hint mutable borrow occurs here
12:11 rustc hint argument requires that `*self` is borrowed for `'static`
use gdnative::prelude::*;
// Running into issues with the borrow checker
trait Physics {
fn apply_force(&mut self, force: &mut Vector2, truncate: bool) {
let max_force = self.max_force();
if force.square_length() > max_force * max_force && truncate {
*force = force.normalize() * max_force;
}
let a = self.acceleration_mut();// Line 12
*a += *force / self.mass();//Line 13
self.accelerate(truncate);
}
fn accelerate(&mut self, truncate: bool) {
let v = self.velocity_mut();
*v += self.acceleration();
let max_speed = self.max_speed();
if v.square_length() > max_speed * max_speed && truncate {
*v = v.normalize() * max_speed;
}
}
fn velocity(&self) -> Vector2;
fn velocity_mut(&mut self) -> &mut Vector2;
fn acceleration(&self) -> Vector2;
fn acceleration_mut(&mut self) -> &mut Vector2;
fn max_speed(&self) -> f32;
fn max_speed_mut(&mut self) -> &mut f32;
fn max_force(&self) -> f32;
fn max_force_mut(&mut self) -> &mut f32;
fn mass(&self) -> f32;
fn mass_mut(&mut self) -> &mut f32;
}
struct Actor {
velocity: Vector2,
acceleration: Vector2,
max_speed: f32,
max_force: f32,
mass: f32
}
impl Physics for Actor {
fn velocity(&self) -> Vector2 {
self.velocity
}
fn velocity_mut(&mut self) -> &mut Vector2 {
&mut self.velocity
}
fn acceleration(&self) -> Vector2 {
self.acceleration
}
fn acceleration_mut(&mut self) -> &mut Vector2 {
&mut self.acceleration
}
fn mass(&self) -> f32 {
self.mass
}
fn mass_mut(&mut self) -> &mut f32 {
&mut self.mass
}
fn max_speed(&self) -> f32 {
self.max_speed
}
fn max_speed_mut(&mut self) -> &mut f32 {
&mut self.max_speed
}
fn max_force(&self) -> f32 {
self.max_force
}
fn max_force_mut(&mut self) -> &mut f32 {
&mut self.max_force
}
}
fn main() {
}
The reason you can't immutably borrow while there is also a mutable borrow is because otherwise it's possible that you could use the mutable borrow to modify the underlying data represented by the immutable borrow. And since immutable borrows are (obviously) not supposed to change, the borrow checker can't take the risk (even if you "know" the mutable borrow won't affect the immutable one).
In this case, I believe you can get around this by assigning self.mass() to a local before making the call to self.acceleration_mut()
let mass = self.mass();
let a = self.acceleration_mut();
*a += *force / mass;
Since mass is just a f32, it is copied on return so the immutable borrow will be done before the next line.
Since the "getters" return owned values, an alternative design is to use a local variable to compute the result, and assign it (via mutable reference) only at the end:
fn apply_force(&mut self, force: &mut Vector2, truncate: bool) {
let max_force = self.max_force();
if force.square_length() > max_force * max_force && truncate {
*force = force.normalize() * max_force;
}
let mut a = self.acceleration(); // Line 12
a += *force / self.mass(); //Line 13
*self.acceleration_mut() = a;
self.accelerate(truncate);
}
fn accelerate(&mut self, truncate: bool) {
let mut v = self.velocity();
v += self.acceleration();
let max_speed = self.max_speed();
if v.square_length() > max_speed * max_speed && truncate {
v = v.normalize() * max_speed;
}
*self.velocity_mut() = v;
}
Avoiding using local variables (e.g. if you assume that the underlying value is cloned, and that this is expensive), is tricky, because locking self via mutable reference for the whole length (or so) of a method is hard to manage.
title seems to be similar with Lifetime parameter for `Self` in trait signature but I create this new post because I believe root cause is different.
I have a trait like following
trait T<'a> {
fn new(y: &'a Y) -> Self where Self: Sized;
fn do_something(&self);
}
and want to write generic function that accept type X (which implements trait T<'a>), and reference of Y, then create dyn Trait T<'a>.
fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>>
my naive implementation is like this
fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>> {
return Box::new(I::new(y)) as Box<dyn T<'a>>;
}
then I got this error.
error[E0310]: the parameter type `I` may not live long enough
but parameter type I has constraint T<'a>, I don't figure out why this does not tell rustc to I::new(y) is alive after execution step go out from this function.
I suspect this is happened by I:new() returns Self, which has no lifetime annotation. but also I cannot find the way to give lifetime annotation to Self.
this is full example to cause the error.
struct Y {
z: i32
}
struct X<'a> {
y: &'a Y
}
trait T<'a> {
fn new(y: &'a Y) -> Self where Self: Sized;
fn do_something(&self);
}
impl<'a> T<'a> for X<'a> {
fn new(y: &'a Y) -> X<'a> {
return X::<'a> {
y: y
}
}
fn do_something(&self) {
println!("{}", self.y.z)
}
}
fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>> {
// error: the parameter type `I` may not live long enough
return Box::new(I::new(y)) as Box<dyn T<'a>>;
}
fn main() {
let y = Y { z: 123 };
{
let t = create_t_from_i::<X>(&y);
t.do_something()
}
}
if I remove definition of T::new and giving X::new to create_t_from_i as function pointer, code seems work (need to use T + 'a instead of T<'a>). but what essential difference is from 1st example?
struct Y {
z: i32
}
struct X<'a> {
y: &'a Y
}
trait T {
fn do_something(&self);
}
impl<'a> X<'a> {
fn new(y: &'a Y) -> X<'a> {
return X::<'a> {
y: y
}
}
}
impl<'a> T for X<'a> {
fn do_something(&self) {
println!("{}", self.y.z)
}
}
fn create_t_from_i<'a, I: T + 'a>(ctor: fn (y: &'a Y) -> I, y: &'a Y) -> Box<dyn T + 'a> {
// if passing constructor function directly and using annotation I: T + 'a, rustc does not complain.
let i = ctor(y);
return Box::new(i) as Box<dyn T + 'a>;
}
fn main() {
let y = Y { z: 123 };
{
let t = create_t_from_i::<X>(X::new, &y);
t.do_something()
}
}
anyone have an idea why this happens and how to make `rustc' happy?
regards.
fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>>
is implicitly the same as
fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn 'static + T<'a>>
which in turns means that I must also have a static lifetime to be able to store it in the returned box (i.e. you need a I: 'static bound).
To solve this, you can add another lifetime parameter for the lifetime of I, and use that in the returned boxed trait. This will work no matter what the lifetime of I actually is:
fn create_t_from_i<'a, 'b, I: 'b + T<'a>>(y: &'a Y) -> Box<dyn 'b + T<'a>>
// ^^^^^^^^^ ^^^^
Playground example
Any trait object has a lifetime annotations, which will implicitly be 'static.
Your function is thus:
fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn 'static + T<'a>>
The solution is to explicitly annotate your trait object's lifetime:
fn create_t_from_i<'a, I: 'a + T<'a>>(y: &'a Y) -> Box<dyn 'a + T<'a>>
I'm trying to implement a mean method for Iterator, like it is done with sum.
However, sum is Iterator method, so I decided to implement trait for any type that implements Iterator:
pub trait Mean<A = Self>: Sized {
fn mean<I: Iterator<Item = A>>(iter: I) -> f64;
}
impl Mean for u64 {
fn mean<I: Iterator<Item = u64>>(iter: I) -> f64 {
//use zip to start enumeration from 1, not 0
iter.zip((1..))
.fold(0., |s, (e, i)| (e as f64 + s * (i - 1) as f64) / i as f64)
}
}
impl<'a> Mean<&'a u64> for u64 {
fn mean<I: Iterator<Item = &'a u64>>(iter: I) -> f64 {
iter.zip((1..))
.fold(0., |s, (&e, i)| (e as f64 + s * (i - 1) as f64) / i as f64)
}
}
trait MeanIterator: Iterator {
fn mean(self) -> f64;
}
impl<T: Iterator> MeanIterator for T {
fn mean(self) -> f64 {
Mean::mean(self)
}
}
fn main() {
assert_eq!([1, 2, 3, 4, 5].iter().mean(), 3.);
}
Playground
The error:
error[E0282]: type annotations needed
--> src/main.rs:26:9
|
26 | Mean::mean(self)
| ^^^^^^^^^^ cannot infer type for `Self`
Is there any way to fix the code, or it is impossible in Rust?
like it is done with sum
Let's review how sum works:
pub fn sum<S>(self) -> S
where
S: Sum<Self::Item>,
sum is implemented on any iterator, so long as the result type S implements Sum for the iterated value. The caller gets to pick the result type. Sum is defined as:
pub trait Sum<A = Self> {
pub fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = A>;
}
Sum::sum takes an iterator of A and produces a value of the type it is implemented from.
We can copy-paste the structure, changing Sum for Mean and put the straightforward implementations:
trait MeanExt: Iterator {
fn mean<M>(self) -> M
where
M: Mean<Self::Item>,
Self: Sized,
{
M::mean(self)
}
}
impl<I: Iterator> MeanExt for I {}
trait Mean<A = Self> {
fn mean<I>(iter: I) -> Self
where
I: Iterator<Item = A>;
}
impl Mean for f64 {
fn mean<I>(iter: I) -> Self
where
I: Iterator<Item = f64>,
{
let mut sum = 0.0;
let mut count: usize = 0;
for v in iter {
sum += v;
count += 1;
}
if count > 0 {
sum / (count as f64)
} else {
0.0
}
}
}
impl<'a> Mean<&'a f64> for f64 {
fn mean<I>(iter: I) -> Self
where
I: Iterator<Item = &'a f64>,
{
iter.copied().mean()
}
}
fn main() {
let mean: f64 = [1.0, 2.0, 3.0].iter().mean();
println!("{:?}", mean);
let mean: f64 = std::array::IntoIter::new([-1.0, 2.0, 1.0]).mean();
println!("{:?}", mean);
}
You can do it like this, for example:
pub trait Mean {
fn mean(self) -> f64;
}
impl<F, T> Mean for T
where T: Iterator<Item = F>,
F: std::borrow::Borrow<f64>
{
fn mean(self) -> f64 {
self.zip((1..))
.fold(0.,
|s, (e, i)| (*e.borrow() + s * (i - 1) as f64) / i as f64)
}
}
fn main() {
assert_eq!([1f64, 2f64, 3f64, 4f64, 5f64].iter().mean(), 3.);
assert_eq!(vec![1f64, 2f64, 3f64, 4f64, 5f64].iter().mean(), 3.);
assert_eq!(vec![1f64, 2f64, 3f64, 4f64, 5f64].into_iter().mean(), 3.);
}
I used Borrow trait to support iterators over f64 and &f64.