Rust: Trait inference not working when variable is a reference - rust

I am implementing a linked list in Rust, and so far, the best way I have found to let the nodes point to other nodes or point to nothing is multiple structs that implement the same trait. (Option wouldn't work, because I couldn't figure out how to modify the item inside the Option without consuming the Option.) To make sure all nodes are owned, I have each node own the next node but have a reference to the previous node.
**Yeah, I know my method of accessing the SomeLLElement fields by calling get_LL_element and then unwrapping the Option is quite janky. If you can think of something better, please let me know.
struct EmptyLLElement;
struct SomeLLElement<'a, T> {
val: T,
next: Box<dyn LLElement<'a, T>>,
prev: &'a Box<dyn LLElement<'a, T>>,
}
fn LLEmpty() -> Box<EmptyLLElement> {
Box::new(EmptyLLElement)
}
trait LLElement<'a, T>{
fn get_LL_element(self) -> Option<SomeLLElement<'a, T>>;
}
impl <'a, T> LLElement<'a, T> for EmptyLLElement {
fn get_LL_element(self) -> Option<SomeLLElement<'a, T>> {
None
}
}
impl <'a, T> LLElement<'a, T> for SomeLLElement<'a, T> {
fn get_LL_element(self) -> Option<SomeLLElement<'a, T>> {
Some(self)
}
}
fn main(){
let myvar: Box<dyn LLElement<i32>> = Box::new(SomeLLElement{ val: 1, next: LLEmpty(), prev: &LLEmpty() });
let myvar2: SomeLLElement<i32> = match myvar.get_LL_element() {
Some(x) => x,
None => panic!("Empty!")
};
// println!("{}", myvar2.val);
}
The compiler is not allowing me to pass in the empty object (&LLEmpty()) to SomeLLElement.prev.
error[E0308]: mismatched types
--> src\main.rs:69:97
|
69 | let myvar: Box<dyn LLElement<i32>> = Box::new(SomeLLElement{ val: 1, next: LLEmpty(), prev: &LLEmpty() });
| ^^^^^^^^^^ expected trait object `dyn LLElement`, found struct `EmptyLLElement`
|
= note: expected reference `&Box<(dyn LLElement<'_, {integer}> + 'static)>`
found reference `&Box<EmptyLLElement>`
If I remove the ampersand from that line
let myvar: Box<dyn LLElement<i32>> = Box::new(SomeLLElement{ val: 1, next: LLEmpty(), prev: LLEmpty() });
and make prev an object instead of a reference,
prev: Box<dyn LLElement<'a, T>>,
--which is not what I want to do, but hey--the error goes away. The compiler should be able to see that EmptyLLElement is an instance of dyn LLElement, right? Shouldn't that also mean that &Box<EmptyLLElement> is compatible for &Box<dyn LLElement>?

EmptyLLElement is a struct, not a trait, so Box<EmptyLLElement> is just a boxed value, not a trait object. You'd need to change LLEmpty to return a Box<dyn LLElement> or create a trait object from the EmptyLLElement directly in your main function.
You can use options instead of traits for this, however, and it's probably more idiomatic to do so. To mutate the value inside an option without moving it, you can match on it with ref mut:
if let Some(ref mut value) = option {
// mutate `value` here
}
You might also find Learn Rust With Entirely Too Many Linked Lists a good read.

Related

How to create a recursive queue?

