This question already has answers here:
Return local String as a slice (&str)
(7 answers)
Is there any way to return a reference to a variable created in a function?
(5 answers)
Closed 5 years ago.
I have defined two structs and a function in my Rust program, in which I am implementing my own linear algebra. While doing so I stumbled onto a gap in my knowledge of lifetimes in Rust. To my understanding, a lifetime annotation simply tells the compiler that one input variable must live at least as long as output variable.
But now I am actually trying to tell the compiler that my output is NOT related to the input. Sure, I take in references, but the new struct is constructed by creating new slices, and filling these with new values (f64).
So, my idea was that I have two inputs, whose lifetimes can be unrelated when the function is called, and a third one, saying it is unrelated to the inputs, because a new struct with no references to the old one is created. (See code below).
Sadly, this returns an error, and to be perfectly honest, I have no idea what it really means. I mean, I can read the words and know these words, but it doesn't really fit in the idea of lifetimes I have in my head. I need a fresh new look on lifetimes, or someone to point out to me what I understood wrong.
What I get from this is that it complains that my output is not related/constrained to the inputs, which is precisely what I want!
error[E0207]: the lifetime parameter `'c` is not constrained by the impl trait, self type, or predicates
--> src/mat.rs:199:14
|
199 | impl<'a, 'b, 'c
| ^^ unconstrained lifetime parameter
error[E0207]: the lifetime parameter `'c` is not constrained by the impl trait, self type, or predicates
I do not require any information on how to properly implement a matrix multiplication, or matrices, because I am toying around to learn Rust. I need an answer that shows me what I misunderstood about Rust.
The two structs:
pub struct ColVector<'a> {
values: &'a [f64],
}
pub struct Matrix<'a> {
values: &'a [&'a [f64]],
shape: (usize, usize) // Tuple containing size. First value is rows, second is columns
}
The implementation over-ride of the *-operator (I have 3 other ones, all giving the same error)
impl<'a, 'b, 'c> Mul<&'a ColVector<'a>> for &'b Matrix<'b> {
type Output = ColVector<'c>;
fn mul(self, v: &'a ColVector) -> ColVector<'c> {
self.mat_mult(v)
}
}
EDIT: I fail to see how this is a duplicate of the question Return local String as a slice (&str) . That question is about someone trying to return a reference to a variable local to the function, which is not what I am trying to do. My function does not return a reference, but a struct containing a reference to a newly created slice.
Related
This question already has answers here:
What is the correct way to return an Iterator (or any other trait)?
(2 answers)
Closed 5 months ago.
I'm trying to change the minigrep application that I've implemented in the rust book to also take stdin input like the real grep does.
I've created a small helper function that takes the configuration and decides (currently according to an environment variable) whether to return the buffered reader iterator or the stdin iterator:
fn stdinOrFile(cfg: &Cfg) -> impl Iterator<Item = String> + '_ {
if cfg.stdin {
return io::stdin().lines();
}
let file = File::open(cfg.path.clone()).unwrap();
let reader = BufReader::new(file);
return reader.lines();
}
Realizing that I'm poking with a stick in the dark, it appears that the syntax of returning a trait object is legal, it's a dead-end for now thought. The compiler appears to still try to infer the concrete type of the returned value and complains that the other type is not of the same type, however to the best of my knowledge both implement the iterator trait.
Some ideas I have to get around this:
Box the value before returning it
Create a generic wrapper that would wrap both underlying types, then, since the minigrep matcher only uses the filter functionality of the iterators, I could have separate filter implementations on the wrapper according to which underlying type it holds, which would then call the relevant method on the underlying type.
Any ideas?
Why is the trait object syntax allowed in the return type if a concrete implementation is inferred?
You're right to think you should box it. impl Iterator is not a trait object. It can mean a couple of different things, but in return position it's a special impl return syntax. Effectively, the function still returns a concrete, ordinary iterator of known type, it's just that the compiler infers that type for you. It's most commonly used with iterators, since writing impl Iterator<Item=u32> is far nicer than the actual return type which can be some shenanigans like Map<Vec::Iter<String>, fn(String) -> i32> (and can even be non-denotable in cases where the function argument is a closure).
However, with impl return, there must still exist a concrete type. You can't return two different types in two different branches. So in this case, you do need a trait object. That's dyn Iterator, but dyn Iterator is not sized, so you need to wrap it in a Box to deal with that.
Box<dyn Iterator<Item = String> + '_>
and, of course, you'll need to wrap your return values in Box::new, since Rust won't do that for you.
This question already has an answer here:
How to abstract over a reference to a value or a value itself?
(1 answer)
Closed 3 years ago.
Is it possible to represent a generic struct in Rust that can either own or borrow its content? The rough idea is:
struct Foo<T> {
value: T,
}
fn make_foo<'a, T: From<&'a str>>(s: &'a str) -> Foo<T> {
Foo<T>(s.into())
}
However, I don't know how to constrain T so that it can represent either an owned value like a String, or a borrowed value like a &'a str.
Do I have to create two separate FooOwned<T> and FooBorrowed<'a, T>?
std::borrow::Cow
pub enum Cow<'a, B>
where
B: 'a + ToOwned + ?Sized,
{
Borrowed(&'a B),
Owned(<B as ToOwned>::Owned),
}
When you borrow the type, it either returns a reference it stores, or reference to the value it stores, but if you want to borrow from it mutably, it converts to Owned variant, allowing you to take mutable reference to whatever it stores.
Which is why it's named Cow - Copy on Write. It implicitly copies, often in form of clone, whenever you access it in a way that allows writing.
It's not so implicit in a sense that you have to explicitly convert it to Owned, using to_mut, which has this example given to you:
use std::borrow::Cow;
let mut cow = Cow::Borrowed("foo");
cow.to_mut().make_ascii_uppercase();
assert_eq!(
cow,
Cow::Owned(String::from("FOO")) as Cow<str>
);
It's implementation is not as simple, but it's source code is fairly easy to follow, to_mut, which is what you might be interested in, is implemented in line 228.
This question already has answers here:
How to write a trait bound for adding two references of a generic type?
(1 answer)
How do I require a generic type implement an operation like Add, Sub, Mul, or Div in a generic function?
(2 answers)
Closed 4 years ago.
I'm trying to use the sprs crate (version 0.6.3) to manipulate sparse vectors. I'd like to add two vectors together.
I started off with an implementation of the Add trait, then simplified this to an implementation function. Finally, I've boiled down the problem to a simple generic function.
// This works: the scalar type `u64` is fixed here
fn adder(first: &CsVec<u64>, second: &CsVec<u64>) -> CsVec<u64> {
first + second
}
// When I try to make the scalar type generic, it doesn't work
fn adder2<T>(first: &CsVec<T>, second: &CsVec<T>) -> CsVec<T>
where
CsVec<T>: Add,
T: Add + Debug,
{
first + second
}
The first version compiles fine, but I'd like to know why the second version won't compile. I get this error message:
error[E0369]: binary operation `+` cannot be applied to type `&sprs::sparse::CsVecBase<std::vec::Vec<usize>, std::vec::Vec<T>>`
--> libp3prime/src/lib/datacache.rs:62:5
|
62 | first + second
| ^^^^^^^^^^^^^^
|
= note: an implementation of `std::ops::Add` might be missing for `&sprs::sparse::CsVecBase<std::vec::Vec<usize>, std::vec::Vec<T>>`
I don't really understand the error message. I know that you can add two CsVecs together, since adder() compiles, so I am a bit lost.
The two vectors should add together.
Be sure that the trait bounds defined on the function match the behavior used in the function.
first and second are not CsVec<T>, but &CsVec<T>. In Rust, &X is a different type from X. You need a trait bound that says that you can add two &CsVec<T>s and get a CsVec<T> as output:
fn adder2<'a, T>(first: &'a CsVec<T>, second: &'a CsVec<T>) -> CsVec<T>
where
&'a CsVec<T>: Add<Output = CsVec<T>>,
{
first + second
}
No bounds on T are needed in this example.
The 'a lifetime parameter in this case was passed in to the function. Sometimes it is useful to define a trait bound on a reference inside the function, for example, to use + on references to local variables. In that case you would want to use the higher-ranked trait bound for<'a> &'a CsVec<T>: Add<Output = CsVec<T>> instead. See the linked questions below for more information.
Lukas Kalbertodt points out that it may sometimes be more flexible to say "I just want to add two &CsVec<T>s, and I will return whatever type that operation gives me", which you can do by returning <&'a CsVec<T> as Add>::Output:
fn adder2<'a, T>(first: &'a CsVec<T>, second: &'a CsVec<T>) -> <&'a CsVec<T> as Add>::Output
where
&'a CsVec<T>: Add,
{
first + second
}
In this case the output type does not have to be exactly CsVec<T>, but when it is, it works the same way as the first version.
Related
How to write a trait bound for adding two references of a generic type?
How do I require a generic type implement an operation like Add, Sub, Mul, or Div in a generic function?
This question already has answers here:
What is the return type of the indexing operation?
(2 answers)
Closed 4 years ago.
I check Index trait in doc and find return type of index() is &T.
Then I write this function to get value from vector:
fn get_value_test(a: usize, v: &Vec<i32>) -> i32 {
v[a]
}
My question is: why v[a] is i32 but &i32? Because i32 ...have a known size at compile time are stored entirely on the stack, so copies of the actual values are quick to make? (from here)
It looks like Rust have hidden rule to convert type in this situation?
There was a small misguidance here. Although the method prototype for Index<Idx> is fn index(&self, index: Idx) -> &T, the syntactical operator x[i] does dereference the output from that &T:
container[index] is actually syntactic sugar for *container.index(index) [...]. This allows nice things such as let value = v[index] if the type of value implements Copy.
So there you go. Your function is indeed returning a copy of the value from the vector, but not from an implicit conversion. If the original intent was to really retrieve a reference to that value, you would do &x[i].
See also:
Meaning of the ampersand '&' and star '*' symbols in Rust
Does Rust automatically dereference primitive type references?
I made a two element Vector struct and I want to overload the + operator.
I made all my functions and methods take references, rather than values, and I want the + operator to work the same way.
impl Add for Vector {
fn add(&self, other: &Vector) -> Vector {
Vector {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
Depending on which variation I try, I either get lifetime problems or type mismatches. Specifically, the &self argument seems to not get treated as the right type.
I have seen examples with template arguments on impl as well as Add, but they just result in different errors.
I found How can an operator be overloaded for different RHS types and return values? but the code in the answer doesn't work even if I put a use std::ops::Mul; at the top.
I am using rustc 1.0.0-nightly (ed530d7a3 2015-01-16 22:41:16 +0000)
I won't accept "you only have two fields, why use a reference" as an answer; what if I wanted a 100 element struct? I will accept an answer that demonstrates that even with a large struct I should be passing by value, if that is the case (I don't think it is, though.) I am interested in knowing a good rule of thumb for struct size and passing by value vs struct, but that is not the current question.
You need to implement Add on &Vector rather than on Vector.
impl<'a, 'b> Add<&'b Vector> for &'a Vector {
type Output = Vector;
fn add(self, other: &'b Vector) -> Vector {
Vector {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
In its definition, Add::add always takes self by value. But references are types like any other1, so they can implement traits too. When a trait is implemented on a reference type, the type of self is a reference; the reference is passed by value. Normally, passing by value in Rust implies transferring ownership, but when references are passed by value, they're simply copied (or reborrowed/moved if it's a mutable reference), and that doesn't transfer ownership of the referent (because a reference doesn't own its referent in the first place). Considering all this, it makes sense for Add::add (and many other operators) to take self by value: if you need to take ownership of the operands, you can implement Add on structs/enums directly, and if you don't, you can implement Add on references.
Here, self is of type &'a Vector, because that's the type we're implementing Add on.
Note that I also specified the RHS type parameter with a different lifetime to emphasize the fact that the lifetimes of the two input parameters are unrelated.
1 Actually, reference types are special in that you can implement traits for references to types defined in your crate (i.e. if you're allowed to implement a trait for T, then you're also allowed to implement it for &T). &mut T and Box<T> have the same behavior, but that's not true in general for U<T> where U is not defined in the same crate.
If you want to support all scenarios, you must support all the combinations:
&T op U
T op &U
&T op &U
T op U
In rust proper, this was done through an internal macro.
Luckily, there is a rust crate, impl_ops, that also offers a macro to write that boilerplate for us: the crate offers the impl_op_ex! macro, which generates all the combinations.
Here is their sample:
#[macro_use] extern crate impl_ops;
use std::ops;
impl_op_ex!(+ |a: &DonkeyKong, b: &DonkeyKong| -> i32 { a.bananas + b.bananas });
fn main() {
let total_bananas = &DonkeyKong::new(2) + &DonkeyKong::new(4);
assert_eq!(6, total_bananas);
let total_bananas = &DonkeyKong::new(2) + DonkeyKong::new(4);
assert_eq!(6, total_bananas);
let total_bananas = DonkeyKong::new(2) + &DonkeyKong::new(4);
assert_eq!(6, total_bananas);
let total_bananas = DonkeyKong::new(2) + DonkeyKong::new(4);
assert_eq!(6, total_bananas);
}
Even better, they have a impl_op_ex_commutative! that'll also generate the operators with the parameters reversed if your operator happens to be commutative.