Trying implement builder function with slice in rust - rust

I'm trying implement builder function:
extern crate debug;
use std::mem::size_of_val;
#[deriving(Show, PartialEq)]
pub struct A<'a> {
pub a: &'a [i64],
pub b: &'a str,
}
fn build<'a>() -> A<'a> {
return A { a: &[1,2,3], b: "test" };
}
fn main() {
let a = build();
println!("{} - {} - `{:?}`", a, size_of_val(&a), a);
}
But this give me next compile error:
/prsrc/main.rs:16:20: 16:27 error: borrowed value does not live long enough
/prsrc/main.rs:16 return A { a: &[1,2,3], b: "test" };
^~~~~~~
/prsrc/main.rs:15:25: 17:2 note: reference must be valid for the lifetime 'a as defined on the block at 15:24...
/prsrc/main.rs:15 fn build<'a>() -> A<'a> {
/prsrc/main.rs:16 return A { a: &[1,2,3], b: "test" };
/prsrc/main.rs:17 }
/prsrc/main.rs:16:5: 16:41 note: ...but borrowed value is only valid for the statement at 16:4; consider using a `let` binding to increase its lifetime
/prsrc/main.rs:16 return A { a: &[1,2,3], b: "test" };
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
I even try A { a: [1,2,3], b: "test" }, A { a: &'a [1,2,3], b: "test" } and std:rc:Rc::new(A { a: &[1,2,3], b: "test" }) but it still not work.
When I replace &[i64] to Vec<i64>:
fn build<'a>() -> A<'a> {
return A { a: vec![1,2,3], b: "test" };
}
all work right:
A { a: [1, 2, 3], b: test } - 40 - `A<'static>{a: collections::vec::Vec<i64>{len: 3u, cap: 4u, ptr: (0x7f1097426000 as *mut ())}, b: "test"}`
I little confused because as I understand &[i64] implementation should be similar to &str and str work when I replace &[i64] to Vec<i64>.
So how can I implement builder function for slice?

The hint that something is wrong with your lifetimes is here :
fn build<'a>() -> A<'a> { /* ... */ }
You have an output lifetime, but no input lifetime.
The only way this is possible is if your lifetime is in fact 'static, as otherwise it must be linked to at least one of the arguments, which defines it.
So your function should in fact be of type :
fn build() -> A<'static>
But here comes the problem : your two references must thus link to static storage. You are lucky, &str is a special case here. String literals ("test" in your case) are always in static storage. So far so good.
But &[1,2,3] is not in static storage. In fact, this shortcut is equivalent to :
let temp = [1,2,3];
return A { a: &temp, b: "test" };
and now, the lifetime issue becomes obvious.
The fix is quite simple : make the temporary variable explicitly 'static, like this :
fn build() -> A<'static> { //'
static temp: [i64, ..3] = [1,2,3];
return A { a: &temp, b: "test" };
}

Related

Rust: error: "returns a value referencing data owned by the current function"

I think this is a kind of common questions. I've read some solutions but my situation is a bit different...
It complains at line 8. However, I can't change the function signature of new_b as well as everything below the common line. They are all external packages.
So how can I design the function new_a to workaround?
fn main() {
new_a();
}
fn new_a() -> A<'static> {
let b = B {};
A { c: new_b(&b) }
}
pub struct A<'a> {
c: C<'a>,
}
// Below are exteral packages
fn new_b<'a>(b: &'a B) -> C<'a> {
C { b: &b }
}
pub struct B {}
pub struct C<'a> {
b: &'a B,
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=160e63f1300506472b7c1b0811b37453

How to wrap a struct in Rust?

