Beginner confused with mismatched opaque types
โ Rust ๐ 2026-02-24 ๐ค surdeus ๐๏ธ 1Hi! I'm a beginner looking for some help. I tried to provide context, but if you just want to read the core problem, skip to the last section for a minimal example.
Any insight would be greatly appreciated. Thanks a lot!
Some context
I'm going through the Rust book, and I just learned about Iterators on chapter 13. Then, on section 13.3, there is a suggested modification to the project in chapter 12. This is suggested, but no code is given for it. Specifically, I mean this paragraph:
For a further improvement, return an iterator from the
searchfunction by removing the call tocollectand changing the return type toimpl Iterator<Item = &'a str>so that the function becomes an iterator adapter. Note that youโll also need to update the tests! Search through a large file using yourminigreptool before and after making this change to observe the difference in behavior. Before this change, the program wonโt print any results until it has collected all of the results, but after the change, the results will be printed as each matching line is found because theforloop in therunfunction is able to take advantage of the laziness of the iterator.
I tried to implement this as an exercise, and found the following issue.
The problem
The project has two similar functions, search and search_case_insensitive. Which one is called depends on a boolean flag, so there is an if-else statement to handle this.
However, with the modifications above, both functions return the iterator resulting from the filter method. The book suggest to treat this as an opaque type implementing Iterator<Item = &str>, by writing the return in the signature as impl Iterator<Item = &'a str>.
Now, the compiler tells me that because these are opaque types, even if I write exactly the same in the signature of both functions, it treats them as different types. I think I understand why this is, but I don't know how to solve it.
I tried to find solutions online, and found two options:
- Use something called trait objects, which I haven't learned about yet because they come much later in the book.
- Change the signature to the explicit type on the return.
I'm hesitant about solution 1. The fact that the book proposes this change to the code suggests to me that there should be a solution that doesn't use stuff I haven't learned about yet. Unless it's an oversight?
As for solution 2, I don't know how to figure out the explicit type.
Minimal example
fn one(text: &str) -> impl Iterator<Item = &str> {
text
.lines()
.filter(|line| line.contains("1"))
}
fn two(text: &str) -> impl Iterator<Item = &str> {
text
.lines()
.filter(|line| line.contains("2"))
}
fn main() {
let choice = true;
let text = "\
this line contains 1
this line contains 2
this line contains neither";
let result = if choice {
one(text)
} else {
two(text)
};
}
The compiler complains in the main function because of a mistmatch in the if block.
5 posts - 3 participants
๐ท๏ธ Rust_feed