Fable: Strange behavior of min/max function under sub scope

Created on 1 Oct 2018  路  12Comments  路  Source: fable-compiler/Fable

Description

I have a strange bug since updating to Fable 2.0 in a bigger Elmish app with the min/max function.
min doesn't return the minimum, it returns the bigger number.
When I redefine min/max in a higher-ranking scope, everything works. It looks like the core min function is shadowed by some other min function, but intellisense shows that it is using FSharp.Core.Operators.min.

Repro code

Sorry, can't reproduce that in a simple example.

This is the code containing the bug:

module App.Common

open Remoting
open Types.Common

// workaround that works
//let min = min
//let max = max

let setFocusedCell direction navigationBounds =
    Option.map (fun (x, y) ->
        match direction with
        | Up -> max (x - 1<x>) 0<x>, y
        | Right -> x, min (y + 1<y>) (snd navigationBounds)
        | Down -> min (x + 1<x>) (fst navigationBounds), y
        | Left -> x, max (y - 1<y>) 0<y>)

I had the suspicion that the unit of measures are the problem, but they aren't.

Update: seems like a scoping issue:

This works:
let setFocusedCell direction navigationBounds =
    let min = Operators.min
    let max = Operators.max
    Option.map (fun (x, y) ->
        match direction with
        | Up -> max (x - 1<x>) 0<x>, y
        | Right -> x, min (y + 1<y>) (snd navigationBounds)
        | Down -> min (x + 1<x>) (fst navigationBounds), y
        | Left -> x, max (y - 1<y>) 0<y>)
This introduces the bug:
let setFocusedCell direction navigationBounds =
    Option.map (fun (x, y) ->
        let min = Operators.min
        let max = Operators.max
        match direction with
        | Up -> max (x - 1<x>) 0<x>, y
        | Right -> x, min (y + 1<y>) (snd navigationBounds)
        | Down -> min (x + 1<x>) (fst navigationBounds), y
        | Left -> x, max (y - 1<y>) 0<y>)

So it seems that something is overriding Operators.min/max during execution.

Expected and actual results

expected: min 1 11 -> 1
actual: min 1 11 -> 11

Related information

  • Fable version (dotnet fable --version): 2.0.1
  • Operating system: Windows

Most helpful comment

I've created a repro here: https://bit.ly/2NULWd3

All 12 comments

Here es a screenshot of the min function behavior in the chrome debugger:

image

Another take to get more information about what's happening:

Log the two min functions to the console.

let setFocusedCell direction navigationBounds =
    Browser.console.log("scope 1: ", min)
    Option.map (fun (x, y) ->
        Browser.console.log("scope 2: ", min)
    ...

And here is the result:

Detailed scope 1:

Detailed scope 2:

Scope 2 has a tupledArg[1] variable introduced in to the function body (should be y?).

Another finding:
When inlining the functions the problem exists again:

let inline min x y = min x y
let inline max x y = max x y

let setFocusedCell direction navigationBounds =
    Option.map (fun (x, y) ->
        match direction with
        | Up -> max (x - 1<x>) 0<x>, y
        | Right -> x, min (y + 1<y>) (snd navigationBounds)
        | Down -> min (x + 1<x>) (fst navigationBounds), y
        | Left -> x, max (y - 1<y>) 0<y>)

Thanks a lot for such a detailed report @toburger! Would it be possible to post code enough to run the sample? Or at least the type signatures, I'm especially interested to see the type of y + 1<y> or snd navigationBounds, is it not a number?

Never mind, I think I found the issue :+1:

Sorry for my late response...

This is the inferred type. Nothing special, except the unit of measure, which is admittedly a bit overkill, but I wanted to make it impossible to mess up x and y coordinates:
image

I can confirm that version 2.0.2 of Fable resolves the issue! 馃憤馃帀

Not at all! Actually the error was different, it was because the generated compare function used values with not unique names (x, y) which where replaced by other optimizations in the pipeline. If it weren't for your insight about y being replaced by tupledArg[1] it would have taken much longer to realize that, so thanks again!

Can you please try with 2.0.2? Hopefully it's fixed now. In any case, it'd be nice if you could post fully working code so we can turn it into a unit test and prevent regressions.

I can confirm that version 2.0.2 of Fable resolves the issue! Thanks a lot!

I will try to make a minimal reproducible example out of my code!

I've created a repro here: https://bit.ly/2NULWd3

Sorry to bother again, I've created a much simpler repro: https://bit.ly/2QvKPgT

Awesome, thank you @toburger! :clap: :clap:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alfonsogarciacaro picture alfonsogarciacaro  路  3Comments

forki picture forki  路  3Comments

MangelMaxime picture MangelMaxime  路  3Comments

et1975 picture et1975  路  3Comments

MangelMaxime picture MangelMaxime  路  3Comments