-
Notifications
You must be signed in to change notification settings - Fork 77
Remove dummy top
and is_top
implementations from int domains
#1727
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Most domains have dummy implementations which aren't used.
| `Definite x, `Excluded (s,r) -> if S.mem x s then of_bool IInt false else top () | ||
| `Excluded (s,r), `Definite x -> if S.mem x s then of_bool IInt false else top () | ||
| `Definite x, `Excluded (s,r) -> if S.mem x s then of_bool IInt false else top_of ik | ||
| `Excluded (s,r), `Definite x -> if S.mem x s then of_bool IInt false else top_of ik |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this not be top_of Iint
then? Just for symmetry with the other case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds right, so I've changed it in eq
and ne
.
Although these things look like a mess: other comparisons (e.g. lt
) go as far as returning top_bool
, regardless of ik
.
(* complete lattice *) | ||
module type S = | ||
module type Bot = | ||
sig | ||
include PO | ||
type t | ||
val bot: unit -> t | ||
val is_bot: t -> bool | ||
end | ||
|
||
module type Top = | ||
sig | ||
type t | ||
val top: unit -> t | ||
val is_top: t -> bool | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we go for BoundedMeetSemiLattice
and BoundedJoinSemiLattice
here as meaningful mathematical objects? And use this opportunity to actually make our PO a PartialOrder and not some sort of lattice in disguise, i.e., remove join
, meet
, narrow
and widen
from it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could try that in #1728 to also weaken arguments of LiftBot
and LiftTop
.
Splitting the signatures into precise algebraic structures is nice, but it comes with a cost that we already have with Printable
and Lattice
: to make meaningful use of them, one needs functors for each one, e.g. Printable.Prod
, Lattice.POProd
, Lattice.BoundedMeetSemiLatticeProd
, Lattice.BoundedJoinSemiLatticeProd
, Lattice.Prod
, etc.
Of course all code duplication can be avoided by include
, but they still need to be separate functors with separate names.
I've thought about splitting Printable.S
in the past, because it is even more bloated, but it just leads to a bigger mess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The question is whether all these lifters are used then. If we don't have a BoundedMeetSemiLatticeProd
anywhere, no need to provide the functor for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course we don't and by just introducing the signatures, nothing new would be needed: using the most powerful Lattice.Prod
will suffice because in all such cases the arguments currently already provide dummy implementations which wouldn't then be needed.
But it means we have to accept such exponential explosion of functors. For example, you might want BoundedMeetSemiLattice
which is also JoinSemiLattice
(so just without top
), etc.
Anyway, it's a completely orthogonal matter to this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not completely orthogonal: I think introducing ill-defined module signatures such as Top
(there is a special element intended to be greater than all others and a way to check whether some element is identical to it, but no way to compare elements) only makes it harder to understand what's going on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could go back to what I did at first and what matches all the signature duplication happening in IntDomain
currently: just declare val top: unit -> t
directly, as opposed to putting the signature into Lattice
to reuse.
Then we just end up with 5 copies of the top
type in Goblint, which isn't nice. But IntDomain
is currently full of such copy-paste signatures, so it wouldn't be worse, but it wouldn't move towards cleaning it up either.
I just don't think we have a clean and usable naming scheme: a Lattice.S
without top
would be the combination of BoundedMeetSemiLattice
and (unbounded) JoinSemiLattice
. What's supposed to be the name for that? BoundedMeetUnboundedJoinSemiLattice
isn't particularly nice.
For these one-off combinations it's much cleaner to just include the necessary components, e.g. PO
and Top
on demand, rather than having to predefine all necessary combinations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get what you mean, I just find the notion of having a Top
signature that one can implement without even having a PO which would seem essential to being able to give such a thing non-helpful. But this is not a hill I am willing to die on!
While doing #1726 I noticed this beauty:
analyzer/src/cdomain/value/cdomains/int/defExcDomain.ml
Line 84 in 18489f3
Although it's supposed to be harmless.
Nevertheless, int domains have dummy
top
andis_top
implementations: in many cases even justfailwith
s because they aren't actually needed. Instead, we only ever usetop_of
andis_top_of
, as evidenced by the fact that we never crash with these dummy implementations.Therefore, this is a slight cleanup of the (rather messy) int domain signature to not require
top
andis_top
at all.EDIT: Now also fixes unsoundness of def_exc for
__int128
.