Hi, thanks for sharing this.
This is an interesting problem.
The reason NCrunch considers the 'type PrimePair' line to be code is because the FSharp compiler generates a number of methods for this type behind the scenes, and binds these methods into the assembly's debugging data. What is particularly interesting about this is that not all autogenerated methods are actually being bound into the debug data - only the CompareTo and GetHashCode methods.
You'll notice that if you extend the test to call PrimePair.GetHashCode(), the generated line will be marked as covered by NCrunch.
NCrunch relies very heavily on the debug data (stored in .pdb files) to identify physical lines of code when it instruments assemblies. Basically, if code in the assembly has data associated with it in the PDB, it's considered to be eligible for tracking by NCrunch. In this case, we have code that is legitimately represented in the debug data but in a logical sense doesn't really exist (i.e. you haven't written a GetHashCode method).
I'm at a bit of a loss as to how this can be fixed within NCrunch itself. NCrunch is language independent - it does not differentiate between C#/VB.NET/F#, simply relying on these compilers behaving consistently in the IL they emit. Trying to devise ways to identify this generated code and screening it out is likely to be error prone and may introduce side-effects. In my belief, it doesn't really seem right that the F# compiler is binding the debug information in this way.. though it's possible they have a good reason for doing this.
If the black dot bothers you, I would suggest marking the line with a coverage suppression comment:
type PrimePair = { //ncrunch: no coverage
p:int; q:int }