Return with move semantics

Is that possible to use the move semantic when returning a value from a function? The code below would give error:
from tensor import Tensor


struct Value[dtype: DType]:
alias TensorD = Tensor[dtype]
var data: Self.TensorD

fn __init__(inout self):
self.data = Self.TensorD()

fn foo(self) -> Self:
var v = Self()
return v


fn main():
alias FValue = Value[DType.float16]
var v1 = FValue()
var v2 = FValue()
var v3 = v1.foo()
from tensor import Tensor


struct Value[dtype: DType]:
alias TensorD = Tensor[dtype]
var data: Self.TensorD

fn __init__(inout self):
self.data = Self.TensorD()

fn foo(self) -> Self:
var v = Self()
return v


fn main():
alias FValue = Value[DType.float16]
var v1 = FValue()
var v2 = FValue()
var v3 = v1.foo()
error: 'Value[dtype]' is not copyable because it has no 'copyinit' return v ^ mojo: error: failed to parse the provided Mojo source module
2 Replies
Ryulord
Ryulord8mo ago
this should work
from tensor import Tensor

@value
struct Value[dtype: DType]:
alias TensorD = Tensor[dtype]
var data: Self.TensorD

fn __init__(inout self):
self.data = Self.TensorD()

fn foo(owned self) -> Self:
return self^
from tensor import Tensor

@value
struct Value[dtype: DType]:
alias TensorD = Tensor[dtype]
var data: Self.TensorD

fn __init__(inout self):
self.data = Self.TensorD()

fn foo(owned self) -> Self:
return self^
I'm not 100% sure if your intention is to consume v1 when calling foo, which is what should happen in my example or if the goal is to return a new value. You need moveinit on Value to move it, which the @value decorator provides. You also need to use the move operator ^ to specify that you'd like to move the value during the return rather than copy. If you'd like to move the new value then simply adding the move operator to your return statement in foo is all you need to do.
geauxeric
geauxericOP8mo ago
thanks! this works:
struct Value[dtype: DType]:
alias TensorD = Tensor[dtype]
var data: Self.TensorD

fn __init__(inout self):
self.data = Self.TensorD()

fn __moveinit__(inout self, owned existing: Self):
self.data = existing.data

fn foo(self) -> Self:
var v = Self()
return v^


fn main():
alias FValue = Value[DType.float16]
var v1 = FValue()
var v2 = FValue()
var v3 = v1.foo()
struct Value[dtype: DType]:
alias TensorD = Tensor[dtype]
var data: Self.TensorD

fn __init__(inout self):
self.data = Self.TensorD()

fn __moveinit__(inout self, owned existing: Self):
self.data = existing.data

fn foo(self) -> Self:
var v = Self()
return v^


fn main():
alias FValue = Value[DType.float16]
var v1 = FValue()
var v2 = FValue()
var v3 = v1.foo()
For now I kind of want to avoid using @value as I am still exploring the data model and not sure about their lifetimes.
Want results from more Discord servers?
Add your server