pub enum ExprKind {
Show 17 variants
Var(Var),
Local(Local),
Constant(Constant),
ConstDefId(DefId),
BinaryOp(BinOp, Expr, Expr),
GlobalFunc(Symbol, SpecFuncKind),
UnaryOp(UnOp, Expr),
FieldProj(Expr, FieldProj),
Aggregate(AggregateKind, List<Expr>),
PathProj(Expr, FieldIdx),
IfThenElse(Expr, Expr, Expr),
KVar(KVar),
Alias(AliasReft, List<Expr>),
App(Expr, List<Expr>),
Abs(Lambda),
Hole(HoleKind),
ForAll(Binder<Expr>),
}
Variants§
Var(Var)
Local(Local)
Constant(Constant)
ConstDefId(DefId)
BinaryOp(BinOp, Expr, Expr)
GlobalFunc(Symbol, SpecFuncKind)
UnaryOp(UnOp, Expr)
FieldProj(Expr, FieldProj)
Aggregate(AggregateKind, List<Expr>)
PathProj(Expr, FieldIdx)
IfThenElse(Expr, Expr, Expr)
KVar(KVar)
Alias(AliasReft, List<Expr>)
App(Expr, List<Expr>)
Function application. The syntax allows arbitrary expressions in function position, but in practice we are restricted by what’s possible to encode in fixpoint. In a nutshell, we need to make sure that expressions that can’t be encoded are eliminated before we generate the fixpoint constraint. Most notably, lambda abstractions have to be fully applied before encoding into fixpoint (except when they appear as an index at the top-level).
Abs(Lambda)
Lambda abstractions. They are purely syntactic and we don’t encode them in the logic. As such, they have some syntactic restrictions that we must carefully maintain:
- They can appear as an index at the top level.
- We can only substitute an abstraction for a variable in function position (or as an index). More generally, we need to partially evaluate expressions such that all abstractions in non-index position are eliminated before encoding into fixpoint. Right now, the implementation only evaluates abstractions that are immediately applied to arguments, thus the restriction.
Hole(HoleKind)
A hole is an expression that must be inferred either semantically by generating a kvar or syntactically by generating an evar. Whether a hole can be inferred semantically or syntactically depends on the position it appears: only holes appearing in predicate position can be inferred with a kvar (provided it satisfies the fixpoint horn constraints) and only holes used as an index (a position that fully determines their value) can be inferred with an evar.
Holes are implicitly defined in a scope, i.e., their solution could mention free and bound variables in this scope. This must be considered when generating an inference variables for them (either evar or kvar). In fact, the main reason we have holes is that we want to decouple the places where we generate holes (where we don’t want to worry about the scope), and the places where we generate inference variable for them (where we do need to worry about the scope).
ForAll(Binder<Expr>)
Implementations§
Trait Implementations§
Source§impl Internable for ExprKind
impl Internable for ExprKind
fn storage() -> &'static InternStorage<Self>
impl Eq for ExprKind
impl StructuralPartialEq for ExprKind
Auto Trait Implementations§
impl Freeze for ExprKind
impl RefUnwindSafe for ExprKind
impl Send for ExprKind
impl Sync for ExprKind
impl Unpin for ExprKind
impl UnwindSafe for ExprKind
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more