FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Tweak unsafePartial usages by JordanMartinez · Pull Request #57 · purescript/purescript-ordered-collections · GitHub

Tweak unsafePartial usages - #57

Merged
JordanMartinez merged 1 commit into
purescript:masterfrom
JordanMartinez:fix-unsafe-partial-usages
Apr 13, 2022
Merged

Tweak unsafePartial usages#57
JordanMartinez merged 1 commit into
purescript:masterfrom
JordanMartinez:fix-unsafe-partial-usages

Conversation

Copy link
Copy Markdown
Contributor

Description of the change

See purescript/purescript#4179 (comment)

CC @rhendric. Would this PR work? Or do I really need to use let x = ... in unsafePartial x? I'm trying to keep the diff small


Checklist:

  • Added the change to the changelog's "Unreleased" section with a reference to this PR (e.g. "- Made a change (#0000)")
  • Linked any existing issues or proposals that this pull request should close
  • Updated or added relevant documentation
  • Added a test for the contribution (if applicable)

rhendric commented Apr 6, 2022

Copy link
Copy Markdown
Member

Using where instead of let should be fine, but the internal recursion needs to use go instead of the outer function name—it's the recursion crossing the unsafePartial call that causes the deoptimization (or, rather, would cause it, if the hack preventing it in purescript/purescript#4283 is removed).

Copy link
Copy Markdown
Contributor Author

Ah... In that case, let me rework how I'm doing that here.

Copy link
Copy Markdown
Contributor Author

How's that?

rhendric commented Apr 6, 2022

Copy link
Copy Markdown
Member

That works—and you don't need to eta-expand pop; unsafePartial down Nil should be sufficient.

But now that I'm bothering to test it, this approach does cause the compiler to introduce a thunk where there wasn't before. Not as big a deal as losing TCO, to be sure, but that does explain why the unsafePartials were where they were: the compiler will inline a thunk if it's immediately unthunked, but not if it's stored in a variable.

Copy link
Copy Markdown
Contributor Author

That works—and you don't need to eta-expand pop; unsafePartial down Nil should be sufficient.

But now that I'm bothering to test it, this approach does cause the compiler to introduce a thunk where there wasn't before. Not as big a deal as losing TCO, to be sure, but that does explain why the unsafePartials were where they were: the compiler will inline a thunk if it's immediately unthunked, but not if it's stored in a variable.

Darn... I'm assuming you're looking at the FFI to conclude that? And if so, is it the FFI of master or of your PR?

Ideas for how to update this without TCO being removed or the thunk being added?

rhendric commented Apr 6, 2022

Copy link
Copy Markdown
Member

My PR, but I'd expect the same on master.

Two ideas:

We could always add _ -> unsafePartial crash clauses to the relevant case expressions and not use unsafePartial elsewhere. That sort of violates the spirit of the Partial pattern. Honestly, though, I've been updating towards thinking the Partial pattern was a neat idea that doesn't work out all that well in practice.

Or, we could move the unsafePartial all the way up to pop, since pop doesn't call itself recursively, and not add Partial => constraints to the inner bindings. This would require using a where instead of a let for the bindings below pop, since those bindings need access to k which would be lambda-bound.

This all makes me a little sad. Efficient code shouldn't be this fragile.

Copy link
Copy Markdown
Contributor Author

We could always add _ -> unsafePartial crash clauses to the relevant case expressions and not use unsafePartial elsewhere.

I went with this approach instead.

rhendric left a comment
edited
Loading

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Would work with my PR and remove the need for the hack (unless we want to keep it in case private user code uses this same idiom), with no negative consequences from an end-user's perspective. I haven't been nearly as involved in developing core libraries as I have with the compiler so this isn't a full ‘I approve of this change as a maintainer’ approval. (Ah, good, GitHub apparently agrees.)

Copy link
Copy Markdown
Contributor Author

@natefaubion Any thoughts on this? Merging this will enable Ryan to remove the "hacky" way of dealing with this particular case in purescript/purescript#4283

I'm not sure how often the pattern of unsafePartial case _ of comes up in practice.

Copy link
Copy Markdown
Contributor

I think unsafeCrashWith is definitely the way to go in this case. My opinion is that unsafePartial should only be used to discharge deliberately partial APIs like fromJust. Otherwise you should use unsafeCrashWith because you can add contextual information.

However... the real question here is whether unsafePartial case _ of should trigger TCO or not, which is difficult to answer, because there is no real spec for when TCO should specifically not trigger. From a syntactic/elaboration standpoint, it's clearly not what we consider a tail call. However, the optimizer treats unsafePartial as irrelevant, and removes it, which coincidentally means that it triggers TCO. Same thing happens if you do something like unsafeCoerce $ go .... This issue will come up with any sort of inlining optimizations. Should inlining open up opportunities for TCO, or should TCO only apply to source syntax?

JordanMartinez merged commit 57a5f2a into purescript:master Apr 13, 2022
JordanMartinez deleted the fix-unsafe-partial-usages branch April 13, 2022 17:41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants


Back | FazBrowse Home | New Git URL