For a project I'm using a library in Rust which has the following structs & traits:
struct Server<C> {
c: C,
}
impl<C: Customization> Server<C> {
type R<'s> = ResultImpl<'s, C> where Self: 's;
fn query<'s>(&mut self) -> Self::R<'_> {
ResultImpl(self)
}
}
trait Customization {}
struct CustomizationImpl<'c> {
reference: &'c Foo,
}
struct Foo {}
impl Customization for CustomizationImpl<'_> {}
trait Result {}
struct ResultImpl<'s, C: Customization>(&'s mut Server<C>);
impl<'s, C: Customization> Result for ResultImpl<'s, C> {}
I know, it seems a bit odd that a Result holds a reference to a Server, but let's assume we can't change the code.
Now I want a wrapper around the Server struct. What I tried was the following:
struct Wrapper<'w> {
server: Server<CustomizationImpl<'w>>,
}
impl<'w> Wrapper<'w> {
fn query(&'w mut self) -> ResultImpl<'_, CustomizationImpl> {
self.server.query()
}
}
But then, I can't call query() more than once on Wrapper.
//compiles
let mut server = Server {
c: CustomizationImpl { reference: &Foo {} }
};
server.query();
server.query();
//does not compile
let mut wrapper = Wrapper {
server: Server { c: CustomizationImpl { reference: &Foo {} } },
};
wrapper.query();
wrapper.query();
With error error[E0499]: cannot borrow wrapper as mutable more than once at a time. You can also find my code at https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=eebfd28e33f5354ffe9b46ff121f5f89
Is there any way to wrap the Server struct?
Your Wrapper lifetime declarations are wrong. Your code is actually equivalent to this one:
impl<'w> Wrapper<'w> {
fn query(&'w mut self) -> ResultImpl<'w, CustomizationImpl<'w>> {
self.server.query()
}
}
But the two lifetimes in the output type should be unrelated. And creating a value of a type such as &'x Type<'x> is known to cause issues such as yours.
The solution is something like this, having the lifetime of self and that of the generic separated:
impl<'w> Wrapper<'w> {
fn query<'s>(&'s mut self) -> ResultImpl<'s, CustomizationImpl<'w>> {
self.server.query()
}
}

How to store a field that only take reference to String created in `::new()`?

In the below code, how should I store a B field in A? Supposed that I can not change the definition of B.
As a newbie to Rust, I searched Google and most of them explain why the error happens. I could understand the compile error, but I can't figure out how to fix it. Or is it bad design to store the field in this case? Are there other solutions to this?
Thanks!
use std::io::Read;
struct A<'a> {
b: B<'a>,
}
impl<'a> A<'a> {
pub fn new(mut reader: impl Read) -> Self {
let mut s = String::new();
reader.read_to_string(&mut s);
let b = B { b: &s };
A { b }
}
}
// From 3rd party library, can't change the struct!
struct B<'a> {
b: &'a str,
}
fn main() {}
Well, in this case you need something to own the data. So just make your A to own it, and then have a method that creates the B type from A:
struct A {
s: String,
}
// From 3rd party library, can't change the struct!
struct B<'a> {
b: &'a str,
}
impl A {
pub fn new(mut reader: impl Read) -> Self {
let mut s = String::new();
reader.read_to_string(&mut s);
A { s }
}
fn as_b(&self) -> B {
B { b: &self.s }
}
}
Playground

Understanding Rust Borrowing/Stack Complications

This rust code doesn't work. Is there any detailed explanation for why?
It gives the error "cannot return reference to temporary value"
trait NonInherited {
fn get_type(&self) -> &str;
}
struct Inherited {
val: usize,
}
impl NonInherited for Inherited {
fn get_type(&self) -> &str {
return "inherited";
}
}
fn helper(list: &mut [usize; 2]) -> &'static dyn NonInherited {
// works
//return &Inherited {val: 3};
// does not work
return &Inherited {val: list[1]}; // Error is here
}
fn main() {
let mut a: [usize; 2] = [1, 7];
println!("{}", helper(&mut a).get_type());
}
My understanding is that Inherited { val: 3 } is a constant struct expression that is evaluated during compilation, however, Inherited { val: list[1] } is dynamic which is evaluated during runtime.
As described in Rust reference on Constant Evaluation, constant expressions do not cause any drop() to be run, thus, its value is not temporary.
The problem here is that the Inherited struct is created on the stack in the function helper, and then a reference to this stack-resident object is being returned. That's a problem because the lifetime of the Inherited struct is only for the scope of the helper function.
You can fix this by returning the created struct itself instead of a reference to it. Below is a simple working example, with some of the type names changed for clarity. Notice that the list variable does not need to be mut.
trait SomeTrait {
fn get_type(&self) -> &str;
}
struct SomeStruct {
val: usize,
}
impl SomeTrait for SomeStruct {
fn get_type(&self) -> &str {
return "overridden";
}
}
fn helper(list: &[usize; 2]) -> impl SomeTrait {
// works
return SomeStruct {val: list[1]};
}
fn main() {
let a: [usize; 2] = [1, 7];
let b = helper(&a);
println!("Type is {}", b.get_type());
}

