Open jacek-lewandowski opened 1 year ago
@jacek-lewandowski Sorry I missed this issue when you initially filed it!
I think the issue here might be that the checker is implicitly assuming that clusterBuilder.build()
may be able to assign session
, so it is invalidating the information it gains from the @EnsuresCalledMethods
annotation on disconnect()
. Basically, the checker's information looks like this (checker information in []
between lines:
public void connect(ProtocolOptions.Compression compression) throws Exception
{
disconnect();
// [ session -> @CalledMethods("close"), cluster -> @CalledMethods("close") ]
cluster = clusterBuilder.build(); // what if build() can assign session, because of secret evil aliasing?
// [ session -> @CalledMethods({}), cluster -> @CalledMethods({}) ]
session = cluster.connect(); // session cannot be assigned anymore, because it's no longer provable that it has been closed
}
You can tell the checker that build()
cannot assign session
by writing an @Pure
or @SideEffectFree
annotation on it; unfortunately, these annotations are trusted rather than checker by default, so this is similar to suppressing a warning. Since they aren't checked, you should probably only do that if build()
really does not have side-effects (and, if you write @Pure
, is deterministic). If not, you'll have to suppress the warning (with a comment indicating why you believe that build()
doesn't assign session
and so the disconnect()
call's information is still valid.
This sort of problem is a consequence of the checker's conservatism: in the absence of a specification that says otherwise, it assumes any call to another method invalidates any information it is holding about fields.
There is a longer explanation of this issue in the manual here: https://checkerframework.org/manual/#type-refinement-purity, if you'd like to read more.
I have this class (relevant part):
and the checker fails with the following exception:
It refers to the
session = cluster.connect();
inconnect
method. It shouldn't becausedisconnect()
was called before. However, it only allows to overwritecluster
afterdisconnect()
and any additional owned resource cannot be overwritten.