rustlings: hashmap3.rs expected `()`, found struct `Team` - rust

I'm learning rust using rustlings. I was trying to implement a solution in a functional way (rustlings only asked for the imperative way). I'm running into the following compiler error and haven't been able to figure this out since 2 hours. Please help
Compiler error:
Progress: [############################>-------------------------------] 45/94
! Compiling of exercises/hashmaps/hashmaps3.rs failed! Please try again. Here's the output:
error[E0308]: mismatched types
--> exercises/hashmaps/hashmaps3.rs:94:28
|
94 | .and_modify(|team| Team {
| ____________________________^
95 | | name: team.name.to_string(),
96 | | goals_scored: team.goals_scored+team_from_iter.goals_scored,
97 | | goals_conceded: team.goals_conceded+team_from_iter.goals_conceded,
98 | | })
| |_________^ expected `()`, found struct `Team`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
Code
This is the set of lines the compiler has an issue with
.and_modify(|team| Team {
name: team.name.to_string(),
goals_scored: team.goals_scored+team_from_iter.goals_scored,
goals_conceded: team.goals_conceded+team_from_iter.goals_conceded,
})
Link to full code repo:
To the exact lines with the issue: https://github.com/dheerajbhaskar/learn-rust-rustlings-PUBLIC/blob/a3d38c643fc178f05a847e7cb8016a784b0a54ac/exercises/hashmaps/hashmaps3.rs#L94-L98
To the repo: https://github.com/dheerajbhaskar/learn-rust-rustlings-PUBLIC
Additional information
I've written very similar code on line 119 which compiles and passes the tests. I've not been able to understand why that worked but code at line 94 above didn't. Edit: looks like I've compiler error both these lines now ¯\_(ツ)_/¯
I'm a rust noob if it wasn't apparent yet :)

pub fn and_modify<F>(self, f: F) -> Self
where
F: FnOnce(&mut V),
and_modify's argument has the type FnOnce(&mut V). This is a function that takes a single argument of type &mut V and returns nothing. (If it were returning something it would have a signature like FnOnce(&V) -> V instead.)
Concretely, you're receiving a mutable Team object that's already in the hash map and you're expected to modify it in place. Instead of constructing a brand new Team you should update the team that you're being passed. Something like this, say:
.and_modify(|team| {
team.goals_scored += team_from_iter.goals_scored;
team.goals_conceded += team_from_iter.goals_conceded;
})
Notice how this modifies team in place and doesn't return anything.

Related

Confusing error message on ? (unwrap operator)

