Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Replace __copyinit__ (a constructor) with an ordinary instance method named __copy__. (And do the same for move constructors.) #3914

Open
1 task done
nmsmith opened this issue Dec 27, 2024 · 2 comments
Labels
enhancement New feature or request mojo-repo Tag all issues with this label

Comments

@nmsmith
Copy link
Contributor

nmsmith commented Dec 27, 2024

Review Mojo's priorities

What is your request?

Following a discussion on Discord #nightly, I propose that we turn __copyinit__ and __moveinit__ into instance methods, and update their names to reflect this change.

In today's Mojo, __copyinit__ is modelled as a special kind of constructor. More precisely, the following program:

var x: Int = 2
var y: Int
y = x

Desugars to:

var x: Int = 2
var y: Int
y = Int.__copyinit__(x)

In my opinion, this is not a very intuitive model for copy operations. It would be simpler if y = x desugared to a method call on x:

var x: Int = 2
var y: Int
y = x.__copy__()

A similar issue occurs with __moveinit__. Ideally, the following program:

var x: Int = 2
var y: Int
y = x^

Would desugar to:

var x: Int = 2
var y: Int
y = x^.__move__()

CC @lattner.

What is your motivation for this change?

To make it easier for Mojo learners to understand what happens when you write y = x or y = x^.

Any other details?

__copy__ and __move__ would still need to be "constructor-like" in that they can initialize their return value field-by-field. In the short term, we can make this happen though compiler magic, as happens for constructors. In the long term, maybe we should try to find a general way to designate a method as being a constructor.

If we agree to adopt this proposal, we should probably first let the design for explicit copyability settle, since this might affect the name that we give the __copy__ method.

@nmsmith nmsmith added enhancement New feature or request mojo-repo Tag all issues with this label labels Dec 27, 2024
@lattner
Copy link
Collaborator

lattner commented Dec 28, 2024

Thanks Nick! FYI y = Int.__copyinit__(x) is the same as y = x.__copyinit__() so this is mostly just a question of what we want the declaration side syntax to look like. Is it an "initializer" or not. I'll raise this with the team over the next weeks. I appreciate you filing this!

@nmsmith
Copy link
Contributor Author

nmsmith commented Dec 28, 2024

@lattner

FYI y = Int.__copyinit__(x) is the same as y = x.__copyinit__()

I don't think this is the case. Try running this program on nightly:

struct Foo:
    var x: Int

    fn __init__(out self, x: Int):
        self.x = x

    fn __copyinit__(out self, other: Foo):
        self.x = other.x


fn main():
    a = Foo(3)
    b = Foo.__copyinit__(a)
    b = a.__copyinit__()  # error: invalid call to '__copyinit__': missing 1 required positional argument: 'other'

This error makes sense, because afaik __copyinit__ is currently an (implicit) static method, just like __init__.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request mojo-repo Tag all issues with this label
Projects
None yet
Development

No branches or pull requests

2 participants