I am trying to implement a recursive queue using the trait Element<T> as a container for all the functions of the different nodes of the queue and two structs implementing it called Node<T> and End.
The Node<T> struct is supposed to handle all the functionality within the queue itself and the End struct's purpose is to deal with the case of the last node.
I've got the following code:
trait Element<T> {
fn append_item(self, item: T) -> Node<T>;
}
struct Node<T> {
data: T,
successor: Box<dyn Element<T>>
}
impl<T> Element<T> for Node<T> {
fn append_item(mut self, item: T) -> Node<T> {
self.successor = Box::new(self.successor.append_item(item));
self
}
}
struct End;
impl<T> Element<T> for End {
fn append_item(self, item: T) -> Node<T> {
Node { data: item, successor: Box::new(self) }
}
}
The problem is, that I get two errors:
Cannot move a value of type dyn Element<T>
The parameter type T may not live long enough
both on the same line in Node::append_item.
Now, I get why the first error occurs (because the size of dyn Element<T> cannot be statically determined) but I don't know how to work around it and I have no idea why the second error occurs.
error[E0161]: cannot move a value of type `dyn Element<T>`
--> src/lib.rs:12:35
|
12 | self.successor = Box::new(self.successor.append_item(item));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the size of `dyn Element<T>` cannot be statically determined
The issue here is that fn append_item(self, item: T) takes self by value, but in this case self has type dyn Element<T>, which is unsized and can therefore never be passed by value.
The easiest solution here is to just take self: Box<Self> instead. This means that this method is defined on a Box<E> instead of directlThis will work perfectly fine with trait objects like dyn Element<T>, and it does not require the type to be sized.
(Additionally, in the updated code below, I've changed the return type to Box<Node<T>> for convenience, but this is not required per se, just a bit more convenient.)
trait Element<T> {
fn append_item(self: Box<Self>, item: T) -> Box<Node<T>>;
}
impl<T> Element<T> for Node<T> {
fn append_item(mut self: Box<Self>, item: T) -> Box<Node<T>> {
self.successor = self.successor.append_item(item);
self
}
}
impl<T> Element<T> for End {
fn append_item(self: Box<Self>, item: T) -> Box<Node<T>> {
Box::new(Node { data: item, successor: self })
}
}
[Playground link]
error[E0310]: the parameter type `T` may not live long enough
--> src/lib.rs:12:26
|
12 | self.successor = Box::new(self.successor.append_item(item));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
The issue here is that dyn Trait has an implicit lifetime. In reality, it's dyn '_ + Trait. What exactly that lifetime is depends on the context, and you can read the exact rules in the Rust reference, but if neither the containing type nor the trait itself has any references, then the lifetime will always be 'static.
This is the case with Box<dyn Element<T>>, which really is Box<dyn 'static + Element<T>>. In other words, whatever type is contained by the Box must have a 'static lifetime. For this to be the case for Node<T>, it must also be that T has a 'static lifetime.
This is easy to fix, though: just follow the compiler's suggestion to add a T: 'static bound:
impl<T: 'static> Element<T> for Node<T> {
// ^^^^^^^^^
// ...
}
[Playground link)
Frxstrem already elaborated how to get around the need to move by using Box<Self> as receiver. If you need more flexibility in the parameter type (i.e. be able to hold on to references as well as owned types) instead of requiring T: 'static you can introduce a named lifetime:
trait Element<'a, T: 'a> {
fn append_item(self: Box<Self>, item: T) -> Node<'a, T>;
}
struct Node<'a, T: 'a> {
data: T,
successor: Box<dyn Element<'a, T> + 'a>,
}
impl<'a, T: 'a> Element<'a, T> for Node<'a, T> {
fn append_item(self: Box<Self>, new_data: T) -> Node<'a, T> {
Node {
successor: Box::new(self.successor.append_item(new_data)),
..*self
}
}
}
struct End;
impl<'a, T: 'a> Element<'a, T> for End {
fn append_item(self: Box<Self>, data: T) -> Node<'a, T> {
Node {
data,
successor: self,
}
}
}

Why do I get the error "the trait `Iterator` is not implemented" for a reference to a generic type even though it implements IntoIterator?

