Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid the warning "Warning 21: this statement never returns (or has an unsound type.)"

Tags:

warnings

ocaml

This is the first time that I met the following warning "Warning 21: this statement never returns (or has an unsound type.)" and I don't have an idea how to fix it.

let display_committers_stats response = match response##readyState with
  | XmlHttpRequest.DONE ->
    begin match response##status with
      | 200 ->
        Js_client_ui.create_menu_tabs "GitSearchTabs";
        let l =
          Json_parser.get_commits (Js.to_string response##responseText) in
        let values = 
          Json_parser.group_commits_by_user l
          |> List.map (fun (author, commits) ->
              Js_data.create_discreteBar_item author (float_of_int commits))
          |> Array.of_list 
          |> Js.array in
        let discreteBar_chart =
          Js_data.create_discreteBar_chart "Commits-impact" values in
        let js_arr = Js.array ([|discreteBar_chart |]) in 
        Js.Unsafe.fun_call
          (Js.Unsafe.variable "create_discreteBar_chart")
          [|
            Js.Unsafe.inject ((js_arr))              
          |];
        let js_arr =
        l
        |> List.mapi (fun i commit ->
            Js_data.create_timeline_data i commit.Git_data.message
              commit.Git_data.time)
        |> Array.of_list
        |> Js.array in
        Js.Unsafe.fun_call
        (Js.Unsafe.variable "create_timeline")
        [|
          Js.Unsafe.inject ((js_arr))              
        |]
      | _ -> Printf.printf "Unexcepted status\n" end
  | _ -> Printf.printf "Unexcepted state\n"

The warning show the following line :

Js.Unsafe.fun_call
          (Js.Unsafe.variable "create_discreteBar_chart")
          [|
            Js.Unsafe.inject ((js_arr))              
          |];

For execute multiples expressions in Ocaml, I know that the issue is to use ; between the expressions but what's is wrong in my function now ? Can I have some tips ?

like image 440
alifirat Avatar asked Jul 07 '15 20:07

alifirat


1 Answers

Try wrapping the call in ignore, i.e. instead of Js.Unsafe.fun_call ...;, ignore (Js.Unsafe.fun_call ...);.

The reason this is happening is because your JS function call has a result type "'b", which is not dependent on any of the argument types. In the OCaml type system, this typically means that the function doesn't return, because the only way to "produce" a value of an arbitrary type 'b from nothing is to raise an exception – that is, to give up trying to produce it.

The sequence expression (semicolon) e1; e2 means complete the first expression, then complete the second one. In this case, OCaml is worried that your e1 (the JS function call) won't complete because of its unconstrained result type, as explained above. That would make the sequence expression pointless, which is why you get the warning. However, we know that the reason e1 has an unconstrained result type isn't because it doesn't complete, but because we are using an unsafe binding to JS.

To get around this, wrap e1 in a call to ignore, which is a function that takes anything and evaluates to unit. Now, ; will "see" unit on its left instead of an unconstrained 'b.

Generally speaking, you always want to have an expression of type unit on the left of a ;. So, even if you have an expression that evaluates to a constrained type (such as a concrete type int or a type parameter that is mentioned in the argument types), if that type is not unit, you should still wrap that expression in ignore.

like image 150
antron Avatar answered Sep 21 '22 13:09

antron