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?
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 answers here:
What are Rust's exact auto-dereferencing rules?
(4 answers)
Confusion over auto-dereferencing rules when using function
(1 answer)
Closed 4 years ago.
The following program works fine:
pub fn foo(_v: &str) -> bool {
false
}
fn main() {
let f = "hello world";
println!("{}", foo(&&&&f)); // note the number of & here
}
In fact it works on passing any number of &. How should I interpret what is going on ?
My rust version:
$ rustc --version
rustc 1.32.0-nightly (13dab66a6 2018-11-05)
From the Rust book:
Deref coercion is a convenience that Rust performs on arguments to
functions and methods. Deref coercion converts a reference to a type
that implements Deref into a reference to a type that Deref can
convert the original type into. Deref coercion happens automatically
when we pass a reference to a particular type’s value as an argument
to a function or method that doesn’t match the parameter type in the
function or method definition. A sequence of calls to the deref method
converts the type we provided into the type the parameter needs.
So basically, in function arguments the compiler will automatically remove any & written or implied until it gets to a type that can be passed to the function.
Because the compiler automatically dereferences the chain of references, you can imagine that it inserts as many * as necessary to get the right type:
foo(&&&f)
is converted to:
foo(&****(&&&f))
that leads to the right invocation:
foo(f)
The insertions of as many * as needed is actually performed by this blanket implementation of Deref trait:
impl<'a, T: ?Sized> Deref for &'a T {
type Target = T;
fn deref(&self) -> &T { *self }
}
Note: I've update my answer because in the original I used the term autoderef in the wrong way, see this post for details.
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 are Rust's exact auto-dereferencing rules?
(4 answers)
Confusion over auto-dereferencing rules when using function
(1 answer)
Closed 4 years ago.
The following program works fine:
pub fn foo(_v: &str) -> bool {
false
}
fn main() {
let f = "hello world";
println!("{}", foo(&&&&f)); // note the number of & here
}
In fact it works on passing any number of &. How should I interpret what is going on ?
My rust version:
$ rustc --version
rustc 1.32.0-nightly (13dab66a6 2018-11-05)
From the Rust book:
Deref coercion is a convenience that Rust performs on arguments to
functions and methods. Deref coercion converts a reference to a type
that implements Deref into a reference to a type that Deref can
convert the original type into. Deref coercion happens automatically
when we pass a reference to a particular type’s value as an argument
to a function or method that doesn’t match the parameter type in the
function or method definition. A sequence of calls to the deref method
converts the type we provided into the type the parameter needs.
So basically, in function arguments the compiler will automatically remove any & written or implied until it gets to a type that can be passed to the function.
Because the compiler automatically dereferences the chain of references, you can imagine that it inserts as many * as necessary to get the right type:
foo(&&&f)
is converted to:
foo(&****(&&&f))
that leads to the right invocation:
foo(f)
The insertions of as many * as needed is actually performed by this blanket implementation of Deref trait:
impl<'a, T: ?Sized> Deref for &'a T {
type Target = T;
fn deref(&self) -> &T { *self }
}
Note: I've update my answer because in the original I used the term autoderef in the wrong way, see this post for details.
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.