-
Notifications
You must be signed in to change notification settings - Fork 360
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
comparing lists with lengths just above and below 100 produces TypeError: y is undefined in Utils.eqHelp #1011
Comments
This looks similar to, and maybe the same root cause as, #945 |
The following is a work-around, if you can manage to hunt down and replace all the places in your code that might test long lists for equality:
|
I made another SSCCE (https://ellie-app.com/4rSsCjfVgmqa1) module Main exposing (main)
import Html exposing (..)
main =
div [] [ text (Debug.toString <| lhs == rhs) ]
rhs =
generate Nothing
lhs =
generate (Just { b = 1})
-- Record is nested exactly 100 times
generate x =
{ a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = x } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } |
do non-recursive tests before the depth check. this ensures that the 'for(key in x)' loop properly short-circuits, and avoids putting Tuple2s containing 'undefined' on the stack. fixes elm#1011 see that issue for further discussion, and the parent commit for test code.
FWIW: just had a regression in prod with this error. Changing the order in comparison "fixes" the issue: - newPlan /= currentPlan
+ currentPlan /= newPlan List len is ~100 when this starts happening. |
I've just encountered this kind of error with a large data structure comparison. Switching the equality check around seems to have worked though I am worried that it will simply move the error to another situation after a different interaction. I'll report back if I have issues. I'm grateful for @danstn suggestion. It is a distressing bug to get as it is not immediately clear what could be done to avoid it. |
Discussion
In
src/Elm/Kernel/Utils.js
, functions_Utils_eq()
and_Utils_eqHelp()
work together to implement the==
operator. In order to avoid stack overflows,eqHelp
will push pairs of values it's asked to test below a depth of 100 onto a stack as 2-tuples.If the lists being compared are shorter than 100 elements, then the
for (var key in x)
loop will examine the$
key and find one side's value is"::"
while the other's is"[]"
. This will prevent it from trying to test thea
andb
keys, which will beundefined
in the"[]"
(tail of the shorter list).However, when the shorter list's length is exactly 100, then the
"::" == "[]"
comparison is not actually performed -- instead it's put onto the stack andtrue
is returned unconditionally. That means that the values of thea
andb
keys are put onto the stack as well, so you end up with tuples on the stack that containundefined
as one of their two values. SinceeqHelp
does not expect that, it crashes.Test Code
This code is structured to allow easy experimentation with the structure of the objects in the list and the number of elements in the lists being compared. If the two numbers passed to
List.range
are both above or both below 100, the bug is not reproduced.Error Produced
The text was updated successfully, but these errors were encountered: