-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
[mojo-stdlib] Create InlineArray
type
#2294
Conversation
bb96de2
to
05ce12f
Compare
c21d061
to
308aeec
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, looks pretty good! Thanks for pushing on this. This will be a critical core type and will simplify several things. 🎉
This is super cool @lsh great work! |
308aeec
to
8df0770
Compare
There is a problem with how alias arr_const = InlineArray[Int, 3](1, 2, 3)
assert_equal(arr_const[0], 1) A workaround is adding a fn __getitem__(self, idx: Int) -> Self.ElementType:
return self.__refitem__(idx) |
Thanks for calling this out. @lattner would this sort of thing work with the latest top-of-tree Edit: confirmed this won't compile on top-of-tree internally. You get an error:
So, to move forward with this PR, I recommend we file a GitHub issue and (potentially) a commented out failing test case with this GitHub issue number. To make this work at comptime, it can't be solved in the library alone AFAICT — some compiler work is needed. So, we'll handle that internally if that works. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost there! Just one minor comment about the use of VariadicList
, and then I'd be happy to merge this.
92d5a3c
to
b17f87a
Compare
Array
typeInlineArray
type
ac0b52f
to
4bcc86f
Compare
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
4bcc86f
to
e52f174
Compare
# This constructor will always cause a compile time error if used. | ||
# It is used to steer users away from uninitialized memory. | ||
@always_inline | ||
fn __init__(inout self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to flag this constructor, which I'm using as a way to enforce safety guarantees. What do you think about this API? @JoeLoser @ConnorGray
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense, since otherwise a zero-argument call like so:
var arr = InlinedArray[Int, 10]()
would call the variadic constructor. Doing it as an explicit constructor rather than a @parameter if
in the variadic constructor makes sense for now. I don't have a good gauge as to the compile time cost difference between the additional overload (constructor) vs. a @parameter if
in the variadic constructor case. Nothing to worry about for now as we're not at the level of compile time perf problems right now 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI this constructor will need public doc strings since it's a public entity still. We have a PR in-flight internally that adds a decorator (such as @doc_private
) that we could apply to things like this in the future. The API doc string checker wouldn't apply in such cases, and the constructor decl would be hidden in our generated docs too.
I moved your comment from above the constructor to be the doc string internally when I just imported this PR. We also have a PR in-flight in the public mojo
repo so the external CI here can do API doc string validation.
self._array = __mlir_op.`kgen.undef`[_type = Self.type]() | ||
|
||
@always_inline | ||
fn __init__(inout self, fill: Self.ElementType): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bikeshed: is fill
the right word here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SIMD
just uses value
for this kind of constructor. Not sure if that's a great precedent or not, although it's probably clear enough. From the name I wouldn't be sure if fill
was a value or a boolean. Maybe fill_value
or fill_with
?
Also, have you tried to create an InlineArray
of size 1? It looks like the two constructors would be ambiguous in that case. Making this a keyword-only argument would avoid that potential issue.
InlineArray[Int, 10](fill_with=0xFF)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At least on my machine, the constructor of size 1 seems to work fine. I'll add a test to make that clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They're not ambiguous as @lsh points out. Consider the following smaller program that shows this is the case:
struct S:
fn __init__(inout self, value: Int):
print("single argument constructor")
fn __init__(inout self, *values: Int):
print("variadic argument constructor")
fn main():
var s1 = S(42) # prints single argument constructor
var s2 = S(42, 100) # prints variadic argument constructor
Re the name, I'm fine with fill
, default_value
, value
, or any of them. I don't feel strongly and we can easily change it at any time since this isn't a keyword-argument-only constructor (therefore it's just an implementation detail at this point).
Signed-off-by: Lukas Hermann <lukashermann28@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, @lsh! Thanks so much for your patience and working on this, even amidst us making you rebase and rework the code a bit as we changed several things across nightly versions.
I've imported this PR internally and I'll keep you updated on the progress of it.
self._array = __mlir_op.`kgen.undef`[_type = Self.type]() | ||
|
||
@always_inline | ||
fn __init__(inout self, fill: Self.ElementType): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They're not ambiguous as @lsh points out. Consider the following smaller program that shows this is the case:
struct S:
fn __init__(inout self, value: Int):
print("single argument constructor")
fn __init__(inout self, *values: Int):
print("variadic argument constructor")
fn main():
var s1 = S(42) # prints single argument constructor
var s2 = S(42, 100) # prints variadic argument constructor
Re the name, I'm fine with fill
, default_value
, value
, or any of them. I don't feel strongly and we can easily change it at any time since this isn't a keyword-argument-only constructor (therefore it's just an implementation detail at this point).
# This constructor will always cause a compile time error if used. | ||
# It is used to steer users away from uninitialized memory. | ||
@always_inline | ||
fn __init__(inout self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense, since otherwise a zero-argument call like so:
var arr = InlinedArray[Int, 10]()
would call the variadic constructor. Doing it as an explicit constructor rather than a @parameter if
in the variadic constructor makes sense for now. I don't have a good gauge as to the compile time cost difference between the additional overload (constructor) vs. a @parameter if
in the variadic constructor case. Nothing to worry about for now as we're not at the level of compile time perf problems right now 😄
alias i = int(index) | ||
constrained[-size <= i < size, "Index must be within bounds."]() | ||
|
||
var normalized_idx = i |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quibble I think we could do this arithmetic at compile time since size
is a compile time parameter. But totally fine for now. 😄
# This constructor will always cause a compile time error if used. | ||
# It is used to steer users away from uninitialized memory. | ||
@always_inline | ||
fn __init__(inout self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI this constructor will need public doc strings since it's a public entity still. We have a PR in-flight internally that adds a decorator (such as @doc_private
) that we could apply to things like this in the future. The API doc string checker wouldn't apply in such cases, and the constructor decl would be hidden in our generated docs too.
I moved your comment from above the constructor to be the doc string internally when I just imported this PR. We also have a PR in-flight in the public mojo
repo so the external CI here can do API doc string validation.
✅🟣 This contribution has been merged 🟣✅ Hey @lsh, As mentioned, we're moving to a new infrastructure for merging contributions to Mojo (we're using a tool called Copybara), and your contribution has now been merged into our internal copy of the Mojo Standard Library. I've added the "merged-internally" label on this PR (FYI @ConnorGray). The changes in this PR will appear here in the mojo repo nightly branch when we do our next outbound synchronization at the time that the next Mojo nightly is released. That should happen on this coming Monday. Please let me know if you have any questions or concerns. |
[External] [mojo-stdlib] Create `InlineArray` type This PR creates an `InlineArray` type that takes any `CollectionElement` rather than just `AnyRegType`. See also [this thread](https://discord.com/channels/1087530497313357884/1228515158234501231) on Discord. --------- Co-authored-by: Lukas Hermann <lukashermann28@gmail.com> Closes modularml#2294 MODULAR_ORIG_COMMIT_REV_ID: d53b6de6f9ecdf035df951ce679cea2aed1b8e65
[External] [mojo-stdlib] Create `InlineArray` type This PR creates an `InlineArray` type that takes any `CollectionElement` rather than just `AnyRegType`. See also [this thread](https://discord.com/channels/1087530497313357884/1228515158234501231) on Discord. --------- Co-authored-by: Lukas Hermann <lukashermann28@gmail.com> Closes #2294 MODULAR_ORIG_COMMIT_REV_ID: d53b6de6f9ecdf035df951ce679cea2aed1b8e65
Closing as this got merged into the latest |
[External] [mojo-stdlib] Create `InlineArray` type This PR creates an `InlineArray` type that takes any `CollectionElement` rather than just `AnyRegType`. See also [this thread](https://discord.com/channels/1087530497313357884/1228515158234501231) on Discord. --------- Co-authored-by: Lukas Hermann <lukashermann28@gmail.com> Closes modularml#2294 MODULAR_ORIG_COMMIT_REV_ID: d53b6de6f9ecdf035df951ce679cea2aed1b8e65
This PR creates an
InlineArray
type that takes anyCollectionElement
rather than justAnyRegType
. See also this thread on Discord.