-
Notifications
You must be signed in to change notification settings - Fork 232
Friend modules
Interfaces provide a way to hide module's implementation details from a client. However, sometimes those details may need to be accessed by specific, trusted clients. In such cases, the friend
declaration is your friend.
See this test-case for the simplest usage, reproduced here.
A module whose implementation is hidden by an interface
In FriendProvider.fst
:
module FriendProvider
let x : int = 0
And in FriendProvider.fsti
:
module FriendProvider
val x : int
A client module that wants to prove, say, that FriendProvider.x
is out of luck: that detail is explicitly hidden by the FriendProvider interface.
But, if you know what you're doing and you really need to access that part of FriendProvider
's implementation, you can write:
In FriendConsumer.fst
module FriendConsumer
friend FriendProvider //this reveals implementation details of FriendProvider
let test = assert (FriendProvider.x == 0)
And you can even expose this fact to other modules:
In FriendConsumer.fsti
:
module FriendConsumer
val test : squash (FriendProvider.x == 0)
The friend M
construct
-
can only appear in the implementation of a module
N
(i.e.,N.fst
) when an interface forN
also exists (i.e.,N.fsti
also exists). This is to prevent a client moduleL
ofN
silently becoming a friend ofM
(in casefriend M
appears inN.fsti
). -
is valid only if both
M.fst
andM.fsti
exist (ifM.fsti
didn't exist, afriend
wouldn't be necessary in the first place)