How to return a mutable reference to a struct member in a trait?

I’m trying to write a trait that has a function which returns a mutable reference to some member in the struct that will implement the trait. Something like this:

trait Trait:
    fn get_x(ref self) -> ref[self] List[Int]:
        ...


struct State(Trait):
    var x: List[Int]

    fn __init__(out self):
        self.x = List[Int]()

    fn get_x(ref self) -> ref[self] List[Int]:
        return self.x


fn modify_x[T: Trait](mut state: T):
    state.get_x().append(2)


fn main():
    state = State()
    modify_x(state)

I get this error when I try to run the above code:

main.mojo:13:20: error: cannot return reference with incompatible origin: ‘self_is_origin.x’ vs ‘self_is_origin’
return self.x

I’m not sure how can I assign the origin of self.x in the trait since the trait doesn’t know about the existence of the member variable.

Mojo defaults to read, so you’re taking an immutable reference to state in modify_x which means you can only borrow x immutably. Try changing it to `mut state: T`.

Oops, sorry that was typo. That’s not the issue that I’m referring to though. I still get this

main.mojo:13:20: error: cannot return reference with incompatible origin: ‘self_is_origin.x’ vs ‘self_is_origin’
return self.x
^

try fn get_x(ref self) -> ref[self.x] List[Int]:

That won’t match the trait definition. Yes, I can get a mutable reference without a trait. The question is about how to declare functions in the trait to get mutable references to members of structs that implement the trait

I think you’ve run into a hole in the origin system. Right now the best way to deal with this is to use a pointer to cast the origin.

1 Like

Oh, okay. Can you tell me how to do that?

You need to make an UnsafePointer and then use origin_cast

1 Like

+1, as Owen says this is an unpaved road in the origin system. We’re interested in improving this, but it won’t happen in the immediate future, so a workaround will be required.

2 Likes

Given that this does have trait conformance implications, is a way to “upcast” an origin (ex: self.xself) something that would be reasonable to implement on a shorter timeline?

Is there a way to know which origin casts are “safe”? Like, is a cast from self.attr to self always safe?

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.