I have this rust method error message:
error[E0277]: the `?` operator can only be used on `Option`s,
not `Result`s, in an async function that returns `Option`
I must admit, I often encounter Rust error messages which appear confusing to me, while to most other coders they make absolute sense.
So, I apologize in advance for posting this question.
First of all: what does that second comma in the error message mean? Should I read it as the following:
"If an async function call [within another function] returns an enum of the type Result then the ? operator can only be applied if, and only if, the respective [other] function also returns an enum of type Result and not an enum of type Option"
Pardon my verbose language. I hope I got my point across.
What also got me confused was the error message with that very same Reference i.e. error[E0277] , which is listed in the official rust error codes index, states:
"You tried to use a type which doesn't implement some trait in a place which expected that trait."
In which universe do these two error messages have anything in common, except for the identical reference number?
And here's the entire error block, which Rust produced:
error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in an async function that returns `Option`
--> src/utils/tokenizer.rs:72:73
|
70 | pub async fn clear(&self) -> Option<String> {
| _________________________________________________-
71 | | let mut conn = self.pool.get().await.unwrap();
72 | | let mut iter: redis::AsyncIter<i32> = conn.sscan("my_set").await?;
| | ^ use `.ok()?` if you want to discard the `Result<Infallible, Red
Error>` error information
73 | | while let Some(element) = iter.next_item().await {
... |
79 | | Some(String::from("A"))
80 | | }
| |_____- this function returns an `Option`
|
= help: the trait `FromResidual<Result<Infallible, RedisError>>` is not implemented for `std::option::Option<std::string::String>`
= help: the following other types implement trait `FromResidual<R>`:
<std::option::Option<T> as FromResidual<Yeet<()>>>
<std::option::Option<T> as FromResidual>
For more information about this error, try `rustc --explain E0277`.
What is the canonical error message, the one from the error code index page or the one, the compiler produces?
Your function clear returns Option<String> but the function conn.sscan("my_set").await?; returns a Result. You cannot use ? to propagate the result because that doesn't match the return type of clear(&self) -> Option<String>.
You will need explicitly handle the Result or convert it to an Option<String>. You could also try adding .ok()? per the compiler hint and see what that gets you.
Whatever you pick the important thing is just to make sure that the return type matches what your ? operator is unwrapping.
Yes, your interpretation is correct, although to be pedantic the error says the opposite:
"If an async function returns Option then the ? operator can only be applied to expressions that has the type Option, and not Result".
And if you ask why on earth this has error code E0277? Well, this is because in order to be propagated using ? a type has to implement the (experimental) Try trait with some combination of type parameters and associated types corresponding to some other combination of the return type of the function. So, in essence, an incompatible type in ? boils down to an unsatisfied trait bound. But unless you're interested in the inner workings of ?, this is not really important.

Declared function return does not match the type of the value that is returned (and inferred by the compiler)

I'm trying to get started with [imgui ] for Rust (along with [glutin] and [winit]), and I'm working on creating the event loop ([glutin]). To do this, I'm calling event_loop.run_return() (not run() since I want it to return control once the UI is closed).
According to the docs (Ctrl+Q in CLion), the return type of run_return() is i32 (an integer):
winit::platform::run_return impl<T> EventLoopExtRunReturn for EventLoop<T>
fn run_return<F>(&mut self, event_handler: F) -> i32 where F: FnMut(Event<'_, Self::UserEvent>, &EventLoopWindowTarget<Self::UserEvent>, &mut ControlFlow),
Initializes the winit event loop.
...
When I look at the source, it show the exact same (an i32):
fn run_return<F>(&mut self, event_handler: F) -> i32
I want to log what this returns (I'm using [tracing]), so I tried to store it as a variable and then print it:
let exit_code = ui_system
.event_loop
.run_return(event_loop_run);
drop(_run_span_entered); //Ignore, tracing
info!("exit_code: {exit_code}");
This errors on the info!(), because () doesn't implement std::fmt::Display
This is pointing at {exit_code}, which is most definitely not (). Also note how CLion infers the type of exit_code to be i32.
If I try to force the type of exit_code, then the info!() is happy, but now the variable definition errors out:
mismatched types [E0308] expected `i32`, found `()`
Unless I'm going crazy, this is clearly wrong, because the function definition says it must return an i32, but yet the compiler somehow thinks it isn't?
cargo build shows the same thing:
error[E0308]: mismatched types
--> src\main.rs:60:25
|
60 | let exit_code:i32 = ui_system
| ___________________---___^
| | |
| | expected due to this
61 | | .event_loop
62 | | .run_return(event_loop_run);
| |___________________________________^ expected `i32`, found `()`
In the previous version of winit, run_return() did return ().
I suspect that your Cargo.toml specifies 0.26 (or earlier) but CLion is somehow incorrectly presenting you with documentation for 0.27.

How do I use the yield keyword in Rust? [duplicate]

This question already has answers here:
Lazy sequence generation in Rust
(4 answers)
Closed 1 year ago.
This post was edited and submitted for review 1 year ago and failed to reopen the post:
Original close reason(s) were not resolved
I'm trying to make a function that will return an iterator of all the files in a directory, including all the files in the subdirectories. As I don't know the size of an array that would contain all the files' paths, I thought that it would be easier to have the function return an iterator instead of an array. It's simple enough to do in Python:
def func():
for i in range(0, 100):
yield i
for i in func():
print(i)
But when I try to do something similar in Rust, I get compiler errors and/or compiler panics. Here, I tried some basic syntax that's close to what it is in Python:
fn func() -> Iterator {
for i in 0..100 {
yield i;
}
}
fn main() {
for i in func() {
println!("{}", i);
}
}
But when I compiled it, it caused two errors and a warning:
error[E0658]: yield syntax is experimental
--> src/main.rs:3:9
|
3 | yield i;
| ^^^^^^^
|
= note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
warning: trait objects without an explicit `dyn` are deprecated
--> src/main.rs:1:14
|
1 | fn func() -> Iterator {
| ^^^^^^^^ help: use `dyn`: `dyn Iterator`
|
= note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
= note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
error[E0191]: the value of the associated type `Item` (from trait `Iterator`) must be specified
--> src/main.rs:1:14
|
1 | fn func() -> Iterator {
| ^^^^^^^^ help: specify the associated type: `Iterator<Item = Type>`
Some errors have detailed explanations: E0191, E0658.
For more information about an error, try `rustc --explain E0191`.
warning: `problem` (bin "problem") generated 1 warning
error: could not compile `problem` due to 2 previous errors; 1 warning emitted
I've been playing around with using different return types, like dyn Iterator<Item = i32>, impl Iterator, etc. according to the help in the error messages, and I either get errors, compiler panics, or both. Sorry if this is a stupid question; I've only been working with Rust for around three months. But somehow, it feels like this should be simpler.
So my question: what's the correct syntax for a function returning an iterator generated using the yield keyword? I've looked in the Rust Documentation and The Book, but I've found nothing useful.
An iterator needs to implement Iterator trait.
Rust doesn't use of the yield keyword for generators (for now, Rust 1.57), so you cannot use it.
Direct translation of your code would be:
fn func() -> impl Iterator<Item=u32> {
0..100u32
}
fn main() {
for i in func() {
println!("{}", i);
}
}
The (0..100) is a Range object that implements Iterator
References
Iterator
Generators (Unstable)
Walkdir (solving a similar problem)

What is the right syntax to use std::iter::Iterator::reduce for summation?

Among many codes I've tried for this one, this I think is the more concise code to show here:
fn summation<I>(nums: I) -> Option<I::Item>
where
I: Iterator,
I::Item: std::ops::Add,
{
nums.reduce(|a, b| a + b)
}
fn main() {
let numbers: Vec<f32> = vec![1f32, 2f32, 3f32];
let result = summation(numbers.into_iter());
}
My goal is mainly tinkering with the Iterator::reduce's function to increase my understanding with Rust.
The code above spits out the following error when I run cargo check in the powershell:
Checking code_demo v0.1.0 (C:\Users\miked\git\code_demo)
error[E0308]: mismatched types
--> src\main.rs:6:24
|
6 | nums.reduce(|a, b| a + b)
| ^^^^^ expected std::iter::Iterator::Item, found std::ops::Add::Output
|
= note: expected associated type `<I as Iterator>::Item`
found associated type `<<I as Iterator>::Item as Add>::Output`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `code_demo`
To learn more, run the command again with --verbose.
I tried to replicate the code on docs.rs, but the code snippet over there is using
Ord trait.
I tried this one as well:
fn summation<I>(nums: I) -> Option<I::Item>
where
I: Iterator,
I::Item: std::ops::Add::Output,
{
nums.reduce(|a, b| a + b)
}
fn main() {
let numbers: Vec<f32> = vec![1f32, 2f32, 3f32];
let result = summation(numbers.into_iter());
}
And running cargo check would spit out:
Checking code_demo v0.1.0 (C:\Users\miked\git\code_demo)
error[E0404]: expected trait, found associated type `std::ops::Add::Output`
--> src\main.rs:4:14
|
4 | I::Item: std::ops::Add::Output,
| ^^^^^^^^^^^^^^^^^^^^^ not a trait
error: aborting due to previous error
For more information about this error, try `rustc --explain E0404`.
error: could not compile `code_demo`
To learn more, run the command again with --verbose.
Is there a way I can implement Add for the function to get the summation of
vector of integers or vector of floats?
Or is it that what I'm trying to do impossible and just use use std::iter::Sum;? If so, how would that be implemented?
Thanks.
edits:
1st Sorry, forgot to remove the generic parameter T
2nd I added other solutions I tried
It seems like you got the general ideal of the issue. Since reduce requires that the reducer function returns I::Item, you need to explicitly set up the bounds of Add so that it is guaranteed to output the same type that it used as input. The syntax you're looking for is
I::Item: std::ops::Add<Output=I::Item>
so your code will compile with
fn summation<I>(nums: I) -> Option<I::Item>
where
I: Iterator,
I::Item: std::ops::Add<Output=I::Item>
{
nums.reduce(|a, b| a + b)
}

Rust: How can a reference be a type?

So what I am asking is, what is the difference between the return types, &std::vec::Vec and std::vec::Vec? Just curious. If I make a reference to something, I'm not creating a new type. It still retains its data and structure and so retains its type. But for some reason I get this error:
error[E0308]: mismatched types
--> src/cam.rs:170:3
|
168 | pub fn index2d(self, x: usize, y: usize) -> Vec<u8> {
| ------- expected `std::vec::Vec<u8>` because of return type
169 | let c = &self.pyxels[y*WIDTH+x];
170 | c
| ^
| |
| expected struct `std::vec::Vec`, found reference
| help: try using a conversion method: `c.to_vec()`
|
= note: expected type `std::vec::Vec<u8>`
found type `&std::vec::Vec<u8>`
^ (umm excuse me?)
That one little symbol (&) really seems to make all the difference and I have no clue why.
If I make a reference to something, I'm not creating a new type.
If by "creating a new type", you mean "creating an object of a different type", then yes, that's exactly what you're doing. A reference to a thing is not that thing. It's similar to the difference between having a house, and having a slip of paper with the address of a house written on it.
Though the syntax of Rust often makes access to an object through a reference look identical to direct access to that object.
let v: Vec<u8> = Vec::new();
let vr = &v;
assert_eq!(v.len(), rv.len());
So perhaps that is why you are confused?

Resources