castfn
viewptr_match
{a:vt0p}{l1,l2:addr | l1==l2}
(pf: INV(a) @ l1 | p: ptr l2):<> [l:addr | l==l1] (a @ l | ptr l)
// end of [viewptr_match]
Why use the extra l2 in the input and l in the output?
Say p is of the type ptr(L) for some L. When seeing !p, the typechecker tries to
find a proof of the view T @ L for some T; if there is a proof pf2 of the view T @ L2
for some L2 such that L and L2 are equal but of different syntactical forms (e.g.,
1+2=3 but 1+2 and 3 are of different forms), then the typechecker cannot pick this pf2.
Under such a situation, the proof function 'viewptr_match' can be called to unify L and L2
syntactically.