In the following example, MyTrait extends IntoIterator but the compiler doesn't recognize it when used in a loop.
pub trait MyTrait: IntoIterator<Item = i32> {
fn foo(&self);
}
pub fn run<M: MyTrait>(my: &M) {
for a in my {
println!("{}", a);
}
}
I get the error:
error[E0277]: `&M` is not an iterator
--> src/lib.rs:6:14
|
6 | for a in my {
| ^^ `&M` is not an iterator
|
= help: the trait `Iterator` is not implemented for `&M`
= note: required because of the requirements on the impl of `IntoIterator` for `&M`
= note: required by `into_iter`
Only M implements IntoIterator, but you're trying to iterate over a &M, which doesn't have to.
It's not clear what you hope to achieve with run, but removing the reference might be a start:
pub fn run<M: MyTrait>(my: M) {
for a in my {
println!("{}", a);
}
}
Note that M itself may be (or contain) a reference, so writing it in this way doesn't mean you can't use it with borrowed data. Here's one way to use run to iterate over a &Vec (playground):
impl<I> MyTrait for I
where
I: IntoIterator<Item = i32>,
{
fn foo(&self) {}
}
fn main() {
let v = vec![10, 12, 20];
run(v.iter().copied());
}
This uses .copied() to turn an Iterator<Item = &i32> to an Iterator<Item = i32>.
Related questions
Why is a borrowed range not an iterator, but the range is?
Am I incorrectly implementing IntoIterator for a reference or is this a Rust bug that should be reported?
How to implement Iterator and IntoIterator for a simple struct?
What is an idiomatic way to collect an iterator of &T into a collection of Ts?
How to properly pass Iterators to a function in Rust

`cannot infer an appropriate lifetime for autoref due to conflicting requirements` but can't change anything due to trait definition constraints

I was implementing linked lists by following along too many linked lists. When trying to implement iter_mut(), I did it myself and made the following code:
type Link<T> = Option<Box<Node<T>>>;
pub struct List<T> {
head: Link<T>,
}
struct Node<T> {
elem: T,
next: Link<T>,
}
impl<T> List<T> {
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut::<T>(&mut self.head)
}
}
pub struct IterMut<'a, T>(&'a mut Link<T>);
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next<'b>(&'b mut self) -> Option<&'a mut T> {
self.0.as_mut().map(|node| {
self.0 = &mut (**node).next;
&mut (**node).elem
})
}
}
I am to avoiding coersions and elisions because being explicit lets me understand more.
Error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/third.rs:24:16
|
24 | self.0.as_mut().map(|node| {
| ^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'b` as defined on the method body at 23:13...
--> src/third.rs:23:13
|
23 | fn next<'b>(&'b mut self) -> Option<&'a mut T> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/third.rs:24:9
|
24 | self.0.as_mut().map(|node| {
| ^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 20:6...
--> src/third.rs:20:6
|
20 | impl<'a, T> Iterator for IterMut<'a, T> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/third.rs:25:22
|
25 | self.0 = &mut (**node).next;
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0495`.
I have looked at Cannot infer an appropriate lifetime for autoref due to conflicting requirements.
I understand a bit but not much. The problem that I am facing here is that if I try to change anything, an error pops saying that can't match the trait definition.
My thought was that basically I need to state somehow that lifetime 'b outlives 'a i.e <'b : 'a> but I can't figure out how to do it. Also, I have similar functions to implement iter() which works fine. It confuses me why iter_mut() produces such errors.
Iter
type Link<T> = Option<Box<Node<T>>>;
pub struct Iter<'a, T>(&'a Link<T>);
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.0.as_ref().map(|node| {
self.0 = &((**node).next);
&((**node).elem)
})
}
}
impl<T> List<T> {
pub fn iter(&self) -> Iter<T> {
Iter::<T>(&self.head)
}
}
☝️This works.
The key thing is that you need to be able to somehow extract an Option<&'a mut T> from a &'b mut IterMut<'a, T>.
To understand why IterMut<'a, T> := &'a mut Link<T> can't work, you need to understand what exactly you can do with a mutable reference. The answer, of course, is almost everything. You can copy data out of it, change its value, and lots of other things. The one thing you can't do is invalidate it. If you want to move the data under the mutable reference out, it has to be replaced with something of the same type (including lifetimes).
Inside the body of next, self is (essentially) &'b mut &'a mut Link<T>. Unless we know something about T (and we can't in this context), there's simply no way to produce something of type &'a mut Link<T> from this. For example, if this were possible in general, we'd be able to do
fn bad<'a, 'b, T>(_x: &'b mut &'a mut T) -> &'a mut T {
todo!()
}
fn do_stuff<'a>(x: &'a mut i32, y: &'a mut i32) {
// lots of stuff that only works if x and y don't alias
*x = 13;
*y = 42;
}
fn main() {
let mut x: &mut i32 = &mut 0;
let y: &mut i32 = {
let z: &mut &mut i32 = &mut x;
bad(z)
};
// `x` and `y` are aliasing mutable references
// and we can use both at once!
do_stuff(x, y);
}
(playground link)
The point is that if we were able to borrow something for a short (generic) lifetime 'b and return something that allowed modification during the longer lifetime 'a, we'd be able to use multiple short lifetimes (shorter than 'a and non-overlapping) to get multiple mutable references with the same lifetime 'a.
This also explains why the immutable version works. With immutable references, it's trivial to go from &'b &'a T to &'a T: just deference and copy the immutable reference. By contrast, mutable references don't implement Copy.
So if we can't produce a &'a mut Link<T> from a &'b mut &'a mut Link<T>, we certainly can't get an Option<&'a mut T out of it either (other than None). (Note that we can produce a &'b mut Link<T> and hence an Option<'b mut T>. That's what your code does right now.)
So what does work? Remember our goal is to be able to produce an Option<&'a mut T> from a &'b mut IterMut<'a, T>.
If we were able to produce a IterMut<'a, T> unconditionally, we'd be able to (temporarily) replace self with it and hence be able to directly access the IterMut<'a, T> associated to our list.
// This actually type-checks!
fn next<'b>(&'b mut self) -> Option<&'a mut T> {
let mut temp: IterMut<'a, T> = todo!(); // obviously this won't work
std::mem::swap(&mut self.0, &mut temp.0);
temp.0.as_mut().map(|node| {
self.0 = &mut node.next;
&mut node.elem
})
}
(playground link)
The easiest way to set things up so that this all works is by transposing IterMut<'a, T> a bit. Rather than having the mutable reference outside the option, make it inside! Now you'll always be able to produce an IterMut<'a, T> with None!
struct IterMut<'a, T>(Option<&mut Box<Node<T>>>);
Translating next, we get
fn next<'b>(&'b mut self) -> Option<&'a mut T> {
let mut temp: IterMut<'a, T> = IterMut(None);
std::mem::swap(&mut self.0, &mut temp.0);
temp.0.map(|node| {
self.0 = node.next.as_mut();
&mut node.elem
})
}
More idiomatically, we can use Option::take rather than std::mem::swap (This is mentioned earlier in Too Many Linked Lists).
fn next<'b>(&'b mut self) -> Option<&'a mut T> {
self.0.take().map(|node| {
self.0 = node.next.as_mut();
&mut node.elem
})
}
(playground link)
This actually ends up being slightly different than the implementation in Too Many Linked Lists. That implementation removes the double indirection of &mut Box<Node<T>> and replaces it with simply &mut Node<T>. However, I'm not sure how much you gain since that implementation still has a double deref in List::iter_mut and Iterator::next.
Rust is trying to say that you have a dangling reference.
self.0.as_mut() // value borrowed
self.0 = <> // underlying value changed here.
The problem is the following definition:
pub struct IterMut<'a, T>(&'a mut Link<T>)
This can't encapsulate that you will have a "empty" node meaning reached the end of the node.
Use the structure as mentioned in the book like:
pub struct IterMut<'a, T>(Option<&'a mut Node<T>>);
This ensures that you can leave None in its place when you run end of list and use take to modify the IterMut content behind the scenes.

Why does the compiler claim that an associated type from a higher-ranked trait bound doesn't implement `Display` even though it should?

I'm building a library that implements string joins; that is, printing all the elements of a container separated by a separator. My basic design looks like this:
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Join<Container, Sep> {
container: Container,
sep: Sep,
}
impl<Container, Sep> fmt::Display for Join<Container, Sep>
where
for<'a> &'a Container: IntoIterator,
for<'a> <&'a Container as IntoIterator>::Item: fmt::Display,
Sep: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut iter = self.container.into_iter();
match iter.next() {
None => Ok(()),
Some(first) => {
first.fmt(f)?;
iter.try_for_each(move |element| {
self.sep.fmt(f)?;
element.fmt(f)
})
}
}
}
}
This trait implementation compiles without complaint. Notice the bound on &'a C: IntoIterator. Many containers implement IntoIterator for a reference to themselves, to allow for iterating over references to the contained items (for instance, Vec implements it here).
However, when I actually try to use my Join struct, I get an unsatisfied trait bound:
fn main() {
let data = vec!["Hello", "World"];
let join = Join {
container: data,
sep: ", ",
};
println!("{}", join);
}
This code produces a compilation error:
error[E0277]: `<&'a std::vec::Vec<&str> as std::iter::IntoIterator>::Item` doesn't implement `std::fmt::Display`
--> src/main.rs:38:20
|
38 | println!("{}", join);
| ^^^^ `<&'a std::vec::Vec<&str> as std::iter::IntoIterator>::Item` cannot be formatted with the default formatter
|
= help: the trait `for<'a> std::fmt::Display` is not implemented for `<&'a std::vec::Vec<&str> as std::iter::IntoIterator>::Item`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
= note: required because of the requirements on the impl of `std::fmt::Display` for `Join<std::vec::Vec<&str>, &str>`
= note: required by `std::fmt::Display::fmt`
The key line seems to be this:
the trait `for<'a> std::fmt::Display` is not implemented for `<&'a std::vec::Vec<&str> as std::iter::IntoIterator>::Item`
Unfortunately, the compiler doesn't actually tell me what the Item type is, but based on my reading of the docs, it appears to be &T, which in this case means &&str.
Why doesn't the compiler think that &&str implements Display? I've tried this with many other types, like usize and String, and none of them work; they all fail with the same error. I know that these reference type don't directly implement Display, but the implementation should be picked up automatically through deref coercion, right?
Seems like a compiler limitation. You can work around it for now by writing the impl bound in terms of a private helper trait that represents "display with lifetime". This enables the compiler to see that for<'a> private::Display<'a> implies fmt::Display.
use std::fmt;
pub struct Join<Container, Sep> {
container: Container,
sep: Sep,
}
mod private {
use std::fmt;
pub trait Display<'a>: fmt::Display {}
impl<'a, T> Display<'a> for T where T: fmt::Display {}
}
impl<Container, Sep> fmt::Display for Join<Container, Sep>
where
for<'a> &'a Container: IntoIterator,
for<'a> <&'a Container as IntoIterator>::Item: private::Display<'a>,
Sep: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut iter = self.container.into_iter();
match iter.next() {
None => Ok(()),
Some(first) => {
first.fmt(f)?;
iter.try_for_each(move |element| {
self.sep.fmt(f)?;
element.fmt(f)
})
}
}
}
}
fn main() {
println!(
"{}",
Join {
container: vec!["Hello", "World"],
sep: ", ",
}
);
}

Can I borrow self immutably for self.callbacks: Vec<Box<FnMut>>?

pub struct Notifier<'a, T> {
callbacks: Vec<Box<'a + FnMut(&T)>>
}
impl<'a, T> Notifier<'a, T>{
fn add_callback<F: 'a + FnMut(&T)>(&mut self, callback: F) {
self.callbacks.push(Box::new(callback));
}
fn trigger(&mut self, payload: T) {
for callback in &mut self.callbacks {
callback(&payload);
}
}
}
struct A {
x: i64
}
impl A {
fn foo(&mut self, x: &i64) {
self.x = x + 1;
}
}
fn test() {
let mut bar = A {x: 3};
let mut notifier = Notifier{callbacks: Vec::new()};
notifier.add_callback(|x| bar.foo(x));
}
Playground
This is a simple observer pattern implemented using callbacks. It works.
However, the fact that trigger(&mut self... causes much trouble in my later coding (How to update self based on reference of value from hashmap from self). Is it possible to make trigger(&self ... instead?
I'm using rustc 1.19.0-nightly.
If you want to change the interior of a struct without having the struct mutable, you should use a Cell:
Values of the Cell<T> and RefCell<T> types may be mutated through shared references (i.e. the common &T type), whereas most Rust types can only be mutated through unique (&mut T) references. We say that Cell<T> and RefCell<T> provide 'interior mutability', in contrast with typical Rust types that exhibit 'inherited mutability'.
Playground

Resources