Compiler: Mutual Recursion causes Runtime Error

Created on 9 Dec 2016  ·  5Comments  ·  Source: elm/compiler

The following program written in 0.18 will generate code improperly:

import Html exposing (..)


main : Program Never Int Int
main =
    beginnerProgram { model = 0, view = view, update = update }


view : Int -> Html Int
view model =
    text (toString model)


type Msg
    = Nop


update : Int -> Int -> Int
update _ model =
    case model of
        0 ->
            0

        1 ->
            yetAnotherUpdate 0

        _ ->
            theOtherUpdate


theOtherUpdate : Int
theOtherUpdate =
    yetAnotherUpdate 0


yetAnotherUpdate : Int -> Int
yetAnotherUpdate model =
    update 0 model

The code that's generated is:

var _user$project$theOtherUpdate = _user$project$yetAnotherUpdate(0);
var _user$project$yetAnotherUpdate = function (model) {
    return A2(_user$project$update, 0, model);
};
var _user$project$update = F2(
    function (_p0, model) {
        var _p1 = model;
        switch (_p1) {
            case 0:
                return 0;
            case 1:
                return _user$project$yetAnotherUpdate(0);
            default:
                return _user$project$theOtherUpdate;
        }
    });

The Runtime Error is _user$project$yetAnotherUpdate is NOT a function.

Unlike issue #1516 reordering the Elm code does NOT fix the problem.

bug

Most helpful comment

With latest version of the compiler, the generated code is in the right order:

var user$project$Main$update = F2(
    function (_p0, model) {
        var _p1 = model;
        switch (_p1) {
            case 0:
                return 0;
            case 1:
                return user$project$Main$yetAnotherUpdate(0);
            default:
                return user$project$Main$theOtherUpdate;
        }
    });
var user$project$Main$yetAnotherUpdate = function (model) {
    return A2(user$project$Main$update, 0, model);
};
var user$project$Main$theOtherUpdate = user$project$Main$yetAnotherUpdate(0);

So things go alright now. Thanks for the report!

All 5 comments

Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it!

Here is what to expect next, and if anyone wants to comment, keep these things in mind.

Here's a perhaps simpler example of what I believe is the same problem:

import Html

anotherNameForFactorial = factorial

factorial n =
  if n == 0 then
    1
  else
    n * anotherNameForFactorial (n - 1)

main = Html.text (toString (factorial 5))

I get the same runtime error (but for factorial).

EDIT: Never mind -- this is #1516, as it is solved by reordering the definitions.

Added this to https://github.com/elm-lang/elm-compiler/issues/1377 so it can be addressed alongside a bunch of similar issues.

Thanks for the report!

With latest version of the compiler, the generated code is in the right order:

var user$project$Main$update = F2(
    function (_p0, model) {
        var _p1 = model;
        switch (_p1) {
            case 0:
                return 0;
            case 1:
                return user$project$Main$yetAnotherUpdate(0);
            default:
                return user$project$Main$theOtherUpdate;
        }
    });
var user$project$Main$yetAnotherUpdate = function (model) {
    return A2(user$project$Main$update, 0, model);
};
var user$project$Main$theOtherUpdate = user$project$Main$yetAnotherUpdate(0);

So things go alright now. Thanks for the report!

Thanks for fixing this!

Was this page helpful?
0 / 5 - 0 ratings