You are correct that a[..]
and [..a.Length]
(and, for that matter, also a[0..]
and a[0..a.Length]
) are the same thing. However, it may be that verifier treats these slightly differently. This makes a difference because the lack of (caution: technical word coming up) extensionality in Dafny.
Extensionality means that, if you know two things have the same elements, then they are the same thing. In your example, extensionality would mean that, if you know a[..]
and a[..a.Length]
to have the same elements, then a[..]
and a[..a.Length]
are the same thing.
The lack of extensionality in Dafny means that the verifier sometimes knows that two things have the same elements, but it still doesn't draw the conclusion that the two things are the same. This tends to be noticeable when the two things are passed to a function. In your example, that function is multiset(...)
, which converts a sequence into a multiset.
While Dafny does not support extensionality automatically, it does offer a simple technique to "remind" the verifier about extensionality. The technique is to assert
the equality between the two things. In particular, when you write assert A == B;
for two sequences A
and B
, then the verifier will first prove that A
and B
have the same elements, and then it will draw the conclusion that A
is in fact equal to B
. In other words, when the verifier is explicitly asked to verify the equality of two sequence-valued expressions like A
and B
, then it instead just proves that they are element-wise equal, after which it concludes A == B
.
So, your remedy above is exactly the right thing to do. When you assert
the equality between a[..a.Length]
and a[..]
, the verifier proves that they have the same elements. After that, it "remembers" that this also means that a[..a.Length]
and a[..]
are equal. Once it has realized the two sequences are the same, it immediately also knows that functions of them, like multiset(a[..a.Length])
and multiset(a[..])
, are the same.
More generally, extensionality is relevant for not just sequences, but also for sets, multisets, and maps. So, if you're working with any of those collection types, you may need to write assertions about sequence equality, set equality, etc., to "remind" the verifier about extensionality.
More generally, there are many things that are true and that the verifier doesn't immediately verify. To home in on what may be missing, the common technique is to start breaking down the proof obligations yourself, like you did in the assert
statements. By breaking down more complicated proof obligations into simpler ones (which is usually done with assert
statements or calc
statements), you essentially provide hints to the verifier about how to prove the more complicated things.