Open jhjourdan opened 11 months ago
My plan for this issue is to:
!
, these types are ADTs such that all the constructors have at least one recursive field. We need to be careful that empty types might be mutually recursive.Hence, in executable code, the values of such a type are exactly those of the type declared by the user, and the user can use the type invariant to leverage this in her reasoning. In the logic, on the contrary, we have added a constructor, so that we are sure that no type in the logic is uninhabited.
We need to be careful, though, with the syntactic criterion, especially when dealing with mutually recursive types or nested recursive types. Examples of types that need to be flagged as potentially empty:
struct A{ // Empty type
x: B;
}
struct B { // Empty type
y: Box<A>;
}
struct C { // Non-empy type, because in A has been added a value
x : A;
}
struct D<T> { // Non empty type
x : Box<T>;
}
struct E { // Empty type
x : D<E>;
}
Of course, @Lysxia, you are welcome to attack this issue. Please simply tell us that you are working on it.
Why3 assumes that every type is non-empty, and so do all the SMT solvers.
However, for several reasons, it seems like we need to support empty types:
!
in Rust), and friends likeInfaillible
are use in crucial places in the standard library (see theTry
trait).is_inhabited
law, which guaranteed that types with invariants are not empty. The reasons are:Map
iterator, which can be uninhabited if the pre and post-conditions of the closure do not match.