Sub-expressions that are logical operators are not spelled out
separately in basic blocks, so we need to manually visit them when we
encounter them. We do this in both the TerminatorVisitor
(conditionally) and the TransferVisitor (unconditionally), which can
cause cause an expression to be visited twice when the binary
operators are nested 2+ times.
This changes the visit in TransferVisitor to check if it has been
evaluated before trying to visit the sub-expression.
I'm afraid this may allow us to hide a bug. Specifically: consider if SubExpr was already evaluated to a RefenceValue and that value's StorageLocation does *not* map to a value. Then, this line will be true, but we won't want to revisit the SubExrp. Now, that may be impossible in practice, so I'm not sure how big a problem this is, but it seems safer to just use SkipPast::None and not rely on any guarantees.
That said, i see why you want the uniformity of Reference because it is used below. That said, any idea if we actually need to use Reference skipping at all? I think so -- the case of a variable or field access as sub-expression, but those probably have a cast around them anyhow, so i'm not sure those will require reference skipping.