M
Modular•9mo ago
Phazer

Store Reference in struct

Is there an example on how to create a struct with a Reference field?
17 Replies
a2svior
a2svior•9mo ago
I saw a couple examples from Chris here if it's helpful https://github.com/modularml/mojo/discussions/1568#discussioncomment-8251023
GitHub
Inferred Mutability: Reachability-based reference lifetime/mutabili...
Summary of idea: The borrow checker shall track the reachability from one reference to another reference within the function (whenever feasible). Inter-procedurally, the type signature may associat...
TilliFe
TilliFe•9mo ago
Is someone able to provide a real example of a struct with a reference as a field? This would be greatly appreciated. 🙂 (The examples by Chris does not specify what thisLifetime actually is in an instantiation)
Michael K
Michael K•9mo ago
@value
struct RefString[L: MutLifetime]:
var s: Reference[String, __mlir_attr.`1: i1`, L]


fn main():
var a = String("hello")
let b = String("world")

let r = Reference(a)
let rs = RefString(r)
rs.s[] += b

print(a)
@value
struct RefString[L: MutLifetime]:
var s: Reference[String, __mlir_attr.`1: i1`, L]


fn main():
var a = String("hello")
let b = String("world")

let r = Reference(a)
let rs = RefString(r)
rs.s[] += b

print(a)
gabrieldemarmiesse
gabrieldemarmiesse•9mo ago
In this example, if the struct rs is returned, I wonder how it works, since the string it's pointing to is on the stack and will be destroyed when the function returns
TilliFe
TilliFe•9mo ago
Sure this works. But what if we want to use other structs than Strings? E.g. a Tensor or something? Then what is L?
gabrieldemarmiesse
gabrieldemarmiesse•9mo ago
I think it's the same
TilliFe
TilliFe•9mo ago
I t is not: @value struct RefTensor[L: MutLifetime]: var tensor_ref: Reference[Tensor, __mlir_attr.1: i1, L] fn main(): var a = TensorDType.float32 var r = Reference(a) var rs = RefTensor(r) # Error: cannot construct 'RefTensor[?]' from 'Reference[Tensor[f32], 1, *"a`0"]' value in 'var' initializer
benny
benny•9mo ago
i’ve had trouble getting References working well, idk that they are ready for production code yet
Michael K
Michael K•9mo ago
struct RefTensor[L: MutLifetime]:
var tensor_ref: Reference[Tensor, __mlir_attr.1: i1, L]
struct RefTensor[L: MutLifetime]:
var tensor_ref: Reference[Tensor, __mlir_attr.1: i1, L]
should be
struct RefTensor[L: MutLifetime]:
var tensor_ref: Reference[Tensor[DType.float32], __mlir_attr.1: i1, L]
struct RefTensor[L: MutLifetime]:
var tensor_ref: Reference[Tensor[DType.float32], __mlir_attr.1: i1, L]
Tensor was missing its type parameter.
TilliFe
TilliFe•9mo ago
crazy times
ModularBot
ModularBot•9mo ago
Congrats @TilliFe, you just advanced to level 3!
TilliFe
TilliFe•9mo ago
thank you
Michael K
Michael K•9mo ago
I think this is what Reference is designed to fix. If I understand your question correctly, this example demonstrates how that works .
@value
struct RefString[L: MutLifetime]:
var s: Reference[String, __mlir_attr.`1: i1`, L]

fn build_string_reference[
L: MutLifetime
](s: Reference[String, __mlir_attr.`1: i1`, L]) -> RefString[L]:
return RefString(s)


fn main():
var a = String("hello")
let b = String("world")
let rs = build_string_reference(Reference(a))

rs.s[] += b
print(rs.s[])
@value
struct RefString[L: MutLifetime]:
var s: Reference[String, __mlir_attr.`1: i1`, L]

fn build_string_reference[
L: MutLifetime
](s: Reference[String, __mlir_attr.`1: i1`, L]) -> RefString[L]:
return RefString(s)


fn main():
var a = String("hello")
let b = String("world")
let rs = build_string_reference(Reference(a))

rs.s[] += b
print(rs.s[])
I think the problem you are describing is what References and Lifetimes are designed to manage. The lifetime of a gets shared with its references and prevents the immediate destruction of a after its last use. I altered the last line so a is not used and you can see the result still prints correctly because the string has not been destroyed.
gabrieldemarmiesse
gabrieldemarmiesse•9mo ago
I had in my mind something like this, wondering how it would work:
@value
struct RefString[L: MutLifetime]:
var s: Reference[String, __mlir_attr.`1: i1`, L]

fn some_factory_func() -> RefString:
var a = String("hello")
let b = String("world")

let r = Reference(a)
let rs = RefString(r)
rs.s[] += b

return rs


fn main():
print(some_factory_func().s[])
@value
struct RefString[L: MutLifetime]:
var s: Reference[String, __mlir_attr.`1: i1`, L]

fn some_factory_func() -> RefString:
var a = String("hello")
let b = String("world")

let r = Reference(a)
let rs = RefString(r)
rs.s[] += b

return rs


fn main():
print(some_factory_func().s[])
But that can't work because when calling some_factory_func, it's not possible to specify a lifetime yet. (i get /projects/open_source/mojo-stdlib-extensions/trying_stuff.mojo:5:27: error: 'RefString' expects 1 input parameter, but 0 were specified, fn some_factory_func() -> RefString:) Furthermore, the variable a is on the stack, thus it will be destroyed when some_factory_func returns.
ModularBot
ModularBot•9mo ago
Congrats @gabrieldemarmiesse, you just advanced to level 8!
gabrieldemarmiesse
gabrieldemarmiesse•9mo ago
I guess that maybe it would work if a was on the heap and not on the stack? But I'm unsure on how to do this with Mojo
nickfury3398
nickfury3398•9mo ago
Is there some way to explicitly pass in L? I would like to have a RefString in the field of another struct
Want results from more Discord servers?
Add your server