I'd like to understand counterexamples produced by Dafny. I'm using the following code as an example:
function update_map<K(!new), V>(m1: map<K, V>, m2: map<K, V>): map<K, V>
ensures
(forall k :: k in m1 || k in m2 ==> k in update_map(m1, m2)) &&
(forall k :: k in m2 ==> update_map(m1, m2)[k] == m2[k]) &&
(forall k :: !(k in m2) && k in m1 ==> update_map(m1, m2)[k] == m1[k]) &&
(forall k :: !(k in m2) && !(k in m1) ==> !(k in update_map(m1, m2)))
{
map k | k in (m1.Keys + m2.Keys) :: if k in m2 then m2[k] else m1[k]
}
predicate map_extends<K, V>(m1: map<K, V>, m2: map<K, V>) {
forall k :: k in m2 ==> k in m1 && m1[k] == m2[k]
}
lemma update_map_extends<K, V>
(m1: map<K, V>, m2: map<K, V>, m3: map<K, V>, m4: map<K, V>)
requires map_extends(m1, m3)
requires map_extends(m2, m4)
requires m1.Keys !! m2.Keys
ensures map_extends(update_map(m1, m2), update_map(m3, m4))
{}
lemma wrong_update_map_extends<K, V>
(m1: map<K, V>, m2: map<K, V>, m3: map<K, V>, m4: map<K, V>)
requires map_extends(m1, m3)
requires map_extends(m2, m4)
ensures map_extends(update_map(m1, m2), update_map(m3, m4))
{}
My first try to get a counterexample was by using Visual Studio Code with the plugin functionalcorrectness.dafny-vscode, and then enabling the option dafny.automaticShowCounterModel. After that, I sometimes manage to get an inline counterexample by pressing F7, or from the right-click menu, but sometimes it doesn't work. I don't yet understand when this feature works and when it doesn't, there seems to be a UI bug, but that's not the subject of this question. The counterexample it displays looks as follows:
_module._default.wrong_update_map_extends$K -> T#U!val!58, _module._default.wrong_update_map_extends$V -> T#U!val!59, m1#0 -> T#U!val!60, m2#0 -> T#U!val!61, m3#0 -> T#U!val!62, m4#0 -> T#U!val!63
So my first question is:
How can I interpret this counterexample?
Another thing I tried was running
dafny -mv:updmodel.bvd update_map.dfy
and then inspecting the file updmodel.bvd, which reads as follows:
*** MODEL
##_System._tuple#0._#Make0 -> T#U!val!39
##_System._tuple#2._#Make2 -> T#U!val!42
#_System._tuple#0._#Make0 -> T#U!val!55
$$Language$Dafny -> true
$_Frame -> **$_Frame
$_Frame#0 -> T#U!val!65
$_reverifyPost -> **$_reverifyPost
$FunctionContextHeight -> 3
$Heap##5 -> T#U!val!57
$mv_state_const -> 13
$OneHeap -> T#U!val!50
$Tick -> **$Tick
%lbl%#1 -> false
%lbl%+0 -> true
%lbl%+2 -> true
_module._default.wrong_update_map_extends$K -> T#U!val!58
_module._default.wrong_update_map_extends$V -> T#U!val!59
alloc -> T#U!val!0
allocName -> T#U!val!24
boolType -> T#T!val!2
BoxType -> T#T!val!9
charType -> T#T!val!10
class._module.__default -> T#U!val!47
class._System.__tuple_h0 -> T#U!val!38
class._System.__tuple_h2 -> T#U!val!41
class._System.array? -> T#U!val!29
class._System.bool -> T#U!val!20
class._System.int -> T#U!val!19
class._System.multiset -> T#U!val!23
class._System.object? -> T#U!val!26
class._System.seq -> T#U!val!22
class._System.set -> T#U!val!21
ClassNameType -> T#T!val!6
DatatypeTypeType -> T#T!val!12
DtCtorIdType -> T#T!val!8
HandleTypeType -> T#T!val!14
intType -> T#T!val!0
k#5!867!125 -> T#U!val!66
LayerTypeType -> T#T!val!13
m1#0##11 -> T#U!val!60
m2#0##11 -> T#U!val!61
m3#0 -> T#U!val!62
m4#0 -> T#U!val!63
NameFamilyType -> T#T!val!7
NoTraitAtAll -> T#U!val!18
null -> T#U!val!52
realType -> T#T!val!1
refType -> T#T!val!11
rmodeType -> T#T!val!3
TagBool -> T#U!val!6
TagChar -> T#U!val!7
TagClass -> T#U!val!17
Tagclass._module.__default -> T#U!val!48
Tagclass._System.___hFunc0 -> T#U!val!32
Tagclass._System.___hFunc1 -> T#U!val!44
Tagclass._System.___hFunc2 -> T#U!val!35
Tagclass._System.___hPartialFunc0 -> T#U!val!33
Tagclass._System.___hPartialFunc1 -> T#U!val!45
Tagclass._System.___hPartialFunc2 -> T#U!val!36
Tagclass._System.___hTotalFunc0 -> T#U!val!34
Tagclass._System.___hTotalFunc1 -> T#U!val!46
Tagclass._System.___hTotalFunc2 -> T#U!val!37
Tagclass._System.__tuple_h0 -> T#U!val!40
Tagclass._System.__tuple_h2 -> T#U!val!43
Tagclass._System.array -> T#U!val!31
Tagclass._System.array? -> T#U!val!30
Tagclass._System.nat -> T#U!val!25
Tagclass._System.object -> T#U!val!28
Tagclass._System.object? -> T#U!val!27
TagIMap -> T#U!val!16
TagInt -> T#U!val!8
TagISet -> T#U!val!12
TagMap -> T#U!val!15
TagMultiSet -> T#U!val!13
TagORDINAL -> T#U!val!10
TagReal -> T#U!val!9
TagSeq -> T#U!val!14
TagSet -> T#U!val!11
TBool -> T#U!val!1
TChar -> T#U!val!2
Tclass._module.__default -> T#U!val!56
Tclass._System.__tuple_h0 -> T#U!val!54
Tclass._System.nat -> T#U!val!51
Tclass._System.object -> T#U!val!53
Tclass._System.object? -> T#U!val!49
TInt -> T#U!val!3
TORDINAL -> T#U!val!5
TReal -> T#U!val!4
TyTagType -> T#T!val!5
TyType -> T#T!val!4
unique-value!100 -> distinct-elems!74!val!24
unique-value!101 -> distinct-elems!74!val!25
unique-value!102 -> distinct-elems!74!val!26
unique-value!103 -> distinct-elems!74!val!27
unique-value!104 -> distinct-elems!74!val!28
unique-value!105 -> distinct-elems!74!val!29
unique-value!106 -> distinct-elems!74!val!30
unique-value!107 -> distinct-elems!74!val!31
unique-value!108 -> distinct-elems!74!val!32
unique-value!109 -> distinct-elems!74!val!33
unique-value!110 -> distinct-elems!74!val!34
unique-value!111 -> distinct-elems!74!val!35
unique-value!112 -> distinct-elems!74!val!36
unique-value!113 -> distinct-elems!74!val!37
unique-value!114 -> distinct-elems!74!val!38
unique-value!115 -> distinct-elems!74!val!39
unique-value!116 -> distinct-elems!74!val!40
unique-value!117 -> distinct-elems!74!val!41
unique-value!118 -> distinct-elems!74!val!42
unique-value!119 -> distinct-elems!74!val!43
unique-value!120 -> distinct-elems!74!val!44
unique-value!121 -> distinct-elems!74!val!45
unique-value!122 -> distinct-elems!74!val!46
unique-value!123 -> distinct-elems!74!val!47
unique-value!124 -> distinct-elems!74!val!48
unique-value!76 -> distinct-elems!74!val!0
unique-value!77 -> distinct-elems!74!val!1
unique-value!78 -> distinct-elems!74!val!2
unique-value!79 -> distinct-elems!74!val!3
unique-value!80 -> distinct-elems!74!val!4
unique-value!81 -> distinct-elems!74!val!5
unique-value!82 -> distinct-elems!74!val!6
unique-value!83 -> distinct-elems!74!val!7
unique-value!84 -> distinct-elems!74!val!8
unique-value!85 -> distinct-elems!74!val!9
unique-value!86 -> distinct-elems!74!val!10
unique-value!87 -> distinct-elems!74!val!11
unique-value!88 -> distinct-elems!74!val!12
unique-value!89 -> distinct-elems!74!val!13
unique-value!90 -> distinct-elems!74!val!14
unique-value!91 -> distinct-elems!74!val!15
unique-value!92 -> distinct-elems!74!val!16
unique-value!93 -> distinct-elems!74!val!17
unique-value!94 -> distinct-elems!74!val!18
unique-value!95 -> distinct-elems!74!val!19
unique-value!96 -> distinct-elems!74!val!20
unique-value!97 -> distinct-elems!74!val!21
unique-value!98 -> distinct-elems!74!val!22
unique-value!99 -> distinct-elems!74!val!23
$Is -> {
T#U!val!55 T#U!val!54 -> true
T#U!val!60 T#U!val!64 -> true
T#U!val!61 T#U!val!64 -> true
T#U!val!62 T#U!val!64 -> true
T#U!val!63 T#U!val!64 -> true
T#U!val!84 T#U!val!64 -> true
T#U!val!85 T#U!val!64 -> true
else -> true
}
$IsAlloc -> {
T#U!val!60 T#U!val!64 T#U!val!57 -> true
T#U!val!61 T#U!val!64 T#U!val!57 -> true
T#U!val!62 T#U!val!64 T#U!val!57 -> true
T#U!val!63 T#U!val!64 T#U!val!57 -> true
else -> true
}
$IsAllocBox -> {
T#U!val!66 T#U!val!58 T#U!val!57 -> true
T#U!val!71 T#U!val!59 T#U!val!57 -> true
T#U!val!73 T#U!val!59 T#U!val!57 -> true
T#U!val!81 T#U!val!58 T#U!val!57 -> true
T#U!val!82 T#U!val!59 T#U!val!57 -> true
T#U!val!83 T#U!val!59 T#U!val!57 -> true
else -> true
}
$IsBox -> {
T#U!val!66 T#U!val!58 -> true
T#U!val!71 T#U!val!59 -> true
T#U!val!73 T#U!val!59 -> true
T#U!val!81 T#U!val!58 -> true
T#U!val!82 T#U!val!59 -> true
T#U!val!83 T#U!val!59 -> true
else -> true
}
$IsGhostField -> {
T#U!val!0 -> false
else -> false
}
$IsGoodHeap -> {
T#U!val!50 -> true
T#U!val!57 -> true
else -> true
}
$IsHeapAnchor -> {
T#U!val!57 -> true
else -> true
}
$mv_state -> {
13 0 -> true
else -> true
}
[2] -> {
T#U!val!67 T#U!val!66 -> true
T#U!val!67 T#U!val!81 -> true
T#U!val!69 T#U!val!66 -> true
T#U!val!69 T#U!val!81 -> true
T#U!val!70 T#U!val!66 -> T#U!val!71
T#U!val!70 T#U!val!81 -> T#U!val!82
T#U!val!72 T#U!val!66 -> T#U!val!73
T#U!val!72 T#U!val!81 -> T#U!val!83
T#U!val!74 T#U!val!66 -> T#U!val!73
T#U!val!74 T#U!val!81 -> T#U!val!83
T#U!val!75 T#U!val!66 -> T#U!val!73
T#U!val!75 T#U!val!81 -> T#U!val!83
T#U!val!76 T#U!val!66 -> true
T#U!val!76 T#U!val!81 -> true
T#U!val!77 T#U!val!66 -> true
T#U!val!77 T#U!val!81 -> true
T#U!val!78 T#U!val!66 -> T#U!val!71
T#U!val!78 T#U!val!81 -> T#U!val!82
T#U!val!79 T#U!val!66 -> true
T#U!val!79 T#U!val!81 -> true
T#U!val!80 T#U!val!66 -> false
T#U!val!80 T#U!val!81 -> false
else -> true
}
_module.__default.map__extends -> {
T#U!val!58 T#U!val!59 T#U!val!60 T#U!val!62 -> true
T#U!val!58 T#U!val!59 T#U!val!61 T#U!val!63 -> true
T#U!val!58 T#U!val!59 T#U!val!84 T#U!val!85 -> false
else -> true
}
_module.__default.map__extends#canCall -> {
T#U!val!58 T#U!val!59 T#U!val!60 T#U!val!62 -> true
T#U!val!58 T#U!val!59 T#U!val!61 T#U!val!63 -> true
T#U!val!58 T#U!val!59 T#U!val!84 T#U!val!85 -> true
else -> true
}
_module.__default.update__map -> {
T#U!val!58 T#U!val!59 T#U!val!60 T#U!val!61 -> T#U!val!84
T#U!val!58 T#U!val!59 T#U!val!62 T#U!val!63 -> T#U!val!85
else -> T#U!val!84
}
bool_2_U -> {
false -> false
true -> true
else -> true
}
Ctor -> {
T#T!val!0 -> 0
T#T!val!1 -> 1
T#T!val!10 -> 11
T#T!val!11 -> 17
T#T!val!12 -> 18
T#T!val!13 -> 19
T#T!val!14 -> 20
T#T!val!15 -> 7
T#T!val!16 -> 16
T#T!val!17 -> 23
T#T!val!18 -> 14
T#T!val!19 -> 12
T#T!val!2 -> 2
T#T!val!20 -> 12
T#T!val!3 -> 3
T#T!val!4 -> 4
T#T!val!5 -> 5
T#T!val!6 -> 6
T#T!val!7 -> 8
T#T!val!8 -> 9
T#T!val!9 -> 10
else -> 12
}
DatatypeCtorId -> {
T#U!val!55 -> T#U!val!39
else -> T#U!val!39
}
DeclName -> {
T#U!val!0 -> T#U!val!24
else -> T#U!val!24
}
distinct-aux-f!!75 -> {
T#U!val!0 -> distinct-elems!74!val!23
T#U!val!1 -> distinct-elems!74!val!0
T#U!val!10 -> distinct-elems!74!val!9
T#U!val!11 -> distinct-elems!74!val!10
T#U!val!12 -> distinct-elems!74!val!11
T#U!val!13 -> distinct-elems!74!val!12
T#U!val!14 -> distinct-elems!74!val!13
T#U!val!15 -> distinct-elems!74!val!14
T#U!val!16 -> distinct-elems!74!val!15
T#U!val!17 -> distinct-elems!74!val!16
T#U!val!18 -> distinct-elems!74!val!17
T#U!val!19 -> distinct-elems!74!val!18
T#U!val!2 -> distinct-elems!74!val!1
T#U!val!20 -> distinct-elems!74!val!19
T#U!val!21 -> distinct-elems!74!val!20
T#U!val!22 -> distinct-elems!74!val!21
T#U!val!23 -> distinct-elems!74!val!22
T#U!val!24 -> distinct-elems!74!val!24
T#U!val!25 -> distinct-elems!74!val!25
T#U!val!26 -> distinct-elems!74!val!26
T#U!val!27 -> distinct-elems!74!val!27
T#U!val!28 -> distinct-elems!74!val!28
T#U!val!29 -> distinct-elems!74!val!29
T#U!val!3 -> distinct-elems!74!val!2
T#U!val!30 -> distinct-elems!74!val!30
T#U!val!31 -> distinct-elems!74!val!31
T#U!val!32 -> distinct-elems!74!val!32
T#U!val!33 -> distinct-elems!74!val!33
T#U!val!34 -> distinct-elems!74!val!34
T#U!val!35 -> distinct-elems!74!val!35
T#U!val!36 -> distinct-elems!74!val!36
T#U!val!37 -> distinct-elems!74!val!37
T#U!val!38 -> distinct-elems!74!val!38
T#U!val!39 -> distinct-elems!74!val!39
T#U!val!4 -> distinct-elems!74!val!3
T#U!val!40 -> distinct-elems!74!val!40
T#U!val!41 -> distinct-elems!74!val!41
T#U!val!42 -> distinct-elems!74!val!42
T#U!val!43 -> distinct-elems!74!val!43
T#U!val!44 -> distinct-elems!74!val!44
T#U!val!45 -> distinct-elems!74!val!45
T#U!val!46 -> distinct-elems!74!val!46
T#U!val!47 -> distinct-elems!74!val!47
T#U!val!48 -> distinct-elems!74!val!48
T#U!val!5 -> distinct-elems!74!val!4
T#U!val!6 -> distinct-elems!74!val!5
T#U!val!7 -> distinct-elems!74!val!6
T#U!val!8 -> distinct-elems!74!val!7
T#U!val!9 -> distinct-elems!74!val!8
else -> distinct-elems!74!val!0
}
FDim -> {
T#U!val!0 -> 0
else -> 0
}
FieldType -> {
T#T!val!2 -> T#T!val!15
else -> T#T!val!15
}
FieldTypeInv0 -> {
T#T!val!15 -> T#T!val!2
else -> T#T!val!2
}
Inv0_TMap -> {
T#U!val!64 -> T#U!val!58
else -> T#U!val!58
}
Inv1_TMap -> {
T#U!val!64 -> T#U!val!59
else -> T#U!val!59
}
k#0##1!838!72 -> {
T#U!val!85 T#U!val!84 T#U!val!58 -> T#U!val!81
else -> T#U!val!81
}
lambda#0 -> {
T#U!val!61 T#U!val!58 T#U!val!60 -> T#U!val!69
T#U!val!63 T#U!val!58 T#U!val!62 -> T#U!val!67
else -> T#U!val!69
}
lambda#1 -> {
T#U!val!61 T#U!val!60 -> T#U!val!70
T#U!val!63 T#U!val!62 -> T#U!val!72
else -> T#U!val!70
}
lambda#9 -> {
T#U!val!0 T#U!val!52 T#U!val!57 -> T#U!val!65
else -> T#U!val!65
}
Lit -> {
T#U!val!55 -> T#U!val!55
else -> T#U!val!55
}
Map#Domain -> {
T#U!val!60 -> T#U!val!76
T#U!val!61 -> T#U!val!79
T#U!val!62 -> T#U!val!77
T#U!val!63 -> T#U!val!80
T#U!val!84 -> T#U!val!69
T#U!val!85 -> T#U!val!67
else -> T#U!val!67
}
Map#Elements -> {
T#U!val!60 -> T#U!val!75
T#U!val!61 -> T#U!val!78
T#U!val!62 -> T#U!val!74
T#U!val!84 -> T#U!val!70
T#U!val!85 -> T#U!val!72
else -> T#U!val!70
}
Map#Glue -> {
T#U!val!67 T#U!val!72 T#U!val!64 -> T#U!val!85
T#U!val!69 T#U!val!70 T#U!val!64 -> T#U!val!84
else -> T#U!val!84
}
MapType -> {
T#T!val!9 T#T!val!9 -> T#T!val!18
else -> T#T!val!18
}
MapType0Type -> {
T#T!val!9 T#T!val!2 -> T#T!val!20
T#T!val!9 T#T!val!9 -> T#T!val!19
else -> T#T!val!19
}
MapType0TypeInv0 -> {
T#T!val!19 -> T#T!val!9
T#T!val!20 -> T#T!val!9
else -> T#T!val!9
}
MapType0TypeInv1 -> {
T#T!val!19 -> T#T!val!9
T#T!val!20 -> T#T!val!2
else -> T#T!val!9
}
MapType1Type -> {
T#T!val!11 -> T#T!val!16
else -> T#T!val!16
}
MapType1TypeInv0 -> {
T#T!val!16 -> T#T!val!11
else -> T#T!val!11
}
MapType4Type -> {
T#T!val!11 T#T!val!2 -> T#T!val!17
else -> T#T!val!17
}
MapType4TypeInv0 -> {
T#T!val!17 -> T#T!val!11
else -> T#T!val!11
}
MapType4TypeInv1 -> {
T#T!val!17 -> T#T!val!2
else -> T#T!val!2
}
MapTypeInv0 -> {
T#T!val!18 -> T#T!val!9
else -> T#T!val!9
}
MapTypeInv1 -> {
T#T!val!18 -> T#T!val!9
else -> T#T!val!9
}
Tag -> {
T#U!val!1 -> T#U!val!6
T#U!val!2 -> T#U!val!7
T#U!val!3 -> T#U!val!8
T#U!val!4 -> T#U!val!9
T#U!val!49 -> T#U!val!27
T#U!val!5 -> T#U!val!10
T#U!val!51 -> T#U!val!25
T#U!val!53 -> T#U!val!28
T#U!val!54 -> T#U!val!40
T#U!val!56 -> T#U!val!48
T#U!val!64 -> T#U!val!15
else -> T#U!val!6
}
tickleBool -> {
false -> true
true -> true
else -> true
}
TMap -> {
T#U!val!58 T#U!val!59 -> T#U!val!64
else -> T#U!val!64
}
type -> {
false -> T#T!val!2
T#U!val!0 -> T#T!val!15
T#U!val!1 -> T#T!val!4
T#U!val!10 -> T#T!val!5
T#U!val!11 -> T#T!val!5
T#U!val!12 -> T#T!val!5
T#U!val!13 -> T#T!val!5
T#U!val!14 -> T#T!val!5
T#U!val!15 -> T#T!val!5
T#U!val!16 -> T#T!val!5
T#U!val!17 -> T#T!val!5
T#U!val!18 -> T#T!val!6
T#U!val!19 -> T#T!val!6
T#U!val!2 -> T#T!val!4
T#U!val!20 -> T#T!val!6
T#U!val!21 -> T#T!val!6
T#U!val!22 -> T#T!val!6
T#U!val!23 -> T#T!val!6
T#U!val!24 -> T#T!val!7
T#U!val!25 -> T#T!val!5
T#U!val!26 -> T#T!val!6
T#U!val!27 -> T#T!val!5
T#U!val!28 -> T#T!val!5
T#U!val!29 -> T#T!val!6
T#U!val!3 -> T#T!val!4
T#U!val!30 -> T#T!val!5
T#U!val!31 -> T#T!val!5
T#U!val!32 -> T#T!val!5
T#U!val!33 -> T#T!val!5
T#U!val!34 -> T#T!val!5
T#U!val!35 -> T#T!val!5
T#U!val!36 -> T#T!val!5
T#U!val!37 -> T#T!val!5
T#U!val!38 -> T#T!val!6
T#U!val!39 -> T#T!val!8
T#U!val!4 -> T#T!val!4
T#U!val!40 -> T#T!val!5
T#U!val!41 -> T#T!val!6
T#U!val!42 -> T#T!val!8
T#U!val!43 -> T#T!val!5
T#U!val!44 -> T#T!val!5
T#U!val!45 -> T#T!val!5
T#U!val!46 -> T#T!val!5
T#U!val!47 -> T#T!val!6
T#U!val!48 -> T#T!val!5
T#U!val!49 -> T#T!val!4
T#U!val!5 -> T#T!val!4
T#U!val!50 -> T#T!val!16
T#U!val!51 -> T#T!val!4
T#U!val!52 -> T#T!val!11
T#U!val!53 -> T#T!val!4
T#U!val!54 -> T#T!val!4
T#U!val!55 -> T#T!val!12
T#U!val!56 -> T#T!val!4
T#U!val!57 -> T#T!val!16
T#U!val!58 -> T#T!val!4
T#U!val!59 -> T#T!val!4
T#U!val!6 -> T#T!val!5
T#U!val!60 -> T#T!val!18
T#U!val!61 -> T#T!val!18
T#U!val!62 -> T#T!val!18
T#U!val!63 -> T#T!val!18
T#U!val!64 -> T#T!val!4
T#U!val!65 -> T#T!val!17
T#U!val!66 -> T#T!val!9
T#U!val!67 -> T#T!val!20
T#U!val!69 -> T#T!val!20
T#U!val!7 -> T#T!val!5
T#U!val!70 -> T#T!val!19
T#U!val!71 -> T#T!val!9
T#U!val!72 -> T#T!val!19
T#U!val!73 -> T#T!val!9
T#U!val!74 -> T#T!val!19
T#U!val!75 -> T#T!val!19
T#U!val!76 -> T#T!val!20
T#U!val!77 -> T#T!val!20
T#U!val!78 -> T#T!val!19
T#U!val!79 -> T#T!val!20
T#U!val!8 -> T#T!val!5
T#U!val!80 -> T#T!val!20
T#U!val!81 -> T#T!val!9
T#U!val!82 -> T#T!val!9
T#U!val!83 -> T#T!val!9
T#U!val!84 -> T#T!val!18
T#U!val!85 -> T#T!val!18
T#U!val!9 -> T#T!val!5
true -> T#T!val!2
else -> T#T!val!5
}
U_2_bool -> {
false -> false
true -> true
else -> true
}
*** STATE <initial>
$_Frame -> **$_Frame
$_reverifyPost -> **$_reverifyPost
$Heap -> T#U!val!57
$Tick -> **$Tick
_module._default.wrong_update_map_extends$K -> T#U!val!58
_module._default.wrong_update_map_extends$V -> T#U!val!59
m1#0 -> T#U!val!60
m2#0 -> T#U!val!61
m3#0 -> T#U!val!62
m4#0 -> T#U!val!63
*** END_STATE
*** STATE update_map.dfy(28,0): initial state
$_Frame -> T#U!val!65
*** END_STATE
*** END_MODEL
This seems to be more detailed, but I still don't understand how to interpret this, so my second question is:
How can I interpret such bvd files?
Then I read about the Boogie Verification Debugger, so I cloned and built
https://github.com/boogie-org/boogie/tree/cd0609f660a5f063b10eacdae142c915115ec162, and ran BVD with the model file created above, and it produced the following:
My third question is:
Does this look as expected? If yes, how to interpret it?
This is not a good answer, but I am posting it as an answer anyway instead of a comment because I believe it is the state of the art.
As far as I know, nobody who uses Dafny looks at the counterexamples. (There may be some people who use Boogie via other front-ends who do look at the counterexamples though.) Personally, I have never even tried to look at a counterexample. Instead, when I get a verification error, I try to add assertions to my program to figure out what the problem is. You can think of assert P as asking the verifier the question "do you know that P is true?". Then you can use this to narrow down your problem.
Related
I have this method that I use for sorting based on object properties:
extension Sequence {
mutating func sorted(
by predicates: [(Element, Element) -> Bool]
) -> [Element] {
return sorted(by:) { lhs, rhs in
for predicate in predicates {
if predicate(lhs, rhs) { return true }
if predicate(rhs, lhs) { return false }
}
return false
}
}
}
And I can use it like this on myArray of a MyClass type:
myArray.sorted(by: [{$0.propertyA > $1.propertyA}, {$0.propertyB > $1.propertyB}, {$0.propertyC < $1.propertyC}])
but I would like to build these predicates dynamically, so that properties used for sorting are not predefined.
I guess I should be using keyPaths (to store something like KeyPath<MyModel, MyComparableType>, but I had no luck with that.
How would I pass correct operator (less than, bigger than) along with property I want to use for sorting?
You can simply pass a predicate to return a comparable property from the element of a sequence and another one to check if both elements are in increasing other:
extension Sequence {
public func sorted<T: Comparable>(
_ predicate: (Element) throws -> T, by areInIncreasingOrder: (T, T) throws -> Bool
) rethrows -> [Element] {
try sorted { try areInIncreasingOrder(predicate($0), predicate($1)) }
}
func sorted<T: Comparable>(_ predicate: (Element) throws -> T) rethrows -> [Element] {
try sorted(predicate, by: <)
}
}
extension MutableCollection where Self: RandomAccessCollection {
public mutating func sort<T: Comparable>(
_ predicate: (Element) throws -> T, by areInIncreasingOrder: (T, T) throws -> Bool
) rethrows {
try sort { try areInIncreasingOrder(predicate($0), predicate($1)) }
}
public mutating func sort<T: Comparable>(_ predicate: (Element) throws -> T) rethrows {
try sort(predicate, by: <)
}
}
To suport multiple criteria (secondary, tertiary, and quaternary) you just need to add more generic types to your method:
extension Sequence {
public func sorted<T: Comparable, U: Comparable>(
_ primary: ((Element) throws -> T, (T, T) throws -> Bool),
_ secondary: ((Element) throws -> U, (U, U) throws -> Bool)
) rethrows -> [Element] {
try sorted {
let lhs = try primary.0($0)
let rhs = try primary.0($1)
guard lhs == rhs else {
return try primary.1(lhs, rhs)
}
return try secondary.1(secondary.0($0), secondary.0($1))
}
}
public func sorted<T: Comparable, U: Comparable, V: Comparable>(
_ primary: ((Element) throws -> T, (T, T) throws -> Bool),
_ secondary: ((Element) throws -> U, (U, U) throws -> Bool),
_ terciary: ((Element) throws -> V, (V, V) throws -> Bool)
) rethrows -> [Element] {
try sorted {
let lhs1 = try primary.0($0)
let rhs1 = try primary.0($1)
guard lhs1 == rhs1 else {
return try primary.1(lhs1, rhs1)
}
let lhs2 = try secondary.0($0)
let rhs2 = try secondary.0($1)
guard lhs2 == rhs2 else {
return try secondary.1(lhs2, rhs2)
}
return try terciary.1(terciary.0($0), terciary.0($1))
}
}
public func sorted<T: Comparable, U: Comparable, V: Comparable, W: Comparable>(
_ primary: ((Element) throws -> T, (T, T) throws -> Bool),
_ secondary: ((Element) throws -> U, (U, U) throws -> Bool),
_ terciary: ((Element) throws -> V, (V, V) throws -> Bool),
_ quaternary: ((Element) throws -> W, (W, W) throws -> Bool)
) rethrows -> [Element] {
try sorted {
let lhs1 = try primary.0($0)
let rhs1 = try primary.0($1)
guard lhs1 == rhs1 else {
return try primary.1(lhs1, rhs1)
}
let lhs2 = try secondary.0($0)
let rhs2 = try secondary.0($1)
guard lhs2 == rhs2 else {
return try secondary.1(lhs2, rhs2)
}
let lhs3 = try terciary.0($0)
let rhs3 = try terciary.0($1)
guard lhs3 == rhs3 else {
return try terciary.1(lhs3, rhs3)
}
return try quaternary.1(quaternary.0($0), quaternary.0($1))
}
}
}
Now if you would like to create the mutating version of those methods you need to extend MutableCollection and constrain Selfto RandomAccessCollection:
extension MutableCollection where Self: RandomAccessCollection {
public mutating func sort<T: Comparable, U: Comparable>(
_ primary: ((Element) throws -> T, (T, T) throws -> Bool),
_ secondary: ((Element) throws -> U, (U, U) throws -> Bool)
) rethrows {
try sort {
let lhs = try primary.0($0)
let rhs = try primary.0($1)
guard lhs == rhs else {
return try primary.1(lhs, rhs)
}
return try secondary.1(secondary.0($0), secondary.0($1))
}
}
public mutating func sort<T: Comparable, U: Comparable, V: Comparable>(
_ primary: ((Element) throws -> T, (T, T) throws -> Bool),
_ secondary: ((Element) throws -> U, (U, U) throws -> Bool),
_ terciary: ((Element) throws -> V, (V, V) throws -> Bool)
) rethrows {
try sort {
let lhs1 = try primary.0($0)
let rhs1 = try primary.0($1)
guard lhs1 == rhs1 else {
return try primary.1(lhs1, rhs1)
}
let lhs2 = try secondary.0($0)
let rhs2 = try secondary.0($1)
guard lhs2 == rhs2 else {
return try secondary.1(lhs2, rhs2)
}
return try terciary.1(terciary.0($0), terciary.0($1))
}
}
public mutating func sort<T: Comparable, U: Comparable, V: Comparable, W: Comparable>(
_ primary: ((Element) throws -> T, (T, T) throws -> Bool),
_ secondary: ((Element) throws -> U, (U, U) throws -> Bool),
_ terciary: ((Element) throws -> V, (V, V) throws -> Bool),
_ quaternary: ((Element) throws -> W, (W, W) throws -> Bool)
) rethrows {
try sort {
let lhs1 = try primary.0($0)
let rhs1 = try primary.0($1)
guard lhs1 == rhs1 else {
return try primary.1(lhs1, rhs1)
}
let lhs2 = try secondary.0($0)
let rhs2 = try secondary.0($1)
guard lhs2 == rhs2 else {
return try secondary.1(lhs2, rhs2)
}
let lhs3 = try terciary.0($0)
let rhs3 = try terciary.0($1)
guard lhs3 == rhs3 else {
return try terciary.1(lhs3, rhs3)
}
return try quaternary.1(quaternary.0($0), quaternary.0($1))
}
}
}
Playground testing:
struct User: Equatable {
let name: String
let age: Int
}
var users: [User] = [
.init(name: "Liza", age: 19),
.init(name: "John", age: 19),
.init(name: "Steve", age: 51)
]
Single property criteria sort:
let sorted = users.sorted(\.age) // [{name "Liza", age 19}, {name "John", age 19}, {name "Steve", age 51}]
users.sort(\.age) // [{name "Liza", age 19}, {name "John", age 19}, {name "Steve", age 51}]
users == sorted // true
Multiple property criteria sort:
let sorted = users.sorted((\.age, >),(\.name, <)) // [{name "Steve", age 51}, {name "John", age 19}, {name "Liza", age 19}]
users.sort((\.age, >),(\.name, <)) // [{name "Steve", age 51}, {name "John", age 19}, {name "Liza", age 19}]
users == sorted // true
For Xcode 13.0+, iOS 15.0+, iPadOS 15.0+, macOS 12.0+, Mac Catalyst 15.0+, tvOS 15.0+, watchOS 8.0+ you can use KeyPathComparator:
Usage:
let sorted1 = users.sorted(using: [KeyPathComparator(\.age)]) // [{name "Liza", age 19}, {name "John", age 19}, {name "Steve", age 51}]
let sorted2 = users.sorted(using: [KeyPathComparator(\.age), KeyPathComparator(\.name)]) // [{name "John", age 19}, {name "Liza", age 19}, {name "Steve", age
let sorted3 = users.sorted(using: [KeyPathComparator(\.age, order: .reverse), KeyPathComparator(\.name)]) // [{name "Steve", age 51}, {name "John", age 19}, {name "Liza", age 19}]
let fun:() -> () = func function() -> (){
print("Hello Function")
}
fun()
error: consecutive statements on a line must be separated by ';'
This is how you'd do it in Swift with closures:
let fun:() -> () = {
print("Hello Function")
}
fun()
Or you can do it this way:
func function() {
print("Hello Function")
}
let fun:(() -> ()) = function
fun()
It says in the type signature in UIKit that UIContentSizeCategory conforms to the Comparable protocol.
The type signature is:
public struct UIContentSizeCategory : RawRepresentable, Equatable, Hashable, Comparable {
public init(rawValue: String)
}
So how come I get this nasty stack trace when I try to compare them?
po UIContentSizeCategory.small < UIContentSizeCategory.medium
error: warning: <EXPR>:12:9: warning: initialization of variable '$__lldb_error_result' was never used; consider replacing with assignment to '_' or removing it
var $__lldb_error_result = __lldb_tmp_error
~~~~^~~~~~~~~~~~~~~~~~~~
_
error: type 'UIContentSizeCategory' does not conform to protocol 'Comparable'
Swift.Comparable:144:24: note: multiple matching functions named '<=' with type '(UIContentSizeCategory, UIContentSizeCategory) -> Bool'
public static func <=(lhs: Self, rhs: Self) -> Bool
^
Swift.<=:10:13: note: candidate exactly matches
public func <=<T>(lhs: T, rhs: T) -> Bool where T : Comparable
^
Swift.<=:1:13: note: candidate exactly matches
public func <=<T>(lhs: T, rhs: T) -> Bool where T : _SwiftNewtypeWrapper, T.RawValue : Comparable
^
Swift.Comparable:151:24: note: multiple matching functions named '>=' with type '(UIContentSizeCategory, UIContentSizeCategory) -> Bool'
public static func >=(lhs: Self, rhs: Self) -> Bool
^
Swift.>=:12:13: note: candidate exactly matches
public func >=<T>(lhs: T, rhs: T) -> Bool where T : Comparable
^
Swift.>=:1:13: note: candidate exactly matches
public func >=<T>(lhs: T, rhs: T) -> Bool where T : _SwiftNewtypeWrapper, T.RawValue : Comparable
^
Swift.Comparable:158:24: note: multiple matching functions named '>' with type '(UIContentSizeCategory, UIContentSizeCategory) -> Bool'
public static func >(lhs: Self, rhs: Self) -> Bool
^
Swift.>:10:13: note: candidate exactly matches
public func ><T>(lhs: T, rhs: T) -> Bool where T : Comparable
^
Swift.>:1:13: note: candidate exactly matches
public func ><T>(lhs: T, rhs: T) -> Bool where T : _SwiftNewtypeWrapper, T.RawValue : Comparable
^
When I try to write my own extension to make UIContentSizeCategory conform to Comparable I get an error that it already conforms.
The goal here is to be able to check if a size is below a certain threshold and clip some text if it is. How do I fix this?
So, although the docs and signature claim conformance, it does not conform.
First time around I tried this:
extension UIContentSizeCategory: Comparable {
static func <(lhs: UIContentSizeCategory, rhs: UIContentSizeCategory) -> Bool {
return true
}
static func >(lhs: UIContentSizeCategory, rhs: UIContentSizeCategory) -> Bool {
return true
}
}
it threw an error because of the redundant conformance to Comparable
When I tried it without:
extension UIContentSizeCategory {
static func <(lhs: UIContentSizeCategory, rhs: UIContentSizeCategory) -> Bool {
return true
}
static func >(lhs: UIContentSizeCategory, rhs: UIContentSizeCategory) -> Bool {
return true
}
}
Magic! Works!
Full code (just in case you were wondering):
extension UIContentSizeCategory {
static var orderedSizes: [UIContentSizeCategory] {
return [.extraSmall,
.small,
.accessibilityMedium,
.medium,
.accessibilityLarge,
.large,
.accessibilityExtraLarge,
.extraLarge,
.accessibilityExtraExtraLarge,
.extraExtraLarge,
.extraExtraExtraLarge,
.accessibilityExtraExtraExtraLarge
]
}
static func < (lhs: UIContentSizeCategory, rhs: UIContentSizeCategory) -> Bool {
var sizes = orderedSizes
while sizes.contains(lhs) {
sizes.removeFirst()
}
return sizes.contains(rhs)
}
static func > (lhs: UIContentSizeCategory, rhs: UIContentSizeCategory) -> Bool {
var sizes = orderedSizes
while sizes.contains(lhs) {
sizes.removeLast()
}
return sizes.contains(rhs)
}
static func <= (lhs: UIContentSizeCategory, rhs: UIContentSizeCategory) -> Bool {
guard lhs != rhs else { return true }
return lhs < rhs
}
static func >= (lhs: UIContentSizeCategory, rhs: UIContentSizeCategory) -> Bool {
guard lhs != rhs else { return true }
return lhs > rhs
}
}
Original
In my project I have a Iterator class, which has a function:
func iterateItems<T: Items>(iterationItems: [T], removeItem: (T) -> Void, addItem: (T) -> Void, calculateEfficiency: () -> Void) -> [T] {
...
return bestComposition as! [T]
}
And in its subclass WPCalculator I run it this way:
func iterateWPItems() -> [Items] {
return iterateItems(iterationItems: WeaponItems.weaponItems, removeItem: removeWeaponItem, addItem: addWeaponItem, calculateEfficiency: calcWeaponDemage)
}
New code
Everything worked fine that way. Now I want to change the iterateItems function to this:
func iterateItems<T: Items>(iterationItems: [T], removeItem: (T) -> Void, addItem: (T) -> Void, calculateEfficiency: () -> Void) -> ([T], Int, String) {
...
return (bestComposition as! [T], bestBuildCost, customMessage)
}
Then I updated WPCalculator accordingly:
func iterateWPItems() -> ([Items], Int, String) {
return iterateItems(iterationItems: WeaponItems.weaponItems, removeItem: removeWeaponItem, addItem: addWeaponItem, calculateEfficiency: calcWeaponDemage)
}
Now I get an error: Cannot express tuple conversion '([WeaponItems], Int,
String)' to '([Items], Int, String)'
The argument passed to iterateWPItems is an array of type WeaponItems, which is a subclass of Items, it worked fine in the original version, where Swift seems to have inferred the subclass-to-superclass conversion, but when I put it in a tuple in the new code, it doesn't work.
Why is that? How do I solve this problem?
Edit:
WeaponItems:
class WeaponItems: Items {
var weaponPower, attackSpeed, criticalChance, criticalDamage, armorPierce: Double
init(name: String, index: Int, price: Int, weaponPower: Double = 0, attackSpeed: Double = 0, criticalChance: Double = 0, criticalDamage: Double = 0, armorPierce: Double = 0, image: UIImage){
self.weaponPower = weaponPower
self.attackSpeed = attackSpeed
self.criticalChance = criticalChance
self.criticalDamage = criticalDamage
self.armorPierce = armorPierce
super.init(name: name, index: index, price: price, image: image)
}
...
}
Items:
class Items {
let name: String
let index: Int
let price: Int
let image: UIImage
init(name: String, index: Int, price: Int, image: UIImage) {
self.name = name
self.index = index
self.price = price
self.image = image
}
...
}
The problem has indeed to do with the fact that although Swift can implicitly convert [WeaponItems] into [Items], it fails to do so when these types come as the components of tuples. E.g. see this: Tuple "upcasting" in Swift
There are several ways to "solve" this problem.
Easiest is:
func iterateWPItems() -> ([Items], Int, String) {
let (composition, cost, message) = iterateItems(iterationItems: WeaponItems.weaponItems, removeItem: removeWeaponItem, addItem: addWeaponItem, calculateEfficiency: calcWeaponDemage)
return (composition, cost, message)
}
Alternatively, you can change iterateItems to return just the tuple you expect, that is ([Items], Int, String):
func iterateItems<T: Items>(iterationItems: [T], removeItem: (T) -> Void, addItem: (T) -> Void, calculateEfficiency: () -> Void) -> ([Items], Int, String) {
...
return (bestComposition as! [Items], bestBuildCost, customMessage)
}
Better still, from the way it looks I do not see why iterateItems has to be a generic method. If that's indeed the case, then simply changing it to:
func iterateItems(iterationItems: [Items], removeItem: (Items) -> Void, addItem: (Items) -> Void, calculateEfficiency: () -> Void) -> ([Items], Int, String) {
...
return (bestComposition as! [Items], bestBuildCost, customMessage)
}
.. should also help.
I have the following methods
var photos = [MWPhoto] = [MWPhoto]()
func numberOfPhotosInPhotoBrowser(photoBrowser: MWPhotoBrowser!) -> UInt {
return self.photos.count
}
func photoBrowser(photoBrowser: MWPhotoBrowser!, photoAtIndex index: UInt) -> MWPhotoProtocol! {
return self.photos[index]
}
However for the first I get Int is not convertible to UInt (since self.photos.count is an Int
and for the second UInt is not convertible to Int - since the self.photos[ can only take an Int for its index.
How can I correctly convert the UInt to Int and back?
In the first one, the return type is UInt, but you return Int since count returns Int.
Basically UInt has initializer which take variants of value types arguments such as Int, CGFloat, Double or event string and return a new value type.
UInt(8) // result is 8 UInt value type
UInt(20.12) // result is 20 UInt value type
UInt(Double(10)) // result is 10 UInt value type
UInt("10") // result is 10 UInt value type, note this is failable initializer, can be a value or nil
-
func numberOfPhotosInPhotoBrowser(photoBrowser: MWPhotoBrowser!) -> UInt {
return UInt(self.photos.count)
}
For the second one, the array subscript expects Int value where you are passing UInt, so create a new Int value type from UInt,
func photoBrowser(photoBrowser: MWPhotoBrowser!, photoAtIndex index: UInt) -> MWPhotoProtocol! {
return self.photos[Int(index)]
}
// initializing Int
var someInt: Int = 8
someInt
// Converting Int to UInt
var someIntToUInt: UInt = UInt(someInt)
someIntToUInt
// initializing UInt
var someUInt: UInt = 10
someUInt
// Converting UInt to Int
var someUIntToInt: Int = Int(someUInt)
someUIntToInt
If you want unsigned int from negative value use UInt(bitPattern:)
let intVal = -1
let uintVal = UInt(bitPattern: intVal) // uintVal == 0xffffffffffffffff
I got so frustrated with Swift's cryptic method parameters bitPattern: and truncatingBitPattern: and my inability to remember which one to use when, that I created the following class containing a large number of conversion methods.
I'm not necessarily recommending that you include this in your program. I'm sure many people will say that Swift is trying to protect us from ourselves and that sabotaging that effort is dumb. So maybe you should just keep this file somewhere as a kind of cheat sheet so you can quickly determine how to do a conversion, and copy the parameters into your program when needed.
Incidentally, JDI stands for "just do it".
/// Class containing a large number of static methods to convert an Int to a UInt or vice-versa, and
/// also to perform conversions between different bit sizes, for example UInt32 to UInt8.
///
/// Many of these "conversions" are trivial, and are only included for the sake of completeness.
///
/// A few of the conversions involving Int and UInt can give different results when run on 32-bit
/// and 64-bit systems. All of the conversion where the bit size of both the source and the target
/// are specified will always give the same result independent of platform.
public class JDI {
// MARK: - To signed Int
// To Int8
public static func ToInt8(_ x : Int8) -> Int8 {
return x
}
public static func ToInt8(_ x : Int32) -> Int8 {
return Int8(truncatingBitPattern: x)
}
public static func ToInt8(_ x : Int64) -> Int8 {
return Int8(truncatingBitPattern: x)
}
public static func ToInt8(_ x : Int) -> Int8 {
return Int8(truncatingBitPattern: x)
}
public static func ToInt8(_ x : UInt8) -> Int8 {
return Int8(bitPattern: x)
}
public static func ToInt8(_ x : UInt32) -> Int8 {
return Int8(truncatingBitPattern: x)
}
public static func ToInt8(_ x : UInt64) -> Int8 {
return Int8(truncatingBitPattern: x)
}
public static func ToInt8(_ x : UInt) -> Int8 {
return Int8(truncatingBitPattern: x)
}
// To Int32
public static func ToInt32(_ x : Int8) -> Int32 {
return Int32(x)
}
public static func ToInt32(_ x : Int32) -> Int32 {
return x
}
public static func ToInt32(_ x : Int64) -> Int32 {
return Int32(truncatingBitPattern: x)
}
public static func ToInt32(_ x : Int) -> Int32 {
return Int32(truncatingBitPattern: x)
}
public static func ToInt32(_ x : UInt8) -> Int32 {
return Int32(x)
}
public static func ToInt32(_ x : UInt32) -> Int32 {
return Int32(bitPattern: x)
}
public static func ToInt32(_ x : UInt64) -> Int32 {
return Int32(truncatingBitPattern: x)
}
public static func ToInt32(_ x : UInt) -> Int32 {
return Int32(truncatingBitPattern: x)
}
// To Int64
public static func ToInt64(_ x : Int8) -> Int64 {
return Int64(x)
}
public static func ToInt64(_ x : Int32) -> Int64 {
return Int64(x)
}
public static func ToInt64(_ x : Int64) -> Int64 {
return x
}
public static func ToInt64(_ x : Int) -> Int64 {
return Int64(x)
}
public static func ToInt64(_ x : UInt8) -> Int64 {
return Int64(x)
}
public static func ToInt64(_ x : UInt32) -> Int64 {
return Int64(x)
}
public static func ToInt64(_ x : UInt64) -> Int64 {
return Int64(bitPattern: x)
}
public static func ToInt64(_ x : UInt) -> Int64 {
return Int64(bitPattern: UInt64(x)) // Does not extend high bit of 32-bit input
}
// To Int
public static func ToInt(_ x : Int8) -> Int {
return Int(x)
}
public static func ToInt(_ x : Int32) -> Int {
return Int(x)
}
public static func ToInt(_ x : Int64) -> Int {
return Int(truncatingBitPattern: x)
}
public static func ToInt(_ x : Int) -> Int {
return x
}
public static func ToInt(_ x : UInt8) -> Int {
return Int(x)
}
public static func ToInt(_ x : UInt32) -> Int {
if MemoryLayout<Int>.size == MemoryLayout<Int32>.size {
return Int(Int32(bitPattern: x)) // For 32-bit systems, non-authorized interpretation
}
return Int(x)
}
public static func ToInt(_ x : UInt64) -> Int {
return Int(truncatingBitPattern: x)
}
public static func ToInt(_ x : UInt) -> Int {
return Int(bitPattern: x)
}
// MARK: - To unsigned Int
// To UInt8
public static func ToUInt8(_ x : Int8) -> UInt8 {
return UInt8(bitPattern: x)
}
public static func ToUInt8(_ x : Int32) -> UInt8 {
return UInt8(truncatingBitPattern: x)
}
public static func ToUInt8(_ x : Int64) -> UInt8 {
return UInt8(truncatingBitPattern: x)
}
public static func ToUInt8(_ x : Int) -> UInt8 {
return UInt8(truncatingBitPattern: x)
}
public static func ToUInt8(_ x : UInt8) -> UInt8 {
return x
}
public static func ToUInt8(_ x : UInt32) -> UInt8 {
return UInt8(truncatingBitPattern: x)
}
public static func ToUInt8(_ x : UInt64) -> UInt8 {
return UInt8(truncatingBitPattern: x)
}
public static func ToUInt8(_ x : UInt) -> UInt8 {
return UInt8(truncatingBitPattern: x)
}
// To UInt32
public static func ToUInt32(_ x : Int8) -> UInt32 {
return UInt32(bitPattern: Int32(x)) // Extend sign bit, assume minus input significant
}
public static func ToUInt32(_ x : Int32) -> UInt32 {
return UInt32(bitPattern: x)
}
public static func ToUInt32(_ x : Int64) -> UInt32 {
return UInt32(truncatingBitPattern: x)
}
public static func ToUInt32(_ x : Int) -> UInt32 {
return UInt32(truncatingBitPattern: x)
}
public static func ToUInt32(_ x : UInt8) -> UInt32 {
return UInt32(x)
}
public static func ToUInt32(_ x : UInt32) -> UInt32 {
return x
}
public static func ToUInt32(_ x : UInt64) -> UInt32 {
return UInt32(truncatingBitPattern: x)
}
public static func ToUInt32(_ x : UInt) -> UInt32 {
return UInt32(truncatingBitPattern: x)
}
// To UInt64
public static func ToUInt64(_ x : Int8) -> UInt64 {
return UInt64(bitPattern: Int64(x)) // Extend sign bit, assume minus input significant
}
public static func ToUInt64(_ x : Int32) -> UInt64 {
return UInt64(bitPattern: Int64(x)) // Extend sign bit, assume minus input significant
}
public static func ToUInt64(_ x : Int64) -> UInt64 {
return UInt64(bitPattern: x)
}
public static func ToUInt64(_ x : Int) -> UInt64 {
return UInt64(bitPattern: Int64(x)) // Extend sign bit if necessary, assume minus input significant
}
public static func ToUInt64(_ x : UInt8) -> UInt64 {
return UInt64(x)
}
public static func ToUInt64(_ x : UInt32) -> UInt64 {
return UInt64(x)
}
public static func ToUInt64(_ x : UInt64) -> UInt64 {
return x
}
public static func ToUInt64(_ x : UInt) -> UInt64 {
return UInt64(x) // Does not extend high bit of 32-bit input
}
// To UInt
public static func ToUInt(_ x : Int8) -> UInt {
return UInt(bitPattern: Int(x)) // Extend sign bit, assume minus input significant
}
public static func ToUInt(_ x : Int32) -> UInt {
return UInt(truncatingBitPattern: Int64(x)) // Extend sign bit, assume minus input significant
}
public static func ToUInt(_ x : Int64) -> UInt {
return UInt(truncatingBitPattern: x)
}
public static func ToUInt(_ x : Int) -> UInt {
return UInt(bitPattern: x)
}
public static func ToUInt(_ x : UInt8) -> UInt {
return UInt(x)
}
public static func ToUInt(_ x : UInt32) -> UInt {
return UInt(x)
}
public static func ToUInt(_ x : UInt64) -> UInt {
return UInt(truncatingBitPattern: x)
}
public static func ToUInt(_ x : UInt) -> UInt {
return x
}
}
Here's some test code:
public func doTest() {
// To Int8
assert(JDI.ToInt8(42 as Int8) == 42)
assert(JDI.ToInt8(-13 as Int8) == -13)
assert(JDI.ToInt8(42 as Int32) == 42)
assert(JDI.ToInt8(257 as Int32) == 1)
assert(JDI.ToInt8(42 as Int64) == 42)
assert(JDI.ToInt8(257 as Int64) == 1)
assert(JDI.ToInt8(42 as Int) == 42)
assert(JDI.ToInt8(257 as Int) == 1)
assert(JDI.ToInt8(42 as UInt8) == 42)
assert(JDI.ToInt8(0xf3 as UInt8) == -13)
assert(JDI.ToInt8(42 as UInt32) == 42)
assert(JDI.ToInt8(0xfffffff3 as UInt32) == -13)
assert(JDI.ToInt8(42 as UInt64) == 42)
assert(JDI.ToInt8(UInt64.max - 12) == -13)
assert(JDI.ToInt8(42 as UInt) == 42)
assert(JDI.ToInt8(UInt.max - 12) == -13)
// To Int32
assert(JDI.ToInt32(42 as Int8) == 42)
assert(JDI.ToInt32(-13 as Int8) == -13)
assert(JDI.ToInt32(42 as Int32) == 42)
assert(JDI.ToInt32(-13 as Int32) == -13)
assert(JDI.ToInt32(42 as Int64) == 42)
assert(JDI.ToInt32(Int64(Int32.min) - 1) == Int32.max)
assert(JDI.ToInt32(42 as Int) == 42)
assert(JDI.ToInt32(-13 as Int) == -13)
assert(JDI.ToInt32(42 as UInt8) == 42)
assert(JDI.ToInt32(0xf3 as UInt8) == 243)
assert(JDI.ToInt32(42 as UInt32) == 42)
assert(JDI.ToInt32(0xfffffff3 as UInt32) == -13)
assert(JDI.ToInt32(42 as UInt64) == 42)
assert(JDI.ToInt32(UInt64.max - 12) == -13)
assert(JDI.ToInt32(42 as UInt) == 42)
assert(JDI.ToInt32(UInt.max - 12) == -13)
// To Int64
assert(JDI.ToInt64(42 as Int8) == 42)
assert(JDI.ToInt64(-13 as Int8) == -13)
assert(JDI.ToInt64(42 as Int32) == 42)
assert(JDI.ToInt64(-13 as Int32) == -13)
assert(JDI.ToInt64(42 as Int64) == 42)
assert(JDI.ToInt64(-13 as Int64) == -13)
assert(JDI.ToInt64(42 as Int) == 42)
assert(JDI.ToInt64(-13 as Int) == -13)
assert(JDI.ToInt64(42 as UInt8) == 42)
assert(JDI.ToInt64(0xf3 as UInt8) == 243)
assert(JDI.ToInt64(42 as UInt32) == 42)
assert(JDI.ToInt64(0xfffffff3 as UInt32) == 4294967283)
assert(JDI.ToInt64(42 as UInt64) == 42)
assert(JDI.ToInt64(UInt64.max - 12) == -13)
assert(JDI.ToInt64(42 as UInt) == 42)
#if (arch(i386) || arch(arm))
assert(JDI.ToInt64(UInt.max - 12) == 4294967283) // For 32-bit systems
#else
assert(JDI.ToInt64(UInt.max - 12) == -13) // For 64-bit systems
#endif
// To Int
assert(JDI.ToInt(42 as Int8) == 42)
assert(JDI.ToInt(-13 as Int8) == -13)
assert(JDI.ToInt(42 as Int32) == 42)
assert(JDI.ToInt(-13 as Int32) == -13)
assert(JDI.ToInt(42 as Int64) == 42)
assert(JDI.ToInt(-13 as Int64) == -13)
assert(JDI.ToInt(42 as Int) == 42)
assert(JDI.ToInt(-13 as Int) == -13)
assert(JDI.ToInt(42 as UInt8) == 42)
assert(JDI.ToInt(0xf3 as UInt8) == 243)
assert(JDI.ToInt(42 as UInt32) == 42)
#if (arch(i386) || arch(arm))
assert(JDI.ToInt(0xfffffff3 as UInt32) == -13) // For 32-bit systems
#else
assert(JDI.ToInt(0xfffffff3 as UInt32) == 4294967283) // For 64-bit systems
#endif
assert(JDI.ToInt(42 as UInt64) == 42)
assert(JDI.ToInt(UInt64.max - 12) == -13)
assert(JDI.ToInt(42 as UInt) == 42)
assert(JDI.ToInt(UInt.max - 12) == -13)
// To UInt8
assert(JDI.ToUInt8(42 as Int8) == 42)
assert(JDI.ToUInt8(-13 as Int8) == 0xf3)
assert(JDI.ToUInt8(42 as Int32) == 42)
assert(JDI.ToUInt8(-13 as Int32) == 0xf3)
assert(JDI.ToUInt8(42 as Int64) == 42)
assert(JDI.ToUInt8(-13 as Int64) == 0xf3)
assert(JDI.ToUInt8(Int64.max - 12) == 0xf3)
assert(JDI.ToUInt8(42 as Int) == 42)
assert(JDI.ToUInt8(-13 as Int) == 0xf3)
assert(JDI.ToUInt8(Int.max - 12) == 0xf3)
assert(JDI.ToUInt8(42 as UInt8) == 42)
assert(JDI.ToUInt8(0xf3 as UInt8) == 0xf3)
assert(JDI.ToUInt8(42 as UInt32) == 42)
assert(JDI.ToUInt8(0xfffffff3 as UInt32) == 0xf3)
assert(JDI.ToUInt8(42 as UInt64) == 42)
assert(JDI.ToUInt8(UInt64.max - 12) == 0xf3)
assert(JDI.ToUInt8(42 as UInt) == 42)
assert(JDI.ToUInt8(UInt.max - 12) == 0xf3)
// To UInt32
assert(JDI.ToUInt32(42 as Int8) == 42)
assert(JDI.ToUInt32(-13 as Int8) == 0xfffffff3)
assert(JDI.ToUInt32(42 as Int32) == 42)
assert(JDI.ToUInt32(-13 as Int32) == 0xfffffff3)
assert(JDI.ToUInt32(42 as Int64) == 42)
assert(JDI.ToUInt32(-13 as Int64) == 0xfffffff3)
assert(JDI.ToUInt32(Int64.max - 12) == 0xfffffff3)
assert(JDI.ToUInt32(42 as Int) == 42)
assert(JDI.ToUInt32(-13 as Int) == 0xfffffff3)
#if (arch(i386) || arch(arm))
assert(JDI.ToUInt32(Int.max - 12) == 0x7ffffff3) // For 32-bit systems
#else
assert(JDI.ToUInt32(Int.max - 12) == 0xfffffff3) // For 64-bit systems
#endif
assert(JDI.ToUInt32(42 as UInt8) == 42)
assert(JDI.ToUInt32(0xf3 as UInt8) == 0xf3)
assert(JDI.ToUInt32(42 as UInt32) == 42)
assert(JDI.ToUInt32(0xfffffff3 as UInt32) == 0xfffffff3)
assert(JDI.ToUInt32(42 as UInt64) == 42)
assert(JDI.ToUInt32(UInt64.max - 12) == 0xfffffff3)
assert(JDI.ToUInt32(42 as UInt) == 42)
assert(JDI.ToUInt32(UInt.max - 12) == 0xfffffff3)
// To UInt64
assert(JDI.ToUInt64(42 as Int8) == 42)
assert(JDI.ToUInt64(-13 as Int8) == 0xfffffffffffffff3)
assert(JDI.ToUInt64(42 as Int32) == 42)
assert(JDI.ToUInt64(-13 as Int32) == 0xfffffffffffffff3)
assert(JDI.ToUInt64(42 as Int64) == 42)
assert(JDI.ToUInt64(-13 as Int64) == 0xfffffffffffffff3)
assert(JDI.ToUInt64(Int64.max - 12) == (UInt64.max >> 1) - 12)
assert(JDI.ToUInt64(42 as Int) == 42)
assert(JDI.ToUInt64(-13 as Int) == 0xfffffffffffffff3)
#if (arch(i386) || arch(arm))
assert(JDI.ToUInt64(Int.max - 12) == 0x7ffffff3) // For 32-bit systems
#else
assert(JDI.ToUInt64(Int.max - 12) == 0x7ffffffffffffff3) // For 64-bit systems
#endif
assert(JDI.ToUInt64(42 as UInt8) == 42)
assert(JDI.ToUInt64(0xf3 as UInt8) == 0xf3)
assert(JDI.ToUInt64(42 as UInt32) == 42)
assert(JDI.ToUInt64(0xfffffff3 as UInt32) == 0xfffffff3)
assert(JDI.ToUInt64(42 as UInt64) == 42)
assert(JDI.ToUInt64(UInt64.max - 12) == 0xfffffffffffffff3)
assert(JDI.ToUInt64(42 as UInt) == 42)
#if (arch(i386) || arch(arm))
assert(JDI.ToUInt64(UInt.max - 12) == 0xfffffff3) // For 32-bit systems
#else
assert(JDI.ToUInt64(UInt.max - 12) == 0xfffffffffffffff3) // For 64-bit systems
#endif
// To UInt
assert(JDI.ToUInt(42 as Int8) == 42)
#if (arch(i386) || arch(arm))
assert(JDI.ToUInt(-13 as Int8) == 0xfffffff3) // For 32-bit systems
#else
assert(JDI.ToUInt(-13 as Int8) == 0xfffffffffffffff3) // For 64-bit systems
#endif
assert(JDI.ToUInt(42 as Int32) == 42)
#if (arch(i386) || arch(arm))
assert(JDI.ToUInt(-13 as Int32) == 0xfffffff3) // For 32-bit systems
#else
assert(JDI.ToUInt(-13 as Int32) == 0xfffffffffffffff3) // For 64-bit systems
#endif
assert(JDI.ToUInt(42 as Int64) == 42)
#if (arch(i386) || arch(arm))
assert(JDI.ToUInt(-13 as Int64) == 0xfffffff3) // For 32-bit systems
assert(JDI.ToUInt(Int64.max - 12) == 0xfffffff3)
#else
assert(JDI.ToUInt(-13 as Int64) == 0xfffffffffffffff3) // For 64-bit systems
assert(JDI.ToUInt(Int64.max - 12) == 0x7ffffffffffffff3)
#endif
assert(JDI.ToUInt(42 as Int) == 42)
#if (arch(i386) || arch(arm))
assert(JDI.ToUInt(Int.max - 12) == 0x7ffffff3) // For 32-bit systems
#else
assert(JDI.ToUInt(Int.max - 12) == 0x7ffffffffffffff3) // For 64-bit systems
#endif
assert(JDI.ToUInt(42 as UInt8) == 42)
assert(JDI.ToUInt(0xf3 as UInt8) == 0xf3)
assert(JDI.ToUInt(42 as UInt32) == 42)
assert(JDI.ToUInt(0xfffffff3 as UInt32) == 0xfffffff3)
assert(JDI.ToUInt(42 as UInt64) == 42)
#if (arch(i386) || arch(arm))
assert(JDI.ToUInt(UInt64.max - 12) == 0xfffffff3) // For 32-bit systems
#else
assert(JDI.ToUInt(UInt64.max - 12) == 0xfffffffffffffff3) // For 64-bit systems
#endif
assert(JDI.ToUInt(42 as UInt) == 42)
#if (arch(i386) || arch(arm))
assert(JDI.ToUInt(UInt.max - 12) == 0xfffffff3) // For 32-bit systems
#else
assert(JDI.ToUInt(UInt.max - 12) == 0xfffffffffffffff3) // For 64-bit systems
#endif
print("\nTesting JDI complete.\n")
}
Add this anywhere outside of a class:
extension UInt {
/// SwiftExtensionKit
var toInt: Int { return Int(self) }
}
Then just call:
self.photos[index].toInt