Make index return value with lifetime [duplicate] - rust

This question already has answers here:
Implementing Index trait to return a value that is not a reference
(2 answers)
How do I specify lifetime parameters in an associated type?
(3 answers)
Closed 3 years ago.
I would like indexing of my type to return a structure bounded with lifetime. The structure needs to contain a reference to the original type to be able to run some methods on it, like foo[index].bar().
When I try a simple approach
impl<'a> Index<usize> for Foo {
type Output = FooIndex<'a>;
fn index(&self, index: usize) -> &Self::Output {
FooIndex {
index,
foo: &self,
}
}
}
I get the following
error[E0207]: the lifetime parameter 'a is not constrained by the impl trait, self type, or predicates
Is there any way how to do it?

Related

How to implement a trait when an associated type includes a closure? [duplicate]

This question already has answers here:
Is it possible to use `impl Trait` as a function's return type in a trait definition?
(4 answers)
What is the correct way to return an Iterator (or any other trait)?
(2 answers)
Closed 1 year ago.
I would like to implement IntoIterator using a map over an iterator, like this:
struct MyStruct {
txt: String,
}
impl IntoIterator for MyStruct {
type Item = String;
type IntoIter = std::iter::Map<std::ops::Range<char>, WhatAmISupposedToWriteHere>;
fn into_iter(self) -> Self::IntoIter {
('a'..'z').into_iter().map(move |c| {
let mut t = self.txt.clone();
t.push(c);
t
})
}
}
What is the type of my |c| self.txt.clone().push(c) closure that I'd have to write into the IntoIter type?
The IDE says the type is [closure#src/example.rs:16:36: 16:64] which isn't very useful.
I tried dyn Fn(char) -> String but then the compiler complains that IntoIter doesn't have a size known at compile-time.
I also tried just writing _ instead of a specific type, but an _ is not allowed in a type signature - although it looks like the compiler can definitely find out the type on its own, so it would be nice if it would just magically define IntoIter for me.
What is the correct way of using map when implementing IntoIterator?

How can I downcast a dyn trait into another trait in Rust? [duplicate]

This question already has answers here:
Why can't `&(?Sized + Trait)` be cast to `&dyn Trait`?
(3 answers)
Can I cast between two traits?
(5 answers)
Why can a &str not be passed to a function accepting a &dyn Display trait object?
(1 answer)
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Duplicate This question has been answered, is not unique, and doesn’t differentiate itself from another question.
I have two Rust traits, and one automatically implements the other:
trait A {
fn something(&self);
}
trait B {}
impl A for dyn B {
fn something(&self) {
println!("hello from B")
}
}
Now I receive a dynamic implementation of B, and I need to return a dynamic implementation of A:
fn downcast(b: Box<dyn B>) -> Box<dyn A> {...}
How can I implement downcast?
Some things I've tried:
I tried to let Rust figure it out statically:
fn downcast(b: Box<dyn B>) -> Box<dyn A> {
b
}
This gives something like
error[E0308]: mismatched types
expected trait `A`, found trait `B`
I tried the same static thing using as or an intermediate variable.
I tried dynamically casting using Any and downcast_ref, but I couldn't get the magic right.

Why can't I return the generic type T from this function? [duplicate]

This question already has answers here:
How to return concrete type from generic function?
(2 answers)
Closed 2 years ago.
I want to return the reference type, but the first make_debug function implementation does not compile. What is the difference between using T or impl std::fmt::Debug for the return type of this function signature?
fn test() -> impl std::fmt::Debug + 'static {
let value = "v".to_string();
make_debug(&value)
}
// This function not work
// fn make_debug<'a, T: std::fmt::Debug>(_: &'a T) -> T {
// 42u8
// }
// This one works well
fn make_debug<'a, T: std::fmt::Debug>(_: &'a T) -> impl std::fmt::Debug {
42u8
}
Playground
Using -> impl std::fmt::Debug means "Hey, I'm gonna return you something of a type that implements Debug, but i don't know what that type is".
while using -> T means "Hey, I'm gonna return something of the T type, which happens to implement Debug"
So the difference is, in the first case you can return a different type than the input and it will work as long as it implements the Debug trait. While the second case you MUST return something of the same type as the Input.

