Avoids redundant substitution in unifyTypes when possible#4163
Avoids redundant substitution in unifyTypes when possible#4163mikesol wants to merge 12 commits intopurescript:masterfrom
Conversation
|
@natefaubion if you have the chance, could you add a note to the PR that describes your initial proposal about skipping |
|
I'm not keen on this if it's going to make the compiler diagnostics worse. An error message which said that there was a failure to unify an unknown type with some other type is most likely just wrong; unknowns should unify with everything, shouldn't they? |
|
In the other golden example too - it's more useful to be told that |
|
@hdgarrood Thanks for the feedback! |
|
Yep, it does indeed look like your most recent change has resolved that issue - thanks! I'd consider both of those changes to be improvements. |
The invariant to preserve is that we should never unify/solve against an unknown if there is already a solution for that unification variable. Or to put it another way, we must always unify against a known solution if one exists. Unification is non-local, so anytime we solve something, this potentially has an effect elsewhere. The coarse way of guarding against this is to always apply the current substitution whenever unifying two types, but this results in more rewrites than necessary. Since substitution only affects unification variables, it is enough to only perform this check and expansion on demand when we go to solve a unification variable. We can check if that unification variable has a solution, and if it does, continue to unify against it's solution rather than solving. In practice there are likely other places to apply a substitution, for example, you'll probably want to apply the substitution against the solution for a unification variable. |
|
I noticed CI was still waiting for us to approve this run. So, I fixed that. |
I unfortunately cannot reproduce the most recent CI failure on my local build: purescript> graph
purescript> should match the graph fixture [✔]
purescript> should fail when trying to include non-existing modules in the graph [✔]
purescript>
purescript> Finished in 119.4557 seconds
purescript> 1116 examples, 0 failures
purescript> Test suite tests passed
Completed 2 action(s).
10:58 meeshkan-abel@Abel:~/mike/purescript$ git commit -a
On branch faster
Your branch is up to date with 'origin/faster'.Does anyone have tips on reproducing the test error locally? |
|
I've checked this out and will be testing it locally to see what's going on. |
|
For reference, CI fails with this error: |
|
When I ran |
|
After pulling in the latest changes from master the issue is now that there is an infinite hang when running the tests: purescript> '2663.purs' should compile and run without error [✔] (82ms)
purescript> '2689.purs' should compile and run without error [✔] (175ms)
purescript> '2756.purs' should compile and run without error [✔] (114ms)
purescript> '2787.purs' should compile and run without error [✔] (111ms)
purescript> '2795.purs' should compile and run without error [✔] (72ms)
purescript> '2803.purs' should compile and run without error [✔] (140ms)
purescript> '2806.purs' should compile and run without error [✔] (89ms)
purescript> '2947.purs' should compile and run without error [✘] (59ms)
purescript> '2958.purs' should compile and run without error [✔] (132ms)
purescript> '2972.purs' should compile and run without error [✘] (39ms)
Progress 1/2: purescript^CI control-C'd after leaving it on for a few hours. My guess is that something that went into the codebase recently doesn't play nice with this PR - I'll have to dig to find out more. |
|
Temporarily merging #4126 into your branch might help you diagnose that hang, FYI. |
|
@rhendric your patch works like a charm! I can fish out the errors now: there are many (45 in total) and they're all of the form: purescript> Error found:
purescript> in module Main
purescript> at tests/purs/passing/Superclasses3.purs:36:1 - 36:37 (line 36, column 1 - line 36, column 37)
purescript>
purescript> Unknown data constructor Control.Monad.Monad$Dict
purescript>
purescript> while inferring the type of Monad$Dict
purescript> in value declaration monadMTraceor purescript> Error found:
purescript> in module Main
purescript> at tests/purs/passing/RebindableSyntax.purs:25:1 - 26:28 (line 25, column 1 - line 26, column 28)
purescript>
purescript> Unknown data constructor Data.Functor.Functor$Dict
purescript>
purescript> while inferring the type of Functor$Dict
purescript> in value declaration functorConst
purescript>
purescript> See https://github.com/purescript/documentation/blob/master/errors/UnknownName.md for more information,
purescript> or to contribute content related to this error.Interestingly, this error wasn't present when I started working on the PR. Does it look familiar to anyone? |
|
Those |
The only stack trace I could find in the logs (which appeared 4 times) is: purescript> src/Language/PureScript/Environment.hs:576:14:
purescript> 42) bundle, Bundle examples, 'ObjectShorthand.purs' should compile, bundle and run without error
purescript> uncaught exception: ErrorCall
purescript> An internal error occurred during compilation: Data constructor not found
purescript> Please report this at https://github.com/purescript/purescript/issues
purescript> CallStack (from HasCallStack):
purescript> error, called at src/Language/PureScript/Crash.hs:23:3 in purescript-cst-0.3.0.0-1JSI7w0XXsV3fsrGnkQELx:Language.PureScript.Crash
purescript> internalError, called at src/Language/PureScript/Environment.hs:576:14 in purescript-cst-0.3.0.0-1JSI7w0XXsV3fsrGnkQELx:Language.PureScript.EnvironmentWhen navigating to line While this PR doesn't interact explicitly with any of the things removed in #4125 (ie it never touched This is all hand-wavey intuition though, I'd need to really dig in to confirm what's going on. |
|
Closing as it is too challenging for me to work on this atm - I need to understand the type checker better first. |
Description of the change
This change speeds up PureScript's compilation for programs that make heavy use of typeclasses. It is unclear the effect it has (if any) on the compilation of other programs.
Benchmarks
Compiling Loops.purs on my ubuntu machine, I get the following result without this change:
With this change, I get the following result:
These times are pretty consistent across several tests. In general, there is a 1.5-2x speedup for heavily-constrained files when using a
pursbuilt with this PR.Checklist: