Search code examples
debuggingf#inlinef#-interactive

F# FSI does not hit break inside inline function


I have several generic inline functions, e.g.:

let inline getRatesImpl<'T when 'T : (member enantiomer : 'T) and 'T : equality> 
    (d : Dictionary<'T, (ReactionRate option * ReactionRate option)>) 
    (calculateRates : 'T -> RelatedReactions<'T>)
    (r : 'T) = 

    match d.TryGetValue r with 
    | true, rates -> 
        rates
    | false, _ -> 
        updateRelatedReactions d (calculateRates r) r

The functions are used like that:

type FoodCreationModel (p : FoodCreationParam) = 
    let rateDictionary = new Dictionary<FoodCreationReaction, (ReactionRate option * ReactionRate option)>()
    let calculateRates _ = getRates (Some p.foodCreationRate, Some 1.0) (None, None)

    member __.getRates r = 
        getRatesImpl rateDictionary calculateRates r

    member __.inputParams = p

When I put a break inside getRatesImpl it is not hit in FSI. Even if I put a break, for example, on getRates (on line getRatesImpl rateDictionary calculateRates r) and then press F11, then FSI does not get inside inline getRatesImpl. However, it does work and I can check that by looking at how the dictionary changes before and after the call.

Some of these inline functions are quite complicated and I really need to debug them once in a while.

The question is how?


Solution

  • Your code probably can be changed to avoid the need for complicated inlines.

    One way to avoid using SRTP is passing the required functions as a parameter instead of a constraint:

    let getRatesImpl
            (d : Dictionary<'T, (ReactionRate option * ReactionRate option)>) 
            (getEnantiomer: 'T -> 'T)
            (calculateRates : 'T -> RelatedReactions<'T>)
            (r : 'T) = 
    
        match d.TryGetValue r with 
        | true, rates -> 
            rates
        | false, _ -> 
            updateRelatedReactions d getEnantiomer (calculateRates r) r
    

    now getRatesImpl does not need to be inlined.

    If more than one function is needed then a record of functions can be passed.