The F# compiler gives an error saying I must add a project reference because the type I'm using has a method argument that lives in that project. But this method is private!
I have the following project structure:
Program -> Library -> SubLibrary
SubLibrary contains this:
namespace SubLibrary
type Widget = { Value: int }
Library contains this:
namespace Library
open SubLibrary
type Banana =
{ Value: int }
member private x.TakeWidget (w: Widget) = ()
Program contains this:
open Library
[<EntryPoint>]
let main argv =
printfn "%A" argv
let banana = { Value = 42 }
0
I get this error:
error FS0074:
The type referenced through 'SubLibrary.Widget' is defined in an assembly that is not referenced.
You must add a reference to assembly 'SubLibrary'
But the TakeWidget
method is private!
I tried changing Banana
into a class, rather than a record, but that made no difference.
As an experiment, I created a C# version of Library, called CLibrary:
using SubLibrary;
namespace CLibrary {
public class CBanana {
int m_value;
public CBanana(int value) {
m_value = value;
}
private void TakeWidget(Widget w) {
}
}
}
Then I changed Program to use CBanana
instead of Banana
:
open Library
[<EntryPoint>]
let main argv =
printfn "%A" argv
let banana = CBanana 42
0
Now I don't get an error. In fact, with C# I can make that method public, and so long as I don't try to compile a call to it, there is no error.
Why is the compiler insisting I add a reference to SubLibrary? Sure, I could just go ahead and do what it tells me to do, for a quiet life, but SubLibrary is a private implementation detail of Library, which should not be exposed to Program.
Actually, when I tried with a class instead of record, it did the trick (F# 3.1):
type BananaClass (value:int) =
member private x.TakeWidget (w: Widget) = ()
member x.Value = value
You can work around it with a record as well - you need to move the private member into a separate module and have it as a type augmentation:
type Banana = { Value: int }
module Ext =
type Banana with
member x.TakeWidget (w: Widget) = ()
Compiler won't complain about the missing dependency until you open the Ext
module.
I don't have a good idea why the compiler was complaining in the first place. Probably one of its quirks. I couldn't find anything seriously suspicious in the generated IL (other than a surprising fact that F# compiler marks both private and internal members as internal in the IL - this turned out to be of no consequence here).
Indeed this to me looks like an error I have raised an issue here, https://github.com/Microsoft/visualfsharp/issues/86. So you'll be able to track feedback from there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With