How do I return an iterator over the keys of a HashSet from a trait method? [duplicate]

This question already has answers here:
What is the correct way to return an Iterator (or any other trait)?
(2 answers)
Is it possible to use `impl Trait` as a function's return type in a trait definition?
(4 answers)
"Expected type parameter" error in the constructor of a generic struct
(1 answer)
Closed 3 years ago.
A struct has a set of items I'd like to allow clients to iterate over. Here's an attempt:
use std::collections::HashSet;
use std::hash::Hash;
pub struct Foo<T: Eq + Hash> {
items: HashSet<T>,
}
impl<'a, T: 'a + Eq + Hash> Foo<T> {
pub fn new() -> Self {
Foo {
items: HashSet::new(),
}
}
pub fn iterate<I>(&self) -> I
where
I: IntoIterator<Item = &'a T>,
{
self.items.iter()
}
}
This fails to compile, giving the error:
error[E0308]: mismatched types
--> src/lib.rs:19:9
|
15 | pub fn iterate<I>(&self) -> I
| - expected `I` because of return type
...
19 | self.items.iter()
| ^^^^^^^^^^^^^^^^^ expected type parameter, found struct `std::collections::hash_set::Iter`
|
= note: expected type `I`
found type `std::collections::hash_set::Iter<'_, T>`
= help: type parameters must be constrained to match other types
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
The return value from HashSet::iter method appears to act like an Iterator when, for example within a for loop. It seems like some kind of type coercion might be possible in my iterate method, but clearly the compiler has other ideas.
How can I specify a return type of Iterator in a function while returning the return value from a HashSet iterator?
In other words, I want to delegate iteration to HashSet. I'd like to avoid implementing a custom iterator to do this, but if that's the only way would be interested in seeing how it's done. I've been able to get this working by returning a Box<dyn Iterator>, but I'd like to avoid that approach as well if it's possible to work just with trait boundaries as described in this answer.
One more requirement: the approach must work when the iterate method is declared on a trait. That appears to rule out an approach like:
pub trait FooTrait {
fn iterate(&self) -> impl Iterator<Item=&T>;
}
You want impl Iterator:
impl<'a, T: 'a + Eq + Hash> Foo<T> {
// ...
pub fn iterate(&'a self) -> impl Iterator<Item = &'a T> {
self.items.iter()
}
}
The Rust book has this section covering it. It is defined and refined in RFC 1522, RFC 1951, and RFC 2071. It isn't all done yet and has this tracking issue.

Storing reference to an element in Vec<Box<_>> [duplicate]

This question already has answers here:
How can I model a bidirectional map without annoying the borrow checker?
(1 answer)
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 5 years ago.
I have a struct Oid, which owns a vector of distinct objects. It also has a reverse map which maps an object to its index in the vector. Objects are never deleted from the struct. However, new objects can be added. The use case is simple: I need fast retrieval of an object by its index and of the index of a given object. Here's my attempt so far:
struct Oid<'a, T>
where
T: Eq + Hash,
{
objects: Vec<Box<T>>,
rev_map: HashMap<&'a T, usize>,
}
impl<'a, T> Oid<'a, T>
where
T: Eq + Hash,
{
pub fn insert(&mut self, t: T) -> usize {
match self.objects.get(&t) {
Some(&i) => i,
_ => {
let i = self.objects.size();
self.objects.push(Box::new(t));
self.rev_map
.insert(unsafe { &*(&*self.objects[i] as *const T) }, i);
i
}
}
}
}
As the memory locations of objects can change as the vector grows, I put each object in a Box, which ensures address stability. The problem is in rev_map, I can't figure out how to tell Rust that the object reference will never outlive the struct. Is there a way to do this in idiomatic Rust?

Resources