Returning a boxed iterator over a value in a structure [duplicate] - iterator

This question already has answers here:
Why is adding a lifetime to a trait with the plus operator (Iterator<Item = &Foo> + 'a) needed?
(1 answer)
What is the correct way to return an Iterator (or any other trait)?
(2 answers)
Closed 5 years ago.
I want a function on a struct which returns an iterator to one of the struct's members. I tried something like the following, which doesn't work.
struct Foo {
bar: Vec<String>,
}
impl Foo {
fn baz(&self) -> Box<Iterator<Item = &String>> {
Box::new(self.bar.iter())
}
}
fn main() {
let x = Foo { bar: vec!["quux".to_string()] };
x.baz();
}
When compiling, I get the error below:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:7:27
|
7 | Box::new(self.bar.iter())
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
--> src/main.rs:6:5
|
6 | / fn baz(&self) -> Box<Iterator<Item = &String>> {
7 | | Box::new(self.bar.iter())
8 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:18
|
7 | Box::new(self.bar.iter())
| ^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that expression is assignable (expected std::boxed::Box<std::iter::Iterator<Item=&std::string::String> + 'static>, found std::boxed::Box<std::iter::Iterator<Item=&std::string::String>>)
--> src/main.rs:7:9
|
7 | Box::new(self.bar.iter())
| ^^^^^^^^^^^^^^^^^^^^^^^^^
I also tried adding lifetime information as suggested elsewhere
struct Foo {
bar: Vec<String>,
}
impl Foo {
fn baz<'a>(&self) -> Box<Iterator<Item = &String> + 'a> {
Box::new(self.bar.iter())
}
}
fn main() {
let x = Foo { bar: vec!["quux".to_string()] };
x.baz();
}
Now my error is the following:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:7:27
|
7 | Box::new(self.bar.iter())
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
--> src/main.rs:6:5
|
6 | / fn baz<'a>(&self) -> Box<Iterator<Item = &String> + 'a> {
7 | | Box::new(self.bar.iter())
8 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:7:18
|
7 | Box::new(self.bar.iter())
| ^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the method body at 6:5...
--> src/main.rs:6:5
|
6 | / fn baz<'a>(&self) -> Box<Iterator<Item = &String> + 'a> {
7 | | Box::new(self.bar.iter())
8 | | }
| |_____^
note: ...so that expression is assignable (expected std::boxed::Box<std::iter::Iterator<Item=&std::string::String> + 'a>, found std::boxed::Box<std::iter::Iterator<Item=&std::string::String>>)
--> src/main.rs:7:9
|
7 | Box::new(self.bar.iter())
| ^^^^^^^^^^^^^^^^^^^^^^^^^

Related

Why do lines 14 and 21 not compile (for my Kotlin function)?

I have a function named collectCustomizerFunctions which should create a MutableList<KCallable<*>> of all the functions of a specified class and its sub-classes which are annotated with CustomizerFunction.
Recursively, customizerFuns (the MutableList<KCallable<*>>) should have all of the "cutomizer functions" added to it.
When I try to build my Gradle project, it fails with two exceptions:
e: collectCustomizerFuns.kt:14:33 Type inference failed. The value of the type parameter T should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.
e: collectCustomizerFuns.kt:21:30 Type mismatch: inferred type is Any but CapturedType(*) was expected
Here is my code:
3 | import kotlin.reflect.KClass
4 | import kotlin.reflect.KCallable
5 | import kotlin.reflect.full.allSuperclasses
6 |
7 | #Utility
8 | public tailrec fun <T: Any> collectCustomizerFuns(
9 | specClass: KClass<T>,
10 | customizerFuns: MutableList<KCallable<*>>
11 | ): Unit {
12 | // add annotated functions of this class
13 | for (member in specClass.members) {
14 | if (CustomizerFunction::class in member.annotations) { <--- ERROR
15 | customizerFuns.add(member)
16 | } else {}
17 | }
18 |
19 | // add annotated functions of all super-classes
20 | for (superclass in specClass.allSuperclasses) {
21 | collectCustomizerFuns<Any>(superclass, customizerFuns) <--- ERROR
22 | }
23 | }
I have been trying to fix these bugs for a while now, and would appreciate any help!
Also, please provide any constructive criticism you want regarding this function, it would help a lot!
For the first error, member.annotations returns List<Annotation>. You have to fetch actual classes of these annotations.
For the second error, remove the type where you call collectCustomizerFuns. Let kotlin infers the type by itself :).
So try this:
public tailrec fun <T: Any> collectCustomizerFuns(
specClass: KClass<T>,
customizerFuns: MutableList<KCallable<*>>
) {
// add annotated functions of this class
for (member in specClass.members) {
if (CustomizerFunction::class in member.annotations.map { it.annotationClass }) {
customizerFuns.add(member)
} else {
}
}
// add annotated functions of all super-classes
for (superclass in specClass.allSuperclasses ) {
collectCustomizerFuns(superclass, customizerFuns)
}
}
By the way, you can remove Unit from the method signature.

Return type errors making a POST request using reqwest in Rust

I'm new to Rust and Typed languages and am having trouble making a post request using reqwest in Rust. I'm not sure which arguments I should pass in to the Result return type enum.
I'm also not sure if my approach so far is the right on because I get errors when I call .await; after send. Does this function need to be async?
error[E0308]: mismatched types
--> rust/src/lib.rs:41:13
|
41 | Ok(res) => res,
| ^^^^^^^ expected opaque type, found enum `std::result::Result`
|
::: home/.cargo/registry/src/reqwest-0.11.3/src/async_impl/request.rs:416:26
|
416 | pub fn send(self) -> impl Future<Output = Result<Response, crate::Error>> {
| ---------------------------------------------------- the expected opaque type
|
= note: expected opaque type `impl std::future::Future`
found enum `std::result::Result<_, _>`
error[E0308]: mismatched types
--> rust/src/lib.rs:42:13
|
42 | Err(err) => err,
| ^^^^^^^^ expected opaque type, found enum `std::result::Result`
|
::: /home/.cargo/registry/src/reqwest-0.11.3/src/async_impl/request.rs:416:26
|
416 | pub fn send(self) -> impl Future<Output = Result<Response, crate::Error>> {
| ---------------------------------------------------- the expected opaque type
|
= note: expected opaque type `impl std::future::Future`
found enum `std::result::Result<_, _>`
error: aborting due to 2 previous errors
Ultimately, I'm not sure if I'm on the right track with making a POST request using reqwest, but this is what I have:
enum Result<T, E> {
Ok(T),
Err(E),
}
pub async fn make_request(path: &str) -> Result<(), ()>{
let client = reqwest::Client::new();
let request = client.post(format!("http://localhost:8000/{}", path))
.body("tbd")
.send();
match request {
Ok(res) => res,
Err(err) => err,
}
}
Any advice on moving forward would be greatly appreciated.

How do I define a from method to convert the error in a foreign result type? [duplicate]

This question already has answers here:
Is it possible to implement methods on type aliases?
(1 answer)
Rust proper error handling (auto convert from one error type to another with question mark)
(5 answers)
How to do error handling in Rust and what are the common pitfalls?
(2 answers)
Closed 2 years ago.
I have a pair of Result type aliases, AResult and BResult. AResult is from another crate, and embeds its own error type AError. I have my result (BResult) and I want to convert errors from AError to BError so I can embed them in the BResults that I return.
TIO demo
struct AError(u32);
struct BError(i64);
type AResult = Result<(), AError>;
type BResult = Result<(), BError>;
impl From<AError> for BError {
fn from(item: AError) -> Self {
(item as i64)
}
}
impl From<AResult> for BResult {
fn from(item: AResult) -> Self {
item.map_err(BError::from)
}
}
fn main() {
let result_as_a: AResult = Err(5u32);
let result_as_b = result_as_a;
if let Err(value) = result_as_b {
print!("{}", value);
}
}
I have defined a conversion for the errors from AError to BError (impl From<AError> for BError { ... }) and I'm trying to define a conversion for the Result which uses it, thinking I could do:
impl From<AResult> for BResult {
fn from(item: AResult) -> Self {
item.map_err(BError::from)
}
}
But Rust complains that I can't define things from another crate:
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
--> src/main.rs:12:1
|
12 | impl From<AResult> for BResult {
| ^^^^^-------------^^^^^-------
| | | |
| | | `std::result::Result` is not defined in the current crate
| | `std::result::Result` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead
I'm trying to define an implementation on BResult, not AResult?!
Am I doing something very stupid? Is there a better way to do this?

How to take an IntoIterator of references and return a boxed Iterator of references to the modified values?

I've grasped the basics of Rust lifetimes and how to work with iterators in it, but still have troubles to define a function that takes an iterable of tuples and return an iterable of tuples also allocated on the heap.
(I know that "iterable" doesn't mean anything in Rust but I will still use it instead of IntoInterator)
use std::iter::{once, repeat};
fn foo<'a, I>(costs: I) -> Box<Iterator<Item = &'a (i32, f32)>>
where
I: IntoIterator<Item = &'a (usize, f32)>,
{
let preliminary_examination_costs = once(10.0).chain(repeat(20.0));
let id_assignment_costs = once(10.0).chain(repeat(20.0));
let batch_fixed = once(10.0).chain(repeat(0.0));
let temp: Vec<(usize, &(i32, f32))> = costs.into_iter().enumerate().collect();
temp.sort_by_key(|&(_, &(n, cost))| n);
Box::new(temp.into_iter().map(|(i, &(n, cost))| {
(
i,
cost + preliminary_examination_costs.next().unwrap()
+ id_assignment_costs.next().unwrap() + batch_fixed.next().unwrap(),
)
}))
}
(playground)
Here's the errors:
error[E0277]: the trait bound `std::vec::Vec<(usize, &(i32, f32))>: std::iter::FromIterator<(usize, &'a (usize, f32))>` is not satisfied
--> src/main.rs:10:73
|
10 | let temp: Vec<(usize, &(i32, f32))> = costs.into_iter().enumerate().collect();
| ^^^^^^^ a collection of type `std::vec::Vec<(usize, &(i32, f32))>` cannot be built from an iterator over elements of type `(usize, &'a (usize, f32))`
|
= help: the trait `std::iter::FromIterator<(usize, &'a (usize, f32))>` is not implemented for `std::vec::Vec<(usize, &(i32, f32))>`
error[E0271]: type mismatch resolving `<[closure#src/main.rs:12:35: 18:6 preliminary_examination_costs:_, id_assignment_costs:_, batch_fixed:_] as std::ops::FnOnce<((usize, &(i32, f32)),)>>::Output == &(i32, f32)`
--> src/main.rs:12:5
|
12 | / Box::new(temp.into_iter().map(|(i, &(n, cost))| {
13 | | (
14 | | i,
15 | | cost + preliminary_examination_costs.next().unwrap()
16 | | + id_assignment_costs.next().unwrap() + batch_fixed.next().unwrap(),
17 | | )
18 | | }))
| |_______^ expected tuple, found &(i32, f32)
|
= note: expected type `(usize, f32)`
found type `&(i32, f32)`
= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Map<std::vec::IntoIter<(usize, &(i32, f32))>, [closure#src/main.rs:12:35: 18:6 preliminary_examination_costs:_, id_assignment_costs:_, batch_fixed:_]>`
= note: required for the cast to the object type `std::iter::Iterator<Item=&(i32, f32)>`
It's very useful to create a MCVE when encountering a problem, and it's something I encourage all learners to undertake. Here's one such MCVE that mirrors your code:
fn foo<'a, I>(costs: I) -> Box<Iterator<Item = &'a i32>>
where
I: IntoIterator<Item = &'a i32>,
{
Box::new(costs.into_iter().map(|i| i + 1))
}
error[E0271]: type mismatch resolving `<[closure#src/main.rs:5:36: 5:45] as std::ops::FnOnce<(&'a i32,)>>::Output == &i32`
--> src/main.rs:5:5
|
5 | Box::new(costs.into_iter().map(|i| i + 1))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found &i32
|
= note: expected type `i32`
found type `&i32`
= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Map<<I as std::iter::IntoIterator>::IntoIter, [closure#src/main.rs:5:36: 5:45]>`
= note: required for the cast to the object type `std::iter::Iterator<Item=&i32>`
You are accepting a reference then creating a brand new value based on the reference. That means that the return type is no longer a reference, thus your function signature is not upheld. You need to change it:
fn foo<'a, I>(costs: I) -> Box<Iterator<Item = i32>>
This will unlock another error because the compiler doesn't know enough about the concrete type of I::IntoIter:
error[E0310]: the associated type `<I as std::iter::IntoIterator>::IntoIter` may not live long enough
--> src/main.rs:6:5
|
6 | Box::new(costs.into_iter().map(|i| i + 1))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<I as std::iter::IntoIterator>::IntoIter: 'static`...
note: ...so that the type `std::iter::Map<<I as std::iter::IntoIterator>::IntoIter, [closure#src/main.rs:6:36: 6:45]>` will meet its required lifetime bounds
--> src/main.rs:6:5
|
6 | Box::new(costs.into_iter().map(|i| i + 1))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
We do as it suggests and add the 'static bound:
fn foo<'a, I>(costs: I) -> Box<Iterator<Item = i32>>
where
I: IntoIterator<Item = &'a i32>,
I::IntoIter: 'static,
{
Box::new(costs.into_iter().map(|i| i + 1))
}
See also:
Is there any way to return a reference to a variable created in a function?
error[E0277]: the trait bound `std::vec::Vec<(usize, &(i32, f32))>: std::iter::FromIterator<(usize, &'a (usize, f32))>` is not satisfied
This error is because you have an iterator of (usize, &'a (usize, f32)) and you are trying to make them into (usize, &(i32, f32)). You can't convert types like this.

Use trait from submodule with same name as struct

Trying to compile the following Rust code
mod traits {
pub trait Dog {
fn bark(&self) {
println!("Bow");
}
}
}
struct Dog;
impl traits::Dog for Dog {}
fn main() {
let dog = Dog;
dog.bark();
}
gives the error message
error[E0599]: no method named `bark` found for type `Dog` in the current scope
--> src/main.rs:15:9
|
9 | struct Dog;
| ----------- method `bark` not found for this
...
15 | dog.bark();
| ^^^^
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope, perhaps add a `use` for it:
|
1 | use crate::traits::Dog;
|
If I add use crate::traits::Dog;, the error becomes:
error[E0255]: the name `Dog` is defined multiple times
--> src/main.rs:11:1
|
1 | use crate::traits::Dog;
| ------------------ previous import of the trait `Dog` here
...
11 | struct Dog;
| ^^^^^^^^^^^ `Dog` redefined here
|
= note: `Dog` must be defined only once in the type namespace of this module
If I rename trait Dog to trait DogTrait, everything works. How can I use a trait from a submodule that has the same name as a struct in my main module?
You could rename the trait when importing it to get the same result without renaming the trait globally:
use traits::Dog as DogTrait;
The compiler now even suggests this:
help: you can use `as` to change the binding name of the import
|
1 | use crate::traits::Dog as OtherDog;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
documentation
If you don't wish to import both (or can't for whatever reason), you can use Fully Qualified Syntax (FQS) to use the trait's method directly:
fn main() {
let dog = Dog;
traits::Dog::bark(&dog);
}