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

[stdlib] mark dict entry as destroyed in Dict.pop() #2796

Closed
wants to merge 1 commit into from

Conversation

helehex
Copy link
Contributor

@helehex helehex commented May 22, 2024

see #2756
this is an attempt to fix errors that sometimes arise when using the pop method. I'm not sure this is the best way, so feedback is much appreciated

@helehex helehex requested a review from a team as a code owner May 22, 2024 23:13
@helehex
Copy link
Contributor Author

helehex commented May 22, 2024

ok, tests passed locally, but test_reversed is still failing, so this fix may not work

return entry_value.value^
_ = entry_value.key^
var value = entry_value.value^
__mlir_op.`lit.ownership.mark_destroyed`(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Mogball @lattner is this the "blessed" way to do this right now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i imagine it's not since the test_reversed still failed... maybe it's not related, but i was really hoping it was

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it did fix a crash locally for me though. (the exmaple given in #2756)

@gabrieldemarmiesse
Copy link
Contributor

ok, tests passed locally, but test_reversed is still failing, so this fix may not work

@helehex I made a PR recently fixing the flakyness in test_reverse.mojo. Can you rebase this PR on nightly and see if that works now?

@rd4com
Copy link
Contributor

rd4com commented Jun 16, 2024

@helehex, based on #2822 last comment,
and that @gabrieldemarmiesse fixed the nasty bug,
PR should now work !

@helehex
Copy link
Contributor Author

helehex commented Jul 21, 2024

Anyone know why this cant go through? last time I checked, pop() still returns garbage data.
@JoeLoser

@JoeLoser
Copy link
Collaborator

Anyone know why this cant go through? last time I checked, pop() still returns garbage data. @JoeLoser

Is there still an issue with pop on latest nightly? Originally, we were seeing failures around the time you opened this PR, but I thought I remember @gabrieldemarmiesse chasing down the root cause and fixing it.

@helehex
Copy link
Contributor Author

helehex commented Jul 21, 2024

I just checked, and the test provided here still fails in the latest nightly.
They were unrelated. If I remember correctly, the issue here is that the entry.value gets destroyed twice.

@helehex
Copy link
Contributor Author

helehex commented Jul 21, 2024

Sorry, after reading through this thread again, I realize I should've communicated better what was going on.

@helehex
Copy link
Contributor Author

helehex commented Jul 21, 2024

Here's a few notes:

  • I moved the functionality into a helper method on DictEntry, after seeing Chris's response in #2822 I called it reap_value(), It makes sense conceptually to me with how it passes itself as owned.
  • The fix Gabriel provided allowed the tests to pass in this branch, but was unrelated to the particular issue.
  • What the issues basically comes down to, as far as I can tell right now, is a segfault when doing something like this:
    var entry = DictEntry[String, String]("a", "b")
    print(entry.value^)
    which also crashes the lsp currently, maybe it's trying to give me an error?

@rd4com
Copy link
Contributor

rd4com commented Jul 21, 2024

Yes, this PR would make it possible the move a value out of the dictionary.
(V of DictEntry[K,V] is not an Optional)

I think that what we return now is a weird copy that gets double freed.
(No problem when V is a trivial type like Int)

If we turn V into an Optional,

we'd have an overhead of the_dict._reserved() * 8 bytes.
(If V is Int, this is huge, even None entries would have the overhead)

So this PR move the value out by scavaging an DictEntry[K,V] with the blessed thing.

 

The problem that could be a bug (without PR)

  • only fully initialized instances can have their destructor used

Currently, we move the value out, and DictEntry is destroyed anyway:

var entry_value = entry[].unsafe_take() #DictEntry
...
return entry_value.value^

So if the user received an instance of a type that has UnsafePointer as fields,
The pointers are probably freed.

@helehex helehex force-pushed the fix/dict-pop branch 3 times, most recently from 666e623 to f25d09c Compare July 26, 2024 13:58
@helehex
Copy link
Contributor Author

helehex commented Jul 26, 2024

!sync

@@ -216,6 +216,15 @@ struct DictEntry[K: KeyElement, V: CollectionElement](
self.key = other.key
self.value = other.value

fn reap_value(owned self) -> V:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make this private? I don't expect users to need to interact with this API directly, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm I'm not sure actually.

def main():
    print(str(take()))

def take() -> String:
    var entry = DictEntry[String, String]("a", "b")
    return entry.value^

Doing this still causes a segfault and the language server to crash.. do you know if this is a bug, or maybe it should give me an error in the editor?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As things are right now, it seems useful to have the function available and documented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding __mlir_op.`lit.ownership.mark_destroyed`(__get_mvalue_as_litref(entry)) after entry is the solution to it, but that's definitely a private function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I don't think this should be private right now.

…ruction of entry_value in `Dict.pop()`

Signed-off-by: Max Brylski <[email protected]>
@JoeLoser
Copy link
Collaborator

JoeLoser commented Aug 9, 2024

!sync

@modularbot modularbot added the imported-internally Signals that a given pull request has been imported internally. label Aug 9, 2024
@modularbot
Copy link
Collaborator

✅🟣 This contribution has been merged 🟣✅

Your pull request has been merged to the internal upstream Mojo sources. It will be reflected here in the Mojo repository on the nightly branch during the next Mojo nightly release, typically within the next 24-48 hours.

We use Copybara to merge external contributions, click here to learn more.

@modularbot modularbot added the merged-internally Indicates that this pull request has been merged internally label Aug 9, 2024
modularbot pushed a commit that referenced this pull request Aug 10, 2024
…897)

[External] [stdlib] mark dict entry as destroyed in `Dict.pop()`

Fixes #2756

Co-authored-by: Helehex <[email protected]>
Closes #2796
MODULAR_ORIG_COMMIT_REV_ID: d9ee05077d11b2b4b54bdd48d1a67100ab624eee
@modularbot modularbot added the merged-externally Merged externally in public mojo repo label Aug 10, 2024
@modularbot
Copy link
Collaborator

Landed in 486ff59! Thank you for your contribution 🎉

@modularbot modularbot closed this Aug 10, 2024
msaelices pushed a commit to msaelices/mojo that referenced this pull request Sep 10, 2024
…897)

[External] [stdlib] mark dict entry as destroyed in `Dict.pop()`

Fixes modularml#2756

Co-authored-by: Helehex <[email protected]>
Closes modularml#2796
MODULAR_ORIG_COMMIT_REV_ID: d9ee05077d11b2b4b54bdd48d1a67100ab624eee

Signed-off-by: Manuel Saelices <[email protected]>
modularbot pushed a commit that referenced this pull request Sep 13, 2024
…897)

[External] [stdlib] mark dict entry as destroyed in `Dict.pop()`

Fixes #2756

Co-authored-by: Helehex <[email protected]>
Closes #2796
MODULAR_ORIG_COMMIT_REV_ID: d9ee05077d11b2b4b54bdd48d1a67100ab624eee
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
imported-internally Signals that a given pull request has been imported internally. merged-externally Merged externally in public mojo repo merged-internally Indicates that this pull request has been merged internally
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants