My understanding is that Mojo is good of optimizing away things that are not used, which is one reason why origins need to be set properly so that the compiler knows about what is used.
I wonder how to do that properly in nontrivial cases, in which the actual origin is only known at runtime, such as for container elements. Consider this example:
@value
struct S1:
var value: Int
@value
struct S2:
var data: List[S1]
fn get(ref self, owned i: Int) -> ref [self.data[0].value] Int:
if self.data[i].value == 1:
i += 1
return self.data[i].value
def main():
s = S2(List(S1(1), S1(2)))
print(s.get(0))
print(s.get(1))
This compiles fine. However, here, the origin of the reference is always set to the first element in S2.data, and if the compiler was using this information, some errors might occur.
I therefore have the following questions:
How does the compiler use the origin information?
Why does my example work?
Am I somewhat free in choosing the origin? What could go wrong?
What could / should I do in cases where the origin is only known at runtime? (Potentially cases exceeding my example in complexity)?
No. And even if, (after all, the shown solution works) I would like to better understand what is going on and how to do things correctly. (See the questions.)
The implementation (and design) of Mojo origins is still incomplete. Chris Lattner is the only person who is able to precisely explain the status of the incomplete implementation, because he wrote it.
By the time origins are finished, the signature of S2.get should look something like: fn get(ref self, owned i: Int) -> ref [self.data.element_origin.value] Int:
In other words, the elements of the collection get their own “element origin”. This avoids needing to describe everything in terms of a particular element, such as data[0].
What could / should I do in cases where the origin is only known at runtime? (Potentially cases exceeding my example in complexity)?
Origins need to be known at compile-time. element_origin facilitates this, even when you’re returning a reference to an element whose offset is computed at runtime.
Modular will publish detailed documentation on how origins work once the design is finalized. Until then, if you need to work with origins, I suggest using the source code of Mojo’s standard library (and this docs page) as a guide.