Calling two member functions that work with different fields at the same time [duplicate]

It seems that if you borrow a reference to a struct field, the whole struct is considered borrowed. I've managed to isolate and example of what I want to do. I just want to get a "read-only" reference to a field in B to obtain some data and then modify another field of B. Is there a idiomatic Rust way to do this?
struct A {
i: i32,
}
struct B {
j: i32,
a: Box<A>,
}
impl B {
fn get<'a>(&'a mut self) -> &'a A {
&*self.a
}
fn set(&mut self, j: i32) {
self.j = j
}
}
fn foo(a: &A) -> i32 {
a.i + 1
}
fn main() {
let a = Box::new(A { i: 47 });
let mut b = B { a: a, j: 1 };
let a_ref = b.get();
b.set(foo(a_ref));
}
error[E0499]: cannot borrow `b` as mutable more than once at a time
--> src/main.rs:27:5
|
26 | let a_ref = b.get();
| - first mutable borrow occurs here
27 | b.set(foo(a_ref));
| ^ second mutable borrow occurs here
28 | }
| - first borrow ends here
It's a feature of the language. From the compiler point of view, there is no way for it to know that it's safe to call your set() function while a is borrowed via get().
Your get() function borrows b mutably, and returns a reference, thus b will remain borrowed until this reference goes out of scope.
You have several way of handling this:
Separate your two fields into two different structs
Move the code which needs to access both attribute inside a method of B
Make your attributes public, you will thus be able to directly get references to them
Compute the new value before setting it, like this:
fn main() {
let a = Box::new(A { i: 47 });
let mut b = B { a: a, j: 1 };
let newval = {
let a_ref = b.get();
foo(a_ref)
};
b.set(newval);
}
Expanding a bit on Levans' answer
Move the code which needs to access both attribute inside a method of B
That might look like this at a first pass:
impl B {
fn do_thing(&mut self) {
self.j = self.a.foo()
}
}
However, this hard-codes the call to foo. You could also accept a closure to allow this to be more flexible:
impl B {
fn update_j_with_a<F>(&mut self, f: F)
where
F: FnOnce(&mut A) -> i32,
{
self.j = f(&mut self.a)
}
}
// ...
b.update_j_with_a(|a| a.foo())
Separate your two fields into two different structs
This is also applicable when you have borrowed two disjoint subsets of attributes. For example:
struct A {
description: String,
name: String,
age: u8,
money: i32,
}
impl A {
fn update_description(&mut self) {
let description = &mut self.description;
*description = self.build_description()
// cannot borrow `*self` as immutable because `self.description` is also borrowed as mutable
}
fn build_description(&self) -> String {
format!(
"{} is {} years old and has {} money",
self.name,
self.age,
self.money
)
}
}
fn main() {}
Can be changed into
struct A {
description: String,
info: Info,
}
struct Info {
name: String,
age: u8,
money: i32,
}
impl A {
fn update_description(&mut self) {
let description = &mut self.description;
*description = self.info.build_description()
}
}
impl Info {
fn build_description(&self) -> String {
format!(
"{} is {} years old and has {} money",
self.name,
self.age,
self.money
)
}
}
fn main() {}
You can combine these two steps (and I'd say that it's better practice) and move the method onto the inner struct.

Resources