Из того же примера: захотелось посмотреть как решаются проблемы с алиасингом - ну соответственно инкремент массива выделился в функцию "о двух массивах" - причем инвариант мы на один задаем, а инкрементируем второй (прикол понятно в том что они могут совпадать:
method inc (a: arrayНу и:, b: array , lo: int, hi: int) requires 0 <= lo <= hi <= a.Length; requires a.Length == b.Length; modifies b; { ghost var prevElements := a[..]; var i := 0; while i < a.Length invariant a[lo..hi] == prevElements[lo..hi]; { if i < lo || i >= hi { b [i] := b [i] + 1; } i := i + 1; } }
var a := new int[6]; forall i | 0 <= i < a.Length { a [i] := (i + 1) * 10; } ... inc (a, a, lo, hi);Компилируется и нормально работает. Однако если мы уберем условие инкремента:
method inc (a: arrayОно заругается - поскольку если a == b, понятно что это некорректно. Сама функция лечится добавлением условия что такого быть не должно:, b: array , lo: int, hi: int) requires 0 <= lo <= hi <= a.Length; requires a.Length == b.Length; modifies b; { ghost var prevElements := a[..]; var i := 0; while i < a.Length invariant a[lo..hi] == prevElements[lo..hi]; { b [i] := b [i] + 1; i := i + 1; } }
method inc (a: arrayНо тогда как и следовало ожидать идет ругань на, b: array , lo: int, hi: int) requires 0 <= lo <= hi <= a.Length; requires a.Length == b.Length; requires a != b; modifies b; ...
inc (a, a, lo, hi);На тему что а должно быть не равно a. После "раздвоения" массивов ошибка естественно пропадает.