summaryrefslogtreecommitdiff
path: root/Test
diff options
context:
space:
mode:
Diffstat (limited to 'Test')
-rw-r--r--Test/VSComp2010/Problem2-Invert.dfy2
-rw-r--r--Test/VSI-Benchmarks/b3.dfy10
-rw-r--r--Test/VSI-Benchmarks/b8.dfy2
-rw-r--r--Test/VerifyThis2015/Problem1.dfy10
-rw-r--r--Test/VerifyThis2015/Problem2.dfy4
-rw-r--r--Test/VerifyThis2015/Problem3.dfy20
-rw-r--r--Test/VerifyThis2015/Problem3.dfy.expect2
-rw-r--r--Test/cloudmake/CloudMake-CachedBuilds.dfy2
-rw-r--r--Test/cloudmake/CloudMake-ConsistentBuilds.dfy26
-rw-r--r--Test/cloudmake/CloudMake-ParallelBuilds.dfy2
-rw-r--r--Test/dafny0/AdvancedLHS.dfy.expect2
-rw-r--r--Test/dafny0/Array.dfy4
-rw-r--r--Test/dafny0/Array.dfy.expect82
-rw-r--r--Test/dafny0/AssumptionVariables0.dfy8
-rw-r--r--Test/dafny0/AssumptionVariables0.dfy.expect9
-rw-r--r--Test/dafny0/AutoReq.dfy7
-rw-r--r--Test/dafny0/AutoReq.dfy.expect53
-rw-r--r--Test/dafny0/Backticks.dfy.expect9
-rw-r--r--Test/dafny0/BadFunction.dfy.expect4
-rw-r--r--Test/dafny0/Basics.dfy4
-rw-r--r--Test/dafny0/Basics.dfy.expect36
-rw-r--r--Test/dafny0/BindingGuards.dfy159
-rw-r--r--Test/dafny0/BindingGuards.dfy.expect183
-rw-r--r--Test/dafny0/BindingGuardsResolution.dfy154
-rw-r--r--Test/dafny0/BindingGuardsResolution.dfy.expect165
-rw-r--r--Test/dafny0/Calculations.dfy3
-rw-r--r--Test/dafny0/Calculations.dfy.expect14
-rw-r--r--Test/dafny0/CallStmtTests.dfy34
-rw-r--r--Test/dafny0/CallStmtTests.dfy.expect4
-rw-r--r--Test/dafny0/Char.dfy.expect6
-rw-r--r--Test/dafny0/CoPrefix.dfy32
-rw-r--r--Test/dafny0/CoPrefix.dfy.expect47
-rw-r--r--Test/dafny0/CoinductiveProofs.dfy59
-rw-r--r--Test/dafny0/CoinductiveProofs.dfy.expect71
-rw-r--r--Test/dafny0/Compilation.dfy98
-rw-r--r--Test/dafny0/Compilation.dfy.expect17
-rw-r--r--Test/dafny0/Comprehensions.dfy10
-rw-r--r--Test/dafny0/Comprehensions.dfy.expect2
-rw-r--r--Test/dafny0/ComputationsLoop.dfy.expect6
-rw-r--r--Test/dafny0/ComputationsLoop2.dfy.expect10
-rw-r--r--Test/dafny0/ComputationsNeg.dfy2
-rw-r--r--Test/dafny0/ComputationsNeg.dfy.expect16
-rw-r--r--Test/dafny0/ContainerRanks.dfy33
-rw-r--r--Test/dafny0/ContainerRanks.dfy.expect2
-rw-r--r--Test/dafny0/ControlStructures.dfy.expect24
-rw-r--r--Test/dafny0/Corecursion.dfy.expect36
-rw-r--r--Test/dafny0/DTypes.dfy38
-rw-r--r--Test/dafny0/DTypes.dfy.expect24
-rw-r--r--Test/dafny0/DatatypeUpdate.dfy50
-rw-r--r--Test/dafny0/DatatypeUpdate.dfy.expect13
-rw-r--r--Test/dafny0/DatatypeUpdateResolution.dfy20
-rw-r--r--Test/dafny0/DatatypeUpdateResolution.dfy.expect5
-rw-r--r--Test/dafny0/Datatypes.dfy.expect46
-rw-r--r--Test/dafny0/Definedness.dfy.expect110
-rw-r--r--Test/dafny0/DeterministicPick.dfy1
-rw-r--r--Test/dafny0/DeterministicPick.dfy.expect4
-rw-r--r--Test/dafny0/DiamondImports.dfy.expect10
-rw-r--r--Test/dafny0/DirtyLoops.dfy3
-rw-r--r--Test/dafny0/DiscoverBounds.dfy.expect6
-rw-r--r--Test/dafny0/EqualityTypes.dfy112
-rw-r--r--Test/dafny0/EqualityTypes.dfy.expect24
-rw-r--r--Test/dafny0/Extern.dfy27
-rw-r--r--Test/dafny0/Extern.dfy.expect4
-rw-r--r--Test/dafny0/Extern2.cs14
-rw-r--r--Test/dafny0/ExternHelloLibrary.cs15
-rw-r--r--Test/dafny0/ExternHelloLibrary.dllbin0 -> 3072 bytes
-rw-r--r--Test/dafny0/ExternNegative.dfy26
-rw-r--r--Test/dafny0/ExternNegative.dfy.expect3
-rw-r--r--Test/dafny0/ExternNegative2.dfy26
-rw-r--r--Test/dafny0/ExternNegative2.dfy.expect2
-rw-r--r--Test/dafny0/ForallCompilation.dfy2
-rw-r--r--Test/dafny0/Fuel.dfy462
-rw-r--r--Test/dafny0/Fuel.dfy.expect113
-rw-r--r--Test/dafny0/FunctionSpecifications.dfy.expect72
-rw-r--r--Test/dafny0/IMaps.dfy.expect2
-rw-r--r--Test/dafny0/ISets.dfy43
-rw-r--r--Test/dafny0/ISets.dfy.expect2
-rw-r--r--Test/dafny0/Include.dfy.expect12
-rw-r--r--Test/dafny0/Includee.dfy.expect10
-rw-r--r--Test/dafny0/IndexIntoUpdate.dfy9
-rw-r--r--Test/dafny0/IndexIntoUpdate.dfy.expect6
-rw-r--r--Test/dafny0/InductivePredicates.dfy45
-rw-r--r--Test/dafny0/InductivePredicates.dfy.expect6
-rw-r--r--Test/dafny0/Inverses.dfy5
-rw-r--r--Test/dafny0/Inverses.dfy.expect10
-rw-r--r--Test/dafny0/Iterators.dfy.expect44
-rw-r--r--Test/dafny0/JustWarnings.dfy19
-rw-r--r--Test/dafny0/JustWarnings.dfy.expect4
-rw-r--r--Test/dafny0/LetExpr.dfy3
-rw-r--r--Test/dafny0/LetExpr.dfy.expect23
-rw-r--r--Test/dafny0/LhsDuplicates.dfy2
-rw-r--r--Test/dafny0/LhsDuplicates.dfy.expect12
-rw-r--r--Test/dafny0/LitTriggers.dfy39
-rw-r--r--Test/dafny0/LitTriggers.dfy.expect2
-rw-r--r--Test/dafny0/LoopModifies.dfy.expect18
-rw-r--r--Test/dafny0/Maps.dfy.expect4
-rw-r--r--Test/dafny0/Matrix-OOB.dfy13
-rw-r--r--Test/dafny0/Matrix-OOB.dfy.expect14
-rw-r--r--Test/dafny0/ModifyStmt.dfy.expect22
-rw-r--r--Test/dafny0/ModuleExport.dfy105
-rw-r--r--Test/dafny0/ModuleExport.dfy.expect13
-rw-r--r--Test/dafny0/Modules0.dfy26
-rw-r--r--Test/dafny0/Modules0.dfy.expect38
-rw-r--r--Test/dafny0/Modules1.dfy4
-rw-r--r--Test/dafny0/Modules1.dfy.expect12
-rw-r--r--Test/dafny0/Modules2.dfy2
-rw-r--r--Test/dafny0/MultiDimArray.dfy.expect4
-rw-r--r--Test/dafny0/MultiSets.dfy5
-rw-r--r--Test/dafny0/MultiSets.dfy.expect14
-rw-r--r--Test/dafny0/NatTypes.dfy.expect26
-rw-r--r--Test/dafny0/NestedMatch.dfy59
-rw-r--r--Test/dafny0/NestedMatch.dfy.expect2
-rw-r--r--Test/dafny0/NestedPatterns.dfy124
-rw-r--r--Test/dafny0/NestedPatterns.dfy.expect9
-rw-r--r--Test/dafny0/Newtypes.dfy.expect26
-rw-r--r--Test/dafny0/NonGhostQuantifiers.dfy7
-rw-r--r--Test/dafny0/NonGhostQuantifiers.dfy.expect20
-rw-r--r--Test/dafny0/OpaqueFunctions.dfy4
-rw-r--r--Test/dafny0/OpaqueFunctions.dfy.expect52
-rw-r--r--Test/dafny0/Parallel.dfy150
-rw-r--r--Test/dafny0/Parallel.dfy.expect20
-rw-r--r--Test/dafny0/ParallelResolveErrors.dfy17
-rw-r--r--Test/dafny0/ParallelResolveErrors.dfy.expect39
-rw-r--r--Test/dafny0/ParseErrors.dfy.expect32
-rw-r--r--Test/dafny0/PredExpr.dfy.expect14
-rw-r--r--Test/dafny0/Predicates.dfy2
-rw-r--r--Test/dafny0/Predicates.dfy.expect28
-rw-r--r--Test/dafny0/Protected.dfy.expect10
-rw-r--r--Test/dafny0/RangeCompilation.dfy25
-rw-r--r--Test/dafny0/RangeCompilation.dfy.expect6
-rw-r--r--Test/dafny0/RankNeg.dfy.expect24
-rw-r--r--Test/dafny0/Reads.dfy81
-rw-r--r--Test/dafny0/Reads.dfy.expect35
-rw-r--r--Test/dafny0/RealCompare.dfy.expect10
-rw-r--r--Test/dafny0/RealTypes.dfy.expect10
-rw-r--r--Test/dafny0/Refinement.dfy.expect38
-rw-r--r--Test/dafny0/RefinementErrors.dfy37
-rw-r--r--Test/dafny0/RefinementErrors.dfy.expect3
-rw-r--r--Test/dafny0/ResolutionErrors.dfy769
-rw-r--r--Test/dafny0/ResolutionErrors.dfy.expect373
-rw-r--r--Test/dafny0/SeqFromArray.dfy18
-rw-r--r--Test/dafny0/Shadows.dfy42
-rw-r--r--Test/dafny0/Shadows.dfy.expect12
-rw-r--r--Test/dafny0/Simple.dfy27
-rw-r--r--Test/dafny0/Simple.dfy.expect29
-rw-r--r--Test/dafny0/Skeletons.dfy.expect4
-rw-r--r--Test/dafny0/SmallTests.dfy92
-rw-r--r--Test/dafny0/SmallTests.dfy.expect109
-rw-r--r--Test/dafny0/SplitExpr.dfy.expect4
-rw-r--r--Test/dafny0/StatementExpressions.dfy.expect14
-rw-r--r--Test/dafny0/Superposition.dfy.expect22
-rw-r--r--Test/dafny0/Termination.dfy.expect26
-rw-r--r--Test/dafny0/Trait/TraitBasix.dfy.expect2
-rw-r--r--Test/dafny0/Trait/TraitExample.dfy113
-rw-r--r--Test/dafny0/Trait/TraitExample.dfy.expect7
-rw-r--r--Test/dafny0/Trait/TraitUsingParentMembers.dfy.expect2
-rw-r--r--Test/dafny0/Trait/TraitsDecreases.dfy46
-rw-r--r--Test/dafny0/Trait/TraitsDecreases.dfy.expect30
-rw-r--r--Test/dafny0/TriggerInPredicate.dfy19
-rw-r--r--Test/dafny0/TriggerInPredicate.dfy.expect7
-rw-r--r--Test/dafny0/Tuples.dfy.expect4
-rw-r--r--Test/dafny0/TypeAntecedents.dfy.expect8
-rw-r--r--Test/dafny0/TypeParameters.dfy.expect30
-rw-r--r--Test/dafny0/TypeTests.dfy50
-rw-r--r--Test/dafny0/TypeTests.dfy.expect14
-rw-r--r--Test/dafny0/UnfoldingPerformance.dfy61
-rw-r--r--Test/dafny0/UnfoldingPerformance.dfy.expect11
-rw-r--r--Test/dafny0/UserSpecifiedTypeParameters.dfy.expect4
-rw-r--r--Test/dafny0/columns.dfy12
-rw-r--r--Test/dafny0/columns.dfy.expect12
-rw-r--r--Test/dafny0/fun-with-slices.dfy19
-rw-r--r--Test/dafny0/fun-with-slices.dfy.expect2
-rw-r--r--Test/dafny0/one-message-per-failed-precondition.dfy20
-rw-r--r--Test/dafny0/one-message-per-failed-precondition.dfy.expect20
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots0.v0.dfy (renamed from Test/dafny0/snapshots/Snapshots0.v0.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots0.v1.dfy (renamed from Test/dafny0/snapshots/Snapshots0.v1.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots1.v0.dfy (renamed from Test/dafny0/snapshots/Snapshots1.v0.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots1.v1.dfy (renamed from Test/dafny0/snapshots/Snapshots1.v1.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots2.v0.dfy (renamed from Test/dafny0/snapshots/Snapshots2.v0.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots2.v1.dfy (renamed from Test/dafny0/snapshots/Snapshots2.v1.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots3.v0.dfy (renamed from Test/dafny0/snapshots/Snapshots3.v0.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots3.v1.dfy (renamed from Test/dafny0/snapshots/Snapshots3.v1.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots4.v0.dfy (renamed from Test/dafny0/snapshots/Snapshots4.v0.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots4.v1.dfy (renamed from Test/dafny0/snapshots/Snapshots4.v1.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots5.v0.dfy (renamed from Test/dafny0/snapshots/Snapshots5.v0.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots5.v1.dfy (renamed from Test/dafny0/snapshots/Snapshots5.v1.dfy)4
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots6.v0.dfy (renamed from Test/dafny0/snapshots/Snapshots6.v0.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots6.v1.dfy (renamed from Test/dafny0/snapshots/Snapshots6.v1.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots7.v0.dfy (renamed from Test/dafny0/snapshots/Snapshots7.v0.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots7.v1.dfy (renamed from Test/dafny0/snapshots/Snapshots7.v1.dfy)0
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots8.v0.dfy29
-rw-r--r--Test/dafny0/snapshots/Inputs/Snapshots8.v1.dfy33
-rw-r--r--Test/dafny0/snapshots/Snapshots0.run.dfy2
-rw-r--r--Test/dafny0/snapshots/Snapshots0.run.dfy.expect25
-rw-r--r--Test/dafny0/snapshots/Snapshots1.run.dfy2
-rw-r--r--Test/dafny0/snapshots/Snapshots1.run.dfy.expect21
-rw-r--r--Test/dafny0/snapshots/Snapshots2.run.dfy2
-rw-r--r--Test/dafny0/snapshots/Snapshots2.run.dfy.expect41
-rw-r--r--Test/dafny0/snapshots/Snapshots3.run.dfy2
-rw-r--r--Test/dafny0/snapshots/Snapshots3.run.dfy.expect18
-rw-r--r--Test/dafny0/snapshots/Snapshots4.run.dfy2
-rw-r--r--Test/dafny0/snapshots/Snapshots4.run.dfy.expect20
-rw-r--r--Test/dafny0/snapshots/Snapshots5.run.dfy2
-rw-r--r--Test/dafny0/snapshots/Snapshots5.run.dfy.expect35
-rw-r--r--Test/dafny0/snapshots/Snapshots6.run.dfy2
-rw-r--r--Test/dafny0/snapshots/Snapshots6.run.dfy.expect11
-rw-r--r--Test/dafny0/snapshots/Snapshots7.run.dfy2
-rw-r--r--Test/dafny0/snapshots/Snapshots7.run.dfy.expect31
-rw-r--r--Test/dafny0/snapshots/Snapshots8.run.dfy2
-rw-r--r--Test/dafny0/snapshots/Snapshots8.run.dfy.expect55
-rw-r--r--Test/dafny0/snapshots/lit.local.cfg5
-rw-r--r--Test/dafny0/snapshots/runtest.snapshot2
-rw-r--r--Test/dafny0/snapshots/runtest.snapshot.expect180
-rw-r--r--Test/dafny1/BDD.dfy1
-rw-r--r--Test/dafny1/ExtensibleArrayAuto.dfy36
-rw-r--r--Test/dafny1/FindZero.dfy10
-rw-r--r--Test/dafny1/Induction.dfy32
-rw-r--r--Test/dafny1/MoreInduction.dfy18
-rw-r--r--Test/dafny1/MoreInduction.dfy.expect16
-rw-r--r--Test/dafny1/PriorityQueue.dfy32
-rw-r--r--Test/dafny1/Rippling.dfy114
-rw-r--r--Test/dafny1/SchorrWaite-stages.dfy2
-rw-r--r--Test/dafny1/SchorrWaite.dfy8
-rw-r--r--Test/dafny1/Substitution.dfy2
-rw-r--r--Test/dafny1/UltraFilter.dfy2
-rw-r--r--Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy9
-rw-r--r--Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy.expect2
-rw-r--r--Test/dafny2/COST-verif-comp-2011-3-TwoDuplicates.dfy4
-rw-r--r--Test/dafny2/COST-verif-comp-2011-4-FloydCycleDetect.dfy4
-rw-r--r--Test/dafny2/Calculations.dfy24
-rw-r--r--Test/dafny2/MajorityVote.dfy4
-rw-r--r--Test/dafny2/SnapshotableTrees.dfy2
-rw-r--r--Test/dafny2/SnapshotableTrees.dfy.expect13
-rw-r--r--Test/dafny3/CachedContainer.dfy.expect1
-rw-r--r--Test/dafny3/CalcExample.dfy6
-rw-r--r--Test/dafny3/Dijkstra.dfy4
-rw-r--r--Test/dafny3/Filter.dfy240
-rw-r--r--Test/dafny3/Filter.dfy.expect2
-rw-r--r--Test/dafny3/GenericSort.dfy60
-rw-r--r--Test/dafny3/InductionVsCoinduction.dfy2
-rw-r--r--Test/dafny3/InfiniteTrees.dfy44
-rw-r--r--Test/dafny3/SimpleInduction.dfy14
-rw-r--r--Test/dafny4/ACL2-extractor.dfy8
-rw-r--r--Test/dafny4/Ackermann.dfy235
-rw-r--r--Test/dafny4/Ackermann.dfy.expect6
-rw-r--r--Test/dafny4/BinarySearch.dfy.expect2
-rw-r--r--Test/dafny4/Bug100.dfy23
-rw-r--r--Test/dafny4/Bug100.dfy.expect2
-rw-r--r--Test/dafny4/Bug101.dfy19
-rw-r--r--Test/dafny4/Bug101.dfy.expect8
-rw-r--r--Test/dafny4/Bug103.dfy20
-rw-r--r--Test/dafny4/Bug103.dfy.expect2
-rw-r--r--Test/dafny4/Bug104.dfy12
-rw-r--r--Test/dafny4/Bug104.dfy.expect3
-rw-r--r--Test/dafny4/Bug107.dfy16
-rw-r--r--Test/dafny4/Bug107.dfy.expect6
-rw-r--r--Test/dafny4/Bug108.dfy11
-rw-r--r--Test/dafny4/Bug108.dfy.expect7
-rw-r--r--Test/dafny4/Bug110.dfy31
-rw-r--r--Test/dafny4/Bug110.dfy.expect2
-rw-r--r--Test/dafny4/Bug111.dfy18
-rw-r--r--Test/dafny4/Bug111.dfy.expect2
-rw-r--r--Test/dafny4/Bug113.dfy10
-rw-r--r--Test/dafny4/Bug113.dfy.expect6
-rw-r--r--Test/dafny4/Bug114.dfy10
-rw-r--r--Test/dafny4/Bug114.dfy.expect7
-rw-r--r--Test/dafny4/Bug116.dfy15
-rw-r--r--Test/dafny4/Bug116.dfy.expect3
-rw-r--r--Test/dafny4/Bug117.dfy37
-rw-r--r--Test/dafny4/Bug117.dfy.expect3
-rw-r--r--Test/dafny4/Bug118.dfy12
-rw-r--r--Test/dafny4/Bug118.dfy.expect2
-rw-r--r--Test/dafny4/Bug120.dfy11
-rw-r--r--Test/dafny4/Bug120.dfy.expect2
-rw-r--r--Test/dafny4/Bug121.dfy18
-rw-r--r--Test/dafny4/Bug121.dfy.expect2
-rw-r--r--Test/dafny4/Bug122.dfy17
-rw-r--r--Test/dafny4/Bug122.dfy.expect2
-rw-r--r--Test/dafny4/Bug124.dfy14
-rw-r--r--Test/dafny4/Bug124.dfy.expect2
-rw-r--r--Test/dafny4/Bug125.dfy58
-rw-r--r--Test/dafny4/Bug125.dfy.expect2
-rw-r--r--Test/dafny4/Bug128.dfy13
-rw-r--r--Test/dafny4/Bug128.dfy.expect2
-rw-r--r--Test/dafny4/Bug129.dfy12
-rw-r--r--Test/dafny4/Bug129.dfy.expect2
-rw-r--r--Test/dafny4/Bug131.dfy11
-rw-r--r--Test/dafny4/Bug131.dfy.expect2
-rw-r--r--Test/dafny4/Bug132.dfy45
-rw-r--r--Test/dafny4/Bug132.dfy.expect18
-rw-r--r--Test/dafny4/Bug133.dfy18
-rw-r--r--Test/dafny4/Bug133.dfy.expect2
-rw-r--r--Test/dafny4/Bug134.dfy23
-rw-r--r--Test/dafny4/Bug134.dfy.expect4
-rw-r--r--Test/dafny4/Bug136.dfy12
-rw-r--r--Test/dafny4/Bug136.dfy.expect2
-rw-r--r--Test/dafny4/Bug138.dfy22
-rw-r--r--Test/dafny4/Bug138.dfy.expect2
-rw-r--r--Test/dafny4/Bug139.dfy25
-rw-r--r--Test/dafny4/Bug139.dfy.expect2
-rw-r--r--Test/dafny4/Bug140.dfy67
-rw-r--r--Test/dafny4/Bug140.dfy.expect6
-rw-r--r--Test/dafny4/Bug148.dfy25
-rw-r--r--Test/dafny4/Bug148.dfy.expect17
-rw-r--r--Test/dafny4/Bug49.dfy74
-rw-r--r--Test/dafny4/Bug49.dfy.expect8
-rw-r--r--Test/dafny4/Bug60.dfy4
-rw-r--r--Test/dafny4/Bug63.dfy4
-rw-r--r--Test/dafny4/Bug73.dfy.expect4
-rw-r--r--Test/dafny4/Bug75.dfy50
-rw-r--r--Test/dafny4/Bug75.dfy.expect2
-rw-r--r--Test/dafny4/Bug79.dfy10
-rw-r--r--Test/dafny4/Bug79.dfy.expect2
-rw-r--r--Test/dafny4/Bug81.dfy9
-rw-r--r--Test/dafny4/Bug81.dfy.expect2
-rw-r--r--Test/dafny4/Bug82.dfy11
-rw-r--r--Test/dafny4/Bug82.dfy.expect2
-rw-r--r--Test/dafny4/Bug88.dfy18
-rw-r--r--Test/dafny4/Bug88.dfy.expect11
-rw-r--r--Test/dafny4/Bug89.dfy15
-rw-r--r--Test/dafny4/Bug89.dfy.expect6
-rw-r--r--Test/dafny4/Bug91.dfy40
-rw-r--r--Test/dafny4/Bug91.dfy.expect2
-rw-r--r--Test/dafny4/Bug93.dfy37
-rw-r--r--Test/dafny4/Bug93.dfy.expect8
-rw-r--r--Test/dafny4/Bug94.dfy35
-rw-r--r--Test/dafny4/Bug94.dfy.expect6
-rw-r--r--Test/dafny4/Bug99.dfy11
-rw-r--r--Test/dafny4/Bug99.dfy.expect2
-rw-r--r--Test/dafny4/Circ.dfy2
-rw-r--r--Test/dafny4/CoqArt-InsertionSort.dfy1
-rw-r--r--Test/dafny4/FlyingRobots.dfy285
-rw-r--r--Test/dafny4/FlyingRobots.dfy.expect5
-rw-r--r--Test/dafny4/Fstar-QuickSort.dfy40
-rw-r--r--Test/dafny4/GHC-MergeSort.dfy9
-rw-r--r--Test/dafny4/KozenSilva.dfy80
-rw-r--r--Test/dafny4/KozenSilva.dfy.expect2
-rw-r--r--Test/dafny4/LargeConstants.dfy14
-rw-r--r--Test/dafny4/LargeConstants.dfy.expect2
-rw-r--r--Test/dafny4/Leq.dfy174
-rw-r--r--Test/dafny4/Leq.dfy.expect3
-rw-r--r--Test/dafny4/McCarthy91.dfy86
-rw-r--r--Test/dafny4/McCarthy91.dfy.expect25
-rw-r--r--Test/dafny4/MonadicLaws.dfy100
-rw-r--r--Test/dafny4/MonadicLaws.dfy.expect2
-rw-r--r--Test/dafny4/NipkowKlein-chapter3.dfy17
-rw-r--r--Test/dafny4/NipkowKlein-chapter3.dfy.expect2
-rw-r--r--Test/dafny4/NipkowKlein-chapter7.dfy164
-rw-r--r--Test/dafny4/NipkowKlein-chapter7.dfy.expect2
-rw-r--r--Test/dafny4/NumberRepresentations.dfy19
-rw-r--r--Test/dafny4/Primes.dfy17
-rw-r--r--Test/dafny4/Regression0.dfy13
-rw-r--r--Test/dafny4/Regression0.dfy.expect3
-rw-r--r--Test/dafny4/Regression1.dfy9
-rw-r--r--Test/dafny4/Regression1.dfy.expect2
-rw-r--r--Test/dafny4/SoftwareFoundations-Basics.dfy.expect2
-rw-r--r--Test/dafny4/UnionFind.dfy332
-rw-r--r--Test/dafny4/UnionFind.dfy.expect3
-rw-r--r--Test/dafny4/set-compr.dfy54
-rw-r--r--Test/dafny4/set-compr.dfy.expect17
-rw-r--r--Test/hofs/Apply.dfy.expect2
-rw-r--r--Test/hofs/Classes.dfy26
-rw-r--r--Test/hofs/Classes.dfy.expect14
-rw-r--r--Test/hofs/Examples.dfy14
-rw-r--r--Test/hofs/Field.dfy.expect8
-rw-r--r--Test/hofs/FnRef.dfy.expect8
-rw-r--r--Test/hofs/Fold.dfy2
-rw-r--r--Test/hofs/Frame.dfy.expect14
-rw-r--r--Test/hofs/Lambda.dfy.expect2
-rw-r--r--Test/hofs/LambdaParsefail.dfy.expect10
-rw-r--r--Test/hofs/LambdaParsefail2.dfy.expect2
-rw-r--r--Test/hofs/Monads.dfy34
-rw-r--r--Test/hofs/Naked.dfy10
-rw-r--r--Test/hofs/Naked.dfy.expect48
-rw-r--r--Test/hofs/OneShot.dfy9
-rw-r--r--Test/hofs/OneShot.dfy.expect6
-rw-r--r--Test/hofs/ReadsReads.dfy52
-rw-r--r--Test/hofs/ReadsReads.dfy.expect24
-rw-r--r--Test/hofs/Requires.dfy82
-rw-r--r--Test/hofs/Requires.dfy.expect5
-rw-r--r--Test/hofs/ResolveError.dfy34
-rw-r--r--Test/hofs/ResolveError.dfy.expect6
-rw-r--r--Test/hofs/Simple.dfy20
-rw-r--r--Test/hofs/Simple.dfy.expect25
-rw-r--r--Test/hofs/TreeMapSimple.dfy24
-rw-r--r--Test/hofs/Twice.dfy4
-rw-r--r--Test/hofs/Twice.dfy.expect8
-rw-r--r--Test/hofs/VectorUpdate.dfy67
-rw-r--r--Test/hofs/VectorUpdate.dfy.expect2
-rw-r--r--Test/hofs/WhileLoop.dfy10
-rw-r--r--Test/irondafny0/FIFO.dfy43
-rw-r--r--Test/irondafny0/FIFO.dfy.expect8
-rw-r--r--Test/irondafny0/LIFO.dfy43
-rw-r--r--Test/irondafny0/LIFO.dfy.expect8
-rw-r--r--Test/irondafny0/Queue.dfyi22
-rw-r--r--Test/irondafny0/inheritreqs0.dfy22
-rw-r--r--Test/irondafny0/inheritreqs0.dfy.expect6
-rw-r--r--Test/irondafny0/inheritreqs1.dfy22
-rw-r--r--Test/irondafny0/inheritreqs1.dfy.expect6
-rw-r--r--Test/irondafny0/opened_workaround.dfy21
-rw-r--r--Test/irondafny0/opened_workaround.dfy.expect3
-rw-r--r--Test/irondafny0/optimize0.dfy6
-rw-r--r--Test/irondafny0/optimize0.dfy.expect6
-rw-r--r--Test/irondafny0/xrefine0.dfy6
-rw-r--r--Test/irondafny0/xrefine0.dfy.expect2
-rw-r--r--Test/irondafny0/xrefine1.dfy77
-rw-r--r--Test/irondafny0/xrefine1.dfy.expect6
-rw-r--r--Test/irondafny0/xrefine2.dfy77
-rw-r--r--Test/irondafny0/xrefine2.dfy.expect9
-rw-r--r--Test/irondafny0/xrefine3.dfy72
-rw-r--r--Test/irondafny0/xrefine3.dfy.expect6
-rw-r--r--Test/lit.site.cfg12
-rw-r--r--Test/pydiff.py3
-rw-r--r--Test/runTests.bat2
-rw-r--r--Test/runTests.py567
-rw-r--r--Test/server/minimal.transcript8
-rw-r--r--Test/server/minimal.transcript.expect14
-rw-r--r--Test/server/simple-session.transcript637
-rw-r--r--Test/server/simple-session.transcript.expect992
-rw-r--r--Test/triggers/auto-triggers-fix-an-issue-listed-in-the-ironclad-notebook.dfy23
-rw-r--r--Test/triggers/auto-triggers-fix-an-issue-listed-in-the-ironclad-notebook.dfy.expect4
-rw-r--r--Test/triggers/constructors-cause-matching-loops.dfy11
-rw-r--r--Test/triggers/constructors-cause-matching-loops.dfy.expect6
-rw-r--r--Test/triggers/function-applications-are-triggers.dfy15
-rw-r--r--Test/triggers/function-applications-are-triggers.dfy.expect13
-rw-r--r--Test/triggers/large-quantifiers-dont-break-dafny.dfy61
-rw-r--r--Test/triggers/large-quantifiers-dont-break-dafny.dfy.expect4
-rw-r--r--Test/triggers/loop-detection-is-not-too-strict.dfy40
-rw-r--r--Test/triggers/loop-detection-is-not-too-strict.dfy.expect17
-rw-r--r--Test/triggers/loop-detection-looks-at-ranges-too.dfy14
-rw-r--r--Test/triggers/loop-detection-looks-at-ranges-too.dfy.expect6
-rw-r--r--Test/triggers/loop-detection-messages--unit-tests.dfy29
-rw-r--r--Test/triggers/loop-detection-messages--unit-tests.dfy.expect37
-rw-r--r--Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy32
-rw-r--r--Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy.expect10
-rw-r--r--Test/triggers/matrix-accesses-are-triggers.dfy9
-rw-r--r--Test/triggers/matrix-accesses-are-triggers.dfy.expect12
-rw-r--r--Test/triggers/nested-quantifiers-all-get-triggers.dfy9
-rw-r--r--Test/triggers/nested-quantifiers-all-get-triggers.dfy.expect4
-rw-r--r--Test/triggers/old-is-a-special-case-for-triggers.dfy32
-rw-r--r--Test/triggers/old-is-a-special-case-for-triggers.dfy.expect22
-rw-r--r--Test/triggers/redundancy-detection-is-bidirectional.dfy29
-rw-r--r--Test/triggers/redundancy-detection-is-bidirectional.dfy.expect12
-rw-r--r--Test/triggers/regression-tests.dfy20
-rw-r--r--Test/triggers/regression-tests.dfy.expect3
-rw-r--r--Test/triggers/set-construction-is-a-good-trigger.dfy12
-rw-r--r--Test/triggers/set-construction-is-a-good-trigger.dfy.expect5
-rw-r--r--Test/triggers/some-proofs-only-work-without-autoTriggers.dfy48
-rw-r--r--Test/triggers/some-proofs-only-work-without-autoTriggers.dfy.expect31
-rw-r--r--Test/triggers/some-terms-do-not-look-like-the-triggers-they-match.dfy16
-rw-r--r--Test/triggers/some-terms-do-not-look-like-the-triggers-they-match.dfy.expect10
-rw-r--r--Test/triggers/splitting-picks-the-right-tokens.dfy24
-rw-r--r--Test/triggers/splitting-picks-the-right-tokens.dfy.expect38
-rw-r--r--Test/triggers/splitting-triggers-recovers-expressivity.dfy61
-rw-r--r--Test/triggers/splitting-triggers-recovers-expressivity.dfy.expect39
-rw-r--r--Test/triggers/splitting-triggers-yields-better-precondition-related-errors.dfy21
-rw-r--r--Test/triggers/splitting-triggers-yields-better-precondition-related-errors.dfy.expect32
-rw-r--r--Test/triggers/suppressing-warnings-behaves-properly.dfy21
-rw-r--r--Test/triggers/suppressing-warnings-behaves-properly.dfy.expect14
-rw-r--r--Test/triggers/triggers-prevent-some-inlining.dfy26
-rw-r--r--Test/triggers/triggers-prevent-some-inlining.dfy.expect9
-rw-r--r--Test/triggers/useless-triggers-are-removed.dfy25
-rw-r--r--Test/triggers/useless-triggers-are-removed.dfy.expect17
-rw-r--r--Test/triggers/wf-checks-use-the-original-quantifier.dfy28
-rw-r--r--Test/triggers/wf-checks-use-the-original-quantifier.dfy.expect17
-rw-r--r--Test/tutorial/maximum.dfy32
-rw-r--r--Test/tutorial/maximum.dfy.expect7
-rw-r--r--Test/vacid0/Composite.dfy2
-rw-r--r--Test/vstte2012/BreadthFirstSearch.dfy2
-rw-r--r--Test/vstte2012/Combinators.dfy12
-rw-r--r--Test/vstte2012/Tree.dfy71
-rw-r--r--Test/wishlist/calc.dfy17
-rw-r--r--Test/wishlist/calc.dfy.expect11
-rw-r--r--Test/wishlist/exists-b-exists-not-b.dfy10
-rw-r--r--Test/wishlist/exists-b-exists-not-b.dfy.expect8
-rw-r--r--Test/wishlist/granted/useless-casts-in-decreases-clauses.dfy9
-rw-r--r--Test/wishlist/granted/useless-casts-in-decreases-clauses.dfy.expect3
-rw-r--r--Test/wishlist/naked-function-in-recursive-setting.dfy13
-rw-r--r--Test/wishlist/naked-function-in-recursive-setting.dfy.expect8
-rw-r--r--Test/wishlist/sequences-literals.dfy58
-rw-r--r--Test/wishlist/sequences-literals.dfy.expect20
-rw-r--r--Test/wishlist/sequences-s0-in-s.dfy25
-rw-r--r--Test/wishlist/sequences-s0-in-s.dfy.expect6
-rw-r--r--Test/wishlist/strings.dfy6
-rw-r--r--Test/wishlist/strings.dfy.expect5
-rw-r--r--Test/wishlist/we-should-always-print-tooltips.dfy4
-rw-r--r--Test/wishlist/we-should-always-print-tooltips.dfy.expect2
487 files changed, 12428 insertions, 2495 deletions
diff --git a/Test/VSComp2010/Problem2-Invert.dfy b/Test/VSComp2010/Problem2-Invert.dfy
index 274d86de..0cf93061 100644
--- a/Test/VSComp2010/Problem2-Invert.dfy
+++ b/Test/VSComp2010/Problem2-Invert.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %dafny /compile:0 /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// VSComp 2010, problem 2, compute the inverse 'B' of a permutation 'A' and prove that 'B' is
diff --git a/Test/VSI-Benchmarks/b3.dfy b/Test/VSI-Benchmarks/b3.dfy
index f59b0c3e..d47c4d4d 100644
--- a/Test/VSI-Benchmarks/b3.dfy
+++ b/Test/VSI-Benchmarks/b3.dfy
@@ -96,7 +96,7 @@ class Benchmark3 {
if x < m { k := j; m := x; }
j := j+1;
}
-
+
j := 0;
while j < k
invariant j <= k;
@@ -108,10 +108,16 @@ class Benchmark3 {
RotationLemma(old(q.contents), j, qc0, q.contents);
j := j+1;
}
-
+
assert j == k;
assert q.contents == old(q.contents)[k..] + old(q.contents)[..k];
+ ghost var qq := q.contents;
m := q.Dequeue();
+ assert q.contents == qq[1..] && m == qq[0];
+ assert [m] + q.contents == qq;
+ assert |old(q.contents)| == |q.contents| + 1;
+
+ assert q.contents == old(q.contents)[k+1..] + old(q.contents)[..k];
}
lemma RotationLemma(O: seq, j: nat, A: seq, C: seq)
diff --git a/Test/VSI-Benchmarks/b8.dfy b/Test/VSI-Benchmarks/b8.dfy
index ea1911fe..a44ff5c3 100644
--- a/Test/VSI-Benchmarks/b8.dfy
+++ b/Test/VSI-Benchmarks/b8.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %dafny /compile:0 /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// Benchmark 8
diff --git a/Test/VerifyThis2015/Problem1.dfy b/Test/VerifyThis2015/Problem1.dfy
index 2e8a5243..1b54e918 100644
--- a/Test/VerifyThis2015/Problem1.dfy
+++ b/Test/VerifyThis2015/Problem1.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:3 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:3 /autoTriggers:1 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// Rustan Leino
@@ -161,18 +161,13 @@ lemma Same2<T>(pat: seq<T>, a: seq<T>)
ensures IRP_Alt(pat, a)
{
if pat == [] {
- assert pat <= a;
} else if a != [] && pat[0] == a[0] {
- assert IsRelaxedPrefixAux(pat[1..], a[1..], 1);
- Same2(pat[1..], a[1..]);
if pat[1..] <= a[1..] {
- assert pat <= a;
} else {
var k :| 0 <= k < |pat[1..]| && pat[1..][..k] + pat[1..][k+1..] <= a[1..];
assert 0 <= k+1 < |pat| && pat[..k+1] + pat[k+2..] <= a;
}
} else {
- assert IsRelaxedPrefixAux(pat[1..], a, 0);
Same2_Prefix(pat[1..], a);
assert pat[1..] <= a;
assert 0 <= 0 < |pat| && pat[..0] + pat[0+1..] <= a;
@@ -182,7 +177,4 @@ lemma Same2_Prefix<T>(pat: seq<T>, a: seq<T>)
requires IsRelaxedPrefixAux(pat, a, 0)
ensures pat <= a
{
- if pat != [] {
- Same2_Prefix(pat[1..], a[1..]);
- }
}
diff --git a/Test/VerifyThis2015/Problem2.dfy b/Test/VerifyThis2015/Problem2.dfy
index 1c7deffd..2bb63e7b 100644
--- a/Test/VerifyThis2015/Problem2.dfy
+++ b/Test/VerifyThis2015/Problem2.dfy
@@ -114,7 +114,7 @@ method ParallelGcd(A: int, B: int) returns (gcd: int)
var pc0, pc1 := 0, 0; // program counter for the two processes
var a0, b0, a1, b1; // local variables for the two processes
// To model fairness of scheduling, these "budget" variable give a bound on the number of times the
- // scheduler will repeatedly schedule on process to execute its "compare a and b" test. When a
+ // scheduler will repeatedly schedule one process to execute its "compare a and b" test. When a
// process executes its comparison, its budget is decreased and the budget for the other process
// is set to some arbitrary positive amount.
var budget0, budget1 :| budget0 > 0 && budget1 > 0;
@@ -315,7 +315,7 @@ lemma GcdDecrease(a: int, b: int)
ensures Gcd(a, b) == Gcd(a - b, b)
{
var k := Gcd(a - b, b);
- assert DividesBoth(k, a-b, b) && forall m :: DividesBoth(m, a-b, b) ==> m <= k;
+ assert DividesBoth(k, a-b, b) && forall m, mm :: mm == a - b ==> DividesBoth(m, mm, b) ==> m <= k; // WISH: auto-generate 'mm'
var n := DividesProperty(k, a-b);
assert n*k == a-b;
var p := DividesProperty(k, b);
diff --git a/Test/VerifyThis2015/Problem3.dfy b/Test/VerifyThis2015/Problem3.dfy
index 4205035d..60506a33 100644
--- a/Test/VerifyThis2015/Problem3.dfy
+++ b/Test/VerifyThis2015/Problem3.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:3 /print:"%t.print" /dprint:"%t.dprint" /vcsMaxKeepGoingSplits:5 "%s" > "%t"
+// RUN: %dafny /compile:3 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// Rustan Leino
@@ -92,6 +92,21 @@ class DoublyLinkedList {
}
Nodes := nodes;
}
+
+ function PopMiddle<T>(s: seq<T>, k: nat) : seq<T>
+ requires k < |s| {
+ s[..k] + s[k+1..]
+ }
+
+ predicate Injective<T>(s: seq<T>) {
+ forall j, k :: 0 <= j < k < |s| ==> s[j] != s[k]
+ }
+
+ lemma InjectiveAfterPop<T>(s: seq<T>, k: nat)
+ requires k < |s|
+ requires Injective(s)
+ ensures Injective(PopMiddle(s, k)) { }
+
method Remove(x: Node) returns (ghost k: int)
requires Valid()
requires x in Nodes && x != Nodes[0] && x != Nodes[|Nodes|-1] // not allowed to remove end nodes; you may think of them as a sentinel nodes
@@ -103,8 +118,11 @@ class DoublyLinkedList {
k :| 1 <= k < |Nodes|-1 && Nodes[k] == x;
x.R.L := x.L;
x.L.R := x.R;
+
+ InjectiveAfterPop(Nodes, k);
Nodes := Nodes[..k] + Nodes[k+1..];
}
+
// One might consider have a precondition that says there exists a "k" with the properties given here.
// However, we want to be able to refer to "k" in the postcondition as well, so it's convenient to
// burden the client with having to pass in "k" as a ghost parameter. This, however, is really no
diff --git a/Test/VerifyThis2015/Problem3.dfy.expect b/Test/VerifyThis2015/Problem3.dfy.expect
index 4035605c..d3a9554b 100644
--- a/Test/VerifyThis2015/Problem3.dfy.expect
+++ b/Test/VerifyThis2015/Problem3.dfy.expect
@@ -1,5 +1,5 @@
-Dafny program verifier finished with 15 verified, 0 errors
+Dafny program verifier finished with 19 verified, 0 errors
Program compiled successfully
Running...
diff --git a/Test/cloudmake/CloudMake-CachedBuilds.dfy b/Test/cloudmake/CloudMake-CachedBuilds.dfy
index 9e1b511e..5f16da90 100644
--- a/Test/cloudmake/CloudMake-CachedBuilds.dfy
+++ b/Test/cloudmake/CloudMake-CachedBuilds.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// This module proves the correctness of the algorithms. It leaves a number of things undefined.
diff --git a/Test/cloudmake/CloudMake-ConsistentBuilds.dfy b/Test/cloudmake/CloudMake-ConsistentBuilds.dfy
index 815352f6..c2fa4205 100644
--- a/Test/cloudmake/CloudMake-ConsistentBuilds.dfy
+++ b/Test/cloudmake/CloudMake-ConsistentBuilds.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
/******* State *******/
@@ -23,7 +23,7 @@ function Union(st: State, st': State): State
(p in DomSt(st) ==> GetSt(p, result) == GetSt(p, st)) &&
(p in DomSt(st') ==> GetSt(p, result) == GetSt(p, st'));
-ghost method StateEqualityProperty(st: State, st': State)
+lemma StateEqualityProperty(st: State, st': State)
requires DomSt(st) == DomSt(st');
requires forall p :: p in DomSt(st) ==> GetSt(p, st) == GetSt(p, st');
ensures st == st';
@@ -60,7 +60,7 @@ function UpdateC(cmd: Expression, deps: Expression, exts: Expression, stC: State
UpdateC(cmd, deps, exts', S(stC.st, c'))
}
-ghost method UpdateCLemma(cmd: Expression, deps: Expression, exts: Expression, stC: StateC)
+lemma UpdateCLemma(cmd: Expression, deps: Expression, exts: Expression, stC: StateC)
requires
cmd.exprLiteral? && cmd.lit.litString? &&
deps.exprLiteral? && deps.lit.litArrOfPaths? &&
@@ -136,7 +136,7 @@ function CombineC(stsC: set<StateC>): StateC
UnionC(stC, CombineC(stsC - {stC}))
}
-ghost method CombineCLemma(stsC: set<StateC>)
+lemma CombineCLemma(stsC: set<StateC>)
requires stsC != {};
requires forall stC :: stC in stsC ==> ConsistentCache(stC);
ensures
@@ -174,7 +174,7 @@ function SetEnv(id: Identifier, expr: Expression, env: Env): Env
/******* Primitive function 'exec' *******/
function exec(cmd: Expression, deps: Expression, exts: Expression, st: State): Tuple<Expression, State>
-ghost method ExecProperty(cmd: Expression, deps: Expression, exts: Expression, st: State)
+lemma ExecProperty(cmd: Expression, deps: Expression, exts: Expression, st: State)
requires
cmd.exprLiteral? && cmd.lit.litString? &&
deps.exprLiteral? && deps.lit.litArrOfPaths? &&
@@ -244,7 +244,7 @@ function execC(cmd: Expression, deps: Expression, exts: Expression, stC: StateC)
Pair(expr', stC')
}
-ghost method ExecCProperty(cmd: Expression, deps: Expression, exts: Expression, stC: StateC)
+lemma ExecCProperty(cmd: Expression, deps: Expression, exts: Expression, stC: StateC)
requires
cmd.exprLiteral? && cmd.lit.litString? &&
deps.exprLiteral? && deps.lit.litArrOfPaths? &&
@@ -305,7 +305,7 @@ predicate PostC(cmd: Expression, deps: Expression, exts: Expression, stC: StateC
function Hash(p: Path): HashValue
-ghost method HashProperty(cmd: Expression, deps: Expression, ext: string, cmd': Expression, deps': Expression, ext': string)
+lemma HashProperty(cmd: Expression, deps: Expression, ext: string, cmd': Expression, deps': Expression, ext': string)
requires Hash(Loc(cmd, deps, ext)) == Hash(Loc(cmd', deps', ext'));
ensures cmd == cmd' && deps == deps' && ext == ext';
@@ -509,7 +509,7 @@ predicate ValidArgsC(prim: Primitive, args: seq<Expression>, stC: StateC)
}
/******* {consistent_cache} buildC {no_bad_cache_error /\ consistent_cache} *******/
-ghost method CachedBuildsTheorem(prog: Program, stC: StateC)
+lemma CachedBuildsTheorem(prog: Program, stC: StateC)
requires Legal(prog.stmts);
requires ConsistentCache(stC);
ensures
@@ -521,7 +521,7 @@ ghost method CachedBuildsTheorem(prog: Program, stC: StateC)
BuildCLemma(prog, stC);
}
-ghost method BuildCLemma(prog: Program, stC: StateC)
+lemma BuildCLemma(prog: Program, stC: StateC)
requires Legal(prog.stmts);
requires ConsistentCache(stC);
ensures
@@ -532,7 +532,7 @@ ghost method BuildCLemma(prog: Program, stC: StateC)
DoCLemma(prog.stmts, stC, EmptyEnv());
}
-ghost method DoCLemma(stmts: seq<Statement>, stC: StateC, env: Env)
+lemma DoCLemma(stmts: seq<Statement>, stC: StateC, env: Env)
requires Legal(stmts);
requires ConsistentCache(stC);
ensures
@@ -558,7 +558,7 @@ ghost method DoCLemma(stmts: seq<Statement>, stC: StateC, env: Env)
}
}
-ghost method {:induction expr} EvalCLemma(expr: Expression, stC: StateC, env: Env)
+lemma {:induction expr} EvalCLemma(expr: Expression, stC: StateC, env: Env)
requires ConsistentCache(stC);
ensures
var result := evalC(expr, stC, env);
@@ -627,7 +627,7 @@ ghost method {:induction expr} EvalCLemma(expr: Expression, stC: StateC, env: En
} else { }
}
-ghost method EvalArgsCLemma(expr: Expression, args: seq<Expression>, stC: StateC, env: Env)
+lemma EvalArgsCLemma(expr: Expression, args: seq<Expression>, stC: StateC, env: Env)
requires ConsistentCache(stC);
requires forall arg :: arg in args ==> arg < expr;
ensures
@@ -640,7 +640,7 @@ ghost method EvalArgsCLemma(expr: Expression, args: seq<Expression>, stC: StateC
EvalArgsC'Lemma(expr, args, stC, env, [], {});
}
-ghost method EvalArgsC'Lemma(expr: Expression, args: seq<Expression>, stC: StateC, env: Env,
+lemma EvalArgsC'Lemma(expr: Expression, args: seq<Expression>, stC: StateC, env: Env,
args': seq<Expression>, stsC': set<StateC>)
requires ConsistentCache(stC);
requires forall stC' :: stC' in stsC' ==> ConsistentCache(stC');
diff --git a/Test/cloudmake/CloudMake-ParallelBuilds.dfy b/Test/cloudmake/CloudMake-ParallelBuilds.dfy
index 07cae317..5cc70994 100644
--- a/Test/cloudmake/CloudMake-ParallelBuilds.dfy
+++ b/Test/cloudmake/CloudMake-ParallelBuilds.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// This module proves the correctness of the algorithms. It leaves a number of things undefined.
diff --git a/Test/dafny0/AdvancedLHS.dfy.expect b/Test/dafny0/AdvancedLHS.dfy.expect
index cb817605..aab12cfc 100644
--- a/Test/dafny0/AdvancedLHS.dfy.expect
+++ b/Test/dafny0/AdvancedLHS.dfy.expect
@@ -1,4 +1,4 @@
-AdvancedLHS.dfy(34,23): Error: target object may be null
+AdvancedLHS.dfy(34,22): Error: target object may be null
Execution trace:
(0,0): anon0
(0,0): anon15_Else
diff --git a/Test/dafny0/Array.dfy b/Test/dafny0/Array.dfy
index 391ca5f7..309e9248 100644
--- a/Test/dafny0/Array.dfy
+++ b/Test/dafny0/Array.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
class A {
@@ -327,3 +327,5 @@ module DtypeRegression {
}
}
}
+
+// WISH: autoTriggers disabled because of induction
diff --git a/Test/dafny0/Array.dfy.expect b/Test/dafny0/Array.dfy.expect
index bf4da25f..40fb318d 100644
--- a/Test/dafny0/Array.dfy.expect
+++ b/Test/dafny0/Array.dfy.expect
@@ -1,16 +1,16 @@
-Array.dfy(13,8): Error: assignment may update an array element not in the enclosing context's modifies clause
+Array.dfy(13,7): Error: assignment may update an array element not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
(0,0): anon5_Then
(0,0): anon2
(0,0): anon6_Then
-Array.dfy(20,16): Error: target object may be null
+Array.dfy(20,15): Error: target object may be null
Execution trace:
(0,0): anon0
-Array.dfy(27,6): Error: index out of range
+Array.dfy(27,5): Error: index out of range
Execution trace:
(0,0): anon0
-Array.dfy(51,20): Error: assertion violation
+Array.dfy(51,19): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon12_Then
@@ -21,19 +21,19 @@ Execution trace:
(0,0): anon16_Then
(0,0): anon9
(0,0): anon11
-Array.dfy(59,8): Error: assignment may update an array element not in the enclosing context's modifies clause
+Array.dfy(59,7): Error: assignment may update an array element not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
(0,0): anon5_Then
(0,0): anon2
(0,0): anon6_Then
-Array.dfy(66,8): Error: assignment may update an array element not in the enclosing context's modifies clause
+Array.dfy(66,7): Error: assignment may update an array element not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
(0,0): anon5_Then
(0,0): anon2
(0,0): anon6_Then
-Array.dfy(110,21): Error: upper bound below lower bound or above length of array
+Array.dfy(110,20): Error: upper bound below lower bound or above length of array
Execution trace:
(0,0): anon0
(0,0): anon14_Else
@@ -41,71 +41,77 @@ Execution trace:
(0,0): anon19_Then
(0,0): anon20_Then
(0,0): anon11
-Array.dfy(120,8): Error: insufficient reads clause to read the indicated range of array elements
+Array.dfy(120,7): Error: insufficient reads clause to read the indicated range of array elements
Execution trace:
(0,0): anon0
- (0,0): anon9_Else
- (0,0): anon10_Then
+ (0,0): anon10_Else
(0,0): anon11_Then
(0,0): anon12_Then
-Array.dfy(122,8): Error: insufficient reads clause to read the indicated range of array elements
+ (0,0): anon13_Then
+ (0,0): anon9
+Array.dfy(122,7): Error: insufficient reads clause to read the indicated range of array elements
Execution trace:
(0,0): anon0
- (0,0): anon9_Else
- (0,0): anon10_Then
+ (0,0): anon10_Else
(0,0): anon11_Then
- (0,0): anon12_Else
-Array.dfy(123,8): Error: insufficient reads clause to read the indicated range of array elements
+ (0,0): anon12_Then
+ (0,0): anon13_Else
+ (0,0): anon9
+Array.dfy(123,7): Error: insufficient reads clause to read the indicated range of array elements
Execution trace:
(0,0): anon0
- (0,0): anon9_Else
- (0,0): anon10_Then
+ (0,0): anon10_Else
(0,0): anon11_Then
- (0,0): anon12_Else
-Array.dfy(124,8): Error: insufficient reads clause to read the indicated range of array elements
+ (0,0): anon12_Then
+ (0,0): anon13_Else
+ (0,0): anon9
+Array.dfy(124,7): Error: insufficient reads clause to read the indicated range of array elements
Execution trace:
(0,0): anon0
- (0,0): anon9_Else
- (0,0): anon10_Then
+ (0,0): anon10_Else
(0,0): anon11_Then
- (0,0): anon12_Else
-Array.dfy(163,6): Error: insufficient reads clause to read array element
+ (0,0): anon12_Then
+ (0,0): anon13_Else
+ (0,0): anon9
+Array.dfy(163,5): Error: insufficient reads clause to read array element
Execution trace:
(0,0): anon0
- (0,0): anon7_Else
- (0,0): anon8_Then
+ (0,0): anon8_Else
(0,0): anon9_Then
-Array.dfy(171,6): Error: insufficient reads clause to read array element
+ (0,0): anon10_Then
+ (0,0): anon7
+Array.dfy(171,5): Error: insufficient reads clause to read array element
Execution trace:
(0,0): anon0
- (0,0): anon7_Else
- (0,0): anon8_Then
+ (0,0): anon8_Else
(0,0): anon9_Then
-Array.dfy(187,6): Error: assignment may update an array element not in the enclosing context's modifies clause
+ (0,0): anon10_Then
+ (0,0): anon7
+Array.dfy(187,5): Error: assignment may update an array element not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
-Array.dfy(194,6): Error: assignment may update an array element not in the enclosing context's modifies clause
+Array.dfy(194,5): Error: assignment may update an array element not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
-Array.dfy(219,1): Error BP5003: A postcondition might not hold on this return path.
-Array.dfy(218,11): Related location: This is the postcondition that might not hold.
+Array.dfy(219,0): Error BP5003: A postcondition might not hold on this return path.
+Array.dfy(218,10): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-Array.dfy(243,1): Error BP5003: A postcondition might not hold on this return path.
-Array.dfy(242,11): Related location: This is the postcondition that might not hold.
+Array.dfy(243,0): Error BP5003: A postcondition might not hold on this return path.
+Array.dfy(242,10): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-Array.dfy(249,1): Error BP5003: A postcondition might not hold on this return path.
-Array.dfy(248,11): Related location: This is the postcondition that might not hold.
+Array.dfy(249,0): Error BP5003: A postcondition might not hold on this return path.
+Array.dfy(248,10): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-Array.dfy(264,10): Error: value assigned to a nat must be non-negative
+Array.dfy(264,9): Error: value assigned to a nat must be non-negative
Execution trace:
(0,0): anon0
(0,0): anon5_Then
(0,0): anon2
(0,0): anon6_Then
-Array.dfy(265,5): Error: value assigned to a nat must be non-negative
+Array.dfy(265,4): Error: value assigned to a nat must be non-negative
Execution trace:
(0,0): anon0
(0,0): anon5_Then
diff --git a/Test/dafny0/AssumptionVariables0.dfy b/Test/dafny0/AssumptionVariables0.dfy
index a3e23b73..b9acc522 100644
--- a/Test/dafny0/AssumptionVariables0.dfy
+++ b/Test/dafny0/AssumptionVariables0.dfy
@@ -6,7 +6,7 @@ method test0(x: int)
ghost var {:assumption} a0 := false; // error
ghost var a1, {:assumption} a2 := true, false; // error
ghost var {:assumption} a3: bool;
- var {:assumption} a4; // 2 errors
+ ghost var {:assumption} a4; // error: type must be bool
a0 := a0 && (0 < x);
@@ -54,7 +54,7 @@ method test2()
if (false)
{
- var {:assumption} a0: bool; // error
+ ghost var {:assumption} a0: bool;
if (false)
{
@@ -73,3 +73,7 @@ method test2()
}
}
}
+
+method test3() {
+ var {:assumption} a: bool; // error: assumption variable must be ghost
+}
diff --git a/Test/dafny0/AssumptionVariables0.dfy.expect b/Test/dafny0/AssumptionVariables0.dfy.expect
index f2d43fe1..83eb8a73 100644
--- a/Test/dafny0/AssumptionVariables0.dfy.expect
+++ b/Test/dafny0/AssumptionVariables0.dfy.expect
@@ -1,14 +1,13 @@
AssumptionVariables0.dfy(6,29): Error: there may be at most one assignment to an assumption variable, the RHS of which must match the expression "a0 && <boolean expression>"
AssumptionVariables0.dfy(7,33): Error: there may be at most one assignment to an assumption variable, the RHS of which must match the expression "a2 && <boolean expression>"
-AssumptionVariables0.dfy(9,20): Error: assumption variable must be ghost
-AssumptionVariables0.dfy(9,2): Error: assumption variable must be of type 'bool'
+AssumptionVariables0.dfy(9,26): Error: assumption variable must be of type 'bool'
AssumptionVariables0.dfy(15,5): Error: there may be at most one assignment to an assumption variable, the RHS of which must match the expression "a3 && <boolean expression>"
AssumptionVariables0.dfy(17,5): Error: there may be at most one assignment to an assumption variable, the RHS of which must match the expression "a3 && <boolean expression>"
AssumptionVariables0.dfy(27,5): Error: there may be at most one assignment to an assumption variable, the RHS of which must match the expression "a0 && <boolean expression>"
AssumptionVariables0.dfy(31,5): Error: there may be at most one assignment to an assumption variable, the RHS of which must match the expression "a0 && <boolean expression>"
AssumptionVariables0.dfy(53,9): Error: there may be at most one assignment to an assumption variable, the RHS of which must match the expression "a0 && <boolean expression>"
-AssumptionVariables0.dfy(57,26): Error: assumption variable must be ghost
AssumptionVariables0.dfy(61,37): Error: there may be at most one assignment to an assumption variable, the RHS of which must match the expression "a0 && <boolean expression>"
-AssumptionVariables0.dfy(61,10): Error: assumption variable must be of type 'bool'
+AssumptionVariables0.dfy(61,34): Error: assumption variable must be of type 'bool'
AssumptionVariables0.dfy(69,15): Error: there may be at most one assignment to an assumption variable, the RHS of which must match the expression "a0 && <boolean expression>"
-13 resolution/type errors detected in AssumptionVariables0.dfy
+AssumptionVariables0.dfy(78,20): Error: assumption variable must be ghost
+12 resolution/type errors detected in AssumptionVariables0.dfy
diff --git a/Test/dafny0/AutoReq.dfy b/Test/dafny0/AutoReq.dfy
index acfe6b8d..d7c87e6d 100644
--- a/Test/dafny0/AutoReq.dfy
+++ b/Test/dafny0/AutoReq.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
function f(x:int) : bool
@@ -313,3 +313,8 @@ module OpaqueTest {
}
}
+
+// autoTriggers added because it causes an extra error message related to
+// violated preconditions to appear. That extra message is due to the extra
+// precondition involving a split quantifier: the user now gets two traces, one
+// for each conjunct.
diff --git a/Test/dafny0/AutoReq.dfy.expect b/Test/dafny0/AutoReq.dfy.expect
index 547b676d..25f00797 100644
--- a/Test/dafny0/AutoReq.dfy.expect
+++ b/Test/dafny0/AutoReq.dfy.expect
@@ -1,45 +1,52 @@
-AutoReq.dfy(247,5): Error: possible violation of function precondition
-AutoReq.dfy(239,14): Related location
+AutoReq.dfy(247,4): Error: possible violation of function precondition
+AutoReq.dfy(239,13): Related location
+AutoReq.dfy(239,59): Related location
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-AutoReq.dfy(13,3): Error: possible violation of function precondition
-AutoReq.dfy(5,14): Related location
+ (0,0): anon4_Else
+AutoReq.dfy(247,4): Error: possible violation of function precondition
+AutoReq.dfy(239,13): Related location
+AutoReq.dfy(239,35): Related location
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-AutoReq.dfy(25,3): Error: possible violation of function precondition
-AutoReq.dfy(5,14): Related location
+ (0,0): anon4_Else
+AutoReq.dfy(13,2): Error: possible violation of function precondition
+AutoReq.dfy(5,13): Related location
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-AutoReq.dfy(38,12): Error: assertion violation
-AutoReq.dfy(31,13): Related location
-AutoReq.dfy(7,5): Related location
+ (0,0): anon4_Else
+AutoReq.dfy(25,2): Error: possible violation of function precondition
+AutoReq.dfy(5,13): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon4_Else
+AutoReq.dfy(38,11): Error: assertion violation
+AutoReq.dfy(31,12): Related location
+AutoReq.dfy(7,4): Related location
Execution trace:
(0,0): anon0
(0,0): anon9_Then
-AutoReq.dfy(38,12): Error: possible violation of function precondition
-AutoReq.dfy(5,14): Related location
+AutoReq.dfy(38,11): Error: possible violation of function precondition
+AutoReq.dfy(5,13): Related location
Execution trace:
(0,0): anon0
(0,0): anon9_Then
-AutoReq.dfy(40,12): Error: assertion violation
-AutoReq.dfy(31,27): Related location
-AutoReq.dfy(7,5): Related location
+AutoReq.dfy(40,11): Error: assertion violation
+AutoReq.dfy(31,26): Related location
+AutoReq.dfy(7,4): Related location
Execution trace:
(0,0): anon0
(0,0): anon10_Then
-AutoReq.dfy(40,12): Error: possible violation of function precondition
-AutoReq.dfy(5,14): Related location
+AutoReq.dfy(40,11): Error: possible violation of function precondition
+AutoReq.dfy(5,13): Related location
Execution trace:
(0,0): anon0
(0,0): anon10_Then
-AutoReq.dfy(45,12): Error: assertion violation
-AutoReq.dfy(31,13): Related location
-AutoReq.dfy(7,5): Related location
+AutoReq.dfy(45,11): Error: assertion violation
+AutoReq.dfy(31,12): Related location
+AutoReq.dfy(7,4): Related location
Execution trace:
(0,0): anon0
(0,0): anon11_Then
-Dafny program verifier finished with 52 verified, 8 errors
+Dafny program verifier finished with 52 verified, 9 errors
diff --git a/Test/dafny0/Backticks.dfy.expect b/Test/dafny0/Backticks.dfy.expect
index ab2bbc52..58977413 100644
--- a/Test/dafny0/Backticks.dfy.expect
+++ b/Test/dafny0/Backticks.dfy.expect
@@ -1,9 +1,10 @@
-Backticks.dfy(38,5): Error: insufficient reads clause to invoke function
+Backticks.dfy(38,4): Error: insufficient reads clause to invoke function
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
- (0,0): anon6_Else
-Backticks.dfy(77,8): Error: call may violate context's modifies clause
+ (0,0): anon7_Else
+ (0,0): anon8_Else
+ (0,0): anon6
+Backticks.dfy(77,7): Error: call may violate context's modifies clause
Execution trace:
(0,0): anon0
(0,0): anon3_Then
diff --git a/Test/dafny0/BadFunction.dfy.expect b/Test/dafny0/BadFunction.dfy.expect
index 7127b60b..1af2608d 100644
--- a/Test/dafny0/BadFunction.dfy.expect
+++ b/Test/dafny0/BadFunction.dfy.expect
@@ -1,6 +1,6 @@
-BadFunction.dfy(9,3): Error: failure to decrease termination measure
+BadFunction.dfy(9,2): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
+ (0,0): anon4_Else
Dafny program verifier finished with 2 verified, 1 error
diff --git a/Test/dafny0/Basics.dfy b/Test/dafny0/Basics.dfy
index c8fa76c8..7b8b632b 100644
--- a/Test/dafny0/Basics.dfy
+++ b/Test/dafny0/Basics.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
class Global {
@@ -100,7 +100,7 @@ method ExpliesAssociativityM(A: bool, B: bool, C: bool) {
}
}
-method ExpliesShortCircuiting(a: array<T>)
+method ExpliesShortCircuiting(a: array)
{
assert a == null || 0 <= a.Length; // (W)
assert a != null ==> 0 <= a.Length; // (X) -- same as (W)
diff --git a/Test/dafny0/Basics.dfy.expect b/Test/dafny0/Basics.dfy.expect
index f28df20a..65d5d101 100644
--- a/Test/dafny0/Basics.dfy.expect
+++ b/Test/dafny0/Basics.dfy.expect
@@ -1,8 +1,8 @@
-Basics.dfy(45,14): Error: assertion violation
+Basics.dfy(45,13): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Else
-Basics.dfy(69,42): Error: assertion violation
+Basics.dfy(69,41): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon13_Then
@@ -12,7 +12,7 @@ Execution trace:
Basics.dfy(69,82): anon17_Else
Basics.dfy(69,95): anon18_Else
(0,0): anon12
-Basics.dfy(93,14): Error: assertion violation
+Basics.dfy(93,13): Error: assertion violation
Execution trace:
(0,0): anon0
Basics.dfy(83,14): anon27_Else
@@ -27,7 +27,7 @@ Execution trace:
Basics.dfy(91,13): anon34_Else
(0,0): anon35_Then
(0,0): anon15
-Basics.dfy(99,14): Error: assertion violation
+Basics.dfy(99,13): Error: assertion violation
Execution trace:
(0,0): anon0
Basics.dfy(83,14): anon27_Else
@@ -42,7 +42,7 @@ Execution trace:
Basics.dfy(97,19): anon40_Else
(0,0): anon41_Then
(0,0): anon26
-Basics.dfy(112,28): Error: target object may be null
+Basics.dfy(112,27): Error: target object may be null
Execution trace:
(0,0): anon0
Basics.dfy(105,20): anon13_Else
@@ -52,7 +52,7 @@ Execution trace:
Basics.dfy(107,24): anon15_Else
(0,0): anon6
(0,0): anon16_Then
-Basics.dfy(114,14): Error: target object may be null
+Basics.dfy(114,13): Error: target object may be null
Execution trace:
(0,0): anon0
Basics.dfy(105,20): anon13_Else
@@ -62,11 +62,11 @@ Execution trace:
Basics.dfy(107,24): anon15_Else
(0,0): anon6
(0,0): anon16_Else
-Basics.dfy(149,16): Error: assertion violation
+Basics.dfy(149,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon10_Then
-Basics.dfy(168,10): Error: when left-hand sides 0 and 1 may refer to the same location, they must be assigned the same value
+Basics.dfy(168,9): Error: when left-hand sides 0 and 1 may refer to the same location, they must be assigned the same value
Execution trace:
(0,0): anon0
(0,0): anon10_Then
@@ -75,28 +75,28 @@ Execution trace:
(0,0): anon6
(0,0): anon12_Then
(0,0): anon9
-Basics.dfy(182,10): Error: when left-hand sides 0 and 1 refer to the same location, they must be assigned the same value
+Basics.dfy(182,9): Error: when left-hand sides 0 and 1 refer to the same location, they must be assigned the same value
Execution trace:
(0,0): anon0
-Basics.dfy(194,19): Error: assertion violation
+Basics.dfy(194,18): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon11_Then
-Basics.dfy(196,10): Error: assignment may update an object not in the enclosing context's modifies clause
+Basics.dfy(196,9): Error: assignment may update an object not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
(0,0): anon3
-Basics.dfy(196,10): Error: target object may be null
+Basics.dfy(196,9): Error: target object may be null
Execution trace:
(0,0): anon0
(0,0): anon3
-Basics.dfy(201,12): Error: left-hand sides 0 and 1 may refer to the same location
+Basics.dfy(201,11): Error: left-hand sides 0 and 1 may refer to the same location
Execution trace:
(0,0): anon0
(0,0): anon11_Then
(0,0): anon3
(0,0): anon12_Then
-Basics.dfy(212,15): Error: assertion violation
+Basics.dfy(212,14): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon11_Then
@@ -106,19 +106,19 @@ Execution trace:
(0,0): anon13_Then
(0,0): anon8
(0,0): anon14_Then
-Basics.dfy(274,10): Error: when left-hand sides 0 and 1 refer to the same location, they must be assigned the same value
+Basics.dfy(274,9): Error: when left-hand sides 0 and 1 refer to the same location, they must be assigned the same value
Execution trace:
(0,0): anon0
-Basics.dfy(465,12): Error: assertion violation
+Basics.dfy(465,11): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon4_Then
(0,0): anon3
-Basics.dfy(476,19): Error: assertion violation
+Basics.dfy(476,18): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon4_Else
-Basics.dfy(478,12): Error: assertion violation
+Basics.dfy(478,11): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon4_Then
diff --git a/Test/dafny0/BindingGuards.dfy b/Test/dafny0/BindingGuards.dfy
new file mode 100644
index 00000000..0706fc5b
--- /dev/null
+++ b/Test/dafny0/BindingGuards.dfy
@@ -0,0 +1,159 @@
+// RUN: %dafny /dprint:- /env:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+predicate P(n: int)
+{
+ n % 2 == 0
+}
+
+predicate R(r: real)
+{
+ 0.0 <= r
+}
+
+method M0()
+{
+ if x :| P(x) {
+ var y := x + 3;
+ }
+}
+
+method M1()
+{
+ if x: int :| P(x) {
+ }
+}
+
+method M2()
+{
+ var x := true;
+ if x, y :| P(x) && R(y) { // this declares a new 'x'
+ var z := x + 12;
+ }
+ x := x && false;
+}
+
+method M3()
+{
+ var x := true;
+ if x: int, y :| P(x) && R(y) {
+ var z := x + y.Trunc;
+ var w := real(x) + y;
+ }
+}
+
+method M4()
+{
+ if x, y: real :| P(x) && R(y) {
+ }
+}
+
+method M5()
+{
+ if x: int, y: real :| P(x) && R(y) {
+ }
+}
+
+method M6()
+{
+ if x {:myattribute x, "hello"} :| P(x) {
+ }
+ if x, y {:myattribute y, "sveika"} :| P(x) && R(y) {
+ }
+ if x: int {:myattribute x, "chello"} :| P(x) {
+ }
+ if x {:myattribute x, "hola"} {:yourattribute x + x, "hej"} :| P(x) {
+ }
+}
+
+ghost method M7() returns (z: real, w: real)
+ ensures -2.0 <= z
+ ensures z == w // error: does not hold
+{
+ var k;
+ if x :| P(x) {
+ k, z := 4, 18.0;
+ } else if * {
+ z := z + -z;
+ } else if y :| R(y) {
+ z := y;
+ } else if y :| P(y) {
+ k := y;
+ } else {
+ z :| R(z);
+ }
+ if P(k) {
+ z := 18.0;
+ }
+}
+
+ghost method M8(m: int, n: int)
+ requires forall y :: m <= y < n ==> P(y)
+{
+ var t := -1;
+ var u;
+ if y :| m <= y < n && P(y) {
+ u := y;
+ if * {
+ t := n - y;
+ } else if * {
+ t := y - m;
+ } else if P(y) {
+ t := 8;
+ } else {
+ t := -100; // will never happen
+ }
+ }
+ if t < 0 && m < n {
+ assert P(m) && !P(m);
+ assert false;
+ }
+ assert t < 0 ==> n <= m;
+}
+
+method P0(m: int, n: int)
+ requires m < n
+{
+ ghost var even, alsoEven := 4, 8;
+ if {
+ case x :| P(x) =>
+ even := x;
+ case x: int :| P(x) =>
+ even := x;
+ case x, y :| P(x) && R(y) =>
+ even, alsoEven := x, y.Trunc; // this assigns to 'alsoEven' a possibly odd number
+ case x: int, y :| P(x) && R(y) =>
+ even := x;
+ case m < n => // just to be different
+ case x, y: real :| P(x) && R(y) =>
+ even := x;
+ case x: int, y: real :| P(x) && R(y) =>
+ even := x;
+ }
+ assert P(even);
+ assert P(alsoEven); // error: may not hold
+}
+
+method P1(m: int, n: int)
+{
+ if { // error: missing case
+ case x :| m <= x < n && P(x) =>
+ }
+}
+
+method P2(m: int, n: int)
+ requires forall y :: m <= y < n ==> P(y)
+{
+ if { // error: missing case
+ case x :| m <= x < n && P(x) =>
+ }
+}
+
+method P3(m: int, n: int)
+ requires m < n && forall y :: m <= y < n ==> P(y)
+{
+ assert P(m); // lemma that proves that the following 'if' covers all possibilities
+ if {
+ case x :| m <= x < n && P(x) =>
+ }
+}
diff --git a/Test/dafny0/BindingGuards.dfy.expect b/Test/dafny0/BindingGuards.dfy.expect
new file mode 100644
index 00000000..b7da7b9e
--- /dev/null
+++ b/Test/dafny0/BindingGuards.dfy.expect
@@ -0,0 +1,183 @@
+// BindingGuards.dfy
+
+predicate P(n: int)
+{
+ n % 2 == 0
+}
+
+predicate R(r: real)
+{
+ 0.0 <= r
+}
+
+method M0()
+{
+ if x :| P(x) {
+ var y := x + 3;
+ }
+}
+
+method M1()
+{
+ if x: int :| P(x) {
+ }
+}
+
+method M2()
+{
+ var x := true;
+ if x, y :| P(x) && R(y) {
+ var z := x + 12;
+ }
+ x := x && false;
+}
+
+method M3()
+{
+ var x := true;
+ if x: int, y :| P(x) && R(y) {
+ var z := x + y.Trunc;
+ var w := real(x) + y;
+ }
+}
+
+method M4()
+{
+ if x, y: real :| P(x) && R(y) {
+ }
+}
+
+method M5()
+{
+ if x: int, y: real :| P(x) && R(y) {
+ }
+}
+
+method M6()
+{
+ if x {:myattribute x, "hello"} :| P(x) {
+ }
+ if x, y {:myattribute y, "sveika"} :| P(x) && R(y) {
+ }
+ if x: int {:myattribute x, "chello"} :| P(x) {
+ }
+ if x {:myattribute x, "hola"} {:yourattribute x + x, "hej"} :| P(x) {
+ }
+}
+
+ghost method M7() returns (z: real, w: real)
+ ensures -2.0 <= z
+ ensures z == w
+{
+ var k;
+ if x :| P(x) {
+ k, z := 4, 18.0;
+ } else if * {
+ z := z + -z;
+ } else if y :| R(y) {
+ z := y;
+ } else if y :| P(y) {
+ k := y;
+ } else {
+ z :| R(z);
+ }
+ if P(k) {
+ z := 18.0;
+ }
+}
+
+ghost method M8(m: int, n: int)
+ requires forall y :: m <= y < n ==> P(y)
+{
+ var t := -1;
+ var u;
+ if y :| m <= y < n && P(y) {
+ u := y;
+ if * {
+ t := n - y;
+ } else if * {
+ t := y - m;
+ } else if P(y) {
+ t := 8;
+ } else {
+ t := -100;
+ }
+ }
+ if t < 0 && m < n {
+ assert P(m) && !P(m);
+ assert false;
+ }
+ assert t < 0 ==> n <= m;
+}
+
+method P0(m: int, n: int)
+ requires m < n
+{
+ ghost var even, alsoEven := 4, 8;
+ if {
+ case x :| P(x) =>
+ even := x;
+ case x: int :| P(x) =>
+ even := x;
+ case x, y :| P(x) && R(y) =>
+ even, alsoEven := x, y.Trunc;
+ case x: int, y :| P(x) && R(y) =>
+ even := x;
+ case m < n =>
+ case x, y: real :| P(x) && R(y) =>
+ even := x;
+ case x: int, y: real :| P(x) && R(y) =>
+ even := x;
+ }
+ assert P(even);
+ assert P(alsoEven);
+}
+
+method P1(m: int, n: int)
+{
+ if {
+ case x :| m <= x < n && P(x) =>
+ }
+}
+
+method P2(m: int, n: int)
+ requires forall y :: m <= y < n ==> P(y)
+{
+ if {
+ case x :| m <= x < n && P(x) =>
+ }
+}
+
+method P3(m: int, n: int)
+ requires m < n && forall y :: m <= y < n ==> P(y)
+{
+ assert P(m);
+ if {
+ case x :| m <= x < n && P(x) =>
+ }
+}
+BindingGuards.dfy(85,10): Error BP5003: A postcondition might not hold on this return path.
+BindingGuards.dfy(71,12): Related location: This is the postcondition that might not hold.
+Execution trace:
+ (0,0): anon0
+ (0,0): anon12_Then
+ (0,0): anon9
+ (0,0): anon16_Then
+BindingGuards.dfy(134,9): Error: assertion violation
+BindingGuards.dfy(6,8): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon20_Then
+ (0,0): anon21_Then
+ (0,0): anon5
+ (0,0): anon17
+BindingGuards.dfy(139,2): Error: alternative cases fail to cover all possibilties
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Else
+BindingGuards.dfy(147,2): Error: alternative cases fail to cover all possibilties
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Else
+
+Dafny program verifier finished with 24 verified, 4 errors
diff --git a/Test/dafny0/BindingGuardsResolution.dfy b/Test/dafny0/BindingGuardsResolution.dfy
new file mode 100644
index 00000000..e2b55a99
--- /dev/null
+++ b/Test/dafny0/BindingGuardsResolution.dfy
@@ -0,0 +1,154 @@
+// RUN: %dafny /dprint:- /env:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+predicate P(n: int)
+
+predicate R(r: real)
+
+method M0()
+{
+ if x :| P(x) {
+ var y := x + 3;
+ var x := true; // error: 'x' is already declared in this scope
+ }
+}
+
+method M1()
+{
+ if x: int :| P(x) {
+ x := x + 1; // error: 'x' is an immutable variable
+ }
+}
+
+method M2()
+{
+ var x := true;
+ if x, y :| P(x) && R(y) { // this declares a new 'x'
+ var z := x + 12;
+ }
+ x := x && false;
+}
+
+method M3()
+{
+ var x := true;
+ if x: int, y :| P(x) && R(y) {
+ var z := x + int(y);
+ var w := real(x) + y;
+ }
+ var x := 0.0; // error: 'x' is already declared in this scope
+}
+
+method M4()
+{
+ if x, y: real :| P(x) && R(y) {
+ }
+}
+
+method M5()
+{
+ if x: int, y: real :| P(x) && R(y) {
+ }
+}
+
+method M6()
+{
+ if x {:myattribute x, "hello"} :| P(x) {
+ }
+ if x, y {:myattribute y, "sveika"} :| P(x) && R(y) {
+ }
+ if x: int {:myattribute x, "chello"} :| P(x) {
+ }
+ if x {:myattribute x, "hola"} {:yourattribute x + x, "hej"} :| P(x) {
+ }
+}
+
+method M7()
+{
+ if x :| P(x) {
+ } else if * {
+ } else if y :| R(y) {
+ } else if y :| P(y) {
+ }
+}
+
+method P0(m: int, n: int)
+ requires m < n
+{
+ var x := true;
+ if {
+ case x :| P(x) =>
+ var t := 3 * x;
+ case x: int :| P(x) =>
+ case x, y :| P(x) && R(y) =>
+ y := y + 1.0; // error: 'y' is an immutable variable
+ case x: int, y :| P(x) && R(y) =>
+ case m < n =>
+ x := x || m + 5 == n;
+ case x, y: real :| P(x) && R(y) =>
+ case x: int, y: real :| P(x) && R(y) =>
+ }
+ assert x;
+}
+
+method P1(m: int, n: int)
+ requires m < n
+{
+ if {
+ case x {:myattribute x, "hello"} :| P(x) =>
+ case x, y {:myattribute y, "sveika"} :| P(x) && R(y) =>
+ case x: int {:myattribute x, "chello"} :| P(x) =>
+ case x {:myattribute x, "hola"} {:yourattribute x + x, "hej"} :| P(x) =>
+ case m < n =>
+ }
+}
+
+module TypesNotFullyDetermined {
+ method T0()
+ {
+ if x :| true { // error: type not entirely resolved
+ }
+ }
+ method T1()
+ {
+ if x :| true {
+ var y := x + 3;
+ }
+ }
+}
+
+module Ghost {
+ predicate P(x: int) // note, P is ghost
+ predicate method R(x: int)
+ method M7() returns (z: int, b: bool)
+ {
+ if * {
+ z := z + -z;
+ } else if y :| 1000 <= y < 2000 && R(y) {
+ z := y;
+ } else if y :| 0 <= y < 100 && P(y) {
+ z := y; // error: not allowed, because the P in the guard makes this a ghost context
+ } else if y :| 0 <= y < 100 && R(y) {
+ z := y; // error: this is also in a ghost context, because it depends on the P above
+ }
+
+ if * {
+ z := z + -z;
+ } else if exists y :: 1000 <= y < 2000 && R(y) {
+ z := 0;
+ } else if exists y :: 0 <= y < 100 && P(y) {
+ z := 0; // error: not allowed, because the P in the guard makes this a ghost context
+ } else if exists y :: 0 <= y < 100 && R(y) {
+ z := 0; // error: this is also in a ghost context, because it depends on the P above
+ }
+
+ if P(z) {
+ z := 20; // error: blatant ghost context
+ }
+
+ b := exists y :: 0 <= y < 100 && P(y); // error: assignment to non-ghost of something that depends on ghost
+ ghost var c;
+ c := exists y :: 0 <= y < 100 && P(y);
+ b := exists y {:myattribute P(y)} :: 0 <= y < 100;
+ }
+}
diff --git a/Test/dafny0/BindingGuardsResolution.dfy.expect b/Test/dafny0/BindingGuardsResolution.dfy.expect
new file mode 100644
index 00000000..b6f23805
--- /dev/null
+++ b/Test/dafny0/BindingGuardsResolution.dfy.expect
@@ -0,0 +1,165 @@
+// BindingGuardsResolution.dfy
+
+
+module TypesNotFullyDetermined {
+ method T0()
+ {
+ if x :| true {
+ }
+ }
+
+ method T1()
+ {
+ if x :| true {
+ var y := x + 3;
+ }
+ }
+}
+
+module Ghost {
+ predicate P(x: int)
+
+ predicate method R(x: int)
+
+ method M7() returns (z: int, b: bool)
+ {
+ if * {
+ z := z + -z;
+ } else if y :| 1000 <= y < 2000 && R(y) {
+ z := y;
+ } else if y :| 0 <= y < 100 && P(y) {
+ z := y;
+ } else if y :| 0 <= y < 100 && R(y) {
+ z := y;
+ }
+ if * {
+ z := z + -z;
+ } else if exists y :: 1000 <= y < 2000 && R(y) {
+ z := 0;
+ } else if exists y :: 0 <= y < 100 && P(y) {
+ z := 0;
+ } else if exists y :: 0 <= y < 100 && R(y) {
+ z := 0;
+ }
+ if P(z) {
+ z := 20;
+ }
+ b := exists y :: 0 <= y < 100 && P(y);
+ ghost var c;
+ c := exists y :: 0 <= y < 100 && P(y);
+ b := exists y {:myattribute P(y)} :: 0 <= y < 100;
+ }
+}
+predicate P(n: int)
+
+predicate R(r: real)
+
+method M0()
+{
+ if x :| P(x) {
+ var y := x + 3;
+ var x := true;
+ }
+}
+
+method M1()
+{
+ if x: int :| P(x) {
+ x := x + 1;
+ }
+}
+
+method M2()
+{
+ var x := true;
+ if x, y :| P(x) && R(y) {
+ var z := x + 12;
+ }
+ x := x && false;
+}
+
+method M3()
+{
+ var x := true;
+ if x: int, y :| P(x) && R(y) {
+ var z := x + int(y);
+ var w := real(x) + y;
+ }
+ var x := 0.0;
+}
+
+method M4()
+{
+ if x, y: real :| P(x) && R(y) {
+ }
+}
+
+method M5()
+{
+ if x: int, y: real :| P(x) && R(y) {
+ }
+}
+
+method M6()
+{
+ if x {:myattribute x, "hello"} :| P(x) {
+ }
+ if x, y {:myattribute y, "sveika"} :| P(x) && R(y) {
+ }
+ if x: int {:myattribute x, "chello"} :| P(x) {
+ }
+ if x {:myattribute x, "hola"} {:yourattribute x + x, "hej"} :| P(x) {
+ }
+}
+
+method M7()
+{
+ if x :| P(x) {
+ } else if * {
+ } else if y :| R(y) {
+ } else if y :| P(y) {
+ }
+}
+
+method P0(m: int, n: int)
+ requires m < n
+{
+ var x := true;
+ if {
+ case x :| P(x) =>
+ var t := 3 * x;
+ case x: int :| P(x) =>
+ case x, y :| P(x) && R(y) =>
+ y := y + 1.0;
+ case x: int, y :| P(x) && R(y) =>
+ case m < n =>
+ x := x || m + 5 == n;
+ case x, y: real :| P(x) && R(y) =>
+ case x: int, y: real :| P(x) && R(y) =>
+ }
+ assert x;
+}
+
+method P1(m: int, n: int)
+ requires m < n
+{
+ if {
+ case x {:myattribute x, "hello"} :| P(x) =>
+ case x, y {:myattribute y, "sveika"} :| P(x) && R(y) =>
+ case x: int {:myattribute x, "chello"} :| P(x) =>
+ case x {:myattribute x, "hola"} {:yourattribute x + x, "hej"} :| P(x) =>
+ case m < n =>
+ }
+}
+BindingGuardsResolution.dfy(109,7): Error: type of bound variable 'x' could not be determined; please specify the type explicitly
+BindingGuardsResolution.dfy(130,8): Error: Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+BindingGuardsResolution.dfy(132,8): Error: Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+BindingGuardsResolution.dfy(140,8): Error: Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+BindingGuardsResolution.dfy(142,8): Error: Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+BindingGuardsResolution.dfy(146,8): Error: Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+BindingGuardsResolution.dfy(149,37): Error: function calls are allowed only in specification contexts (consider declaring the function a 'function method')
+BindingGuardsResolution.dfy(12,8): Error: Duplicate local-variable name: x
+BindingGuardsResolution.dfy(19,4): Error: LHS of assignment must denote a mutable variable
+BindingGuardsResolution.dfy(39,6): Error: Duplicate local-variable name: x
+BindingGuardsResolution.dfy(84,6): Error: LHS of assignment must denote a mutable variable
+11 resolution/type errors detected in BindingGuardsResolution.dfy
diff --git a/Test/dafny0/Calculations.dfy b/Test/dafny0/Calculations.dfy
index c77bced7..eb4ff1b9 100644
--- a/Test/dafny0/Calculations.dfy
+++ b/Test/dafny0/Calculations.dfy
@@ -1,4 +1,5 @@
-// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint.dfy" "%s" > "%t"; %dafny /noVerify /compile:0 "%t.dprint.dfy" >> "%t"
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint.dfy" /autoTriggers:0 "%s" > "%t"
+// RUN: %dafny /noVerify /compile:0 "%t.dprint.dfy" >> "%t"
// RUN: %diff "%s.expect" "%t"
method CalcTest0(s: seq<int>) {
diff --git a/Test/dafny0/Calculations.dfy.expect b/Test/dafny0/Calculations.dfy.expect
index 3f6ef226..d4559f53 100644
--- a/Test/dafny0/Calculations.dfy.expect
+++ b/Test/dafny0/Calculations.dfy.expect
@@ -1,24 +1,24 @@
-Calculations.dfy(6,6): Error: index out of range
+Calculations.dfy(7,5): Error: index out of range
Execution trace:
(0,0): anon0
(0,0): anon24_Then
-Calculations.dfy(11,15): Error: index out of range
+Calculations.dfy(12,14): Error: index out of range
Execution trace:
(0,0): anon0
(0,0): anon26_Then
-Calculations.dfy(11,19): Error: assertion violation
+Calculations.dfy(12,18): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon26_Then
-Calculations.dfy(55,12): Error: assertion violation
+Calculations.dfy(56,11): Error: assertion violation
Execution trace:
(0,0): anon0
- Calculations.dfy(50,3): anon5_Else
-Calculations.dfy(78,15): Error: index out of range
+ Calculations.dfy(51,3): anon5_Else
+Calculations.dfy(79,14): Error: index out of range
Execution trace:
(0,0): anon0
(0,0): anon12_Then
-Calculations.dfy(78,19): Error: assertion violation
+Calculations.dfy(79,18): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon12_Then
diff --git a/Test/dafny0/CallStmtTests.dfy b/Test/dafny0/CallStmtTests.dfy
index 67e66b34..46c466ff 100644
--- a/Test/dafny0/CallStmtTests.dfy
+++ b/Test/dafny0/CallStmtTests.dfy
@@ -1,23 +1,27 @@
// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
-method testing1(t: int)
-{
- t := m(); // error: should be checked at the Dafny level, not fall to Boogie.
-}
+module M0 {
+ method testing1(t: int)
+ {
+ t := m(); // error: should be checked at the Dafny level, not fall to Boogie.
+ }
-method m() returns (r: int)
-{
- return 3;
+ method m() returns (r: int)
+ {
+ return 3;
+ }
}
-method testing2()
-{
- var v;
- v := m2(); // error: v needs to be ghost because r is.
-}
+module M1 {
+ method testing2()
+ {
+ var v;
+ v := m2(); // error: v needs to be ghost because r is.
+ }
-method m2() returns (ghost r: int)
-{
- r := 23;
+ method m2() returns (ghost r: int)
+ {
+ r := 23;
+ }
}
diff --git a/Test/dafny0/CallStmtTests.dfy.expect b/Test/dafny0/CallStmtTests.dfy.expect
index 8a334754..246b89f8 100644
--- a/Test/dafny0/CallStmtTests.dfy.expect
+++ b/Test/dafny0/CallStmtTests.dfy.expect
@@ -1,3 +1,3 @@
-CallStmtTests.dfy(6,3): Error: LHS of assignment must denote a mutable variable
-CallStmtTests.dfy(17,10): Error: actual out-parameter 0 is required to be a ghost variable
+CallStmtTests.dfy(7,4): Error: LHS of assignment must denote a mutable variable
+CallStmtTests.dfy(20,11): Error: actual out-parameter 0 is required to be a ghost variable
2 resolution/type errors detected in CallStmtTests.dfy
diff --git a/Test/dafny0/Char.dfy.expect b/Test/dafny0/Char.dfy.expect
index 55418934..874aaa65 100644
--- a/Test/dafny0/Char.dfy.expect
+++ b/Test/dafny0/Char.dfy.expect
@@ -1,14 +1,14 @@
-Char.dfy(48,21): Error: assertion violation
+Char.dfy(48,20): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon9_Then
(0,0): anon10_Then
-Char.dfy(52,21): Error: assertion violation
+Char.dfy(52,20): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon9_Then
(0,0): anon11_Else
-Char.dfy(63,17): Error: assertion violation
+Char.dfy(63,16): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon5_Else
diff --git a/Test/dafny0/CoPrefix.dfy b/Test/dafny0/CoPrefix.dfy
index 0becb24d..3b6bd670 100644
--- a/Test/dafny0/CoPrefix.dfy
+++ b/Test/dafny0/CoPrefix.dfy
@@ -192,3 +192,35 @@ module Recursion {
}
}
}
+
+module PrefixEquality {
+ codatatype Stream<T> = Cons(head: T, Stream)
+
+ colemma Test0(s: Stream, t: Stream)
+ requires s.head == t.head
+ {
+ calc {
+ s;
+ ==#[_k-1]
+ t; // error: this step might not hold
+ ==#[if 2 <= _k then _k-2 else _k-1]
+ s; // error: this step might not hold
+ ==#[0]
+ t;
+ }
+ }
+
+ colemma Test1(s: Stream, t: Stream)
+ requires s == t
+ {
+ calc {
+ s;
+ ==#[_k-1]
+ t;
+ ==#[_k-2] // error: prefix-equality limit must be at least 0
+ s;
+ ==#[0]
+ t;
+ }
+ }
+}
diff --git a/Test/dafny0/CoPrefix.dfy.expect b/Test/dafny0/CoPrefix.dfy.expect
index c92a09c1..b42f2593 100644
--- a/Test/dafny0/CoPrefix.dfy.expect
+++ b/Test/dafny0/CoPrefix.dfy.expect
@@ -1,50 +1,65 @@
-CoPrefix.dfy(164,3): Error BP5003: A postcondition might not hold on this return path.
-CoPrefix.dfy(163,15): Related location: This is the postcondition that might not hold.
+CoPrefix.dfy(164,2): Error BP5003: A postcondition might not hold on this return path.
+CoPrefix.dfy(163,14): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
(0,0): anon3_Else
-CoPrefix.dfy(169,3): Error BP5003: A postcondition might not hold on this return path.
-CoPrefix.dfy(168,15): Related location: This is the postcondition that might not hold.
+CoPrefix.dfy(169,2): Error BP5003: A postcondition might not hold on this return path.
+CoPrefix.dfy(168,14): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
(0,0): anon3_Else
-CoPrefix.dfy(176,11): Error: cannot prove termination; try supplying a decreases clause
+CoPrefix.dfy(176,10): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-CoPrefix.dfy(63,57): Error: failure to decrease termination measure
+CoPrefix.dfy(205,6): Error: the calculation step between the previous line and this line might not hold
+Execution trace:
+ (0,0): anon0
+ (0,0): anon8_Then
+ (0,0): anon10_Then
+CoPrefix.dfy(207,6): Error: the calculation step between the previous line and this line might not hold
+Execution trace:
+ (0,0): anon0
+ (0,0): anon8_Then
+ (0,0): anon11_Then
+CoPrefix.dfy(220,12): Error: prefix-equality limit must be at least 0
+Execution trace:
+ (0,0): anon0
+ (0,0): anon8_Then
+ (0,0): anon11_Then
+CoPrefix.dfy(63,56): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
(0,0): anon7_Then
(0,0): anon8_Else
(0,0): anon9_Then
-CoPrefix.dfy(76,56): Error: cannot prove termination; try supplying a decreases clause
+CoPrefix.dfy(76,55): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
(0,0): anon7_Then
(0,0): anon8_Else
(0,0): anon9_Then
-CoPrefix.dfy(114,1): Error BP5003: A postcondition might not hold on this return path.
-CoPrefix.dfy(113,11): Related location: This is the postcondition that might not hold.
-CoPrefix.dfy(101,17): Related location
+CoPrefix.dfy(114,0): Error BP5003: A postcondition might not hold on this return path.
+CoPrefix.dfy(113,10): Related location: This is the postcondition that might not hold.
+CoPrefix.dfy(101,16): Related location
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-CoPrefix.dfy(138,25): Error: assertion violation
+CoPrefix.dfy(138,24): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon9_Then
(0,0): anon10_Then
-CoPrefix.dfy(142,25): Error: assertion violation
-CoPrefix.dfy(117,23): Related location
+CoPrefix.dfy(142,24): Error: assertion violation
+CoPrefix.dfy(117,22): Related location
Execution trace:
(0,0): anon0
(0,0): anon9_Then
(0,0): anon12_Then
-CoPrefix.dfy(151,1): Error BP5003: A postcondition might not hold on this return path.
-CoPrefix.dfy(150,11): Related location: This is the postcondition that might not hold.
+CoPrefix.dfy(151,0): Error BP5003: A postcondition might not hold on this return path.
+CoPrefix.dfy(150,10): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
(0,0): anon3_Else
-Dafny program verifier finished with 41 verified, 9 errors
+Dafny program verifier finished with 43 verified, 12 errors
diff --git a/Test/dafny0/CoinductiveProofs.dfy b/Test/dafny0/CoinductiveProofs.dfy
index d990ae51..c8bb45c7 100644
--- a/Test/dafny0/CoinductiveProofs.dfy
+++ b/Test/dafny0/CoinductiveProofs.dfy
@@ -12,6 +12,7 @@ copredicate Pos(s: Stream<int>)
{
0 < s.head && Pos(s.tail)
}
+predicate FullPos(s: Stream<int>) { Pos(s) } // a way in the test file to sidestep focal-predicate rewrites
colemma {:induction false} PosLemma0(n: int)
requires 1 <= n;
@@ -26,7 +27,25 @@ colemma {:induction false} PosLemma1(n: int)
{
PosLemma1(n + 1);
if (*) {
- assert Pos(Upward(n + 1)); // error: cannot conclude this here, because we only have prefix predicates
+ assert FullPos(Upward(n + 1)); // error: cannot conclude this here, because we only have prefix predicates
+ }
+}
+
+colemma {:induction false} PosLemma2(n: int)
+ requires 1 <= n;
+ ensures Pos(Upward(n));
+{
+ PosLemma2(n + 1);
+ if (*) {
+ assert Pos(Upward(n + 1)); // Pos gets rewritten to Pos#[_k-1], which does hold
+ } else if (*) {
+ assert Pos#[_k-1](Upward(n + 1)); // explicitly saying Pos#[_k-1] also holds
+ } else if (*) {
+ assert Pos#[_k](Upward(n + 1)); // error: this is not known to hold for _k and n+1
+ } else if (*) {
+ assert Pos#[_k](Upward(n)); // but it does hold with Pos#[_k] and n (which is the postcondition of the prefix lemma)
+ } else if (*) {
+ assert Pos#[_k+1](Upward(n)); // error: this is too much to ask for
}
}
@@ -65,13 +84,29 @@ colemma {:induction false} AlwaysLemma_X1(s: Stream)
{
AlwaysLemma_X1(s); // this is the right proof
}
+predicate FullX(s: Stream) { X(s) } // a way in the test file to sidestep focal-predicate rewrites
colemma {:induction false} AlwaysLemma_X2(s: Stream)
ensures X(s);
{
AlwaysLemma_X2(s);
if (*) {
- assert X(s); // error: cannot conclude the full predicate here
+ assert FullX(s); // error: cannot conclude the full predicate here
+ }
+}
+
+colemma {:induction false} AlwaysLemma_X3(s: Stream)
+ ensures X(s);
+{
+ AlwaysLemma_X3(s);
+ if (*) {
+ assert X(s); // holds, because it gets rewritten to X#[_k-1]
+ } else if (*) {
+ assert X#[_k-1](s); // explicitly saying X#[_k-1] also holds
+ } else if (*) {
+ assert X#[_k](s); // in fact, X#[_k] holds, too (which is the postcondition of the prefix lemma)
+ } else if (*) {
+ assert X#[_k+1](s); // as it turns out, this holds too, since the definition of X makes X#[_k+1] equal X#[_k]
}
}
@@ -79,6 +114,7 @@ copredicate Y(s: Stream) // this is equivalent to always returning 'true'
{
Y(s.tail)
}
+predicate FullY(s: Stream) { Y(s) } // a way in the test file to sidestep focal-predicate rewrites
colemma {:induction false} AlwaysLemma_Y0(s: Stream)
ensures Y(s); // prove that Y(s) really is always 'true'
@@ -97,7 +133,24 @@ colemma {:induction false} AlwaysLemma_Y2(s: Stream)
{
AlwaysLemma_Y2(s.tail);
if (*) {
- assert Y(s.tail); // error: not provable here
+ assert FullY(s.tail); // error: not provable here
+ }
+}
+
+colemma {:induction false} AlwaysLemma_Y3(s: Stream)
+ ensures Y(s);
+{
+ AlwaysLemma_Y3(s.tail);
+ if (*) {
+ assert Y(s.tail); // this holds, because it's rewritten to Y#[_k-1]
+ } else if (*) {
+ assert Y#[_k-1](s.tail);
+ } else if (*) {
+ assert Y#[_k](s.tail); // error: not known to hold for _k and s.tail
+ } else if (*) {
+ assert Y#[_k](s); // this is also the postcondition of the prefix lemma
+ } else if (*) {
+ assert Y#[_k+1](s); // error: this is too much to ask for
}
}
diff --git a/Test/dafny0/CoinductiveProofs.dfy.expect b/Test/dafny0/CoinductiveProofs.dfy.expect
index 12ce2f01..c4f4c405 100644
--- a/Test/dafny0/CoinductiveProofs.dfy.expect
+++ b/Test/dafny0/CoinductiveProofs.dfy.expect
@@ -1,50 +1,77 @@
-CoinductiveProofs.dfy(29,12): Error: assertion violation
-CoinductiveProofs.dfy(13,17): Related location
+CoinductiveProofs.dfy(30,11): Error: assertion violation
+CoinductiveProofs.dfy(15,36): Related location
+CoinductiveProofs.dfy(13,16): Related location
Execution trace:
(0,0): anon0
(0,0): anon5_Then
(0,0): anon6_Then
-CoinductiveProofs.dfy(59,1): Error BP5003: A postcondition might not hold on this return path.
-CoinductiveProofs.dfy(58,11): Related location: This is the postcondition that might not hold.
-CoinductiveProofs.dfy(54,3): Related location
+CoinductiveProofs.dfy(44,11): Error: assertion violation
+CoinductiveProofs.dfy(13,16): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon13_Then
+ (0,0): anon16_Then
+CoinductiveProofs.dfy(48,11): Error: assertion violation
+CoinductiveProofs.dfy(13,16): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon13_Then
+ (0,0): anon18_Then
+CoinductiveProofs.dfy(78,0): Error BP5003: A postcondition might not hold on this return path.
+CoinductiveProofs.dfy(77,10): Related location: This is the postcondition that might not hold.
+CoinductiveProofs.dfy(73,2): Related location
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-CoinductiveProofs.dfy(74,12): Error: assertion violation
-CoinductiveProofs.dfy(54,3): Related location
+CoinductiveProofs.dfy(94,11): Error: assertion violation
+CoinductiveProofs.dfy(87,29): Related location
+CoinductiveProofs.dfy(73,2): Related location
Execution trace:
(0,0): anon0
(0,0): anon5_Then
(0,0): anon6_Then
-CoinductiveProofs.dfy(91,1): Error BP5003: A postcondition might not hold on this return path.
-CoinductiveProofs.dfy(90,11): Related location: This is the postcondition that might not hold.
-CoinductiveProofs.dfy(80,3): Related location
+CoinductiveProofs.dfy(127,0): Error BP5003: A postcondition might not hold on this return path.
+CoinductiveProofs.dfy(126,10): Related location: This is the postcondition that might not hold.
+CoinductiveProofs.dfy(115,2): Related location
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-CoinductiveProofs.dfy(100,12): Error: assertion violation
-CoinductiveProofs.dfy(80,3): Related location
+CoinductiveProofs.dfy(136,11): Error: assertion violation
+CoinductiveProofs.dfy(117,29): Related location
+CoinductiveProofs.dfy(115,2): Related location
Execution trace:
(0,0): anon0
(0,0): anon5_Then
(0,0): anon6_Then
-CoinductiveProofs.dfy(111,1): Error BP5003: A postcondition might not hold on this return path.
-CoinductiveProofs.dfy(110,11): Related location: This is the postcondition that might not hold.
-CoinductiveProofs.dfy(106,3): Related location
+CoinductiveProofs.dfy(149,11): Error: assertion violation
+CoinductiveProofs.dfy(115,2): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon13_Then
+ (0,0): anon16_Then
+CoinductiveProofs.dfy(153,11): Error: assertion violation
+CoinductiveProofs.dfy(115,2): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon13_Then
+ (0,0): anon18_Then
+CoinductiveProofs.dfy(164,0): Error BP5003: A postcondition might not hold on this return path.
+CoinductiveProofs.dfy(163,10): Related location: This is the postcondition that might not hold.
+CoinductiveProofs.dfy(159,2): Related location
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-CoinductiveProofs.dfy(150,1): Error BP5003: A postcondition might not hold on this return path.
-CoinductiveProofs.dfy(149,22): Related location: This is the postcondition that might not hold.
-CoinductiveProofs.dfy(4,24): Related location
+CoinductiveProofs.dfy(203,0): Error BP5003: A postcondition might not hold on this return path.
+CoinductiveProofs.dfy(202,21): Related location: This is the postcondition that might not hold.
+CoinductiveProofs.dfy(4,23): Related location
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-CoinductiveProofs.dfy(156,1): Error BP5003: A postcondition might not hold on this return path.
-CoinductiveProofs.dfy(155,22): Related location: This is the postcondition that might not hold.
-CoinductiveProofs.dfy(4,24): Related location
+CoinductiveProofs.dfy(209,0): Error BP5003: A postcondition might not hold on this return path.
+CoinductiveProofs.dfy(208,21): Related location: This is the postcondition that might not hold.
+CoinductiveProofs.dfy(4,23): Related location
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-Dafny program verifier finished with 35 verified, 8 errors
+Dafny program verifier finished with 42 verified, 12 errors
diff --git a/Test/dafny0/Compilation.dfy b/Test/dafny0/Compilation.dfy
index a2b96996..213ace54 100644
--- a/Test/dafny0/Compilation.dfy
+++ b/Test/dafny0/Compilation.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny "%s" > "%t"
+// RUN: %dafny /compile:3 /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// The tests in this file are designed to run through the compiler. They contain
@@ -43,7 +43,9 @@ module CoRecursion {
// 40
// 41
// 42
- method Main() {
+ // 9
+ // 9
+ method TestMain() {
var m := 17;
var cell := new Cell;
cell.data := 40;
@@ -58,6 +60,37 @@ module CoRecursion {
print l.car, "\n";
l := l.cdr;
}
+ var nio := OneLess(0, 10);
+ print nio, "\n";
+ nio := OneLess'(0, 10);
+ print nio, "\n";
+ }
+
+ method OneLess(lo: int, hi: int) returns (m: int)
+ requires lo < hi
+ // This method ensures m == hi - 1, but we don't care to prove it
+ decreases hi - lo
+ {
+ if y :| lo < y < hi {
+ m := OneLess(y, hi);
+ } else {
+ m := lo;
+ }
+ }
+
+ method OneLess'(lo: int, hi: int) returns (m: int)
+ requires lo < hi
+ // This method ensures m == hi - 1, but we don't care to prove it
+ decreases hi - lo
+ {
+ if {
+ case y :| lo < y < hi =>
+ m := OneLess'(y, hi);
+ case lo+1 < hi =>
+ m := OneLess'(lo+1, hi);
+ case lo + 1 == hi =>
+ m := lo;
+ }
}
}
@@ -76,8 +109,8 @@ module T refines S {
}
}
module A {
- import X as S default T
- import Y as S default T
+ import X : T
+ import Y : T
import Z = T
method run() {
var x := new X.C;
@@ -95,7 +128,7 @@ method NotMain() {
abstract module S1 {
- import B as S default T
+ import B : T
method do()
}
@@ -105,7 +138,7 @@ module T1 refines S1 {
}
}
module A1 {
- import X as S1 default T1
+ import X : T1
method run() {
X.do();
var x := new X.B.C;
@@ -227,3 +260,56 @@ class DigitUnderscore_Names {
this.10 := 20;
}
}
+
+// ------------------------------------------------------------------
+
+method Main()
+{
+ CoRecursion.TestMain();
+ EqualityTests.TestMain();
+}
+
+// ------------------------------------------------------------------
+
+module EqualityTests {
+ class C<T> {
+ }
+
+ method TestMain()
+ {
+ // regression tests:
+ var a: C<int>, b: C<int> := null, null;
+ if a == null {
+ print "a is null\n";
+ }
+ if a != null {
+ print "a is not null\n";
+ }
+ if a == b {
+ print "a and b are equal\n";
+ }
+ if a != b {
+ print "a and b are not equal\n";
+ }
+
+ var H := new real[10];
+ ArrayTests(H);
+ }
+
+ method ArrayTests<T>(H: array<T>)
+ {
+ var G := new int[10];
+ if G == H { // this comparison is allowed in Dafny, but requires a cast in C#
+ print "this would be highly suspicious\n";
+ }
+ if G != H { // this comparison is allowed in Dafny, but requires a cast in C#
+ print "good world order\n";
+ }
+ if null == H {
+ print "given array is null\n";
+ }
+ if null != H {
+ print "given array is non-null\n";
+ }
+ }
+}
diff --git a/Test/dafny0/Compilation.dfy.expect b/Test/dafny0/Compilation.dfy.expect
index 0a1938ae..0a934a63 100644
--- a/Test/dafny0/Compilation.dfy.expect
+++ b/Test/dafny0/Compilation.dfy.expect
@@ -1,3 +1,16 @@
-Dafny program verifier finished with 46 verified, 0 errors
-Compiled assembly into Compilation.exe
+Dafny program verifier finished with 56 verified, 0 errors
+Program compiled successfully
+Running...
+
+400
+320
+40
+41
+42
+9
+9
+a is null
+a and b are equal
+good world order
+given array is non-null
diff --git a/Test/dafny0/Comprehensions.dfy b/Test/dafny0/Comprehensions.dfy
index d0436815..dd83e46c 100644
--- a/Test/dafny0/Comprehensions.dfy
+++ b/Test/dafny0/Comprehensions.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
method M()
@@ -19,18 +19,18 @@ datatype D = A | B
// have to run the resulting program to check that the compiler is doing the right thing.
method Main()
{
- var q := set i,j | 0 <= i && i < 10 && 0 <= j && j < 3 :: i+j;
+ var q := set i,j | 0 <= i < 10 && 0 <= j < 3 :: i+j;
PrintSet(q);
q := set b: bool | true :: if b then 3 else 7;
var d := set b:D | true;
- var test := forall d:D :: d == A || d == B;
+ var test := forall d:D {:nowarn} :: d == A || d == B; // Ignoring the warning as we're only compiling here
PrintSet(q);
var m := set k | k in q :: 2*k;
PrintSet(m);
PrintSet(set k | k in q && k % 2 == 0);
var sq := [30, 40, 20];
- PrintSet(set k, i | k in sq && 0 <= i && i < k && i % 7 == 0 :: k + i);
- var bb := forall k, i | k in sq && 0 <= i && i < k && i % 7 == 0 :: k + i == 17;
+ PrintSet(set k, i | k in sq && 0 <= i < k && i % 7 == 0 :: k + i);
+ var bb := forall k, i {:nowarn} | k in sq && 0 <= i < k && i % 7 == 0 :: k + i == 17; // Ignoring the warning as we're only compiling here
}
method PrintSet<T>(s: set<T>) {
diff --git a/Test/dafny0/Comprehensions.dfy.expect b/Test/dafny0/Comprehensions.dfy.expect
index 88873fd8..887a3249 100644
--- a/Test/dafny0/Comprehensions.dfy.expect
+++ b/Test/dafny0/Comprehensions.dfy.expect
@@ -1,4 +1,4 @@
-Comprehensions.dfy(12,14): Error: assertion violation
+Comprehensions.dfy(12,13): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon9_Then
diff --git a/Test/dafny0/ComputationsLoop.dfy.expect b/Test/dafny0/ComputationsLoop.dfy.expect
index d9d48024..84674030 100644
--- a/Test/dafny0/ComputationsLoop.dfy.expect
+++ b/Test/dafny0/ComputationsLoop.dfy.expect
@@ -1,8 +1,8 @@
-ComputationsLoop.dfy(7,3): Error: failure to decrease termination measure
+ComputationsLoop.dfy(7,2): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-ComputationsLoop.dfy(12,26): Error: assertion violation
+ (0,0): anon4_Else
+ComputationsLoop.dfy(12,25): Error: assertion violation
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/ComputationsLoop2.dfy.expect b/Test/dafny0/ComputationsLoop2.dfy.expect
index 0a45e6d0..48fc618f 100644
--- a/Test/dafny0/ComputationsLoop2.dfy.expect
+++ b/Test/dafny0/ComputationsLoop2.dfy.expect
@@ -1,12 +1,12 @@
-ComputationsLoop2.dfy(6,3): Error: cannot prove termination; try supplying a decreases clause
+ComputationsLoop2.dfy(6,2): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-ComputationsLoop2.dfy(11,3): Error: cannot prove termination; try supplying a decreases clause
+ (0,0): anon4_Else
+ComputationsLoop2.dfy(11,2): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-ComputationsLoop2.dfy(16,26): Error: assertion violation
+ (0,0): anon4_Else
+ComputationsLoop2.dfy(16,25): Error: assertion violation
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/ComputationsNeg.dfy b/Test/dafny0/ComputationsNeg.dfy
index 0c539117..b9425d64 100644
--- a/Test/dafny0/ComputationsNeg.dfy
+++ b/Test/dafny0/ComputationsNeg.dfy
@@ -16,7 +16,7 @@ predicate ThProperty(step: nat, t: Nat, r: nat)
{
match t
case Zero => true
- case Succ(o) => step>0 && exists ro:nat :: ThProperty(step-1, o, ro)
+ case Succ(o) => step>0 && exists ro:nat, ss :: ss == step-1 ==> ThProperty(ss, o, ro) // WISH: auto-generate ss
}
ghost method test_ThProperty()
ensures ThProperty(10, Succ(Zero), 0);
diff --git a/Test/dafny0/ComputationsNeg.dfy.expect b/Test/dafny0/ComputationsNeg.dfy.expect
index 16c8963f..598e9fa5 100644
--- a/Test/dafny0/ComputationsNeg.dfy.expect
+++ b/Test/dafny0/ComputationsNeg.dfy.expect
@@ -1,19 +1,19 @@
-ComputationsNeg.dfy(7,3): Error: failure to decrease termination measure
+ComputationsNeg.dfy(7,2): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-ComputationsNeg.dfy(11,1): Error BP5003: A postcondition might not hold on this return path.
-ComputationsNeg.dfy(10,17): Related location: This is the postcondition that might not hold.
+ (0,0): anon4_Else
+ComputationsNeg.dfy(11,0): Error BP5003: A postcondition might not hold on this return path.
+ComputationsNeg.dfy(10,16): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-ComputationsNeg.dfy(23,1): Error BP5003: A postcondition might not hold on this return path.
-ComputationsNeg.dfy(22,11): Related location: This is the postcondition that might not hold.
+ComputationsNeg.dfy(23,0): Error BP5003: A postcondition might not hold on this return path.
+ComputationsNeg.dfy(22,10): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-ComputationsNeg.dfy(36,13): Error: assertion violation
+ComputationsNeg.dfy(36,12): Error: assertion violation
Execution trace:
(0,0): anon0
-ComputationsNeg.dfy(45,13): Error: assertion violation
+ComputationsNeg.dfy(45,12): Error: assertion violation
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/ContainerRanks.dfy b/Test/dafny0/ContainerRanks.dfy
new file mode 100644
index 00000000..df35e214
--- /dev/null
+++ b/Test/dafny0/ContainerRanks.dfy
@@ -0,0 +1,33 @@
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+datatype Abc = End | Wrapper(seq<Abc>)
+
+lemma SeqRank0(a: Abc)
+ ensures a != Wrapper([a])
+{
+ assert [a][0] == a; // TODO: one could consider strengthening axioms to eliminate the need for this assert
+ // The reason we need the assert is to match the trigger in the rank axioms produced
+ // for datatypes containing sequences.
+ // See "is SeqType" case of AddDatatype in Translator.cs
+}
+
+lemma SeqRank1(s: seq<Abc>)
+ requires s != []
+ ensures s[0] != Wrapper(s)
+{
+}
+
+datatype Def = End | MultiWrapper(multiset<Def>)
+
+lemma MultisetRank(a: Def)
+ ensures a != MultiWrapper(multiset{a})
+{
+}
+
+datatype Ghi = End | SetWrapper(set<Ghi>)
+
+lemma SetRank(a: Ghi)
+ ensures a != SetWrapper({a})
+{
+}
diff --git a/Test/dafny0/ContainerRanks.dfy.expect b/Test/dafny0/ContainerRanks.dfy.expect
new file mode 100644
index 00000000..42fd56a5
--- /dev/null
+++ b/Test/dafny0/ContainerRanks.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 8 verified, 0 errors
diff --git a/Test/dafny0/ControlStructures.dfy.expect b/Test/dafny0/ControlStructures.dfy.expect
index 43124912..5638bcbc 100644
--- a/Test/dafny0/ControlStructures.dfy.expect
+++ b/Test/dafny0/ControlStructures.dfy.expect
@@ -1,41 +1,41 @@
-ControlStructures.dfy(8,3): Error: missing case in case statement: Purple
+ControlStructures.dfy(8,2): Error: missing case in case statement: Purple
Execution trace:
(0,0): anon0
(0,0): anon6_Else
(0,0): anon7_Else
(0,0): anon8_Then
-ControlStructures.dfy(8,3): Error: missing case in case statement: Blue
+ControlStructures.dfy(8,2): Error: missing case in case statement: Blue
Execution trace:
(0,0): anon0
(0,0): anon6_Else
(0,0): anon7_Else
(0,0): anon8_Else
(0,0): anon9_Then
-ControlStructures.dfy(17,3): Error: missing case in case statement: Purple
+ControlStructures.dfy(17,2): Error: missing case in case statement: Purple
Execution trace:
(0,0): anon0
(0,0): anon6_Else
(0,0): anon7_Else
(0,0): anon8_Then
-ControlStructures.dfy(46,5): Error: missing case in case statement: Red
+ControlStructures.dfy(46,4): Error: missing case in case statement: Red
Execution trace:
(0,0): anon0
(0,0): anon8_Then
(0,0): anon9_Else
(0,0): anon10_Then
-ControlStructures.dfy(54,3): Error: missing case in case statement: Red
+ControlStructures.dfy(54,2): Error: missing case in case statement: Red
Execution trace:
(0,0): anon0
- (0,0): anon8_Else
(0,0): anon9_Else
(0,0): anon10_Else
(0,0): anon11_Else
- (0,0): anon12_Then
-ControlStructures.dfy(75,3): Error: alternative cases fail to cover all possibilties
+ (0,0): anon12_Else
+ (0,0): anon13_Then
+ControlStructures.dfy(75,2): Error: alternative cases fail to cover all possibilties
Execution trace:
(0,0): anon0
(0,0): anon5_Else
-ControlStructures.dfy(218,18): Error: assertion violation
+ControlStructures.dfy(218,17): Error: assertion violation
Execution trace:
(0,0): anon0
ControlStructures.dfy(197,3): anon59_LoopHead
@@ -51,7 +51,7 @@ Execution trace:
(0,0): anon69_LoopBody
ControlStructures.dfy(213,9): anon70_Else
(0,0): anon71_Then
-ControlStructures.dfy(235,21): Error: assertion violation
+ControlStructures.dfy(235,20): Error: assertion violation
Execution trace:
(0,0): anon0
ControlStructures.dfy(197,3): anon59_LoopHead
@@ -77,7 +77,7 @@ Execution trace:
(0,0): anon38
(0,0): anon83_Then
(0,0): anon52
-ControlStructures.dfy(238,30): Error: assertion violation
+ControlStructures.dfy(238,29): Error: assertion violation
Execution trace:
(0,0): anon0
ControlStructures.dfy(197,3): anon59_LoopHead
@@ -92,7 +92,7 @@ Execution trace:
(0,0): anon84_Then
(0,0): anon85_Then
(0,0): anon56
-ControlStructures.dfy(241,17): Error: assertion violation
+ControlStructures.dfy(241,16): Error: assertion violation
Execution trace:
(0,0): anon0
ControlStructures.dfy(197,3): anon59_LoopHead
diff --git a/Test/dafny0/Corecursion.dfy.expect b/Test/dafny0/Corecursion.dfy.expect
index e30f6f1a..a6b3fdce 100644
--- a/Test/dafny0/Corecursion.dfy.expect
+++ b/Test/dafny0/Corecursion.dfy.expect
@@ -1,36 +1,36 @@
-Corecursion.dfy(17,13): Error: cannot prove termination; try supplying a decreases clause (note that only functions without side effects can be called co-recursively)
+Corecursion.dfy(17,12): Error: cannot prove termination; try supplying a decreases clause (note that only functions without side effects can be called co-recursively)
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-Corecursion.dfy(23,13): Error: cannot prove termination; try supplying a decreases clause (note that only functions without any ensures clause can be called co-recursively)
+ (0,0): anon4_Else
+Corecursion.dfy(23,12): Error: cannot prove termination; try supplying a decreases clause (note that only functions without any ensures clause can be called co-recursively)
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-Corecursion.dfy(58,5): Error: cannot prove termination; try supplying a decreases clause
+ (0,0): anon4_Else
+Corecursion.dfy(58,4): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-Corecursion.dfy(71,16): Error: cannot prove termination; try supplying a decreases clause (note that calls cannot be co-recursive in this context)
+ (0,0): anon4_Else
+Corecursion.dfy(71,15): Error: cannot prove termination; try supplying a decreases clause (note that calls cannot be co-recursive in this context)
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
-Corecursion.dfy(93,15): Error: cannot prove termination; try supplying a decreases clause (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts)
+ (0,0): anon7_Else
+Corecursion.dfy(93,14): Error: cannot prove termination; try supplying a decreases clause (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts)
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
- (0,0): anon6_Then
-Corecursion.dfy(103,15): Error: cannot prove termination; try supplying a decreases clause (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts)
+ (0,0): anon7_Else
+ (0,0): anon8_Then
+Corecursion.dfy(103,14): Error: cannot prove termination; try supplying a decreases clause (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts)
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
- (0,0): anon6_Then
-Corecursion.dfy(148,13): Error: failure to decrease termination measure (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts)
+ (0,0): anon7_Else
+ (0,0): anon8_Then
+Corecursion.dfy(148,12): Error: failure to decrease termination measure (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts)
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-Corecursion.dfy(161,13): Error: failure to decrease termination measure (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts)
+ (0,0): anon4_Else
+Corecursion.dfy(161,12): Error: failure to decrease termination measure (note that a call can be co-recursive only if all intra-cluster calls are in non-destructive contexts)
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
+ (0,0): anon4_Else
Dafny program verifier finished with 20 verified, 8 errors
diff --git a/Test/dafny0/DTypes.dfy b/Test/dafny0/DTypes.dfy
index c8c893a0..9891c040 100644
--- a/Test/dafny0/DTypes.dfy
+++ b/Test/dafny0/DTypes.dfy
@@ -1,11 +1,11 @@
-// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /autoTriggers:1 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
class C {
var n: set<Node>;
method M(v: Stack)
- requires v != null;
+ requires v != null
{
var o: object := v;
assert o !in n; // should be known from the types involved
@@ -28,12 +28,12 @@ class C {
method A1(a: CP<int,C>)
{
var x: object := a;
- assert (forall b: CP<int,Stack> :: x == b ==> b == null); // follows from type antecedents
+ assert (forall b: CP<int,Stack> {:nowarn} :: x == b ==> b == null); // follows from type antecedents
}
var a2x: set<CP<C,Node>>;
method A2(b: set<CP<Node,C>>)
- requires null !in b;
+ requires null !in b
{
var x: set<object> := a2x;
var y: set<object> := b;
@@ -81,7 +81,7 @@ class CP<T,U> {
datatype Data = Lemon | Kiwi(int)
function G(d: Data): int
- requires d != Data.Lemon;
+ requires d != Data.Lemon
{
match d
case Lemon => G(d)
@@ -101,28 +101,28 @@ class DatatypeInduction<T> {
}
method Theorem0(tree: Tree<T>)
- ensures 1 <= LeafCount(tree);
+ ensures 1 <= LeafCount(tree)
{
assert (forall t: Tree<T> :: 1 <= LeafCount(t));
}
// also make sure it works for an instantiated generic datatype
method Theorem1(bt: Tree<bool>, it: Tree<int>)
- ensures 1 <= LeafCount(bt);
- ensures 1 <= LeafCount(it);
+ ensures 1 <= LeafCount(bt)
+ ensures 1 <= LeafCount(it)
{
assert (forall t: Tree<bool> :: 1 <= LeafCount(t));
assert (forall t: Tree<int> :: 1 <= LeafCount(t));
}
method NotATheorem0(tree: Tree<T>)
- ensures LeafCount(tree) % 2 == 1;
+ ensures LeafCount(tree) % 2 == 1
{
assert (forall t: Tree<T> :: LeafCount(t) % 2 == 1); // error: fails for Branch case
}
method NotATheorem1(tree: Tree<T>)
- ensures 2 <= LeafCount(tree);
+ ensures 2 <= LeafCount(tree)
{
assert (forall t: Tree<T> :: 2 <= LeafCount(t)); // error: fails for Leaf case
}
@@ -140,22 +140,22 @@ class DatatypeInduction<T> {
// ----- here is a test for induction over integers
method IntegerInduction_Succeeds(a: array<int>)
- requires a != null;
- requires a.Length == 0 || a[0] == 0;
- requires forall j :: 1 <= j && j < a.Length ==> a[j] == a[j-1]+2*j-1;
+ requires a != null
+ requires a.Length == 0 || a[0] == 0
+ requires forall j {:nowarn} :: 1 <= j < a.Length ==> a[j] == a[j-1]+2*j-1 // WISH: If induction was more powerful, we wouldn't need to rely on the quantifier to produce the j-1 term.
{
// The following assertion can be proved by induction:
- assert forall n {:induction} :: 0 <= n && n < a.Length ==> a[n] == n*n;
+ assert forall n {:induction} :: 0 <= n < a.Length ==> a[n] == n*n;
}
method IntegerInduction_Fails(a: array<int>)
- requires a != null;
- requires a.Length == 0 || a[0] == 0;
- requires forall j :: 1 <= j && j < a.Length ==> a[j] == a[j-1]+2*j-1;
+ requires a != null
+ requires a.Length == 0 || a[0] == 0
+ requires forall j {:nowarn} :: 1 <= j < a.Length ==> a[j] == a[j-1]+2*j-1 // WISH: Same as above
{
// ...but the induction heuristics don't recognize the situation as one where
// applying induction would be profitable:
- assert forall n :: 0 <= n && n < a.Length ==> a[n] == n*n; // error reported
+ assert forall n :: 0 <= n < a.Length ==> a[n] == n*n; // error reported
}
}
@@ -171,7 +171,7 @@ abstract module OpaqueTypesWithParameters {
}
method DifferentTypes(a: array<P<int>>, b: array<P<bool>>)
- requires a != null && b != null;
+ requires a != null && b != null
// If P were a known type, then it would also be known that P<int> and P<bool>
// would be different types, and then the types of 'a' and 'b' would be different,
// which would imply that the following postcondition would hold.
diff --git a/Test/dafny0/DTypes.dfy.expect b/Test/dafny0/DTypes.dfy.expect
index 9b4288e9..76088e9b 100644
--- a/Test/dafny0/DTypes.dfy.expect
+++ b/Test/dafny0/DTypes.dfy.expect
@@ -1,27 +1,27 @@
-DTypes.dfy(182,3): Error BP5003: A postcondition might not hold on this return path.
-DTypes.dfy(181,15): Related location: This is the postcondition that might not hold.
+DTypes.dfy(182,2): Error BP5003: A postcondition might not hold on this return path.
+DTypes.dfy(181,14): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-DTypes.dfy(18,14): Error: assertion violation
+DTypes.dfy(18,13): Error: assertion violation
Execution trace:
(0,0): anon0
-DTypes.dfy(56,18): Error: assertion violation
+DTypes.dfy(56,17): Error: assertion violation
Execution trace:
(0,0): anon0
-DTypes.dfy(121,13): Error: assertion violation
-DTypes.dfy(93,30): Related location
+DTypes.dfy(121,12): Error: assertion violation
+DTypes.dfy(93,29): Related location
Execution trace:
(0,0): anon0
-DTypes.dfy(127,13): Error: assertion violation
-DTypes.dfy(93,20): Related location
+DTypes.dfy(127,12): Error: assertion violation
+DTypes.dfy(93,19): Related location
Execution trace:
(0,0): anon0
-DTypes.dfy(137,12): Error: assertion violation
-DTypes.dfy(132,6): Related location
-DTypes.dfy(93,20): Related location
+DTypes.dfy(137,11): Error: assertion violation
+DTypes.dfy(132,5): Related location
+DTypes.dfy(93,19): Related location
Execution trace:
(0,0): anon0
-DTypes.dfy(158,12): Error: assertion violation
+DTypes.dfy(158,11): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon5_Then
diff --git a/Test/dafny0/DatatypeUpdate.dfy b/Test/dafny0/DatatypeUpdate.dfy
index 76cce5ce..b7905928 100644
--- a/Test/dafny0/DatatypeUpdate.dfy
+++ b/Test/dafny0/DatatypeUpdate.dfy
@@ -1,6 +1,6 @@
// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
-
+module OldSyntax {
datatype MyDataType = MyConstructor(myint:int, mybool:bool)
| MyOtherConstructor(otherbool:bool)
| MyNumericConstructor(42:int)
@@ -35,3 +35,51 @@ method UpdateNumNam(nn: NumericNames, y: int) returns (pp: NumericNames)
{
pp := nn[010 := y]; // not to be confused with a field name 10
}
+}
+
+module NewSyntax {
+datatype MyDataType = MyConstructor(myint:int, mybool:bool)
+ | MyOtherConstructor(otherbool:bool)
+ | MyNumericConstructor(42:int)
+
+method test(foo:MyDataType, x:int) returns (abc:MyDataType, def:MyDataType, ghi:MyDataType, jkl:MyDataType)
+ requires foo.MyConstructor?;
+ ensures abc == foo.(myint := x + 2);
+ ensures def == foo.(otherbool := !foo.mybool);
+ ensures ghi == foo.(myint := 2).(mybool := false);
+ //ensures jkl == foo.(non_destructor := 5); // Resolution error: no non_destructor in MyDataType
+ ensures jkl == foo.(42 := 7);
+{
+ abc := MyConstructor(x + 2, foo.mybool);
+ abc := foo.(myint := x + 2);
+ def := MyOtherConstructor(!foo.mybool);
+ ghi := MyConstructor(2, false);
+ jkl := foo.(42 := 7);
+
+ assert abc.(myint := abc.myint - 2) == foo.(myint := x);
+}
+
+// regression test (for a previous bug in the Translator.Substituter):
+datatype Dt = Ctor(x: int, y: bool)
+function F(d: Dt): Dt
+{
+ d.(x := 5)
+}
+
+datatype NumericNames = NumNam(010: int, 10: real, f: bool)
+
+method UpdateNumNam(nn: NumericNames, y: int) returns (pp: NumericNames)
+{
+ pp := nn.(010 := y); // not to be confused with a field name 10
+}
+
+method MultipleUpdates(nn: NumericNames, y: int) returns (pp: NumericNames)
+ ensures pp.010 == y
+{
+ if * {
+ pp := nn.(10 := 0.10, 010 := y);
+ } else {
+ pp := nn.(010 := y, f := true, 10 := 0.10);
+ }
+}
+}
diff --git a/Test/dafny0/DatatypeUpdate.dfy.expect b/Test/dafny0/DatatypeUpdate.dfy.expect
index 790f6509..9a924214 100644
--- a/Test/dafny0/DatatypeUpdate.dfy.expect
+++ b/Test/dafny0/DatatypeUpdate.dfy.expect
@@ -1,2 +1,13 @@
+DatatypeUpdate.dfy(10,22): Warning: datatype update syntax D[f := E] is deprecated; the new syntax is D.(f := E)
+DatatypeUpdate.dfy(11,22): Warning: datatype update syntax D[f := E] is deprecated; the new syntax is D.(f := E)
+DatatypeUpdate.dfy(12,22): Warning: datatype update syntax D[f := E] is deprecated; the new syntax is D.(f := E)
+DatatypeUpdate.dfy(12,34): Warning: datatype update syntax D[f := E] is deprecated; the new syntax is D.(f := E)
+DatatypeUpdate.dfy(14,22): Warning: datatype update syntax D[f := E] is deprecated; the new syntax is D.(f := E)
+DatatypeUpdate.dfy(17,14): Warning: datatype update syntax D[f := E] is deprecated; the new syntax is D.(f := E)
+DatatypeUpdate.dfy(20,14): Warning: datatype update syntax D[f := E] is deprecated; the new syntax is D.(f := E)
+DatatypeUpdate.dfy(22,14): Warning: datatype update syntax D[f := E] is deprecated; the new syntax is D.(f := E)
+DatatypeUpdate.dfy(22,45): Warning: datatype update syntax D[f := E] is deprecated; the new syntax is D.(f := E)
+DatatypeUpdate.dfy(29,3): Warning: datatype update syntax D[f := E] is deprecated; the new syntax is D.(f := E)
+DatatypeUpdate.dfy(36,10): Warning: datatype update syntax D[f := E] is deprecated; the new syntax is D.(f := E)
-Dafny program verifier finished with 5 verified, 0 errors
+Dafny program verifier finished with 12 verified, 0 errors
diff --git a/Test/dafny0/DatatypeUpdateResolution.dfy b/Test/dafny0/DatatypeUpdateResolution.dfy
new file mode 100644
index 00000000..26142fa8
--- /dev/null
+++ b/Test/dafny0/DatatypeUpdateResolution.dfy
@@ -0,0 +1,20 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+datatype MyDataType = MyConstructor(myint:int, mybool:bool)
+ | MyOtherConstructor(otherbool:bool)
+ | MyNumericConstructor(42:int)
+datatype SomeOtherType = S_O_T(non_destructor: int)
+
+method test(foo:MyDataType, x:int) returns (abc:MyDataType, def:MyDataType, ghi:MyDataType, jkl:MyDataType)
+ requires foo.MyConstructor?
+ ensures abc == foo.(myint := x + 2)
+ ensures jkl == foo.(non_destructor := 5) // error: 'non_destructor' is not a destructor in MyDataType
+ ensures jkl == foo.(mybool := true, 40 := 100, myint := 200) // error: '40' is not a destructor
+{
+ abc := MyConstructor(x + 2, foo.mybool).(myint := x + 3);
+ abc := foo.(myint := x + 2, mybool := true).(mybool := false); // allowed
+ def := MyOtherConstructor(!foo.mybool).(otherbool := true, otherbool := true); // error: duplicated member
+ ghi := MyConstructor(2, false).(otherbool := true); // allowed, and will generate verification error
+ jkl := foo.(42 := 7, otherbool := true); // error: members are from different constructors
+}
diff --git a/Test/dafny0/DatatypeUpdateResolution.dfy.expect b/Test/dafny0/DatatypeUpdateResolution.dfy.expect
new file mode 100644
index 00000000..db3e1fe2
--- /dev/null
+++ b/Test/dafny0/DatatypeUpdateResolution.dfy.expect
@@ -0,0 +1,5 @@
+DatatypeUpdateResolution.dfy(12,22): Error: member 'non_destructor' does not exist in datatype 'MyDataType'
+DatatypeUpdateResolution.dfy(13,38): Error: member '40' does not exist in datatype 'MyDataType'
+DatatypeUpdateResolution.dfy(17,61): Error: duplicate update member 'otherbool'
+DatatypeUpdateResolution.dfy(19,23): Error: updated datatype members must belong to the same constructor ('otherbool' belongs to 'MyOtherConstructor' and '42' belongs to 'MyNumericConstructor'
+4 resolution/type errors detected in DatatypeUpdateResolution.dfy
diff --git a/Test/dafny0/Datatypes.dfy.expect b/Test/dafny0/Datatypes.dfy.expect
index 874df45e..7147ca60 100644
--- a/Test/dafny0/Datatypes.dfy.expect
+++ b/Test/dafny0/Datatypes.dfy.expect
@@ -1,43 +1,43 @@
-Datatypes.dfy(297,10): Error BP5003: A postcondition might not hold on this return path.
-Datatypes.dfy(295,15): Related location: This is the postcondition that might not hold.
+Datatypes.dfy(297,9): Error BP5003: A postcondition might not hold on this return path.
+Datatypes.dfy(295,14): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
(0,0): anon13_Then
(0,0): anon14_Else
(0,0): anon15_Then
(0,0): anon6
-Datatypes.dfy(298,12): Error: missing case in case statement: Appendix
+Datatypes.dfy(298,11): Error: missing case in case statement: Appendix
Execution trace:
(0,0): anon0
(0,0): anon13_Then
(0,0): anon14_Else
(0,0): anon15_Else
(0,0): anon16_Then
-Datatypes.dfy(349,5): Error: missing case in case statement: Cons
+Datatypes.dfy(349,4): Error: missing case in case statement: Cons
Execution trace:
(0,0): anon0
- (0,0): anon6_Else
- (0,0): anon7_Then
-Datatypes.dfy(349,5): Error: missing case in case statement: Nil
+ (0,0): anon7_Else
+ (0,0): anon8_Then
+Datatypes.dfy(349,4): Error: missing case in case statement: Nil
Execution trace:
(0,0): anon0
- (0,0): anon6_Else
(0,0): anon7_Else
- (0,0): anon8_Then
-Datatypes.dfy(356,8): Error: missing case in case statement: Cons
+ (0,0): anon8_Else
+ (0,0): anon9_Then
+Datatypes.dfy(356,7): Error: missing case in case statement: Cons
Execution trace:
(0,0): anon0
- (0,0): anon9_Else
- (0,0): anon10_Then
+ (0,0): anon10_Else
(0,0): anon11_Then
-Datatypes.dfy(356,8): Error: missing case in case statement: Nil
+ (0,0): anon12_Then
+Datatypes.dfy(356,7): Error: missing case in case statement: Nil
Execution trace:
(0,0): anon0
- (0,0): anon9_Else
- (0,0): anon10_Then
- (0,0): anon11_Else
- (0,0): anon12_Then
-Datatypes.dfy(82,20): Error: assertion violation
+ (0,0): anon10_Else
+ (0,0): anon11_Then
+ (0,0): anon12_Else
+ (0,0): anon13_Then
+Datatypes.dfy(82,19): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon20_Else
@@ -47,23 +47,23 @@ Execution trace:
(0,0): anon23_Then
(0,0): anon24_Else
(0,0): anon25_Then
-Datatypes.dfy(170,16): Error: assertion violation
+Datatypes.dfy(170,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon4_Then
-Datatypes.dfy(172,16): Error: assertion violation
+Datatypes.dfy(172,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon4_Else
(0,0): anon5_Then
-Datatypes.dfy(201,13): Error: destructor 'Car' can only be applied to datatype values constructed by 'XCons'
+Datatypes.dfy(201,12): Error: destructor 'Car' can only be applied to datatype values constructed by 'XCons'
Execution trace:
(0,0): anon0
-Datatypes.dfy(204,17): Error: destructor 'Car' can only be applied to datatype values constructed by 'XCons'
+Datatypes.dfy(204,16): Error: destructor 'Car' can only be applied to datatype values constructed by 'XCons'
Execution trace:
(0,0): anon0
(0,0): anon6_Then
-Datatypes.dfy(225,17): Error: destructor 'c' can only be applied to datatype values constructed by 'T''
+Datatypes.dfy(225,16): Error: destructor 'c' can only be applied to datatype values constructed by 'T''
Execution trace:
(0,0): anon0
(0,0): anon5_Then
diff --git a/Test/dafny0/Definedness.dfy.expect b/Test/dafny0/Definedness.dfy.expect
index 41073c0e..b5b015ad 100644
--- a/Test/dafny0/Definedness.dfy.expect
+++ b/Test/dafny0/Definedness.dfy.expect
@@ -1,87 +1,87 @@
-Definedness.dfy(11,7): Error: possible division by zero
+Definedness.dfy(11,6): Error: possible division by zero
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-Definedness.dfy(18,16): Error: possible division by zero
+ (0,0): anon4_Else
+Definedness.dfy(18,15): Error: possible division by zero
Execution trace:
(0,0): anon0
-Definedness.dfy(27,16): Error: target object may be null
+Definedness.dfy(27,15): Error: target object may be null
Execution trace:
(0,0): anon0
-Definedness.dfy(28,21): Error: target object may be null
+Definedness.dfy(28,20): Error: target object may be null
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-Definedness.dfy(29,17): Error: possible division by zero
+Definedness.dfy(29,16): Error: possible division by zero
Execution trace:
(0,0): anon0
-Definedness.dfy(36,16): Error: target object may be null
+Definedness.dfy(36,15): Error: target object may be null
Execution trace:
(0,0): anon0
-Definedness.dfy(45,16): Error: target object may be null
+Definedness.dfy(45,15): Error: target object may be null
Execution trace:
(0,0): anon0
-Definedness.dfy(53,18): Error: target object may be null
+Definedness.dfy(53,17): Error: target object may be null
Execution trace:
(0,0): anon0
-Definedness.dfy(54,3): Error BP5003: A postcondition might not hold on this return path.
-Definedness.dfy(53,22): Related location: This is the postcondition that might not hold.
+Definedness.dfy(54,2): Error BP5003: A postcondition might not hold on this return path.
+Definedness.dfy(53,21): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-Definedness.dfy(60,18): Error: target object may be null
+Definedness.dfy(60,17): Error: target object may be null
Execution trace:
(0,0): anon0
-Definedness.dfy(61,3): Error BP5003: A postcondition might not hold on this return path.
-Definedness.dfy(60,22): Related location: This is the postcondition that might not hold.
+Definedness.dfy(61,2): Error BP5003: A postcondition might not hold on this return path.
+Definedness.dfy(60,21): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-Definedness.dfy(68,3): Error BP5003: A postcondition might not hold on this return path.
-Definedness.dfy(67,22): Related location: This is the postcondition that might not hold.
+Definedness.dfy(68,2): Error BP5003: A postcondition might not hold on this return path.
+Definedness.dfy(67,21): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-Definedness.dfy(88,7): Error: target object may be null
+Definedness.dfy(88,6): Error: target object may be null
Execution trace:
(0,0): anon0
-Definedness.dfy(89,5): Error: possible violation of function precondition
-Definedness.dfy(79,16): Related location
+Definedness.dfy(89,4): Error: possible violation of function precondition
+Definedness.dfy(79,15): Related location
Execution trace:
(0,0): anon0
-Definedness.dfy(89,10): Error: assignment may update an object not in the enclosing context's modifies clause
+Definedness.dfy(89,9): Error: assignment may update an object not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
-Definedness.dfy(89,10): Error: target object may be null
+Definedness.dfy(89,9): Error: target object may be null
Execution trace:
(0,0): anon0
-Definedness.dfy(90,10): Error: possible violation of function precondition
-Definedness.dfy(79,16): Related location
+Definedness.dfy(90,9): Error: possible violation of function precondition
+Definedness.dfy(79,15): Related location
Execution trace:
(0,0): anon0
-Definedness.dfy(95,14): Error: possible division by zero
+Definedness.dfy(95,13): Error: possible division by zero
Execution trace:
(0,0): anon0
-Definedness.dfy(95,23): Error: possible division by zero
+Definedness.dfy(95,22): Error: possible division by zero
Execution trace:
(0,0): anon0
-Definedness.dfy(96,15): Error: possible division by zero
+Definedness.dfy(96,14): Error: possible division by zero
Execution trace:
(0,0): anon0
-Definedness.dfy(101,12): Error: possible division by zero
+Definedness.dfy(101,11): Error: possible division by zero
Execution trace:
(0,0): anon0
-Definedness.dfy(108,15): Error: possible division by zero
+Definedness.dfy(108,14): Error: possible division by zero
Execution trace:
Definedness.dfy(108,5): anon7_LoopHead
(0,0): anon7_LoopBody
Definedness.dfy(108,5): anon8_Else
-Definedness.dfy(117,23): Error: possible violation of function precondition
-Definedness.dfy(79,16): Related location
+Definedness.dfy(117,22): Error: possible violation of function precondition
+Definedness.dfy(79,15): Related location
Execution trace:
(0,0): anon0
Definedness.dfy(116,5): anon12_LoopHead
(0,0): anon12_LoopBody
(0,0): anon13_Then
-Definedness.dfy(123,17): Error: possible violation of function precondition
-Definedness.dfy(79,16): Related location
+Definedness.dfy(123,16): Error: possible violation of function precondition
+Definedness.dfy(79,15): Related location
Execution trace:
(0,0): anon0
Definedness.dfy(116,5): anon12_LoopHead
@@ -91,30 +91,30 @@ Execution trace:
Definedness.dfy(122,5): anon15_LoopHead
(0,0): anon15_LoopBody
(0,0): anon16_Then
-Definedness.dfy(133,17): Error: possible violation of function precondition
-Definedness.dfy(79,16): Related location
+Definedness.dfy(133,16): Error: possible violation of function precondition
+Definedness.dfy(79,15): Related location
Execution trace:
(0,0): anon0
Definedness.dfy(132,5): anon6_LoopHead
(0,0): anon6_LoopBody
(0,0): anon7_Then
-Definedness.dfy(133,22): Error BP5004: This loop invariant might not hold on entry.
+Definedness.dfy(133,21): Error BP5004: This loop invariant might not hold on entry.
Execution trace:
(0,0): anon0
-Definedness.dfy(134,17): Error: possible violation of function precondition
-Definedness.dfy(79,16): Related location
+Definedness.dfy(134,16): Error: possible violation of function precondition
+Definedness.dfy(79,15): Related location
Execution trace:
(0,0): anon0
Definedness.dfy(132,5): anon6_LoopHead
(0,0): anon6_LoopBody
(0,0): anon7_Then
-Definedness.dfy(143,15): Error: possible division by zero
+Definedness.dfy(143,14): Error: possible division by zero
Execution trace:
(0,0): anon0
Definedness.dfy(143,5): anon8_LoopHead
(0,0): anon8_LoopBody
Definedness.dfy(143,5): anon9_Else
-Definedness.dfy(162,15): Error: possible division by zero
+Definedness.dfy(162,14): Error: possible division by zero
Execution trace:
(0,0): anon0
Definedness.dfy(156,5): anon16_LoopHead
@@ -126,11 +126,11 @@ Execution trace:
Definedness.dfy(162,5): anon20_LoopHead
(0,0): anon20_LoopBody
Definedness.dfy(162,5): anon21_Else
-Definedness.dfy(175,28): Error BP5004: This loop invariant might not hold on entry.
+Definedness.dfy(175,27): Error BP5004: This loop invariant might not hold on entry.
Execution trace:
(0,0): anon0
-Definedness.dfy(181,17): Error: possible violation of function precondition
-Definedness.dfy(79,16): Related location
+Definedness.dfy(181,16): Error: possible violation of function precondition
+Definedness.dfy(79,15): Related location
Execution trace:
(0,0): anon0
Definedness.dfy(173,5): anon18_LoopHead
@@ -142,38 +142,34 @@ Execution trace:
(0,0): anon22_Then
(0,0): anon23_Then
(0,0): anon11
-Definedness.dfy(196,19): Error: possible division by zero
+Definedness.dfy(196,18): Error: possible division by zero
Execution trace:
(0,0): anon0
Definedness.dfy(194,5): anon6_LoopHead
(0,0): anon6_LoopBody
(0,0): anon7_Then
-Definedness.dfy(196,23): Error BP5004: This loop invariant might not hold on entry.
+Definedness.dfy(196,22): Error BP5004: This loop invariant might not hold on entry.
Execution trace:
(0,0): anon0
-Definedness.dfy(196,28): Error: possible division by zero
+Definedness.dfy(196,27): Error: possible division by zero
Execution trace:
(0,0): anon0
Definedness.dfy(194,5): anon6_LoopHead
(0,0): anon6_LoopBody
(0,0): anon7_Then
-Definedness.dfy(215,10): Error BP5003: A postcondition might not hold on this return path.
-Definedness.dfy(217,46): Related location: This is the postcondition that might not hold.
+Definedness.dfy(215,9): Error BP5003: A postcondition might not hold on this return path.
+Definedness.dfy(217,45): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
-Definedness.dfy(224,22): Error: target object may be null
+ (0,0): anon4_Else
+Definedness.dfy(224,21): Error: target object may be null
Execution trace:
(0,0): anon0
- (0,0): anon5_Then
- (0,0): anon2
- (0,0): anon6_Then
-Definedness.dfy(237,10): Error BP5003: A postcondition might not hold on this return path.
-Definedness.dfy(240,24): Related location: This is the postcondition that might not hold.
+ (0,0): anon4_Then
+Definedness.dfy(237,9): Error BP5003: A postcondition might not hold on this return path.
+Definedness.dfy(240,23): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
- (0,0): anon7_Then
- (0,0): anon2
- (0,0): anon8_Else
+ (0,0): anon4_Else
Dafny program verifier finished with 21 verified, 37 errors
diff --git a/Test/dafny0/DeterministicPick.dfy b/Test/dafny0/DeterministicPick.dfy
index a7ec55fa..13db1bfc 100644
--- a/Test/dafny0/DeterministicPick.dfy
+++ b/Test/dafny0/DeterministicPick.dfy
@@ -29,6 +29,7 @@ module Attempt_Smallest refines Specification {
var z :| z in s;
if s != {z} {
var s' := s - {z};
+ assert forall y :: y in s ==> y in s' || y == z;
ASmallestToPick(s');
}
}
diff --git a/Test/dafny0/DeterministicPick.dfy.expect b/Test/dafny0/DeterministicPick.dfy.expect
index f8b779ef..aef97ebd 100644
--- a/Test/dafny0/DeterministicPick.dfy.expect
+++ b/Test/dafny0/DeterministicPick.dfy.expect
@@ -1,6 +1,6 @@
-DeterministicPick.dfy(13,5): Error: to be compilable, the value of a let-such-that expression must be uniquely determined
+DeterministicPick.dfy(13,4): Error: to be compilable, the value of a let-such-that expression must be uniquely determined
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
+ (0,0): anon4_Else
Dafny program verifier finished with 6 verified, 1 error
diff --git a/Test/dafny0/DiamondImports.dfy.expect b/Test/dafny0/DiamondImports.dfy.expect
index e9e8c2b9..1acca075 100644
--- a/Test/dafny0/DiamondImports.dfy.expect
+++ b/Test/dafny0/DiamondImports.dfy.expect
@@ -1,12 +1,12 @@
-DiamondImports.dfy(34,16): Error: assertion violation
+DiamondImports.dfy(34,15): Error: assertion violation
Execution trace:
(0,0): anon0
-DiamondImports.dfy(50,16): Error: assertion violation
+DiamondImports.dfy(50,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Then
(0,0): anon2
-DiamondImports.dfy(101,16): Error: assertion violation
+DiamondImports.dfy(101,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon7_Then
@@ -14,7 +14,7 @@ Execution trace:
(0,0): anon8_Then
(0,0): anon9_Then
(0,0): anon6
-DiamondImports.dfy(120,16): Error: assertion violation
+DiamondImports.dfy(120,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon9_Then
@@ -25,7 +25,7 @@ Execution trace:
(0,0): anon6
(0,0): anon12_Then
(0,0): anon8
-DiamondImports.dfy(140,26): Error: assertion violation
+DiamondImports.dfy(140,25): Error: assertion violation
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/DirtyLoops.dfy b/Test/dafny0/DirtyLoops.dfy
index 265fadb5..1a61a7e6 100644
--- a/Test/dafny0/DirtyLoops.dfy
+++ b/Test/dafny0/DirtyLoops.dfy
@@ -1,4 +1,5 @@
-// RUN: %dafny /compile:0 /dprint:"%t.dprint.dfy" "%s" > "%t"; %dafny /noVerify /compile:1 "%t.dprint.dfy" >> "%t"
+// RUN: %dafny /compile:0 /dprint:"%t.dprint.dfy" "%s" > "%t"
+// RUN: %dafny /noVerify /compile:1 "%t.dprint.dfy" >> "%t"
// RUN: %diff "%s.expect" "%t"
class MyClass {
diff --git a/Test/dafny0/DiscoverBounds.dfy.expect b/Test/dafny0/DiscoverBounds.dfy.expect
index ee816683..34003053 100644
--- a/Test/dafny0/DiscoverBounds.dfy.expect
+++ b/Test/dafny0/DiscoverBounds.dfy.expect
@@ -1,4 +1,4 @@
-DiscoverBounds.dfy(36,7): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'o''
-DiscoverBounds.dfy(39,7): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'r'
-DiscoverBounds.dfy(40,7): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'r''
+DiscoverBounds.dfy(36,7): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce or compile a bounded set of values for 'o''
+DiscoverBounds.dfy(39,7): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce or compile a bounded set of values for 'r'
+DiscoverBounds.dfy(40,7): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce or compile a bounded set of values for 'r''
3 resolution/type errors detected in DiscoverBounds.dfy
diff --git a/Test/dafny0/EqualityTypes.dfy b/Test/dafny0/EqualityTypes.dfy
index b2812759..c510cfb1 100644
--- a/Test/dafny0/EqualityTypes.dfy
+++ b/Test/dafny0/EqualityTypes.dfy
@@ -241,3 +241,115 @@ module Deep {
var m1 := map[ko := 5]; // error: bad type
}
}
+
+//--------------------------
+
+module UnderspecifiedTypeParameters {
+ method UP<T>()
+ function method UG<T>(): int
+ method Callee<T(==)>()
+ class TakesParam<U> { }
+
+ method MPG()
+ {
+ var g := UG(); // error: type parameter underspecified
+ UP(); // error: type parameter underspecified
+ }
+ method M() {
+ var zs: set; // error: type is underspecified
+ Callee<(int)>();
+ Callee<set>(); // error: type is underspecified
+ Callee<()>();
+ // The following
+ Callee<TakesParam>(); // error: type is underspecified
+ }
+}
+
+module EqualitySupportingTypes {
+ method P<T>()
+ function method G<T>(): int
+ class AClass<V(==),Y> {
+ static function method H<W,X(==)>(): bool
+ static method Q<A,B(==)>()
+ }
+
+ method Callee<T(==)>()
+ function method FCallee<T>(): T
+
+ datatype Dt = Dt(f: int -> int)
+ codatatype Stream<T> = Cons(T, Stream)
+
+ method M<ArbitraryTypeArg>()
+ {
+ Callee<Dt>(); // error: Dt is not an equality-supporting type
+ Callee<Stream<int>>(); // error: specified type does not support equality
+
+ // set<X> is allowed in a non-ghost context only if X is equality supporting.
+ // Ditto for multiset<X> and map<X,Y>.
+ var s3x: set<Dt>; // error: this type not allowed in a non-ghost context
+ var is3x: iset<Dt>; // error: this type not allowed in a non-ghost context
+ var mast: multiset<ArbitraryTypeArg>; // error: this type not allowed in a non-ghost context
+ var qt: seq<Stream<int>>; // allowed
+ var mp0: map<Dt,int>; // error: this type not allowed in a non-ghost context
+ var mp1: map<int,Dt>; // allowed
+ var imp0: imap<Dt,int>; // error: this type not allowed in a non-ghost context
+ var imp1: imap<int,Dt>; // allowed
+
+ var S := FCallee<set>(); // this gives s:set<?>
+ if 4 in S { // this constrains the type further to be s:set<int>
+ }
+
+ var xy: set<set<int>>;
+ var xz: set<set<Stream<int>>>; // error: set type argument must support equality
+
+ Callee<set<Stream<int>>>(); // bogus: a set shouldn't ever be allowed to take a Stream as an argument (this check seems to be missing for explicit type arguments) -- Note: language definition should be changed, because it doesn't make sense for it to talk about a type appearing in a ghost or non-ghost context. Instead, set/iset/multiset/map/imap should always be allowed to take any type argument, but these types may or may not support equality.
+ var xg := G<set<Stream<int>>>();
+
+ var ac0: AClass<int,int>;
+ var ac1: AClass<Stream<int>,int>; // error: type parameter 0 is required to support equality
+ var ac2: AClass<int,Stream<int>>;
+ var xd0 := ac0.H<real,real>();
+ var xd1 := ac1.H<Stream<real>,real>(); // error (remnant of the fact that the type of ac1 is not allowed)
+ var xd2 := ac2.H<real,Stream<real>>(); // error: type parameter 1 is required to support equality
+ var xe0 := ac0.H<real,real>;
+ var xe1 := ac1.H<Stream<real>,real>; // error (remnant of the fact that the type of ac1 is not allowed)
+ var xe2 := ac2.H<real,Stream<real>>; // error: type parameter 1 is required to support equality
+ var xh0 := AClass<int,int>.H<real,real>();
+ var xh1 := AClass<int,int>.H<Stream<real>,real>();
+ var xh2 := AClass<int,int>.H<real,Stream<real>>(); // error: type parameter 1 is required to support equality
+ var xk0 := AClass<real,real>.H<int,int>;
+ var xk1 := AClass<Stream<real>,real>.H<int,int>; // error: class type param 0 wants an equality-supporting type
+ var xk2 := AClass<real,Stream<real>>.H<int,int>;
+ AClass<Stream<int>,int>.Q<real,real>(); // error: class type param 0 wants an equality-supporting type
+ AClass<int,Stream<int>>.Q<real,real>();
+ AClass<int,Stream<int>>.Q<Stream<real>,real>();
+ AClass<int,Stream<int>>.Q<real,Stream<real>>(); // error: method type param 1 wants an equality-supporting type
+
+/*************************** TESTS YET TO COME
+ var ac8: AClass<real,real>;
+ var xd8 := (if 5/0 == 3 then ac0 else ac8).H<real,real>(); // error: this should be checked by the verifier
+
+ AClass<int,set<Stream<int>>>.Q<real,real>(); // error: cannot utter "set<Stream<int>>" Or is that okay???
+ AClass<int,int>.Q<set<Stream<real>>,real>(); // error: cannot utter "set<Stream<real>>" Or is that okay???
+ var xi0 := AClass<int,set<Stream<int>>>.H<real,real>(); // error: cannot utter "set<Stream<int>>" Or is that okay???
+ var xi1 := AClass<int,int>.H<real,set<Stream<real>>>(); // error: cannot utter "set<Stream<real>>" Or is that okay???
+
+ var x, t, s: seq<int -> int>, fii: int -> int;
+ if s == t {
+ x := 5; // error: assigning to non-ghost variable in ghost context
+ }
+ if fii in s {
+ x := 4; // error: assigning to non-ghost variable in ghost context
+ }
+ if !(fii in s) {
+ x := 3; // error: assigning to non-ghost variable in ghost context
+ }
+
+ ghost var ghostset: set<Stream<int>> := {}; // fine, since this is ghost
+ forall u | 0 <= u < 100
+ ensures var lets: set<Stream<int>> := {}; lets == lets // this is ghost, so the equality requirement doesn't apply
+ {
+ }
+*********************************************/
+ }
+}
diff --git a/Test/dafny0/EqualityTypes.dfy.expect b/Test/dafny0/EqualityTypes.dfy.expect
index 9f277582..1c02f3a0 100644
--- a/Test/dafny0/EqualityTypes.dfy.expect
+++ b/Test/dafny0/EqualityTypes.dfy.expect
@@ -35,4 +35,26 @@ EqualityTypes.dfy(238,24): Error: set argument type must support equality (got C
EqualityTypes.dfy(239,21): Error: multiset argument type must support equality (got Co)
EqualityTypes.dfy(241,8): Error: map domain type must support equality (got Co)
EqualityTypes.dfy(241,14): Error: map domain type must support equality (got Co)
-37 resolution/type errors detected in EqualityTypes.dfy
+EqualityTypes.dfy(255,13): Error: type variable 'T' in the function call to 'UG' could not be determined
+EqualityTypes.dfy(256,4): Error: type '?' to the method 'UP' is not determined
+EqualityTypes.dfy(259,8): Error: the type of this local variable is underspecified
+EqualityTypes.dfy(261,4): Error: type 'set<?>' to the method 'Callee' is not determined
+EqualityTypes.dfy(264,4): Error: type 'TakesParam<?>' to the method 'Callee' is not determined
+EqualityTypes.dfy(284,14): Error: type parameter 0 (T) passed to method Callee must support equality (got Dt)
+EqualityTypes.dfy(285,23): Error: type parameter 0 (T) passed to method Callee must support equality (got Stream<int>)
+EqualityTypes.dfy(289,8): Error: set argument type must support equality (got Dt)
+EqualityTypes.dfy(290,8): Error: iset argument type must support equality (got Dt)
+EqualityTypes.dfy(291,8): Error: multiset argument type must support equality (got ArbitraryTypeArg) (perhaps try declaring type parameter 'ArbitraryTypeArg' on line 282 as 'ArbitraryTypeArg(==)', which says it can only be instantiated with a type that supports equality)
+EqualityTypes.dfy(293,8): Error: map domain type must support equality (got Dt)
+EqualityTypes.dfy(295,8): Error: imap domain type must support equality (got Dt)
+EqualityTypes.dfy(303,8): Error: set argument type must support equality (got Stream<int>)
+EqualityTypes.dfy(309,8): Error: type parameter 0 (V) passed to type AClass must support equality (got Stream<int>)
+EqualityTypes.dfy(312,19): Error: type parameter 0 (V) passed to type AClass must support equality (got Stream<int>)
+EqualityTypes.dfy(313,19): Error: type parameter 1 (X) passed to function H must support equality (got Stream<real>)
+EqualityTypes.dfy(315,19): Error: type parameter 0 (V) passed to type AClass must support equality (got Stream<int>)
+EqualityTypes.dfy(316,19): Error: type parameter 1 (X) passed to function 'H' must support equality (got Stream<real>)
+EqualityTypes.dfy(319,31): Error: type parameter 1 (X) passed to function H must support equality (got Stream<real>)
+EqualityTypes.dfy(321,41): Error: type parameter 0 (V) passed to type AClass must support equality (got Stream<real>)
+EqualityTypes.dfy(323,28): Error: type parameter 0 (V) passed to type AClass must support equality (got Stream<int>)
+EqualityTypes.dfy(326,48): Error: type parameter 1 (B) passed to method Q must support equality (got Stream<real>)
+59 resolution/type errors detected in EqualityTypes.dfy
diff --git a/Test/dafny0/Extern.dfy b/Test/dafny0/Extern.dfy
new file mode 100644
index 00000000..cbdffe34
--- /dev/null
+++ b/Test/dafny0/Extern.dfy
@@ -0,0 +1,27 @@
+// RUN: %dafny /compile:1 /print:"%t.print" /dprint:"%t.dprint" "%s" "%S\Extern2.cs" "%S\ExternHelloLibrary.dll" > "%t"
+// RUN: %diff "%s.expect" "%t"
+extern "Modx" module Mod1
+{
+ extern "classx" class Class1
+ {
+ extern "Fun1x" static function method Fun1() : int
+ ensures Fun1() > 0
+ extern "Method1x" static method Method1() returns (x: int)
+ ensures x > 0
+ static function method Fun2() : int
+ ensures Fun2() > 0
+ {
+ Fun1()
+ }
+ static method Method2() returns (x: int)
+ ensures x > 0
+ {
+ x := Method1();
+ }
+ }
+ method Main()
+ {
+ var m2 := Class1.Method2();
+ print ("Fun2() = ", Class1.Fun2(), "Method2() = ", m2, "\n");
+ }
+}
diff --git a/Test/dafny0/Extern.dfy.expect b/Test/dafny0/Extern.dfy.expect
new file mode 100644
index 00000000..25c1c3ee
--- /dev/null
+++ b/Test/dafny0/Extern.dfy.expect
@@ -0,0 +1,4 @@
+
+Dafny program verifier finished with 7 verified, 0 errors
+Compiled program written to Extern.cs
+Compiled assembly into Extern.exe
diff --git a/Test/dafny0/Extern2.cs b/Test/dafny0/Extern2.cs
new file mode 100644
index 00000000..2fcaf18b
--- /dev/null
+++ b/Test/dafny0/Extern2.cs
@@ -0,0 +1,14 @@
+using System.Numerics;
+namespace @Modx {
+
+ public partial class @classx {
+ public static BigInteger @Fun1x() {
+ return BigInteger.One;
+ }
+ public static void @Method1x(out BigInteger @x)
+ {
+ ExternHelloLibrary.ExternHelloLibrary.SayHello();
+ @x = BigInteger.One;
+ }
+ }
+}
diff --git a/Test/dafny0/ExternHelloLibrary.cs b/Test/dafny0/ExternHelloLibrary.cs
new file mode 100644
index 00000000..81163997
--- /dev/null
+++ b/Test/dafny0/ExternHelloLibrary.cs
@@ -0,0 +1,15 @@
+// Note that ExternHelloLibrary.dll was produced from this file using
+// csc /t:library ExternHelloLibrary.cs
+
+using System;
+
+namespace ExternHelloLibrary
+{
+ public static class ExternHelloLibrary
+ {
+ public static void SayHello()
+ {
+ Console.WriteLine("Hello from ExternHelloLibrary.");
+ }
+ }
+}
diff --git a/Test/dafny0/ExternHelloLibrary.dll b/Test/dafny0/ExternHelloLibrary.dll
new file mode 100644
index 00000000..914e4248
--- /dev/null
+++ b/Test/dafny0/ExternHelloLibrary.dll
Binary files differ
diff --git a/Test/dafny0/ExternNegative.dfy b/Test/dafny0/ExternNegative.dfy
new file mode 100644
index 00000000..4ae73232
--- /dev/null
+++ b/Test/dafny0/ExternNegative.dfy
@@ -0,0 +1,26 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+extern "Modx" module Mod1
+{
+ extern "classx" class Class1
+ {
+ extern "Fun1x" static function method Fun1() : int
+ ensures Fun1() > 0
+ extern "Method1x" static method Method1() returns (x: int)
+ ensures x > 0
+ static abstract function method Fun2() : int
+ ensures Fun2() > 0
+ {
+ Fun1()
+ }
+ static static method Method2() returns (x: int)
+ ensures x > 0
+ {
+ x := Method1();
+ }
+ }
+}
+// Will give error about duplicate CompileName for module.
+extern "Modx" module Mod2
+{
+}
diff --git a/Test/dafny0/ExternNegative.dfy.expect b/Test/dafny0/ExternNegative.dfy.expect
new file mode 100644
index 00000000..5d95ced7
--- /dev/null
+++ b/Test/dafny0/ExternNegative.dfy.expect
@@ -0,0 +1,3 @@
+ExternNegative.dfy(11,11): Error: Function methods cannot be declared 'abstract'.
+ExternNegative.dfy(16,11): Error: Duplicate declaration modifier: static
+2 parse errors detected in ExternNegative.dfy
diff --git a/Test/dafny0/ExternNegative2.dfy b/Test/dafny0/ExternNegative2.dfy
new file mode 100644
index 00000000..3d09913b
--- /dev/null
+++ b/Test/dafny0/ExternNegative2.dfy
@@ -0,0 +1,26 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+extern "Modx" module Mod1
+{
+ extern "classx" class Class1
+ {
+ extern "Fun1x" static function method Fun1() : int
+ ensures Fun1() > 0
+ extern "Method1x" static method Method1() returns (x: int)
+ ensures x > 0
+ static function method Fun2() : int
+ ensures Fun2() > 0
+ {
+ Fun1()
+ }
+ static method Method2() returns (x: int)
+ ensures x > 0
+ {
+ x := Method1();
+ }
+ }
+}
+// Will give error about duplicate CompileName for module.
+extern "Modx" module Mod2
+{
+}
diff --git a/Test/dafny0/ExternNegative2.dfy.expect b/Test/dafny0/ExternNegative2.dfy.expect
new file mode 100644
index 00000000..64194de0
--- /dev/null
+++ b/Test/dafny0/ExternNegative2.dfy.expect
@@ -0,0 +1,2 @@
+ExternNegative2.dfy(24,21): Error: Modules 'Mod1' and 'Mod2' both have CompileName 'Modx'.
+1 resolution/type errors detected in ExternNegative2.dfy
diff --git a/Test/dafny0/ForallCompilation.dfy b/Test/dafny0/ForallCompilation.dfy
index c812983a..4d89f70d 100644
--- a/Test/dafny0/ForallCompilation.dfy
+++ b/Test/dafny0/ForallCompilation.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:3 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:3 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
method Main() {
diff --git a/Test/dafny0/Fuel.dfy b/Test/dafny0/Fuel.dfy
new file mode 100644
index 00000000..a768db02
--- /dev/null
+++ b/Test/dafny0/Fuel.dfy
@@ -0,0 +1,462 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+module TestModule1 {
+ function pos(x:int) : int
+ {
+ if x < 0 then 0
+ else 1 + pos(x - 1)
+ }
+
+ method test(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert pos(z) == 0;
+ assert pos(-1) == 0;
+ assert pos(y) == 3 + pos(y - 3); // error: Should fail, due to lack of fuel
+ assert pos(y) == 4 + pos(y - 4); // Succeeds, thanks to the assume from the preceding assert
+ }
+}
+
+// Test with function-level fuel boost
+module TestModule2 {
+ function {:fuel 3} pos1(x:int) : int
+ {
+ if x < 0 then 0
+ else 1 + pos1(x - 1)
+ }
+
+ function {:fuel 3,5} pos2(x:int) : int
+ {
+ if x < 0 then 0
+ else 1 + pos2(x - 1)
+ }
+
+ function {:fuel 3,5} pos3(x:int) : int
+ {
+ if x < 0 then 0
+ else 1 + pos3(x - 1)
+ }
+
+ function {:opaque} {:fuel 3,5} pos4(x:int) : int
+ {
+ if x < 0 then 0
+ else 1 + pos3(x - 1)
+ }
+
+ method test(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert pos1(z) == 0;
+ assert pos1(-1) == 0;
+ assert pos1(y) == 3 + pos1(y - 3);
+ assert pos1(y) == 4 + pos1(y - 4);
+
+ assert pos2(z) == 0;
+ assert pos2(-1) == 0;
+ assert pos2(y) == 3 + pos2(y - 3);
+ assert pos2(y) == 4 + pos2(y - 4);
+
+ if (*) {
+ assert pos3(y) == 5 + pos3(y - 5); // Just enough fuel to get here
+ } else {
+ assert pos3(y) == 6 + pos3(y - 6); // error: Should fail even with a boost, since boost is too small
+ }
+
+ if (*) {
+ assert pos4(z) == 0; // error: Fuel shouldn't overcome opaque
+ } else {
+ reveal_pos4();
+ assert pos4(y) == 5 + pos4(y - 5); // With reveal, everything should work as above
+ }
+
+
+ }
+}
+
+
+module TestModule3 {
+ // This fuel setting is equivalent to opaque, except for literals
+ function {:fuel 0,0} pos(x:int) : int
+ {
+ if x < 0 then 0
+ else 1 + pos(x - 1)
+ }
+
+ method test(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert pos(z) == 0; // error: Opaque setting hides body
+ assert pos(-1) == 0; // Passes, since Dafny's computation mode for lits ignore fuel
+ assert pos(y) == 3 + pos(y - 3);// error: Opaque setting hides body
+ }
+}
+
+// Test fuel settings via different contexts
+module TestModule4 {
+ function pos(x:int) : int
+ {
+ if x < 0 then 0
+ else 1 + pos(x - 1)
+ }
+
+ // Should pass
+ method {:fuel pos,3,5} test1(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert pos(z) == 0;
+ assert pos(-1) == 0;
+ assert pos(y) == 3 + pos(y - 3);
+ }
+
+ method {:fuel pos,0,0} test2(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert pos(z) == 0; // error: Should fail due to "opaque" fuel setting
+ assert pos(-1) == 0;
+ assert pos(y) == 3 + pos(y - 3); // error: Should fail due to "opaque" fuel setting
+ }
+
+ method test3(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert {:fuel pos,0,0} pos(z) == 0; // error: fuel can't be decreased
+ assert pos(-1) == 0;
+ if (*) {
+ assert pos(y) == 3 + pos(y - 3); // error: Should fail without extra fuel setting
+ assert pos(y) == 6 + pos(y - 6); // error: Should fail even with previous assert turned into assume
+ } else {
+ assert {:fuel pos,3,5} pos(y) == 3 + pos(y - 3); // Should succeed with extra fuel setting
+ assert pos(y) == 6 + pos(y - 6); // Should succeed thanks to previous assert turned into assume
+ }
+ }
+
+ method test4(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ forall t:int {:fuel pos,3} | t > 0
+ ensures true;
+ {
+ assert pos(y) == 3 + pos(y - 3); // Expected to pass, due to local fuel boost
+ }
+
+ if (*) {
+ calc {:fuel pos,3} {
+ pos(y);
+ 3 + pos(y - 3);
+ }
+ }
+
+ assert pos(y) == 3 + pos(y - 3); // error: Should fail, due to lack of fuel outside the forall
+ }
+}
+
+// Test fuel settings via different module contexts
+module TestModule5 {
+ // Test module level fuel settings, with nested modules
+
+ module TestModule5a {
+ module {:fuel TestModule5aiA.pos,3} TestModule5ai {
+ module TestModule5aiA {
+ function pos(x:int) : int
+ {
+ if x < 0 then 0
+ else 1 + pos(x - 1)
+ }
+
+ method test(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert pos(z) == 0;
+ assert pos(-1) == 0;
+ assert pos(y) == 3 + pos(y - 3); // Should pass due to intermediate module's fuel setting
+ }
+ }
+
+ method test(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert TestModule5aiA.pos(z) == 0;
+ assert TestModule5aiA.pos(-1) == 0;
+ assert TestModule5aiA.pos(y) == 3 + TestModule5aiA.pos(y - 3); // Should pass due to module level fuel
+ }
+ }
+
+ method test(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert TestModule5ai.TestModule5aiA.pos(z) == 0;
+ assert TestModule5ai.TestModule5aiA.pos(-1) == 0;
+ assert TestModule5ai.TestModule5aiA.pos(y) == 3 + TestModule5ai.TestModule5aiA.pos(y - 3); // error: Should fail, due to lack of fuel
+ }
+ }
+
+ module {:fuel TestModule5bi.TestModule5biA.pos,3} TestModule5b {
+ module TestModule5bi {
+ module TestModule5biA {
+ function pos(x:int) : int
+ {
+ if x < 0 then 0
+ else 1 + pos(x - 1)
+ }
+
+ method test(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert pos(z) == 0;
+ assert pos(-1) == 0;
+ assert pos(y) == 3 + pos(y - 3); // Should succceed due to outer module fuel setting
+ }
+ }
+ }
+ }
+}
+
+// Test fuel setting for multiple functions
+module TestModule6 {
+ function pos(x:int) : int
+ {
+ if x < 0 then 0
+ else 1 + pos(x - 1)
+ }
+
+ function neg(x:int) : int
+ decreases 1 - x;
+ {
+ if x > 0 then 0
+ else 1 + neg(x + 1)
+ }
+
+ method test1(y:int, z:int)
+ requires y > 5;
+ requires z < 5;
+ {
+ assert pos(y) == 3 + pos(y - 3); // error: Should fail, due to lack of fuel
+
+ assert neg(z) == 3 + neg(z + 3); // error: Should fail, due to lack of fuel
+ }
+
+ method {:fuel pos,3} {:fuel neg,4} test2(y:int, z:int)
+ requires y > 5;
+ requires z < -5;
+ {
+ assert pos(y) == 3 + pos(y - 3);
+
+ assert neg(z) == 3 + neg(z + 3);
+ }
+}
+
+// Test fuel settings with multiple overlapping contexts
+module TestModule7 {
+ function {:fuel 3} pos(x:int) : int
+ {
+ if x < 0 then 0
+ else 1 + pos(x - 1)
+ }
+
+ function {:fuel 0,0} neg(x:int) : int
+ decreases 1 - x;
+ {
+ if x > 0 then 0
+ else 1 + neg(x + 1)
+ }
+
+ method {:fuel neg,4} {:fuel pos,0,0} test1(y:int, z:int)
+ requires y > 5;
+ requires z < -5;
+ {
+ if (*) {
+ assert pos(y) == 3 + pos(y - 3); // error: Method fuel should override function fuel, so this should fail
+ assert neg(z) == 3 + neg(z + 3); // Method fuel should override function fuel, so this succeeds
+ }
+
+ forall t:int {:fuel pos,3} | t > 0
+ ensures true;
+ {
+ assert pos(y) == 3 + pos(y - 3); // Statement fuel should override method fuel, so this should succeed
+ }
+ }
+}
+
+// Test fuel in a slightly more complicated setting
+module TestModule8 {
+
+ newtype byte = i:int | 0 <= i < 0x100
+ newtype uint64 = i:int | 0 <= i < 0x10000000000000000
+
+ datatype G = GUint64
+ | GArray(elt:G)
+ | GTuple(t:seq<G>)
+ | GByteArray
+ | GTaggedUnion(cases:seq<G>)
+
+ datatype V = VUint64(u:uint64)
+ | VTuple(t:seq<V>)
+ | VCase(c:uint64, val:V)
+
+ predicate {:fuel 2} ValInGrammar(val:V, grammar:G)
+ {
+ match val
+ case VUint64(_) => grammar.GUint64?
+ case VTuple(t) => grammar.GTuple? && |t| == |grammar.t|
+ && forall i :: 0 <= i < |t| ==> ValInGrammar(t[i], grammar.t[i])
+ case VCase(c, val) => grammar.GTaggedUnion? && int(c) < |grammar.cases| && ValInGrammar(val, grammar.cases[c])
+ }
+
+ datatype CRequest = CRequest(client:EndPoint, seqno:uint64, request:CAppMessage) | CRequestNoOp()
+
+ type EndPoint
+ function method EndPoint_grammar() : G { GUint64 }
+ function method CRequest_grammar() : G { GTaggedUnion([ GTuple([EndPoint_grammar(), GUint64, CAppMessage_grammar()]), GUint64]) }
+
+ function method parse_EndPoint(val:V) : EndPoint
+ requires ValInGrammar(val, EndPoint_grammar());
+
+ type CAppMessage
+ function method CAppMessage_grammar() : G { GTaggedUnion([GUint64, GUint64, GUint64]) }
+ function method parse_AppMessage(val:V) : CAppMessage
+ requires ValInGrammar(val, CAppMessage_grammar());
+
+ function method {:fuel ValInGrammar,1,2} parse_Request1(val:V) : CRequest
+ requires ValInGrammar(val, CRequest_grammar());
+ {
+ if val.c == 0 then
+ var ep := parse_EndPoint(val.val.t[0]); // With default fuel, error: function precondition, destructor, index
+ CRequest(ep, val.val.t[1].u, parse_AppMessage(val.val.t[2])) // error: index out of range, destructor
+ else
+ CRequestNoOp()
+ }
+
+ function method parse_Request2(val:V) : CRequest
+ requires ValInGrammar(val, CRequest_grammar());
+ {
+ if val.c == 0 then
+ var ep := parse_EndPoint(val.val.t[0]); // With fuel boosted to 2 this succeeds
+ CRequest(ep, val.val.t[1].u, parse_AppMessage(val.val.t[2])) // error: destructor
+ else
+ CRequestNoOp()
+ }
+
+ function method {:fuel ValInGrammar,3} parse_Request3(val:V) : CRequest
+ requires ValInGrammar(val, CRequest_grammar());
+ {
+ if val.c == 0 then
+ var ep := parse_EndPoint(val.val.t[0]);
+ CRequest(ep, val.val.t[1].u, parse_AppMessage(val.val.t[2])) // With one more boost, everything succeeds
+ else
+ CRequestNoOp()
+ }
+
+ // With the method, everything succeeds with one less fuel boost (i.e., 2, rather than 3, as in parse_Request3)
+ method parse_Request4(val:V) returns (req:CRequest)
+ requires ValInGrammar(val, CRequest_grammar());
+ {
+ if val.c == 0 {
+ var ep := parse_EndPoint(val.val.t[0]);
+ req := CRequest(ep, val.val.t[1].u, parse_AppMessage(val.val.t[2]));
+ } else {
+ req := CRequestNoOp();
+ }
+ }
+}
+
+
+// Test fuel when it's applied to a non-recursive function
+module TestModule9 {
+ function abs(x:int) : int
+ {
+ if x < 0 then -1 * x else x
+ }
+
+ // All should pass.
+ method test1(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert abs(z) == -1*z;
+ assert abs(y) == y;
+ assert abs(-1) == 1;
+ }
+
+ // Method-level fuel override
+ method {:fuel abs,0,0} test2(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert abs(z) == -1*z; // error: Cannot see the body of abs
+ assert abs(y) == y; // error: Cannot see the body of abs
+ assert abs(-1) == 1; // lit bypasses fuel, so this should succeed
+ }
+
+ // Statement-level fuel override
+ method test3(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert {:fuel abs,0,0} abs(z) == -1*z; // error: fuel can't be decreased
+ assert abs(y) == y; // Normal success
+ assert abs(-1) == 1; // lit bypasses fuel, so this should succeed
+ }
+
+ // Giving more fuel to a non-recursive function won't help,
+ // but it shouldn't hurt either.
+ method {:fuel abs,5,7} test4(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert abs(z) == -1*z;
+ assert abs(y) == y;
+ assert abs(-1) == 1;
+ }
+}
+
+// Test fuel when it's applied to a non-recursive function directly (to simulate opaque)
+module TestModule10 {
+ function {:fuel 0,0} abs(x:int) : int
+ {
+ if x < 0 then -1 * x else x
+ }
+
+ method test1(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert abs(z) == -1*z; // error: Cannot see the body of abs
+ assert abs(y) == y; // error: Cannot see the body of abs
+ assert abs(-1) == 1; // lit bypasses fuel, so this should succeed
+ }
+}
+
+// Test fuel when it's mentioned in other functions function to simulate a local opaque
+module TestModule11 {
+ function abs(x:int) : int
+ {
+ if x < 0 then -1 * x else x
+ }
+
+ function {:fuel abs,0,0} abs'(x:int) : int
+ {
+ abs(x)
+ }
+
+ method test1(y:int, z:int)
+ requires y > 5;
+ requires z < 0;
+ {
+ assert abs'(z) == -1*z; // error: Cannot see the body of abs
+ assert abs'(y) == y; // error: Cannot see the body of abs
+ assert abs'(-1) == 1; // lit bypasses fuel, so this should succeed
+ }
+}
+
diff --git a/Test/dafny0/Fuel.dfy.expect b/Test/dafny0/Fuel.dfy.expect
new file mode 100644
index 00000000..275be237
--- /dev/null
+++ b/Test/dafny0/Fuel.dfy.expect
@@ -0,0 +1,113 @@
+Fuel.dfy(129,8): Error: Fuel can only increase within a given scope.
+Fuel.dfy(407,8): Error: Fuel can only increase within a given scope.
+Fuel.dfy(17,22): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Fuel.dfy(65,27): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon6_Else
+Fuel.dfy(69,27): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon6_Then
+ (0,0): anon7_Then
+Fuel.dfy(92,22): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Fuel.dfy(94,22): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Fuel.dfy(120,22): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Fuel.dfy(122,22): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Fuel.dfy(129,38): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Then
+Fuel.dfy(132,26): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ Fuel.dfy(129,9): anon7_Else
+ (0,0): anon8_Then
+Fuel.dfy(133,26): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ Fuel.dfy(129,9): anon7_Else
+ (0,0): anon8_Then
+Fuel.dfy(157,22): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon10_Else
+ (0,0): anon9
+Fuel.dfy(200,55): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Fuel.dfy(245,22): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Fuel.dfy(247,22): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Fuel.dfy(280,26): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Then
+Fuel.dfy(335,26): Error: possible violation of function precondition
+Fuel.dfy(324,21): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Else
+ (0,0): anon8_Then
+Fuel.dfy(335,49): Error: destructor 't' can only be applied to datatype values constructed by 'VTuple'
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Else
+ (0,0): anon8_Then
+Fuel.dfy(335,50): Error: index out of range
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Else
+ (0,0): anon8_Then
+Fuel.dfy(336,38): Error: index out of range
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Else
+ (0,0): anon8_Then
+Fuel.dfy(336,42): Error: destructor 'u' can only be applied to datatype values constructed by 'VUint64'
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Else
+ (0,0): anon8_Then
+Fuel.dfy(346,42): Error: destructor 'u' can only be applied to datatype values constructed by 'VUint64'
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Else
+ (0,0): anon8_Then
+Fuel.dfy(397,22): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Fuel.dfy(398,22): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Fuel.dfy(407,38): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Then
+Fuel.dfy(435,22): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Fuel.dfy(436,22): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Fuel.dfy(457,23): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Fuel.dfy(458,23): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 56 verified, 28 errors
diff --git a/Test/dafny0/FunctionSpecifications.dfy.expect b/Test/dafny0/FunctionSpecifications.dfy.expect
index 4b9aa202..078afaef 100644
--- a/Test/dafny0/FunctionSpecifications.dfy.expect
+++ b/Test/dafny0/FunctionSpecifications.dfy.expect
@@ -1,70 +1,70 @@
-FunctionSpecifications.dfy(35,25): Error BP5003: A postcondition might not hold on this return path.
-FunctionSpecifications.dfy(31,13): Related location: This is the postcondition that might not hold.
+FunctionSpecifications.dfy(29,9): Error BP5003: A postcondition might not hold on this return path.
+FunctionSpecifications.dfy(31,12): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
- (0,0): anon8_Else
- (0,0): anon9_Else
- (0,0): anon10_Then
+ (0,0): anon10_Else
(0,0): anon11_Else
-FunctionSpecifications.dfy(45,3): Error BP5003: A postcondition might not hold on this return path.
-FunctionSpecifications.dfy(40,24): Related location: This is the postcondition that might not hold.
+ (0,0): anon12_Then
+ (0,0): anon13_Else
+ (0,0): anon9
+FunctionSpecifications.dfy(38,9): Error BP5003: A postcondition might not hold on this return path.
+FunctionSpecifications.dfy(40,23): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
- (0,0): anon11_Else
- (0,0): anon14_Else
- (0,0): anon15_Then
-FunctionSpecifications.dfy(53,11): Error: cannot prove termination; try supplying a decreases clause
+ (0,0): anon15_Else
+ (0,0): anon18_Else
+ (0,0): anon19_Then
+ (0,0): anon14
+FunctionSpecifications.dfy(53,10): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon8_Then
- (0,0): anon3
-FunctionSpecifications.dfy(59,10): Error BP5003: A postcondition might not hold on this return path.
-FunctionSpecifications.dfy(60,22): Related location: This is the postcondition that might not hold.
+ (0,0): anon11_Then
+ (0,0): anon5
+FunctionSpecifications.dfy(59,9): Error BP5003: A postcondition might not hold on this return path.
+FunctionSpecifications.dfy(60,21): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
-FunctionSpecifications.dfy(108,23): Error: assertion violation
+ (0,0): anon7_Else
+FunctionSpecifications.dfy(108,22): Error: assertion violation
Execution trace:
(0,0): anon0
-FunctionSpecifications.dfy(111,23): Error: assertion violation
+FunctionSpecifications.dfy(111,22): Error: assertion violation
Execution trace:
(0,0): anon0
-FunctionSpecifications.dfy(126,27): Error: assertion violation
+FunctionSpecifications.dfy(126,26): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-FunctionSpecifications.dfy(130,27): Error: assertion violation
+FunctionSpecifications.dfy(130,26): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Else
-FunctionSpecifications.dfy(158,3): Error: cannot prove termination; try supplying a decreases clause
+FunctionSpecifications.dfy(158,2): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-FunctionSpecifications.dfy(167,11): Error: cannot prove termination; try supplying a decreases clause
+ (0,0): anon4_Else
+FunctionSpecifications.dfy(167,10): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-FunctionSpecifications.dfy(135,20): Error BP5003: A postcondition might not hold on this return path.
-FunctionSpecifications.dfy(137,29): Related location: This is the postcondition that might not hold.
+ (0,0): anon4_Else
+FunctionSpecifications.dfy(135,19): Error BP5003: A postcondition might not hold on this return path.
+FunctionSpecifications.dfy(137,28): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
- (0,0): anon5_Then
- (0,0): anon2
- (0,0): anon6_Else
-FunctionSpecifications.dfy(146,3): Error: failure to decrease termination measure
+ (0,0): anon4_Else
+FunctionSpecifications.dfy(146,2): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-FunctionSpecifications.dfy(153,3): Error: failure to decrease termination measure
+ (0,0): anon4_Else
+FunctionSpecifications.dfy(153,2): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-FunctionSpecifications.dfy(174,3): Error: cannot prove termination; try supplying a decreases clause
+ (0,0): anon4_Else
+FunctionSpecifications.dfy(174,2): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-FunctionSpecifications.dfy(171,20): Error: cannot prove termination; try supplying a decreases clause
+ (0,0): anon4_Else
+FunctionSpecifications.dfy(171,19): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/IMaps.dfy.expect b/Test/dafny0/IMaps.dfy.expect
index c2da9505..28ca8ca3 100644
--- a/Test/dafny0/IMaps.dfy.expect
+++ b/Test/dafny0/IMaps.dfy.expect
@@ -1,4 +1,4 @@
-IMaps.dfy(52,8): Error: element may not be in domain
+IMaps.dfy(52,7): Error: element may not be in domain
Execution trace:
(0,0): anon0
(0,0): anon5_Then
diff --git a/Test/dafny0/ISets.dfy b/Test/dafny0/ISets.dfy
new file mode 100644
index 00000000..703039c8
--- /dev/null
+++ b/Test/dafny0/ISets.dfy
@@ -0,0 +1,43 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+ghost method M()
+{
+ ghost var s := iset{2};
+ // test "in"
+ if(2 in s)
+ {
+ }
+ else
+ { assert false; }
+ // test "!in"
+ if(3 !in s)
+ {
+ }
+ else
+ { assert false; }
+
+ if(s == iset{2})
+ {
+ }
+ else
+ { assert false; }
+}
+
+ghost method m1() {
+ var s1:iset<int> := iset{}; // the empty set
+ var s2 := iset{1, 2, 3}; // set contains exactly 1, 2, and 3
+ assert s2 == iset{1,1,2,3,3,3,3}; // same as before
+ var s3, s4 := iset{1,2}, iset{1,4};
+
+ assert s2 + s4 == iset{1,2,3,4}; // set union
+ assert s2 * s3 == iset{1,2} && s2 * s4 == iset{1}; // set intersection
+ assert s2 - s3 == iset{3}; // set difference
+
+ assert (iset x | x in s2 :: x+1) == iset{2,3,4}; // set comprehension
+ assert 17 in (iset x: int | true :: x); // set comprehension
+
+ assert (imap x: int | true :: x+1)[14] == 15;
+}
+
+
diff --git a/Test/dafny0/ISets.dfy.expect b/Test/dafny0/ISets.dfy.expect
new file mode 100644
index 00000000..73ba063c
--- /dev/null
+++ b/Test/dafny0/ISets.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 4 verified, 0 errors
diff --git a/Test/dafny0/Include.dfy.expect b/Test/dafny0/Include.dfy.expect
index cb329398..d4543afe 100644
--- a/Test/dafny0/Include.dfy.expect
+++ b/Test/dafny0/Include.dfy.expect
@@ -1,13 +1,13 @@
-Include.dfy(19,19): Error BP5003: A postcondition might not hold on this return path.
-Includee.dfy(17,20): Related location: This is the postcondition that might not hold.
+Include.dfy(19,18): Error BP5003: A postcondition might not hold on this return path.
+Includee.dfy(17,19): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-Includee.dfy[Concrete](22,16): Error: assertion violation
+ (0,0): anon4_Else
+Includee.dfy[Concrete](22,15): Error: assertion violation
Execution trace:
(0,0): anon0
-Include.dfy(27,7): Error BP5003: A postcondition might not hold on this return path.
-Includee.dfy[Concrete](20,15): Related location: This is the postcondition that might not hold.
+Include.dfy(27,6): Error BP5003: A postcondition might not hold on this return path.
+Includee.dfy[Concrete](20,14): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
(0,0): anon6_Then
diff --git a/Test/dafny0/Includee.dfy.expect b/Test/dafny0/Includee.dfy.expect
index e0f0689c..ce61e32a 100644
--- a/Test/dafny0/Includee.dfy.expect
+++ b/Test/dafny0/Includee.dfy.expect
@@ -1,12 +1,12 @@
-Includee.dfy(21,3): Error BP5003: A postcondition might not hold on this return path.
-Includee.dfy(20,15): Related location: This is the postcondition that might not hold.
+Includee.dfy(21,2): Error BP5003: A postcondition might not hold on this return path.
+Includee.dfy(20,14): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-Includee.dfy(24,18): Error: assertion violation
+Includee.dfy(24,17): Error: assertion violation
Execution trace:
(0,0): anon0
-Includee.dfy(6,1): Error BP5003: A postcondition might not hold on this return path.
-Includee.dfy(5,13): Related location: This is the postcondition that might not hold.
+Includee.dfy(6,0): Error BP5003: A postcondition might not hold on this return path.
+Includee.dfy(5,12): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/IndexIntoUpdate.dfy b/Test/dafny0/IndexIntoUpdate.dfy
new file mode 100644
index 00000000..01359e04
--- /dev/null
+++ b/Test/dafny0/IndexIntoUpdate.dfy
@@ -0,0 +1,9 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+method M() {
+ var s := [1, 2, 3, 4];
+ assert 3 in s;
+ s := s[0 := 1];
+ if * { assert 3 in s; } // FIXME: This should verify
+ else { assert s[2] == 3; assert 3 in s; }
+}
diff --git a/Test/dafny0/IndexIntoUpdate.dfy.expect b/Test/dafny0/IndexIntoUpdate.dfy.expect
new file mode 100644
index 00000000..2db3aa0a
--- /dev/null
+++ b/Test/dafny0/IndexIntoUpdate.dfy.expect
@@ -0,0 +1,6 @@
+IndexIntoUpdate.dfy(7,18): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Then
+
+Dafny program verifier finished with 1 verified, 1 error
diff --git a/Test/dafny0/InductivePredicates.dfy b/Test/dafny0/InductivePredicates.dfy
index 424118e7..e9aa7604 100644
--- a/Test/dafny0/InductivePredicates.dfy
+++ b/Test/dafny0/InductivePredicates.dfy
@@ -18,7 +18,7 @@ lemma M(x: natinf)
}
// yay! my first proof involving an inductive predicate :)
-lemma M'(k: nat, x: natinf)
+lemma {:induction false} M'(k: nat, x: natinf)
requires Even#[k](x)
ensures x.N? && x.n % 2 == 0
{
@@ -32,8 +32,14 @@ lemma M'(k: nat, x: natinf)
}
}
+lemma M'_auto(k: nat, x: natinf)
+ requires Even#[k](x)
+ ensures x.N? && x.n % 2 == 0
+{
+}
+
// Here is the same proof as in M / M', but packaged into a single "inductive lemma":
-inductive lemma IL(x: natinf)
+inductive lemma {:induction false} IL(x: natinf)
requires Even(x)
ensures x.N? && x.n % 2 == 0
{
@@ -45,18 +51,24 @@ inductive lemma IL(x: natinf)
}
}
-inductive lemma IL_EvenBetter(x: natinf)
+inductive lemma {:induction false} IL_EvenBetter(x: natinf)
requires Even(x)
ensures x.N? && x.n % 2 == 0
{
if {
case x.N? && x.n == 0 =>
// trivial
- case x.N? && 2 <= x.n && Even(N(x.n - 2)) =>
+ case x.N? && 2 <= x.n && Even(N(x.n - 2)) => // syntactic rewrite makes this like in IL
IL_EvenBetter(N(x.n - 2));
}
}
+inductive lemma IL_Best(x: natinf)
+ requires Even(x)
+ ensures x.N? && x.n % 2 == 0
+{
+}
+
inductive lemma IL_Bad(x: natinf)
requires Even(x)
ensures x.N? && x.n % 2 == 0
@@ -107,7 +119,7 @@ module Alt {
{
match x
case N(n) => N(n+1)
- case Inf => Inf
+ case Inf => Inf
}
inductive predicate Even(x: natinf)
@@ -116,7 +128,7 @@ module Alt {
exists y :: x == S(S(y)) && Even(y)
}
- inductive lemma MyLemma_NotSoNice(x: natinf)
+ inductive lemma {:induction false} MyLemma_NotSoNice(x: natinf)
requires Even(x)
ensures x.N? && x.n % 2 == 0
{
@@ -130,7 +142,7 @@ module Alt {
}
}
- inductive lemma MyLemma_NiceButNotFast(x: natinf)
+ inductive lemma {:induction false} MyLemma_Nicer(x: natinf) // same as MyLemma_NotSoNice but relying on syntactic rewrites
requires Even(x)
ensures x.N? && x.n % 2 == 0
{
@@ -139,11 +151,17 @@ module Alt {
// trivial
case exists y :: x == S(S(y)) && Even(y) =>
var y :| x == S(S(y)) && Even(y);
- MyLemma_NiceButNotFast(y);
+ MyLemma_Nicer(y);
assert x.n == y.n + 2;
}
}
-
+
+ inductive lemma MyLemma_RealNice_AndFastToo(x: natinf)
+ requires Even(x)
+ ensures x.N? && x.n % 2 == 0
+ {
+ }
+
lemma InfNotEven()
ensures !Even(Inf)
{
@@ -156,15 +174,6 @@ module Alt {
requires Even(Inf)
ensures false
{
- var x := Inf;
- if {
- case x.N? && x.n == 0 =>
- assert false; // this case is absurd
- case exists y :: x == S(S(y)) && Even(y) =>
- var y :| x == S(S(y)) && Even(y);
- assert y == Inf;
- InfNotEven_Aux();
- }
}
lemma NextEven(x: natinf)
diff --git a/Test/dafny0/InductivePredicates.dfy.expect b/Test/dafny0/InductivePredicates.dfy.expect
index b09b7903..48beade5 100644
--- a/Test/dafny0/InductivePredicates.dfy.expect
+++ b/Test/dafny0/InductivePredicates.dfy.expect
@@ -1,9 +1,9 @@
-InductivePredicates.dfy(64,10): Error: assertion violation
+InductivePredicates.dfy(76,9): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-InductivePredicates.dfy(76,11): Error: assertion violation
+InductivePredicates.dfy(88,10): Error: assertion violation
Execution trace:
(0,0): anon0
-Dafny program verifier finished with 29 verified, 2 errors
+Dafny program verifier finished with 35 verified, 2 errors
diff --git a/Test/dafny0/Inverses.dfy b/Test/dafny0/Inverses.dfy
index 7995255a..b424cfd9 100644
--- a/Test/dafny0/Inverses.dfy
+++ b/Test/dafny0/Inverses.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// This identity function is used to so that if the occurrence of i below
@@ -110,3 +110,6 @@ method RotateD<T>(a: array<T>) returns (r: array<T>)
r[if a.Length - 1 == i then 0 else i + 1] := a[Id(i)]; // yes, Dafny can invert this one
}
}
+
+// autoTriggers added because it causes a slight rephrasing of an error
+// message.
diff --git a/Test/dafny0/Inverses.dfy.expect b/Test/dafny0/Inverses.dfy.expect
index a04f21dc..b9530e3f 100644
--- a/Test/dafny0/Inverses.dfy.expect
+++ b/Test/dafny0/Inverses.dfy.expect
@@ -1,10 +1,12 @@
-Inverses.dfy(70,1): Error BP5003: A postcondition might not hold on this return path.
-Inverses.dfy(69,11): Related location: This is the postcondition that might not hold.
+Inverses.dfy(70,0): Error BP5003: A postcondition might not hold on this return path.
+Inverses.dfy(69,10): Related location: This is the postcondition that might not hold.
+Inverses.dfy(69,66): Related location
Execution trace:
(0,0): anon0
(0,0): anon6_Else
-Inverses.dfy(83,1): Error BP5003: A postcondition might not hold on this return path.
-Inverses.dfy(82,11): Related location: This is the postcondition that might not hold.
+Inverses.dfy(83,0): Error BP5003: A postcondition might not hold on this return path.
+Inverses.dfy(82,10): Related location: This is the postcondition that might not hold.
+Inverses.dfy(82,66): Related location
Execution trace:
(0,0): anon0
(0,0): anon9_Else
diff --git a/Test/dafny0/Iterators.dfy.expect b/Test/dafny0/Iterators.dfy.expect
index f0c6e400..d9129e3e 100644
--- a/Test/dafny0/Iterators.dfy.expect
+++ b/Test/dafny0/Iterators.dfy.expect
@@ -1,55 +1,55 @@
-Iterators.dfy(251,10): Error: failure to decrease termination measure
+Iterators.dfy(251,9): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
(0,0): anon5_Else
(0,0): anon6_Else
-Iterators.dfy(274,10): Error: failure to decrease termination measure
+Iterators.dfy(274,9): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
(0,0): anon5_Else
(0,0): anon6_Else
-Iterators.dfy(284,32): Error: failure to decrease termination measure
+Iterators.dfy(284,31): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
-Iterators.dfy(296,10): Error: cannot prove termination; try supplying a decreases clause
+Iterators.dfy(296,9): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
(0,0): anon5_Else
(0,0): anon6_Else
-Iterators.dfy(317,10): Error: cannot prove termination; try supplying a decreases clause
+Iterators.dfy(317,9): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
(0,0): anon5_Else
(0,0): anon6_Else
-Iterators.dfy(326,32): Error: cannot prove termination; try supplying a decreases clause
+Iterators.dfy(326,31): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
-Iterators.dfy(343,10): Error: failure to decrease termination measure
+Iterators.dfy(343,9): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
(0,0): anon5_Else
(0,0): anon6_Else
-Iterators.dfy(353,32): Error: cannot prove termination; try supplying a decreases clause
+Iterators.dfy(353,31): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
-Iterators.dfy(370,10): Error: failure to decrease termination measure
+Iterators.dfy(370,9): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
(0,0): anon5_Else
(0,0): anon6_Else
-Iterators.dfy(103,22): Error: assertion violation
+Iterators.dfy(103,21): Error: assertion violation
Execution trace:
(0,0): anon0
-Iterators.dfy(106,14): Error: assertion violation
+Iterators.dfy(106,13): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon4_Then
(0,0): anon3
-Iterators.dfy(177,28): Error: assertion violation
+Iterators.dfy(177,27): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon15_Then
-Iterators.dfy(208,7): Error: an assignment to _new is only allowed to shrink the set
+Iterators.dfy(208,6): Error: an assignment to _new is only allowed to shrink the set
Execution trace:
(0,0): anon0
Iterators.dfy(197,3): anon16_LoopHead
@@ -57,7 +57,7 @@ Execution trace:
Iterators.dfy(197,3): anon17_Else
Iterators.dfy(197,3): anon19_Else
(0,0): anon20_Then
-Iterators.dfy(212,21): Error: assertion violation
+Iterators.dfy(212,20): Error: assertion violation
Execution trace:
(0,0): anon0
Iterators.dfy(197,3): anon16_LoopHead
@@ -65,8 +65,8 @@ Execution trace:
Iterators.dfy(197,3): anon17_Else
Iterators.dfy(197,3): anon19_Else
(0,0): anon21_Then
-Iterators.dfy(40,22): Error BP5002: A precondition for this call might not hold.
-Iterators.dfy(4,10): Related location: This is the precondition that might not hold.
+Iterators.dfy(40,21): Error BP5002: A precondition for this call might not hold.
+Iterators.dfy(4,9): Related location: This is the precondition that might not hold.
Execution trace:
(0,0): anon0
(0,0): anon35_Then
@@ -74,24 +74,24 @@ Execution trace:
(0,0): anon36_Then
(0,0): anon5
(0,0): anon37_Then
-Iterators.dfy(89,14): Error: assertion violation
+Iterators.dfy(89,13): Error: assertion violation
Execution trace:
(0,0): anon0
-Iterators.dfy(119,16): Error: assertion violation
+Iterators.dfy(119,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Else
-Iterators.dfy(150,16): Error: assertion violation
+Iterators.dfy(150,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon4_Else
-Iterators.dfy(155,24): Error BP5002: A precondition for this call might not hold.
-Iterators.dfy(125,10): Related location: This is the precondition that might not hold.
+Iterators.dfy(155,23): Error BP5002: A precondition for this call might not hold.
+Iterators.dfy(125,9): Related location: This is the precondition that might not hold.
Execution trace:
(0,0): anon0
(0,0): anon4_Then
(0,0): anon3
-Iterators.dfy(234,21): Error: assertion violation
+Iterators.dfy(234,20): Error: assertion violation
Execution trace:
(0,0): anon0
Iterators.dfy(225,3): anon14_LoopHead
diff --git a/Test/dafny0/JustWarnings.dfy b/Test/dafny0/JustWarnings.dfy
new file mode 100644
index 00000000..86523f5b
--- /dev/null
+++ b/Test/dafny0/JustWarnings.dfy
@@ -0,0 +1,19 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /warnShadowing "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file tests the behavior where the Resolver reports some warnings
+// but no errors. In the case of errors, resolution does not continue
+// to clone modules and resolve them, but the cloning does proceed if there
+// are only warnings. Dafny should report only one copy of these warnings,
+// and warnings are therefore turned off when processing the clones. This
+// test file makes sure the warnings don't appear twice.
+
+method M(x: int)
+{
+ var x := 10; // warning: this shadows the parameter 'x'
+}
+
+class C<T> {
+ var u: T
+ method P<T>(t: T) // warning: this shadows the type parameter 'T'
+}
diff --git a/Test/dafny0/JustWarnings.dfy.expect b/Test/dafny0/JustWarnings.dfy.expect
new file mode 100644
index 00000000..5f0e66d8
--- /dev/null
+++ b/Test/dafny0/JustWarnings.dfy.expect
@@ -0,0 +1,4 @@
+JustWarnings.dfy(18,11): Warning: Shadowed type-parameter name: T
+JustWarnings.dfy(13,6): Warning: Shadowed local-variable name: x
+
+Dafny program verifier finished with 3 verified, 0 errors
diff --git a/Test/dafny0/LetExpr.dfy b/Test/dafny0/LetExpr.dfy
index b8d68bd6..6a0ca66b 100644
--- a/Test/dafny0/LetExpr.dfy
+++ b/Test/dafny0/LetExpr.dfy
@@ -1,4 +1,5 @@
-// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint.dfy" "%s" > "%t"; %dafny /noVerify /compile:0 "%t.dprint.dfy" >> "%t"
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint.dfy" /autoTriggers:0 "%s" > "%t"
+// RUN: %dafny /noVerify /compile:0 "%t.dprint.dfy" >> "%t"
// RUN: %diff "%s.expect" "%t"
method M0(n: int)
diff --git a/Test/dafny0/LetExpr.dfy.expect b/Test/dafny0/LetExpr.dfy.expect
index 36fc9361..8f365da3 100644
--- a/Test/dafny0/LetExpr.dfy.expect
+++ b/Test/dafny0/LetExpr.dfy.expect
@@ -1,39 +1,40 @@
-LetExpr.dfy(108,23): Error: assertion violation
+LetExpr.dfy(109,22): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon11_Then
-LetExpr.dfy(8,12): Error: assertion violation
+LetExpr.dfy(9,11): Error: assertion violation
Execution trace:
(0,0): anon0
-LetExpr.dfy(253,19): Error: value assigned to a nat must be non-negative
+LetExpr.dfy(254,18): Error: value assigned to a nat must be non-negative
Execution trace:
(0,0): anon0
(0,0): anon5_Then
-LetExpr.dfy(256,19): Error: value assigned to a nat must be non-negative
+LetExpr.dfy(257,18): Error: value assigned to a nat must be non-negative
Execution trace:
(0,0): anon0
(0,0): anon6_Then
-LetExpr.dfy(258,24): Error: value assigned to a nat must be non-negative
+LetExpr.dfy(259,23): Error: value assigned to a nat must be non-negative
Execution trace:
(0,0): anon0
(0,0): anon6_Else
-LetExpr.dfy(287,14): Error: RHS is not certain to look like the pattern 'Agnes'
+LetExpr.dfy(288,13): Error: RHS is not certain to look like the pattern 'Agnes'
Execution trace:
(0,0): anon0
(0,0): anon3_Else
-LetExpr.dfy(304,42): Error: value assigned to a nat must be non-negative
+LetExpr.dfy(305,41): Error: value assigned to a nat must be non-negative
Execution trace:
(0,0): anon0
- (0,0): anon6_Else
-LetExpr.dfy(306,12): Error: assertion violation
+ (0,0): anon7_Else
+LetExpr.dfy(307,11): Error: assertion violation
Execution trace:
(0,0): anon0
- (0,0): anon6_Else
-LetExpr.dfy(316,12): Error: to be compilable, the value of a let-such-that expression must be uniquely determined
+ (0,0): anon7_Else
+LetExpr.dfy(317,11): Error: to be compilable, the value of a let-such-that expression must be uniquely determined
Execution trace:
(0,0): anon0
(0,0): anon10_Then
Dafny program verifier finished with 39 verified, 9 errors
+LetExpr.dfy.tmp.dprint.dfy(162,2): Warning: /!\ No terms found to trigger on.
Dafny program verifier finished with 0 verified, 0 errors
diff --git a/Test/dafny0/LhsDuplicates.dfy b/Test/dafny0/LhsDuplicates.dfy
index 6a84c5a5..8a57f6ce 100644
--- a/Test/dafny0/LhsDuplicates.dfy
+++ b/Test/dafny0/LhsDuplicates.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
class MyClass<T> {
diff --git a/Test/dafny0/LhsDuplicates.dfy.expect b/Test/dafny0/LhsDuplicates.dfy.expect
index a864390f..d6689047 100644
--- a/Test/dafny0/LhsDuplicates.dfy.expect
+++ b/Test/dafny0/LhsDuplicates.dfy.expect
@@ -1,27 +1,27 @@
-LhsDuplicates.dfy(18,10): Error: left-hand sides for different forall-statement bound variables may refer to the same location
+LhsDuplicates.dfy(18,9): Error: left-hand sides for different forall-statement bound variables may refer to the same location
Execution trace:
(0,0): anon0
(0,0): anon16_Else
(0,0): anon18_Else
(0,0): anon21_Then
(0,0): anon13
-LhsDuplicates.dfy(34,12): Error: left-hand sides for different forall-statement bound variables may refer to the same location
+LhsDuplicates.dfy(34,11): Error: left-hand sides for different forall-statement bound variables may refer to the same location
Execution trace:
(0,0): anon0
(0,0): anon16_Else
(0,0): anon18_Else
(0,0): anon21_Then
(0,0): anon13
-LhsDuplicates.dfy(42,12): Error: when left-hand sides 1 and 3 refer to the same location, they must be assigned the same value
+LhsDuplicates.dfy(42,11): Error: when left-hand sides 1 and 3 refer to the same location, they must be assigned the same value
Execution trace:
(0,0): anon0
-LhsDuplicates.dfy(51,18): Error: when left-hand sides 0 and 2 refer to the same location, they must be assigned the same value
+LhsDuplicates.dfy(51,17): Error: when left-hand sides 0 and 2 refer to the same location, they must be assigned the same value
Execution trace:
(0,0): anon0
-LhsDuplicates.dfy(60,16): Error: when left-hand sides 1 and 2 may refer to the same location, they must be assigned the same value
+LhsDuplicates.dfy(60,15): Error: when left-hand sides 1 and 2 may refer to the same location, they must be assigned the same value
Execution trace:
(0,0): anon0
-LhsDuplicates.dfy(69,20): Error: when left-hand sides 1 and 2 refer to the same location, they must be assigned the same value
+LhsDuplicates.dfy(69,19): Error: when left-hand sides 1 and 2 refer to the same location, they must be assigned the same value
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/LitTriggers.dfy b/Test/dafny0/LitTriggers.dfy
new file mode 100644
index 00000000..93e65643
--- /dev/null
+++ b/Test/dafny0/LitTriggers.dfy
@@ -0,0 +1,39 @@
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:1 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// Imported from bug 76. LitInt would be triggered on, causing matching failures.
+
+predicate P(x:int, y:int)
+
+lemma L1(x:int, y:int)
+ requires y == 2;
+ requires forall i :: P(i, 3);
+{
+ assert P(x, y + 1);
+}
+
+lemma L2(x:int, y:int)
+ requires y == 2;
+ requires forall i {:trigger P(i, 3)} :: P(i, 3);
+{
+ assert P(x, y + 1);
+}
+
+lemma L3(x:int, y:int)
+ requires y == 2;
+ requires forall i :: P(i, 3);
+{
+ var dummy := 3;
+ assert P(x, y + 1);
+}
+
+lemma L4(x:int, y:int)
+ requires y == 2;
+ requires forall i, j :: j == 3 ==> P(i, j);
+{
+ assert P(x, y + 1);
+}
+
+// Local Variables:
+// dafny-prover-local-args: ("/autoTriggers:1")
+// End:
diff --git a/Test/dafny0/LitTriggers.dfy.expect b/Test/dafny0/LitTriggers.dfy.expect
new file mode 100644
index 00000000..249e77e5
--- /dev/null
+++ b/Test/dafny0/LitTriggers.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 9 verified, 0 errors
diff --git a/Test/dafny0/LoopModifies.dfy.expect b/Test/dafny0/LoopModifies.dfy.expect
index 682975fb..a7ded8a4 100644
--- a/Test/dafny0/LoopModifies.dfy.expect
+++ b/Test/dafny0/LoopModifies.dfy.expect
@@ -1,38 +1,38 @@
-LoopModifies.dfy(8,5): Error: assignment may update an array element not in the enclosing context's modifies clause
+LoopModifies.dfy(8,4): Error: assignment may update an array element not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
-LoopModifies.dfy(19,8): Error: assignment may update an array element not in the enclosing context's modifies clause
+LoopModifies.dfy(19,7): Error: assignment may update an array element not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
LoopModifies.dfy(16,4): anon8_LoopHead
(0,0): anon8_LoopBody
LoopModifies.dfy(16,4): anon9_Else
LoopModifies.dfy(16,4): anon11_Else
-LoopModifies.dfy(48,8): Error: assignment may update an array element not in the enclosing context's modifies clause
+LoopModifies.dfy(48,7): Error: assignment may update an array element not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
LoopModifies.dfy(44,4): anon8_LoopHead
(0,0): anon8_LoopBody
LoopModifies.dfy(44,4): anon9_Else
LoopModifies.dfy(44,4): anon11_Else
-LoopModifies.dfy(63,8): Error: assignment may update an array element not in the enclosing context's modifies clause
+LoopModifies.dfy(63,7): Error: assignment may update an array element not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
LoopModifies.dfy(59,4): anon9_LoopHead
(0,0): anon9_LoopBody
LoopModifies.dfy(59,4): anon10_Else
LoopModifies.dfy(59,4): anon12_Else
-LoopModifies.dfy(76,4): Error: loop modifies clause may violate context's modifies clause
+LoopModifies.dfy(76,3): Error: loop modifies clause may violate context's modifies clause
Execution trace:
(0,0): anon0
-LoopModifies.dfy(100,8): Error: assignment may update an array element not in the enclosing context's modifies clause
+LoopModifies.dfy(100,7): Error: assignment may update an array element not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
LoopModifies.dfy(92,4): anon8_LoopHead
(0,0): anon8_LoopBody
LoopModifies.dfy(92,4): anon9_Else
LoopModifies.dfy(92,4): anon11_Else
-LoopModifies.dfy(148,11): Error: assignment may update an array element not in the enclosing context's modifies clause
+LoopModifies.dfy(148,10): Error: assignment may update an array element not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
LoopModifies.dfy(136,4): anon17_LoopHead
@@ -43,14 +43,14 @@ Execution trace:
(0,0): anon21_LoopBody
LoopModifies.dfy(141,7): anon22_Else
LoopModifies.dfy(141,7): anon24_Else
-LoopModifies.dfy(199,10): Error: assignment may update an array element not in the enclosing context's modifies clause
+LoopModifies.dfy(199,9): Error: assignment may update an array element not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
LoopModifies.dfy(195,4): anon8_LoopHead
(0,0): anon8_LoopBody
LoopModifies.dfy(195,4): anon9_Else
LoopModifies.dfy(195,4): anon11_Else
-LoopModifies.dfy(287,13): Error: assignment may update an array element not in the enclosing context's modifies clause
+LoopModifies.dfy(287,12): Error: assignment may update an array element not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
LoopModifies.dfy(275,4): anon16_LoopHead
diff --git a/Test/dafny0/Maps.dfy.expect b/Test/dafny0/Maps.dfy.expect
index f46549dd..8b4a6a36 100644
--- a/Test/dafny0/Maps.dfy.expect
+++ b/Test/dafny0/Maps.dfy.expect
@@ -1,7 +1,7 @@
-Maps.dfy(78,8): Error: element may not be in domain
+Maps.dfy(78,7): Error: element may not be in domain
Execution trace:
(0,0): anon0
-Maps.dfy(128,13): Error: assertion violation
+Maps.dfy(128,12): Error: assertion violation
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/Matrix-OOB.dfy b/Test/dafny0/Matrix-OOB.dfy
new file mode 100644
index 00000000..d7aacd79
--- /dev/null
+++ b/Test/dafny0/Matrix-OOB.dfy
@@ -0,0 +1,13 @@
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This is a regression test: OOB errors for matrices used to be reported on the
+// quantifier that introduced the variables that constituted the invalid indices.
+
+// WISH: It would be even better to report the error on the variables inside the
+// array instead of the array itself.
+
+method M(m: array2<int>)
+ requires m != null
+ ensures forall i, j :: m[i, j] == 0
+{ }
diff --git a/Test/dafny0/Matrix-OOB.dfy.expect b/Test/dafny0/Matrix-OOB.dfy.expect
new file mode 100644
index 00000000..e2920445
--- /dev/null
+++ b/Test/dafny0/Matrix-OOB.dfy.expect
@@ -0,0 +1,14 @@
+Matrix-OOB.dfy(12,10): Info: Selected triggers: {m[i, j]}
+Matrix-OOB.dfy(12,26): Error: index 0 out of range
+Execution trace:
+ (0,0): anon0
+Matrix-OOB.dfy(12,26): Error: index 1 out of range
+Execution trace:
+ (0,0): anon0
+Matrix-OOB.dfy(13,0): Error BP5003: A postcondition might not hold on this return path.
+Matrix-OOB.dfy(12,10): Related location: This is the postcondition that might not hold.
+Matrix-OOB.dfy(12,33): Related location
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 0 verified, 3 errors
diff --git a/Test/dafny0/ModifyStmt.dfy.expect b/Test/dafny0/ModifyStmt.dfy.expect
index 4ea872e0..019453d1 100644
--- a/Test/dafny0/ModifyStmt.dfy.expect
+++ b/Test/dafny0/ModifyStmt.dfy.expect
@@ -1,19 +1,19 @@
-ModifyStmt.dfy(27,14): Error: assertion violation
+ModifyStmt.dfy(27,13): Error: assertion violation
Execution trace:
(0,0): anon0
-ModifyStmt.dfy(42,5): Error: modify statement may violate context's modifies clause
+ModifyStmt.dfy(42,4): Error: modify statement may violate context's modifies clause
Execution trace:
(0,0): anon0
-ModifyStmt.dfy(48,5): Error: modify statement may violate context's modifies clause
+ModifyStmt.dfy(48,4): Error: modify statement may violate context's modifies clause
Execution trace:
(0,0): anon0
-ModifyStmt.dfy(61,5): Error: modify statement may violate context's modifies clause
+ModifyStmt.dfy(61,4): Error: modify statement may violate context's modifies clause
Execution trace:
(0,0): anon0
-ModifyStmt.dfy(70,14): Error: assertion violation
+ModifyStmt.dfy(70,13): Error: assertion violation
Execution trace:
(0,0): anon0
-ModifyStmt.dfy(89,14): Error: assertion violation
+ModifyStmt.dfy(89,13): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon9_Then
@@ -22,20 +22,20 @@ Execution trace:
ModifyStmt.dfy(81,7): anon11_Else
(0,0): anon12_Then
(0,0): anon8
-ModifyStmt.dfy(99,14): Error: assertion violation
+ModifyStmt.dfy(99,13): Error: assertion violation
Execution trace:
(0,0): anon0
-ModifyStmt.dfy(110,14): Error: assertion violation
+ModifyStmt.dfy(110,13): Error: assertion violation
Execution trace:
(0,0): anon0
-ModifyStmt.dfy(122,16): Error: assertion violation
+ModifyStmt.dfy(122,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-ModifyStmt.dfy(134,7): Error: assignment may update an object not in the enclosing context's modifies clause
+ModifyStmt.dfy(134,6): Error: assignment may update an object not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
-ModifyStmt.dfy(172,15): Error: assertion violation
+ModifyStmt.dfy(172,14): Error: assertion violation
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/ModuleExport.dfy b/Test/dafny0/ModuleExport.dfy
new file mode 100644
index 00000000..1e69764f
--- /dev/null
+++ b/Test/dafny0/ModuleExport.dfy
@@ -0,0 +1,105 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+module A {
+ default export Public { f, h}
+ export E1 { f, g}
+ export E2 extends Public, E1 {T}
+ export Friend extends Public {g, T}
+ export Fruit {Data}
+
+ method h() {}
+ function f(): int { 818 }
+ function g() : int { 819 }
+ function k() : int { 820 }
+
+ class T
+ {
+ static method l() {}
+ }
+
+ datatype Data = Lemon | Kiwi(int)
+
+}
+
+module B {
+ import X = A.Public
+ method m() {
+ X.h(); // OK
+ assert X.f() == 818; // OK
+ assert X.g() == 819; // error
+ assert X.k() == 820; // error
+ X.T.l(); // error
+ }
+}
+
+module C {
+ import X = A.Friend
+ method m() {
+ X.h(); // OK
+ assert X.f() == 818; // OK
+ assert X.g() == 819; // OK
+ assert X.k() == 820; // error
+ X.T.l(); // OK
+ }
+}
+
+module D {
+ import opened A
+ method m() {
+ h(); // OK
+ assert f() == 818; // OK
+ assert g() == 819; // error
+ assert k() == 820; // error
+ }
+}
+
+module E {
+ import opened A.Fruit
+
+ function G(d: Data): int
+ requires d != Data.Lemon
+ {
+ match d
+ case Lemon => G(d)
+ case Kiwi(x) => 7
+ case Orang => 8 // error
+ }
+}
+
+module F {
+ default export Public { f, h}
+ default export E1 { f, g}
+ export E2 extends Public2, E1 {T} // error: Public2 is not a exported view of F
+ export Friend extends Public {g2, T} // error: g2 is not a member of F
+ export Fruit {Data}
+
+ method h() {}
+ function f(): int { 818 }
+ function g() : int { 819 }
+ function k() : int { 820 }
+
+ class T
+ {
+ static method l() {}
+ }
+
+ datatype Data = Lemon | Kiwi(int)
+}
+
+module G {
+ export Public { f, h}
+
+ method h() {}
+ function f(): int { 818 }
+ function g() : int { 819 }
+ function k() : int { 820 }
+}
+
+module H {
+ import G // error: G has no default export
+}
+
+module I {
+ import G.Public // OK
+} \ No newline at end of file
diff --git a/Test/dafny0/ModuleExport.dfy.expect b/Test/dafny0/ModuleExport.dfy.expect
new file mode 100644
index 00000000..274c8f31
--- /dev/null
+++ b/Test/dafny0/ModuleExport.dfy.expect
@@ -0,0 +1,13 @@
+ModuleExport.dfy(30,11): Error: unresolved identifier: g
+ModuleExport.dfy(31,11): Error: unresolved identifier: k
+ModuleExport.dfy(32,4): Error: unresolved identifier: T
+ModuleExport.dfy(32,7): Error: expected method call, found expression
+ModuleExport.dfy(42,11): Error: unresolved identifier: k
+ModuleExport.dfy(52,9): Error: unresolved identifier: g
+ModuleExport.dfy(53,9): Error: unresolved identifier: k
+ModuleExport.dfy(66,2): Error: member Orang does not exist in datatype Data
+ModuleExport.dfy(70,7): Error: Public2 must be an export of F to be extended
+ModuleExport.dfy(74,9): Error: g2 must be a member of F to be exported
+ModuleExport.dfy(70,7): Error: more than one default export declared in module F
+ModuleExport.dfy(90,7): Error: no default export declared in module: G
+12 resolution/type errors detected in ModuleExport.dfy
diff --git a/Test/dafny0/Modules0.dfy b/Test/dafny0/Modules0.dfy
index 34aba3de..4b86d848 100644
--- a/Test/dafny0/Modules0.dfy
+++ b/Test/dafny0/Modules0.dfy
@@ -71,16 +71,17 @@ module X1 {
}
module X2 {
+ import opened X1
class MyClass2 {
- method Down(x1: MyClass1, x0: MyClass0) {
+ method Down(x1: MyClass1, x0: X0'.MyClass0) {
x1.Down(x0);
}
- method WayDown(x0: MyClass0) {
+ method WayDown(x0: X0'.MyClass0) {
x0.Down();
}
method Up() {
}
- method Somewhere(y: MyClassY) {
+ method Somewhere(y: MyClassY) { // error: no such type in scope
y.M();
}
}
@@ -97,8 +98,7 @@ module YY {
class ClassG {
method T() { }
function method TFunc(): int { 10 }
- method V(y: MyClassY) { // Note, MyClassY is in scope, since we are in the _default
- // module, which imports everything
+ method V(y: MyClassY) {
y.M();
}
}
@@ -141,10 +141,10 @@ class AClassWithSomeField {
SomeField := SomeField + 4;
var a := old(SomeField); // error: old can only be used in ghost contexts
var b := fresh(this); // error: fresh can only be used in ghost contexts
- var c := allocated(this); // error: allocated can only be used in ghost contexts
+// var c := allocated(this); // error: allocated can only be used in ghost contexts
if (fresh(this)) { // this guard makes the if statement a ghost statement
ghost var x := old(SomeField); // this is a ghost context, so it's okay
- ghost var y := allocated(this); // this is a ghost context, so it's okay
+// ghost var y := allocated(this); // this is a ghost context, so it's okay
}
}
}
@@ -335,3 +335,15 @@ module TopLevelStatics {
static method M() // error/warning: static keyword does not belong here
{ }
}
+
+module Library {
+ class T { }
+}
+
+module AA {
+ import opened Library
+}
+
+module B refines AA {
+ datatype T = MakeT(int) // illegal
+}
diff --git a/Test/dafny0/Modules0.dfy.expect b/Test/dafny0/Modules0.dfy.expect
index 5d11f9c9..f51e0f6c 100644
--- a/Test/dafny0/Modules0.dfy.expect
+++ b/Test/dafny0/Modules0.dfy.expect
@@ -1,27 +1,22 @@
-Modules0.dfy(333,3): warning: module-level functions are always non-instance, so the 'static' keyword is not allowed here
-Modules0.dfy(335,3): warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+Modules0.dfy(333,2): Warning: module-level functions are always non-instance, so the 'static' keyword is not allowed here
+Modules0.dfy(335,2): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
Modules0.dfy(8,8): Error: Duplicate name of top-level declaration: WazzupA
Modules0.dfy(9,11): Error: Duplicate name of top-level declaration: WazzupA
Modules0.dfy(10,7): Error: Duplicate name of top-level declaration: WazzupA
Modules0.dfy(13,7): Error: Duplicate name of top-level declaration: WazzupB
Modules0.dfy(14,8): Error: Duplicate name of top-level declaration: WazzupB
Modules0.dfy(15,11): Error: Duplicate name of top-level declaration: WazzupB
-Modules0.dfy(56,21): Error: Undeclared top-level type or type parameter: MyClass1 (did you forget to qualify a name?)
-Modules0.dfy(57,21): Error: Undeclared top-level type or type parameter: MyClass2 (did you forget to qualify a name?)
-Modules0.dfy(68,21): Error: Undeclared top-level type or type parameter: MyClass2 (did you forget to qualify a name?)
-Modules0.dfy(76,9): Error: type MyClass1 does not have a member Down
-Modules0.dfy(76,13): Error: expected method call, found expression
-Modules0.dfy(79,9): Error: type MyClass0 does not have a member Down
-Modules0.dfy(79,13): Error: expected method call, found expression
-Modules0.dfy(84,8): Error: type MyClassY does not have a member M
-Modules0.dfy(84,9): Error: expected method call, found expression
-Modules0.dfy(92,19): Error: Undeclared top-level type or type parameter: ClassG (did you forget to qualify a name?)
-Modules0.dfy(226,15): Error: Undeclared top-level type or type parameter: X (did you forget to qualify a name?)
+Modules0.dfy(56,21): Error: Undeclared top-level type or type parameter: MyClass1 (did you forget to qualify a name or declare a module import 'opened?')
+Modules0.dfy(57,21): Error: Undeclared top-level type or type parameter: MyClass2 (did you forget to qualify a name or declare a module import 'opened?')
+Modules0.dfy(68,21): Error: Undeclared top-level type or type parameter: MyClass2 (did you forget to qualify a name or declare a module import 'opened?')
+Modules0.dfy(84,24): Error: Undeclared top-level type or type parameter: MyClassY (did you forget to qualify a name or declare a module import 'opened?')
+Modules0.dfy(93,19): Error: Undeclared top-level type or type parameter: ClassG (did you forget to qualify a name or declare a module import 'opened?')
+Modules0.dfy(226,15): Error: Undeclared top-level type or type parameter: X (did you forget to qualify a name or declare a module import 'opened?')
Modules0.dfy(226,8): Error: new can be applied only to reference types (got X)
Modules0.dfy(235,13): Error: module 'B' does not declare a type 'X'
Modules0.dfy(245,13): Error: unresolved identifier: X
Modules0.dfy(246,15): Error: member DoesNotExist does not exist in class X
-Modules0.dfy(285,19): Error: Undeclared top-level type or type parameter: D (did you forget to qualify a name?)
+Modules0.dfy(285,19): Error: Undeclared top-level type or type parameter: D (did you forget to qualify a name or declare a module import 'opened?')
Modules0.dfy(285,12): Error: new can be applied only to reference types (got D)
Modules0.dfy(288,25): Error: type of the receiver is not fully determined at this program point
Modules0.dfy(289,16): Error: type of the receiver is not fully determined at this program point
@@ -30,16 +25,11 @@ Modules0.dfy(290,16): Error: type of the receiver is not fully determined at thi
Modules0.dfy(290,17): Error: expected method call, found expression
Modules0.dfy(314,18): Error: second argument to "in" must be a set, multiset, or sequence with elements of type Q_Imp.Node, or a map with domain Q_Imp.Node (instead got set<Node>)
Modules0.dfy(318,13): Error: arguments must have the same type (got Q_Imp.Node and Node)
-Modules0.dfy(319,11): Error: Undeclared top-level type or type parameter: LongLostModule (did you forget to qualify a name?)
-Modules0.dfy(320,11): Error: Undeclared top-level type or type parameter: Wazzup (did you forget to qualify a name?)
+Modules0.dfy(319,11): Error: Undeclared top-level type or type parameter: LongLostModule (did you forget to qualify a name or declare a module import 'opened?')
+Modules0.dfy(320,11): Error: Undeclared top-level type or type parameter: Wazzup (did you forget to qualify a name or declare a module import 'opened?')
Modules0.dfy(321,17): Error: module 'Q_Imp' does not declare a type 'Edon'
Modules0.dfy(323,10): Error: new can be applied only to reference types (got Q_Imp.List<?>)
Modules0.dfy(324,30): Error: member Create does not exist in class Klassy
-Modules0.dfy(102,6): Error: type MyClassY does not have a member M
-Modules0.dfy(102,7): Error: expected method call, found expression
-Modules0.dfy(127,11): Error: ghost variables are allowed only in specification contexts
-Modules0.dfy(142,13): Error: old expressions are allowed only in specification and ghost contexts
-Modules0.dfy(143,13): Error: fresh expressions are allowed only in specification and ghost contexts
-Modules0.dfy(144,13): Error: unresolved identifier: allocated
-Modules0.dfy(147,21): Error: unresolved identifier: allocated
-42 resolution/type errors detected in Modules0.dfy
+Modules0.dfy(348,11): Error: a datatype declaration (T) in a refinement module can only replace an opaque type declaration
+Modules0.dfy(101,14): Error: Undeclared top-level type or type parameter: MyClassY (did you forget to qualify a name or declare a module import 'opened?')
+32 resolution/type errors detected in Modules0.dfy
diff --git a/Test/dafny0/Modules1.dfy b/Test/dafny0/Modules1.dfy
index 505d9b74..3025cc00 100644
--- a/Test/dafny0/Modules1.dfy
+++ b/Test/dafny0/Modules1.dfy
@@ -125,11 +125,11 @@ abstract module Regression {
predicate p<c,d>(m: map<c,d>)
lemma m<a,b>(m: map<a,b>)
- ensures exists m :: p(var m : map<a,b> := m; m);
+ ensures exists m {:nowarn} :: p(var m : map<a,b> := m; m) // WISH: Zeta-expanding the let binding would provide a good trigger
}
abstract module B
{
- import X as A
+ import X : A
}
}
diff --git a/Test/dafny0/Modules1.dfy.expect b/Test/dafny0/Modules1.dfy.expect
index 342b5808..feddf46a 100644
--- a/Test/dafny0/Modules1.dfy.expect
+++ b/Test/dafny0/Modules1.dfy.expect
@@ -1,20 +1,20 @@
-Modules1.dfy(79,16): Error: assertion violation
+Modules1.dfy(79,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-Modules1.dfy(92,16): Error: assertion violation
+Modules1.dfy(92,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-Modules1.dfy(94,18): Error: assertion violation
+Modules1.dfy(94,17): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Else
-Modules1.dfy(56,9): Error: decreases expression must be bounded below by 0
-Modules1.dfy(54,13): Related location
+Modules1.dfy(56,8): Error: decreases expression must be bounded below by 0
+Modules1.dfy(54,12): Related location
Execution trace:
(0,0): anon0
-Modules1.dfy(62,9): Error: failure to decrease termination measure
+Modules1.dfy(62,8): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/Modules2.dfy b/Test/dafny0/Modules2.dfy
index a8dde8ce..beb80546 100644
--- a/Test/dafny0/Modules2.dfy
+++ b/Test/dafny0/Modules2.dfy
@@ -31,7 +31,7 @@ module Test {
}
module Test2 {
- import opened B as A
+ import opened B : A
method m() {
var c := new C; // fine, as A was opened
var c' := new B.C;// also fine, as A is bound
diff --git a/Test/dafny0/MultiDimArray.dfy.expect b/Test/dafny0/MultiDimArray.dfy.expect
index 597ade30..f2bf74de 100644
--- a/Test/dafny0/MultiDimArray.dfy.expect
+++ b/Test/dafny0/MultiDimArray.dfy.expect
@@ -1,9 +1,9 @@
-MultiDimArray.dfy(56,21): Error: assertion violation
+MultiDimArray.dfy(56,20): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon11_Then
(0,0): anon12_Then
-MultiDimArray.dfy(83,25): Error: assertion violation
+MultiDimArray.dfy(83,24): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon5_Then
diff --git a/Test/dafny0/MultiSets.dfy b/Test/dafny0/MultiSets.dfy
index 3535f857..ba075fc3 100644
--- a/Test/dafny0/MultiSets.dfy
+++ b/Test/dafny0/MultiSets.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
method test1()
@@ -295,3 +295,6 @@ lemma Set_and_Multiset_Cardinalities(x: int, y: int)
assert |multiset{x,y}| == 2;
}
}
+
+// AutoTriggers explicitly removed, as simplifications of set expressions such
+// as x in {1,2} cause invalid terms to appear in the triggers
diff --git a/Test/dafny0/MultiSets.dfy.expect b/Test/dafny0/MultiSets.dfy.expect
index 30534b11..aed70bd2 100644
--- a/Test/dafny0/MultiSets.dfy.expect
+++ b/Test/dafny0/MultiSets.dfy.expect
@@ -1,24 +1,24 @@
-MultiSets.dfy(159,3): Error BP5003: A postcondition might not hold on this return path.
-MultiSets.dfy(158,15): Related location: This is the postcondition that might not hold.
+MultiSets.dfy(159,2): Error BP5003: A postcondition might not hold on this return path.
+MultiSets.dfy(158,14): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-MultiSets.dfy(165,3): Error BP5003: A postcondition might not hold on this return path.
-MultiSets.dfy(164,15): Related location: This is the postcondition that might not hold.
+MultiSets.dfy(165,2): Error BP5003: A postcondition might not hold on this return path.
+MultiSets.dfy(164,14): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-MultiSets.dfy(178,11): Error: new number of occurrences might be negative
+MultiSets.dfy(178,10): Error: new number of occurrences might be negative
Execution trace:
(0,0): anon0
(0,0): anon4_Then
(0,0): anon3
-MultiSets.dfy(269,24): Error: assertion violation
+MultiSets.dfy(269,23): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon11_Then
(0,0): anon3
(0,0): anon12_Then
(0,0): anon14_Else
-MultiSets.dfy(292,16): Error: assertion violation
+MultiSets.dfy(292,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon8_Then
diff --git a/Test/dafny0/NatTypes.dfy.expect b/Test/dafny0/NatTypes.dfy.expect
index 99fa16e5..2bc00e95 100644
--- a/Test/dafny0/NatTypes.dfy.expect
+++ b/Test/dafny0/NatTypes.dfy.expect
@@ -1,43 +1,43 @@
-NatTypes.dfy(35,12): Error: value assigned to a nat must be non-negative
+NatTypes.dfy(35,11): Error: value assigned to a nat must be non-negative
Execution trace:
(0,0): anon0
NatTypes.dfy(23,5): anon10_LoopHead
(0,0): anon10_LoopBody
NatTypes.dfy(23,5): anon11_Else
(0,0): anon12_Then
-NatTypes.dfy(10,5): Error: value assigned to a nat must be non-negative
+NatTypes.dfy(10,4): Error: value assigned to a nat must be non-negative
Execution trace:
(0,0): anon0
-NatTypes.dfy(43,14): Error: assertion violation
+NatTypes.dfy(43,13): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon4_Then
-NatTypes.dfy(45,14): Error: assertion violation
+NatTypes.dfy(45,13): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon4_Then
-NatTypes.dfy(62,16): Error: assertion violation
+NatTypes.dfy(62,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-NatTypes.dfy(76,16): Error: assertion violation
+NatTypes.dfy(76,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon5_Else
(0,0): anon6_Then
-NatTypes.dfy(94,22): Error: value assigned to a nat must be non-negative
+NatTypes.dfy(94,21): Error: value assigned to a nat must be non-negative
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-NatTypes.dfy(109,45): Error: value assigned to a nat must be non-negative
+NatTypes.dfy(109,44): Error: value assigned to a nat must be non-negative
Execution trace:
(0,0): anon0
- (0,0): anon6_Else
- (0,0): anon7_Else
- (0,0): anon8_Then
-NatTypes.dfy(132,35): Error: value assigned to a nat must be non-negative
+ (0,0): anon8_Else
+ (0,0): anon9_Else
+ (0,0): anon10_Then
+NatTypes.dfy(132,34): Error: value assigned to a nat must be non-negative
Execution trace:
(0,0): anon0
- (0,0): anon3_Then
+ (0,0): anon4_Then
Dafny program verifier finished with 15 verified, 9 errors
diff --git a/Test/dafny0/NestedMatch.dfy b/Test/dafny0/NestedMatch.dfy
new file mode 100644
index 00000000..81319b4a
--- /dev/null
+++ b/Test/dafny0/NestedMatch.dfy
@@ -0,0 +1,59 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+datatype Nat = Zero | Suc(Nat)
+
+predicate Even(n: Nat)
+{
+ match n
+ case Zero => true
+ case Suc(Zero) => false
+ case Suc(Suc(p)) => Even(p)
+}
+
+
+method checkEven(n: Nat) {
+ assert Even(Zero) == true;
+ assert Even(Suc(Zero)) == false;
+ assert Even(Suc(Suc(n))) == Even(n);
+}
+
+datatype List<T> = Nil | Cons(T, List<T>)
+
+function last<T>(xs: List<T>): T
+ requires xs != Nil
+{
+ match xs
+ case Cons(y, Nil) => y
+ case Cons(y, Cons(z, zs)) => last(Cons(z, zs))
+}
+
+method checkLast<T>(y: T) {
+ assert last(Cons(y, Nil)) == y;
+ assert last(Cons(y, Cons(y, Nil))) == last(Cons(y, Nil));
+}
+
+
+function minus(x: Nat, y: Nat): Nat
+{
+ match (x, y)
+ case (Zero, _) => Zero
+ case (Suc(_), Zero) => x
+ case (Suc(a), Suc(b)) => minus(a, b)
+}
+
+method checkMinus(x:Nat, y: Nat) {
+ assert minus(Suc(x), Suc(y)) == minus(x,y);
+}
+
+
+// nested match statement
+method Last<T>(xs: List<T>) returns (x: T)
+ requires xs != Nil
+{
+
+ match xs {
+ case Cons(y, Nil) => x:= y;
+ case Cons(y, Cons(z, zs)) => x:=Last(Cons(z, zs));
+ }
+}
diff --git a/Test/dafny0/NestedMatch.dfy.expect b/Test/dafny0/NestedMatch.dfy.expect
new file mode 100644
index 00000000..f3a9c95f
--- /dev/null
+++ b/Test/dafny0/NestedMatch.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 11 verified, 0 errors
diff --git a/Test/dafny0/NestedPatterns.dfy b/Test/dafny0/NestedPatterns.dfy
new file mode 100644
index 00000000..d1d88b2a
--- /dev/null
+++ b/Test/dafny0/NestedPatterns.dfy
@@ -0,0 +1,124 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+datatype List<T> = Nil | Cons(head: T, tail: List<T>)
+
+method MethodA<T>(xs: List<T>) returns (ys: List<T>)
+{
+ match xs
+ case Nil =>
+ ys := Nil;
+ case Cons(h, Nil) =>
+ ys := Nil;
+ case Cons(h, Cons(h', tt)) =>
+ ys := tt;
+}
+
+method MethodB<T>(xs: List<T>)
+{
+ match xs
+ case Nil =>
+ case Cons(h, Nil) =>
+ var x := 12;
+ var xxs := Cons(Nil, Nil);
+ case Cons(h, Cons(h', tt)) =>
+}
+
+method MethodC<T>(xs: List<T>) returns (ys: List<T>)
+ requires xs.Cons? ==> !xs.tail.Cons?;
+{
+ match xs
+ case Nil =>
+ ys := Nil;
+ case Cons(h, Nil) =>
+ ys := Nil;
+}
+
+method MethodD<T>(xs: List<T>) returns (ys: List<T>)
+{
+ match xs
+ case Nil =>
+ ys := Nil;
+ case Cons(h, Nil) =>
+ var xxs: List<List<T>> := Cons(Nil, Nil); // BUG: type inference is not doing the right thing on this lint
+ case Cons(h, Cons(h0, tt)) =>
+}
+
+method MethodE<T>(xs: List<T>) returns (ys: List<T>)
+{
+ var xxs: List<List<T>> := Cons(Nil, Nil); // here it works! (but the same line in MethodD does not work)
+}
+
+method MethodF<T>(xs: List<T>) returns (ys: List<T>)
+ requires xs.Cons? ==> !xs.tail.Cons?;
+{
+ match xs
+ case Nil =>
+ case Cons(h, Nil) =>
+ case Cons(h0, Cons(h1, tt)) => // BUG: Dafny complains that Cons appears in more than one case; it seems to be due to the
+ // fact that the previous case uses identifier "h" as the first argument to Cons, whereas this
+ // line uses "h0"
+}
+
+method MethodG<T>(xs: List<T>) returns (xxs: List<List<T>>)
+{
+ match xs
+ case Nil =>
+ xxs := Cons(Nil, Nil); // BUG: this causes there to be an "unresolved identifier: _mc#0" error; oddly enough, the error goes away if the third case is commented out
+ case Cons(h, t) =>
+ case Cons(h, Cons(ht, tt)) =>
+}
+
+method AssertionFailure(xs: List)
+{
+ match xs
+ case (Nil) => // BUG: this line causes an assertion in the Dafny implementation (what should happen is that "(Nil)" should not be allowed here)
+ case (Cons(h, t)) => // BUG: ditto
+}
+
+method DuplicateIdentifierInPattern0<T>(xs: List<T>)
+{
+ match xs
+ case Nil =>
+ case Cons(h, Nil) =>
+ case Cons(h, Cons(_, h)) => // BUG: this duplicate identifier name should give rise to an error (from the Resolver), but no error is reported
+}
+
+method DuplicateIdentifierInPattern1<T>(xs: List<T>)
+{
+ match xs
+ case Nil =>
+ case Cons(h, Nil) =>
+ case Cons(h, Cons(h, _)) => // BUG: this duplicate identifier name should give rise to an error (from the Resolver), but no error is reported
+}
+
+method DuplicateIdentifierInPattern2<T>(xs: List<T>)
+{
+ match xs
+ case Nil =>
+ case Cons(h, Nil) =>
+ case Cons(h, Cons(e, e)) => // BUG: here, the duplicate identifier is detected, but the error message is shown 3 times, which is less than ideal
+}
+
+method Tuples0(xs: List, ys: List)
+{
+ match (xs, ys)
+ case (Nil, Nil) =>
+ case (Cons(a, b), Nil) =>
+ case (Nil, Cons(x, y)) =>
+ case (Cons(a, b), Cons(x, y)) => // BUG: here and in some other places above, not all identifiers are highlighted in the Dafny IDE; it looks like
+ // only the identifiers in the last constructors are
+}
+
+method Tuples1(xs: List, ys: List)
+{
+ match (xs, ys, 4)
+ case (Nil, Nil) => // BUG: the mismatch of 3 versus 2 arguments in the previous line and this line causes Dafny to crash with an
+ // assertion failure "mc.CasePatterns.Count == e.Arguments.Count"
+}
+
+method Tuples2(xs: List, ys: List)
+{
+ match (xs, ys, ())
+ case (Nil, Nil, ()) => // BUG: Dafny crashes with an assertion failure "e.Arguments.Count >= 1"
+}
diff --git a/Test/dafny0/NestedPatterns.dfy.expect b/Test/dafny0/NestedPatterns.dfy.expect
new file mode 100644
index 00000000..d83a7da1
--- /dev/null
+++ b/Test/dafny0/NestedPatterns.dfy.expect
@@ -0,0 +1,9 @@
+NestedPatterns.dfy(69,2): Error: member Cons appears in more than one case
+NestedPatterns.dfy(75,2): Error: member does not exist in datatype List
+NestedPatterns.dfy(76,2): Error: member does not exist in datatype List
+NestedPatterns.dfy(84,23): Error: Duplicate parameter name: h
+NestedPatterns.dfy(92,20): Error: Duplicate parameter name: h
+NestedPatterns.dfy(100,23): Error: Duplicate parameter name: e
+NestedPatterns.dfy(116,2): Error: case arguments count does not match source arguments count
+NestedPatterns.dfy(122,2): Error: match source tuple needs at least 1 argument
+8 resolution/type errors detected in NestedPatterns.dfy
diff --git a/Test/dafny0/Newtypes.dfy.expect b/Test/dafny0/Newtypes.dfy.expect
index 8e6ff4c5..425ee9a9 100644
--- a/Test/dafny0/Newtypes.dfy.expect
+++ b/Test/dafny0/Newtypes.dfy.expect
@@ -1,54 +1,54 @@
-Newtypes.dfy(74,11): Error: cannot find witness that shows type is inhabited (sorry, for now, only tried 0)
+Newtypes.dfy(74,10): Error: cannot find witness that shows type is inhabited (sorry, for now, only tried 0)
Execution trace:
(0,0): anon0
-Newtypes.dfy(76,45): Error: possible division by zero
+Newtypes.dfy(76,44): Error: possible division by zero
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-Newtypes.dfy(87,14): Error: result of operation might violate newtype constraint
+Newtypes.dfy(87,13): Error: result of operation might violate newtype constraint
Execution trace:
(0,0): anon0
-Newtypes.dfy(95,12): Error: result of operation might violate newtype constraint
+Newtypes.dfy(95,11): Error: result of operation might violate newtype constraint
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-Newtypes.dfy(97,14): Error: result of operation might violate newtype constraint
+Newtypes.dfy(97,13): Error: result of operation might violate newtype constraint
Execution trace:
(0,0): anon0
(0,0): anon3_Else
-Newtypes.dfy(104,16): Error: result of operation might violate newtype constraint
+Newtypes.dfy(104,15): Error: result of operation might violate newtype constraint
Execution trace:
(0,0): anon0
-Newtypes.dfy(177,14): Error: result of operation might violate newtype constraint
+Newtypes.dfy(177,13): Error: result of operation might violate newtype constraint
Execution trace:
(0,0): anon0
-Newtypes.dfy(193,64): Error: index 0 out of range
+Newtypes.dfy(193,63): Error: index 0 out of range
Execution trace:
(0,0): anon0
(0,0): anon32_Then
(0,0): anon33_Then
(0,0): anon16
-Newtypes.dfy(194,67): Error: index 1 out of range
+Newtypes.dfy(194,66): Error: index 1 out of range
Execution trace:
(0,0): anon0
(0,0): anon34_Then
(0,0): anon35_Then
(0,0): anon19
-Newtypes.dfy(222,16): Error: new number of occurrences might be negative
+Newtypes.dfy(222,15): Error: new number of occurrences might be negative
Execution trace:
(0,0): anon0
(0,0): anon6_Then
-Newtypes.dfy(225,40): Error: result of operation might violate newtype constraint
+Newtypes.dfy(225,39): Error: result of operation might violate newtype constraint
Execution trace:
(0,0): anon0
(0,0): anon8_Then
-Newtypes.dfy(237,19): Error: result of operation might violate newtype constraint
+Newtypes.dfy(237,18): Error: result of operation might violate newtype constraint
Execution trace:
(0,0): anon0
Newtypes.dfy(236,5): anon9_LoopHead
(0,0): anon9_LoopBody
(0,0): anon10_Then
-Newtypes.dfy(277,19): Error: result of operation might violate newtype constraint
+Newtypes.dfy(277,18): Error: result of operation might violate newtype constraint
Execution trace:
(0,0): anon0
Newtypes.dfy(276,5): anon9_LoopHead
diff --git a/Test/dafny0/NonGhostQuantifiers.dfy b/Test/dafny0/NonGhostQuantifiers.dfy
index bff1d65b..e522d0fc 100644
--- a/Test/dafny0/NonGhostQuantifiers.dfy
+++ b/Test/dafny0/NonGhostQuantifiers.dfy
@@ -181,6 +181,12 @@ module DependencyOnAllAllocatedObjects {
forall c: SomeClass :: true // error: not allowed to dependend on which objects are allocated
}
+ class SomeClass {
+ var f: int;
+ }
+}
+
+module DependencyOnAllAllocatedObjects_More {
method M()
{
var b := forall c: SomeClass :: c != null ==> c.f == 0; // error: non-ghost code requires bounds
@@ -192,3 +198,4 @@ module DependencyOnAllAllocatedObjects {
var f: int;
}
}
+
diff --git a/Test/dafny0/NonGhostQuantifiers.dfy.expect b/Test/dafny0/NonGhostQuantifiers.dfy.expect
index 1e2fce17..0abf0b6c 100644
--- a/Test/dafny0/NonGhostQuantifiers.dfy.expect
+++ b/Test/dafny0/NonGhostQuantifiers.dfy.expect
@@ -6,16 +6,12 @@ NonGhostQuantifiers.dfy(167,4): Error: a quantifier involved in a function defin
NonGhostQuantifiers.dfy(171,4): Error: a quantifier involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'c'
NonGhostQuantifiers.dfy(176,4): Error: a quantifier involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'c'
NonGhostQuantifiers.dfy(181,4): Error: a quantifier involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'c'
-NonGhostQuantifiers.dfy(186,13): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'c'
-NonGhostQuantifiers.dfy(16,5): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'n'
-NonGhostQuantifiers.dfy(45,4): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'n'
-NonGhostQuantifiers.dfy(49,4): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'd'
-NonGhostQuantifiers.dfy(53,4): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'n'
-NonGhostQuantifiers.dfy(77,5): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'i'
-NonGhostQuantifiers.dfy(81,5): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'j'
-NonGhostQuantifiers.dfy(91,5): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'j'
-NonGhostQuantifiers.dfy(106,5): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'j'
-NonGhostQuantifiers.dfy(114,10): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'y'
-NonGhostQuantifiers.dfy(123,8): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'x'
+NonGhostQuantifiers.dfy(192,13): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce or compile a bounded set of values for 'c'
+NonGhostQuantifiers.dfy(16,5): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce or compile a bounded set of values for 'n'
+NonGhostQuantifiers.dfy(45,4): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce or compile a bounded set of values for 'n'
+NonGhostQuantifiers.dfy(49,4): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce or compile a bounded set of values for 'd'
+NonGhostQuantifiers.dfy(53,4): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce or compile a bounded set of values for 'n'
+NonGhostQuantifiers.dfy(114,10): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce or compile a bounded set of values for 'y'
+NonGhostQuantifiers.dfy(123,8): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce or compile a bounded set of values for 'x'
NonGhostQuantifiers.dfy(140,8): Error: Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
-20 resolution/type errors detected in NonGhostQuantifiers.dfy
+16 resolution/type errors detected in NonGhostQuantifiers.dfy
diff --git a/Test/dafny0/OpaqueFunctions.dfy b/Test/dafny0/OpaqueFunctions.dfy
index e1c0756c..b3cde309 100644
--- a/Test/dafny0/OpaqueFunctions.dfy
+++ b/Test/dafny0/OpaqueFunctions.dfy
@@ -44,7 +44,7 @@ module A' refines A {
}
module B {
- import X as A
+ import X : A
method Main() {
var c := new X.C();
c.M(); // fine
@@ -68,7 +68,7 @@ module B {
}
}
module B_direct {
- import X as A'
+ import X : A'
method Main() {
var c := new X.C();
c.M(); // fine
diff --git a/Test/dafny0/OpaqueFunctions.dfy.expect b/Test/dafny0/OpaqueFunctions.dfy.expect
index 2fb1701f..e9f6e60c 100644
--- a/Test/dafny0/OpaqueFunctions.dfy.expect
+++ b/Test/dafny0/OpaqueFunctions.dfy.expect
@@ -1,86 +1,86 @@
-OpaqueFunctions.dfy(27,16): Error: assertion violation
+OpaqueFunctions.dfy(27,15): Error: assertion violation
Execution trace:
(0,0): anon0
-OpaqueFunctions.dfy(52,8): Error BP5002: A precondition for this call might not hold.
-OpaqueFunctions.dfy(24,16): Related location: This is the precondition that might not hold.
+OpaqueFunctions.dfy(52,7): Error BP5002: A precondition for this call might not hold.
+OpaqueFunctions.dfy(24,15): Related location: This is the precondition that might not hold.
Execution trace:
(0,0): anon0
-OpaqueFunctions.dfy(58,20): Error: assertion violation
+OpaqueFunctions.dfy(58,19): Error: assertion violation
Execution trace:
(0,0): anon0
-OpaqueFunctions.dfy(60,21): Error: assertion violation
+OpaqueFunctions.dfy(60,20): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon5_Then
-OpaqueFunctions.dfy(63,21): Error: assertion violation
+OpaqueFunctions.dfy(63,20): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon6_Then
-OpaqueFunctions.dfy(66,21): Error: assertion violation
+OpaqueFunctions.dfy(66,20): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon6_Else
-OpaqueFunctions.dfy(77,21): Error: assertion violation
+OpaqueFunctions.dfy(77,20): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-OpaqueFunctions.dfy(79,10): Error BP5002: A precondition for this call might not hold.
-OpaqueFunctions.dfy[A'](24,16): Related location: This is the precondition that might not hold.
+OpaqueFunctions.dfy(79,9): Error BP5002: A precondition for this call might not hold.
+OpaqueFunctions.dfy[A'](24,15): Related location: This is the precondition that might not hold.
Execution trace:
(0,0): anon0
(0,0): anon3_Else
-OpaqueFunctions.dfy(86,20): Error: assertion violation
+OpaqueFunctions.dfy(86,19): Error: assertion violation
Execution trace:
(0,0): anon0
-OpaqueFunctions.dfy(88,21): Error: assertion violation
+OpaqueFunctions.dfy(88,20): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon5_Then
-OpaqueFunctions.dfy(91,21): Error: assertion violation
+OpaqueFunctions.dfy(91,20): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon6_Then
-OpaqueFunctions.dfy(94,21): Error: assertion violation
+OpaqueFunctions.dfy(94,20): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon6_Else
-OpaqueFunctions.dfy(105,21): Error: assertion violation
+OpaqueFunctions.dfy(105,20): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-OpaqueFunctions.dfy(107,10): Error BP5002: A precondition for this call might not hold.
-OpaqueFunctions.dfy[A'](24,16): Related location: This is the precondition that might not hold.
+OpaqueFunctions.dfy(107,9): Error BP5002: A precondition for this call might not hold.
+OpaqueFunctions.dfy[A'](24,15): Related location: This is the precondition that might not hold.
Execution trace:
(0,0): anon0
(0,0): anon3_Else
-OpaqueFunctions.dfy(114,20): Error: assertion violation
+OpaqueFunctions.dfy(114,19): Error: assertion violation
Execution trace:
(0,0): anon0
-OpaqueFunctions.dfy(116,21): Error: assertion violation
+OpaqueFunctions.dfy(116,20): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon5_Then
-OpaqueFunctions.dfy(119,21): Error: assertion violation
+OpaqueFunctions.dfy(119,20): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon6_Then
-OpaqueFunctions.dfy(122,21): Error: assertion violation
+OpaqueFunctions.dfy(122,20): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon6_Else
-OpaqueFunctions.dfy(138,13): Error: assertion violation
+OpaqueFunctions.dfy(138,12): Error: assertion violation
Execution trace:
(0,0): anon0
-OpaqueFunctions.dfy(202,12): Error: assertion violation
+OpaqueFunctions.dfy(202,11): Error: assertion violation
Execution trace:
(0,0): anon0
-OpaqueFunctions.dfy(218,12): Error: assertion violation
+OpaqueFunctions.dfy(218,11): Error: assertion violation
Execution trace:
(0,0): anon0
-OpaqueFunctions.dfy(170,16): Error: assertion violation
+OpaqueFunctions.dfy(170,15): Error: assertion violation
Execution trace:
(0,0): anon0
-OpaqueFunctions.dfy(185,20): Error: assertion violation
+OpaqueFunctions.dfy(185,19): Error: assertion violation
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/Parallel.dfy b/Test/dafny0/Parallel.dfy
index 030eb350..00a1514c 100644
--- a/Test/dafny0/Parallel.dfy
+++ b/Test/dafny0/Parallel.dfy
@@ -1,14 +1,14 @@
-// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
class C {
- var data: int;
- var n: nat;
- var st: set<object>;
+ var data: int
+ var n: nat
+ var st: set<object>
ghost method CLemma(k: int)
- requires k != -23;
- ensures data < k; // magic, isn't it (or bogus, some would say)
+ requires k != -23
+ ensures data < k // magic, isn't it (or bogus, some would say)
}
// This method more or less just tests the syntax, resolution, and basic verification
@@ -19,31 +19,31 @@ method ParallelStatement_Resolve(
S: set<int>,
clx: C, cly: C, clk: int
)
- requires a != null && null !in spine;
- modifies a, spine;
+ requires a != null && null !in spine
+ modifies a, spine
{
- forall (i: int | 0 <= i < a.Length && i % 2 == 0) {
+ forall i | 0 <= i < a.Length && i % 2 == 0 {
a[i] := a[(i + 1) % a.Length] + 3;
}
- forall (o | o in spine) {
+ forall o | o in spine {
o.st := o.st + Repr;
}
- forall (x, y | x in S && 0 <= y+x < 100) {
+ forall x, y | x in S && 0 <= y+x < 100 {
Lemma(clx, x, y); // error: precondition does not hold (clx may be null)
}
- forall (x, y | x in S && 0 <= y+x < 100) {
+ forall x, y | x in S && 0 <= y+x < 100 {
cly.CLemma(x + y); // error: receiver might be null
}
- forall (p | 0 <= p)
- ensures F(p) <= Sum(p) + p - 1; // error (no connection is known between F and Sum)
+ forall p | 0 <= p
+ ensures F(p) <= Sum(p) + p - 1 // error (no connection is known between F and Sum)
{
assert 0 <= G(p);
ghost var t;
- if (p % 2 == 0) {
+ if p % 2 == 0 {
assert G(p) == F(p+2); // error (there's nothing that gives any relation between F and G)
t := p+p;
} else {
@@ -56,11 +56,11 @@ method ParallelStatement_Resolve(
}
}
-ghost method Lemma(c: C, x: int, y: int)
- requires c != null;
- ensures c.data <= x+y;
-ghost method PowerLemma(x: int, y: int)
- ensures Pred(x, y);
+lemma Lemma(c: C, x: int, y: int)
+ requires c != null
+ ensures c.data <= x+y
+lemma PowerLemma(x: int, y: int)
+ ensures Pred(x, y)
function F(x: int): int
function G(x: int): nat
@@ -71,54 +71,54 @@ function Pred(x: int, y: int): bool
// ---------------------------------------------------------------------
method M0(S: set<C>)
- requires null !in S;
- modifies S;
- ensures forall o :: o in S ==> o.data == 85;
- ensures forall o :: o != null && o !in S ==> o.data == old(o.data);
+ requires null !in S
+ modifies S
+ ensures forall o :: o in S ==> o.data == 85
+ ensures forall o :: o != null && o !in S ==> o.data == old(o.data)
{
- forall (s | s in S) {
+ forall s | s in S {
s.data := 85;
}
}
method M1(S: set<C>, x: C)
- requires null !in S && x in S;
+ requires null !in S && x in S
{
- forall (s | s in S)
- ensures s.data < 100;
+ forall s | s in S
+ ensures s.data < 100
{
assume s.data == 85;
}
- if (*) {
+ if * {
assert x.data == 85; // error (cannot be inferred from forall ensures clause)
} else {
assert x.data < 120;
}
- forall (s | s in S)
- ensures s.data < 70; // error
+ forall s | s in S
+ ensures s.data < 70 // error
{
assume s.data == 85;
}
}
method M2() returns (a: array<int>)
- ensures a != null;
- ensures forall i,j :: 0 <= i < a.Length/2 <= j < a.Length ==> a[i] < a[j];
+ ensures a != null
+ ensures forall i,j :: 0 <= i < a.Length/2 <= j < a.Length ==> a[i] < a[j]
{
a := new int[250];
- forall (i: nat | i < 125) {
+ forall i: nat | i < 125 {
a[i] := 423;
}
- forall (i | 125 <= i < 250) {
+ forall i | 125 <= i < 250 {
a[i] := 300 + i;
}
}
method M4(S: set<C>, k: int)
- modifies S;
+ modifies S
{
- forall (s | s in S && s != null) {
+ forall s | s in S && s != null {
s.n := k; // error: k might be negative
}
}
@@ -127,25 +127,25 @@ method M5()
{
if {
case true =>
- forall (x | 0 <= x < 100) {
+ forall x | 0 <= x < 100 {
PowerLemma(x, x);
}
assert Pred(34, 34);
case true =>
- forall (x,y | 0 <= x < 100 && y == x+1) {
+ forall x,y | 0 <= x < 100 && y == x+1 {
PowerLemma(x, y);
}
assert Pred(34, 35);
case true =>
- forall (x,y | 0 <= x < y < 100) {
+ forall x,y | 0 <= x < y < 100 {
PowerLemma(x, y);
}
assert Pred(34, 35);
case true =>
- forall (x | x in set k | 0 <= k < 100) {
+ forall x | x in set k | 0 <= k < 100 {
PowerLemma(x, x);
}
assert Pred(34, 34);
@@ -155,22 +155,22 @@ method M5()
method Main()
{
var a := new int[180];
- forall (i | 0 <= i < 180) {
+ forall i | 0 <= i < 180 {
a[i] := 2*i + 100;
}
var sq := [0, 0, 0, 2, 2, 2, 5, 5, 5];
- forall (i | 0 <= i < |sq|) {
+ forall i | 0 <= i < |sq| {
a[20+i] := sq[i];
}
- forall (t | t in sq) {
+ forall t | t in sq {
a[t] := 1000;
}
- forall (t,u | t in sq && t < 4 && 10 <= u < 10+t) {
+ forall t,u | t in sq && t < 4 && 10 <= u < 10+t {
a[u] := 6000 + t;
}
var k := 0;
- while (k < 180) {
- if (k != 0) { print ", "; }
+ while k < 180 {
+ if k != 0 { print ", "; }
print a[k];
k := k + 1;
}
@@ -180,50 +180,50 @@ method Main()
method DuplicateUpdate() {
var a := new int[180];
var sq := [0, 0, 0, 2, 2, 2, 5, 5, 5];
- if (*) {
- forall (t,u | t in sq && 10 <= u < 10+t) {
+ if * {
+ forall t,u | t in sq && 10 <= u < 10+t {
a[u] := 6000 + t; // error: a[10] (and a[11]) are assigned more than once
}
} else {
- forall (t,u | t in sq && t < 4 && 10 <= u < 10+t) {
+ forall t,u | t in sq && t < 4 && 10 <= u < 10+t {
a[u] := 6000 + t; // with the 't < 4' conjunct in the line above, this is fine
}
}
}
-ghost method DontDoMuch(x: int)
+lemma DontDoMuch(x: int)
{
}
method OmittedRange() {
- forall (x: int) { } // a type is still needed for the bound variable
- forall (x) {
+ forall x: int { } // a type is still needed for the bound variable
+ forall x {
DontDoMuch(x);
}
}
// ----------------------- two-state postconditions ---------------------------------
-class TwoState_C { ghost var data: int; }
+class TwoState_C { ghost var data: int }
// It is not possible to achieve this postcondition in a ghost method, because ghost
// contexts are not allowed to allocate state. Callers of this ghost method will know
// that the postcondition is tantamount to 'false'.
ghost method TwoState0(y: int)
- ensures exists o: TwoState_C :: o != null && fresh(o);
+ ensures exists o: TwoState_C {:nowarn} :: o != null && fresh(o)
method TwoState_Main0() {
- forall (x) { TwoState0(x); }
+ forall x { TwoState0(x); }
assert false; // no prob, because the postcondition of TwoState0 implies false
}
method X_Legit(c: TwoState_C)
- requires c != null;
- modifies c;
+ requires c != null
+ modifies c
{
c.data := c.data + 1;
- forall (x | c.data <= x)
- ensures old(c.data) < x; // note that the 'old' refers to the method's initial state
+ forall x | c.data <= x
+ ensures old(c.data) < x // note that the 'old' refers to the method's initial state
{
}
}
@@ -235,8 +235,8 @@ method X_Legit(c: TwoState_C)
// method, not the beginning of the 'forall' statement.
method TwoState_Main2()
{
- forall (x: int)
- ensures exists o: TwoState_C :: o != null && fresh(o);
+ forall x: int
+ ensures exists o: TwoState_C {:nowarn} :: o != null && fresh(o)
{
TwoState0(x);
}
@@ -251,8 +251,8 @@ method TwoState_Main2()
// statement's effect on the heap is not optimized away.
method TwoState_Main3()
{
- forall (x: int)
- ensures exists o: TwoState_C :: o != null && fresh(o);
+ forall x: int
+ ensures exists o: TwoState_C {:nowarn} :: o != null && fresh(o)
{
assume false; // (there's no other way to achieve this forall-statement postcondition)
}
@@ -262,11 +262,11 @@ method TwoState_Main3()
// ------- empty forall statement -----------------------------------------
class EmptyForallStatement {
- var emptyPar: int;
+ var emptyPar: int
method Empty_Parallel0()
- modifies this;
- ensures emptyPar == 8;
+ modifies this
+ ensures emptyPar == 8
{
forall () {
this.emptyPar := 8;
@@ -274,11 +274,11 @@ class EmptyForallStatement {
}
function EmptyPar_P(x: int): bool
- ghost method EmptyPar_Lemma(x: int)
- ensures EmptyPar_P(x);
+ lemma EmptyPar_Lemma(x: int)
+ ensures EmptyPar_P(x)
method Empty_Parallel1()
- ensures EmptyPar_P(8);
+ ensures EmptyPar_P(8)
{
forall {
EmptyPar_Lemma(8);
@@ -288,7 +288,7 @@ class EmptyForallStatement {
method Empty_Parallel2()
{
forall
- ensures exists k :: EmptyPar_P(k);
+ ensures exists k :: EmptyPar_P(k)
{
var y := 8;
assume EmptyPar_P(y);
@@ -309,12 +309,12 @@ predicate ThProperty(step: nat, t: Nat, r: nat)
{
match t
case Zero => true
- case Succ(o) => step>0 && exists ro:nat :: ThProperty(step-1, o, ro)
+ case Succ(o) => step>0 && exists ro:nat, ss | ss == step-1 :: ThProperty(ss, o, ro) //WISH: ss should be autogrnerated. Note that step is not a bound variable.
}
-ghost method Th(step: nat, t: Nat, r: nat)
- requires t.Succ? && ThProperty(step, t, r);
+lemma Th(step: nat, t: Nat, r: nat)
+ requires t.Succ? && ThProperty(step, t, r)
// the next line follows from the precondition and the definition of ThProperty
- ensures exists ro:nat :: ThProperty(step-1, t.tail, ro);
+ ensures exists ro:nat, ss | ss == step-1 :: ThProperty(ss, t.tail, ro) //WISH same as above
{
}
diff --git a/Test/dafny0/Parallel.dfy.expect b/Test/dafny0/Parallel.dfy.expect
index db551bba..5d9b044f 100644
--- a/Test/dafny0/Parallel.dfy.expect
+++ b/Test/dafny0/Parallel.dfy.expect
@@ -1,9 +1,9 @@
-Parallel.dfy(297,22): Error: assertion violation
+Parallel.dfy(297,21): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon4_Else
-Parallel.dfy(34,10): Error BP5002: A precondition for this call might not hold.
-Parallel.dfy(60,14): Related location: This is the precondition that might not hold.
+Parallel.dfy(34,9): Error BP5002: A precondition for this call might not hold.
+Parallel.dfy(60,13): Related location: This is the precondition that might not hold.
Execution trace:
(0,0): anon0
(0,0): anon29_Else
@@ -12,7 +12,7 @@ Execution trace:
(0,0): anon34_Then
(0,0): anon35_Then
(0,0): anon14
-Parallel.dfy(38,5): Error: target object may be null
+Parallel.dfy(38,4): Error: target object may be null
Execution trace:
(0,0): anon0
(0,0): anon29_Else
@@ -22,7 +22,7 @@ Execution trace:
(0,0): anon37_Then
(0,0): anon38_Then
(0,0): anon20
-Parallel.dfy(42,18): Error: possible violation of postcondition of forall statement
+Parallel.dfy(42,17): Error: possible violation of postcondition of forall statement
Execution trace:
(0,0): anon0
(0,0): anon29_Else
@@ -32,7 +32,7 @@ Execution trace:
(0,0): anon39_Then
(0,0): anon40_Then
(0,0): anon26
-Parallel.dfy(47,19): Error: assertion violation
+Parallel.dfy(47,18): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon29_Else
@@ -41,24 +41,24 @@ Execution trace:
(0,0): anon36_Else
(0,0): anon39_Then
(0,0): anon40_Then
-Parallel.dfy(93,19): Error: assertion violation
+Parallel.dfy(93,18): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon10_Else
(0,0): anon11_Then
-Parallel.dfy(99,20): Error: possible violation of postcondition of forall statement
+Parallel.dfy(99,19): Error: possible violation of postcondition of forall statement
Execution trace:
(0,0): anon0
(0,0): anon10_Else
(0,0): anon11_Then
(0,0): anon12_Then
-Parallel.dfy(122,12): Error: value assigned to a nat must be non-negative
+Parallel.dfy(122,11): Error: value assigned to a nat must be non-negative
Execution trace:
(0,0): anon0
(0,0): anon6_Then
(0,0): anon7_Then
(0,0): anon3
-Parallel.dfy(185,12): Error: left-hand sides for different forall-statement bound variables may refer to the same location
+Parallel.dfy(185,11): Error: left-hand sides for different forall-statement bound variables may refer to the same location
Execution trace:
(0,0): anon0
(0,0): anon19_Then
diff --git a/Test/dafny0/ParallelResolveErrors.dfy b/Test/dafny0/ParallelResolveErrors.dfy
index 5e01f019..8c48487d 100644
--- a/Test/dafny0/ParallelResolveErrors.dfy
+++ b/Test/dafny0/ParallelResolveErrors.dfy
@@ -7,7 +7,6 @@ class C {
ghost method Init_ModifyNothing() { }
ghost method Init_ModifyThis() modifies this;
{
- data := 6; // error: assignment to a non-ghost field
gdata := 7;
}
ghost method Init_ModifyStuff(c: C) modifies this, c; { }
@@ -40,8 +39,8 @@ method M0(IS: set<int>)
{
var x := i;
x := x + 1;
- y := 18; // (this statement is not allowed, since y is declared outside the forall, but that check happens only if the first resolution pass of the forall statement passes, which it doesn't in this case because of the next line)
- z := 20; // error: assigning to a non-ghost variable inside a ghost forall block
+ y := 18; // error: assigning to a (ghost) variable inside a ghost forall block
+ z := 20; // error: assigning to a (non-ghost) variable inside a ghost forall block
}
forall (i | 0 <= i)
@@ -120,3 +119,15 @@ method M3(c: C)
c.GhostMethodWithModifies(x); // error: not allowed to call method with nonempty modifies clause
}
}
+
+module AnotherModule {
+ class C {
+ var data: int;
+ ghost var gdata: int;
+ ghost method Init_ModifyThis() modifies this;
+ {
+ data := 6; // error: assignment to a non-ghost field
+ gdata := 7;
+ }
+ }
+}
diff --git a/Test/dafny0/ParallelResolveErrors.dfy.expect b/Test/dafny0/ParallelResolveErrors.dfy.expect
index 7305bfce..4d25ba11 100644
--- a/Test/dafny0/ParallelResolveErrors.dfy.expect
+++ b/Test/dafny0/ParallelResolveErrors.dfy.expect
@@ -1,22 +1,23 @@
-ParallelResolveErrors.dfy(10,9): Error: Assignment to non-ghost field is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
-ParallelResolveErrors.dfy(21,4): Error: LHS of assignment must denote a mutable variable
-ParallelResolveErrors.dfy(26,6): Error: body of forall statement is attempting to update a variable declared outside the forall statement
-ParallelResolveErrors.dfy(44,6): Error: Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
-ParallelResolveErrors.dfy(56,13): Error: new allocation not supported in forall statements
+ParallelResolveErrors.dfy(129,11): Error: Assignment to non-ghost field is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+ParallelResolveErrors.dfy(20,4): Error: LHS of assignment must denote a mutable variable
+ParallelResolveErrors.dfy(25,6): Error: body of forall statement is attempting to update a variable declared outside the forall statement
+ParallelResolveErrors.dfy(42,6): Error: body of forall statement is attempting to update a variable declared outside the forall statement
+ParallelResolveErrors.dfy(43,6): Error: body of forall statement is attempting to update a variable declared outside the forall statement
+ParallelResolveErrors.dfy(55,13): Error: new allocation not supported in forall statements
+ParallelResolveErrors.dfy(60,13): Error: new allocation not allowed in ghost context
ParallelResolveErrors.dfy(61,13): Error: new allocation not allowed in ghost context
ParallelResolveErrors.dfy(62,13): Error: new allocation not allowed in ghost context
ParallelResolveErrors.dfy(63,13): Error: new allocation not allowed in ghost context
-ParallelResolveErrors.dfy(64,13): Error: new allocation not allowed in ghost context
-ParallelResolveErrors.dfy(65,22): Error: the body of the enclosing forall statement is not allowed to update heap locations, so any call must be to a method with an empty modifies clause
-ParallelResolveErrors.dfy(66,20): Error: the body of the enclosing forall statement is not allowed to call non-ghost methods
-ParallelResolveErrors.dfy(73,19): Error: trying to break out of more loop levels than there are enclosing loops
-ParallelResolveErrors.dfy(77,18): Error: return statement is not allowed inside a forall statement
-ParallelResolveErrors.dfy(84,21): Error: trying to break out of more loop levels than there are enclosing loops
-ParallelResolveErrors.dfy(85,20): Error: trying to break out of more loop levels than there are enclosing loops
-ParallelResolveErrors.dfy(86,20): Error: break label is undefined or not in scope: OutsideLoop
-ParallelResolveErrors.dfy(95,24): Error: trying to break out of more loop levels than there are enclosing loops
-ParallelResolveErrors.dfy(96,24): Error: break label is undefined or not in scope: OutsideLoop
-ParallelResolveErrors.dfy(107,9): Error: the body of the enclosing forall statement is not allowed to update heap locations
-ParallelResolveErrors.dfy(115,29): Error: the body of the enclosing forall statement is not allowed to update heap locations, so any call must be to a method with an empty modifies clause
-ParallelResolveErrors.dfy(120,29): Error: the body of the enclosing forall statement is not allowed to update heap locations, so any call must be to a method with an empty modifies clause
-21 resolution/type errors detected in ParallelResolveErrors.dfy
+ParallelResolveErrors.dfy(64,22): Error: the body of the enclosing forall statement is not allowed to update heap locations, so any call must be to a method with an empty modifies clause
+ParallelResolveErrors.dfy(65,20): Error: the body of the enclosing forall statement is not allowed to call non-ghost methods
+ParallelResolveErrors.dfy(72,19): Error: trying to break out of more loop levels than there are enclosing loops
+ParallelResolveErrors.dfy(76,18): Error: return statement is not allowed inside a forall statement
+ParallelResolveErrors.dfy(83,21): Error: trying to break out of more loop levels than there are enclosing loops
+ParallelResolveErrors.dfy(84,20): Error: trying to break out of more loop levels than there are enclosing loops
+ParallelResolveErrors.dfy(85,20): Error: break label is undefined or not in scope: OutsideLoop
+ParallelResolveErrors.dfy(94,24): Error: trying to break out of more loop levels than there are enclosing loops
+ParallelResolveErrors.dfy(95,24): Error: break label is undefined or not in scope: OutsideLoop
+ParallelResolveErrors.dfy(106,9): Error: the body of the enclosing forall statement is not allowed to update heap locations
+ParallelResolveErrors.dfy(114,29): Error: the body of the enclosing forall statement is not allowed to update heap locations, so any call must be to a method with an empty modifies clause
+ParallelResolveErrors.dfy(119,29): Error: the body of the enclosing forall statement is not allowed to update heap locations, so any call must be to a method with an empty modifies clause
+22 resolution/type errors detected in ParallelResolveErrors.dfy
diff --git a/Test/dafny0/ParseErrors.dfy.expect b/Test/dafny0/ParseErrors.dfy.expect
index 30898479..660ed926 100644
--- a/Test/dafny0/ParseErrors.dfy.expect
+++ b/Test/dafny0/ParseErrors.dfy.expect
@@ -1,17 +1,17 @@
-ParseErrors.dfy(7,19): error: a chain cannot have more than one != operator
-ParseErrors.dfy(9,37): error: this operator chain cannot continue with a descending operator
-ParseErrors.dfy(10,38): error: this operator chain cannot continue with an ascending operator
-ParseErrors.dfy(15,24): error: this operator chain cannot continue with a descending operator
-ParseErrors.dfy(18,18): error: this operator cannot be part of a chain
-ParseErrors.dfy(19,19): error: this operator cannot be part of a chain
-ParseErrors.dfy(20,18): error: this operator cannot be part of a chain
-ParseErrors.dfy(21,18): error: chaining not allowed from the previous operator
-ParseErrors.dfy(28,19): error: chaining not allowed from the previous operator
-ParseErrors.dfy(31,20): error: can only chain disjoint (!!) with itself.
-ParseErrors.dfy(58,8): error: the main operator of a calculation must be transitive
-ParseErrors.dfy(74,2): error: this operator cannot continue this calculation
-ParseErrors.dfy(75,2): error: this operator cannot continue this calculation
-ParseErrors.dfy(80,2): error: this operator cannot continue this calculation
-ParseErrors.dfy(81,2): error: this operator cannot continue this calculation
-ParseErrors.dfy(87,2): error: this operator cannot continue this calculation
+ParseErrors.dfy(7,18): Error: a chain cannot have more than one != operator
+ParseErrors.dfy(9,36): Error: this operator chain cannot continue with a descending operator
+ParseErrors.dfy(10,37): Error: this operator chain cannot continue with an ascending operator
+ParseErrors.dfy(15,23): Error: this operator chain cannot continue with a descending operator
+ParseErrors.dfy(18,17): Error: this operator cannot be part of a chain
+ParseErrors.dfy(19,18): Error: this operator cannot be part of a chain
+ParseErrors.dfy(20,17): Error: this operator cannot be part of a chain
+ParseErrors.dfy(21,17): Error: chaining not allowed from the previous operator
+ParseErrors.dfy(28,18): Error: chaining not allowed from the previous operator
+ParseErrors.dfy(31,19): Error: can only chain disjoint (!!) with itself.
+ParseErrors.dfy(58,7): Error: the main operator of a calculation must be transitive
+ParseErrors.dfy(74,1): Error: this operator cannot continue this calculation
+ParseErrors.dfy(75,1): Error: this operator cannot continue this calculation
+ParseErrors.dfy(80,1): Error: this operator cannot continue this calculation
+ParseErrors.dfy(81,1): Error: this operator cannot continue this calculation
+ParseErrors.dfy(87,1): Error: this operator cannot continue this calculation
16 parse errors detected in ParseErrors.dfy
diff --git a/Test/dafny0/PredExpr.dfy.expect b/Test/dafny0/PredExpr.dfy.expect
index 07bd5f20..80f311cb 100644
--- a/Test/dafny0/PredExpr.dfy.expect
+++ b/Test/dafny0/PredExpr.dfy.expect
@@ -1,16 +1,16 @@
-PredExpr.dfy(7,12): Error: assertion violation
+PredExpr.dfy(7,11): Error: assertion violation
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-PredExpr.dfy(39,15): Error: value assigned to a nat must be non-negative
+ (0,0): anon4_Else
+PredExpr.dfy(39,14): Error: value assigned to a nat must be non-negative
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
- (0,0): anon6_Else
-PredExpr.dfy(52,17): Error: assertion violation
+ (0,0): anon7_Else
+ (0,0): anon8_Else
+PredExpr.dfy(52,16): Error: assertion violation
Execution trace:
(0,0): anon0
-PredExpr.dfy(77,14): Error: assertion violation
+PredExpr.dfy(77,13): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon8_Else
diff --git a/Test/dafny0/Predicates.dfy b/Test/dafny0/Predicates.dfy
index 737dacd2..f8b3355d 100644
--- a/Test/dafny0/Predicates.dfy
+++ b/Test/dafny0/Predicates.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
module A {
diff --git a/Test/dafny0/Predicates.dfy.expect b/Test/dafny0/Predicates.dfy.expect
index dac4eb3c..36c9dfdd 100644
--- a/Test/dafny0/Predicates.dfy.expect
+++ b/Test/dafny0/Predicates.dfy.expect
@@ -1,26 +1,28 @@
-Predicates.dfy[B](21,5): Error BP5003: A postcondition might not hold on this return path.
-Predicates.dfy[B](20,15): Related location: This is the postcondition that might not hold.
-Predicates.dfy(31,9): Related location
+Predicates.dfy[B](21,4): Error BP5003: A postcondition might not hold on this return path.
+Predicates.dfy[B](20,14): Related location: This is the postcondition that might not hold.
+Predicates.dfy(31,8): Related location
Execution trace:
(0,0): anon0
-Predicates.dfy(88,16): Error: assertion violation
+Predicates.dfy(88,15): Error: assertion violation
Execution trace:
(0,0): anon0
-Predicates.dfy(92,14): Error: assertion violation
+Predicates.dfy(92,13): Error: assertion violation
Execution trace:
(0,0): anon0
-Predicates.dfy[Tricky_Full](126,5): Error BP5003: A postcondition might not hold on this return path.
-Predicates.dfy[Tricky_Full](125,15): Related location: This is the postcondition that might not hold.
-Predicates.dfy(136,7): Related location
-Predicates.dfy[Tricky_Full](116,9): Related location
+Predicates.dfy[Tricky_Full](126,4): Error BP5003: A postcondition might not hold on this return path.
+Predicates.dfy[Tricky_Full](125,14): Related location: This is the postcondition that might not hold.
+Predicates.dfy(136,6): Related location
+Predicates.dfy[Tricky_Full](116,8): Related location
Execution trace:
(0,0): anon0
-Predicates.dfy(164,5): Error BP5003: A postcondition might not hold on this return path.
-Predicates.dfy(163,15): Related location: This is the postcondition that might not hold.
+Predicates.dfy(164,4): Error BP5003: A postcondition might not hold on this return path.
+Predicates.dfy(163,14): Related location: This is the postcondition that might not hold.
+Predicates.dfy(163,42): Related location
Execution trace:
(0,0): anon0
-Predicates.dfy[Q1](154,5): Error BP5003: A postcondition might not hold on this return path.
-Predicates.dfy[Q1](153,15): Related location: This is the postcondition that might not hold.
+Predicates.dfy[Q1](154,4): Error BP5003: A postcondition might not hold on this return path.
+Predicates.dfy[Q1](153,14): Related location: This is the postcondition that might not hold.
+Predicates.dfy[Q1](153,45): Related location
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/Protected.dfy.expect b/Test/dafny0/Protected.dfy.expect
index d50f2dd5..6796e847 100644
--- a/Test/dafny0/Protected.dfy.expect
+++ b/Test/dafny0/Protected.dfy.expect
@@ -1,20 +1,20 @@
-Protected.dfy(17,20): Error: assertion violation
+Protected.dfy(17,19): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon9_Then
-Protected.dfy(31,18): Error: assertion violation
+Protected.dfy(31,17): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon12_Then
(0,0): anon6
(0,0): anon13_Else
-Protected.dfy(35,16): Error: assertion violation
+Protected.dfy(35,15): Error: assertion violation
Execution trace:
(0,0): anon0
-Protected.dfy(48,20): Error: assertion violation
+Protected.dfy(48,19): Error: assertion violation
Execution trace:
(0,0): anon0
-Protected.dfy(55,20): Error: assertion violation
+Protected.dfy(55,19): Error: assertion violation
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/RangeCompilation.dfy b/Test/dafny0/RangeCompilation.dfy
new file mode 100644
index 00000000..de8ca68e
--- /dev/null
+++ b/Test/dafny0/RangeCompilation.dfy
@@ -0,0 +1,25 @@
+// RUN: %dafny /compile:3 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+newtype Byte = x | 0 <= x < 256
+predicate method GoodByte(b: Byte) {
+ b % 3 == 2
+}
+predicate method GoodInteger(i: int) {
+ i % 5 == 4
+}
+
+method Main() {
+ assert GoodByte(11) && GoodInteger(24);
+ var b: Byte :| GoodByte(b);
+ var i: int :| 0 <= i < 256 && GoodInteger(i);
+ print "b=", b, " i=", i, "\n";
+ var m0 := new MyClass;
+ var m17 := new M17.AnotherClass;
+}
+
+class MyClass { }
+
+module M17 {
+ class AnotherClass { }
+}
diff --git a/Test/dafny0/RangeCompilation.dfy.expect b/Test/dafny0/RangeCompilation.dfy.expect
new file mode 100644
index 00000000..c3275d12
--- /dev/null
+++ b/Test/dafny0/RangeCompilation.dfy.expect
@@ -0,0 +1,6 @@
+
+Dafny program verifier finished with 5 verified, 0 errors
+Program compiled successfully
+Running...
+
+b=2 i=4
diff --git a/Test/dafny0/RankNeg.dfy.expect b/Test/dafny0/RankNeg.dfy.expect
index d740f8a0..33cd4f1e 100644
--- a/Test/dafny0/RankNeg.dfy.expect
+++ b/Test/dafny0/RankNeg.dfy.expect
@@ -1,22 +1,22 @@
-RankNeg.dfy(10,26): Error: cannot prove termination; try supplying a decreases clause
+RankNeg.dfy(10,25): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
- (0,0): anon6_Then
-RankNeg.dfy(15,28): Error: cannot prove termination; try supplying a decreases clause
+ (0,0): anon7_Else
+ (0,0): anon8_Then
+RankNeg.dfy(15,27): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
- (0,0): anon6_Then
-RankNeg.dfy(22,31): Error: cannot prove termination; try supplying a decreases clause
+ (0,0): anon7_Else
+ (0,0): anon8_Then
+RankNeg.dfy(22,30): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
- (0,0): anon6_Then
-RankNeg.dfy(32,25): Error: cannot prove termination; try supplying a decreases clause
+ (0,0): anon7_Else
+ (0,0): anon8_Then
+RankNeg.dfy(32,24): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
- (0,0): anon6_Then
+ (0,0): anon7_Else
+ (0,0): anon8_Then
Dafny program verifier finished with 1 verified, 4 errors
diff --git a/Test/dafny0/Reads.dfy b/Test/dafny0/Reads.dfy
index 645494cb..6dedbada 100644
--- a/Test/dafny0/Reads.dfy
+++ b/Test/dafny0/Reads.dfy
@@ -55,3 +55,84 @@ function ok5(r : R):()
reads if r != null then {r, r.r} else {};
{()}
+// Reads checking where there are circularities among the expressions
+
+class CircularChecking {
+ ghost var Repr: set<object>
+
+ function F(): int
+ reads this, Repr
+
+ function F'(): int
+ reads Repr, this // this is also fine
+
+ function G0(): int
+ reads this
+ requires Repr == {} && F() == 100
+
+ function G1(): int
+ reads this
+ requires F() == 100 // fine, since the next line tells us that Repr is empty
+ requires Repr == {}
+
+ function H0(cell: Cell): int
+ reads Repr // by itself, this reads is not self-framing
+ requires this in Repr // lo and behold! So, reads clause is fine after all
+
+ function H1(cell: Cell): int
+ reads this, Repr
+ requires cell in Repr
+ requires cell != null && cell.data == 10
+
+ function H2(cell: Cell): int
+ reads this, Repr
+ requires cell != null && cell.data == 10 // this is okay, too, since reads checks are postponed
+ requires cell in Repr
+}
+
+class Cell { var data: int }
+
+// Test the benefits of the new reads checking for function checking
+
+function ApplyToSet<X>(S: set<X>, f: X -> X): set<X>
+ requires forall x :: x in S ==> f.reads(x) == {} && f.requires(x)
+{
+ if S == {} then {} else
+ var x :| x in S;
+ ApplyToSet(S - {x}, f) + {f(x)}
+}
+
+function ApplyToSet_AltSignature0<X>(S: set<X>, f: X -> X): set<X>
+ requires forall x :: x in S ==> f.requires(x) && f.reads(x) == {}
+
+function ApplyToSet_AltSignature1<X>(S: set<X>, f: X -> X): set<X>
+ requires forall x :: x in S ==> f.reads(x) == {}
+ requires forall x :: x in S ==> f.requires(x)
+
+function ApplyToSet_AltSignature2<X>(S: set<X>, f: X -> X): set<X>
+ requires (forall x :: x in S ==> f.reads(x) == {}) ==> forall x :: x in S ==> f.requires(x)
+ // (this precondition would not be good enough to check the body above)
+
+function FunctionInQuantifier0(): int
+ requires exists f: int -> int :: f(10) == 100 // error (x2): precondition violation and insufficient reads
+
+function FunctionInQuantifier1(): int
+ requires exists f: int -> int :: f.requires(10) && f(10) == 100 // error: insufficient reads
+
+function FunctionInQuantifier2(): int
+ requires exists f: int -> int :: f.reads(10) == {} && f.requires(10) && f(10) == 100
+ ensures FunctionInQuantifier2() == 100
+{
+ var f: int -> int :| f.reads(10) == {} && f.requires(10) && f(10) == 100; // fine :) :)
+ f(10)
+}
+
+class DynamicFramesIdiom {
+ ghost var Repr: set<object>
+ predicate IllFormed_Valid()
+ reads Repr // error: reads is not self framing (notice the absence of "this")
+ {
+ this in Repr // this says that the predicate returns true if "this in Repr", but the
+ // predicate can also be invoked in a state where its body will evaluate to false
+ }
+}
diff --git a/Test/dafny0/Reads.dfy.expect b/Test/dafny0/Reads.dfy.expect
index 090cf99d..0ef90aec 100644
--- a/Test/dafny0/Reads.dfy.expect
+++ b/Test/dafny0/Reads.dfy.expect
@@ -1,26 +1,33 @@
-Reads.dfy(9,30): Error: insufficient reads clause to read field
+Reads.dfy(133,10): Error: insufficient reads clause to read field
Execution trace:
(0,0): anon0
- (0,0): anon5_Then
-Reads.dfy(18,30): Error: insufficient reads clause to read field
+Reads.dfy(9,29): Error: insufficient reads clause to read field
Execution trace:
(0,0): anon0
- (0,0): anon11_Then
- (0,0): anon12_Then
-Reads.dfy(28,50): Error: insufficient reads clause to read field
+Reads.dfy(18,29): Error: insufficient reads clause to read field
Execution trace:
(0,0): anon0
- (0,0): anon7_Then
- (0,0): anon8_Then
-Reads.dfy(37,43): Error: insufficient reads clause to read field
+Reads.dfy(28,49): Error: insufficient reads clause to read field
+Execution trace:
+ (0,0): anon0
+Reads.dfy(37,42): Error: insufficient reads clause to read field
Execution trace:
(0,0): anon0
(0,0): anon7_Then
- (0,0): anon8_Then
-Reads.dfy(51,30): Error: insufficient reads clause to read field
+ (0,0): anon4
+Reads.dfy(51,29): Error: insufficient reads clause to read field
+Execution trace:
+ (0,0): anon0
+ (0,0): anon10_Then
+ (0,0): anon4
+Reads.dfy(117,35): Error: insufficient reads clause to invoke function
+Execution trace:
+ (0,0): anon0
+Reads.dfy(117,35): Error: possible violation of function precondition
+Execution trace:
+ (0,0): anon0
+Reads.dfy(120,37): Error: insufficient reads clause to invoke function
Execution trace:
(0,0): anon0
- (0,0): anon9_Then
- (0,0): anon3
-Dafny program verifier finished with 5 verified, 5 errors
+Dafny program verifier finished with 17 verified, 9 errors
diff --git a/Test/dafny0/RealCompare.dfy.expect b/Test/dafny0/RealCompare.dfy.expect
index 5b25fa25..48524bdf 100644
--- a/Test/dafny0/RealCompare.dfy.expect
+++ b/Test/dafny0/RealCompare.dfy.expect
@@ -1,19 +1,19 @@
-RealCompare.dfy(35,6): Error: failure to decrease termination measure
+RealCompare.dfy(35,5): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-RealCompare.dfy(50,4): Error: decreases expression must be bounded below by 0.0
-RealCompare.dfy(48,13): Related location
+RealCompare.dfy(50,3): Error: decreases expression must be bounded below by 0.0
+RealCompare.dfy(48,12): Related location
Execution trace:
(0,0): anon0
-RealCompare.dfy(141,12): Error: assertion violation
+RealCompare.dfy(141,11): Error: assertion violation
Execution trace:
(0,0): anon0
RealCompare.dfy(133,3): anon7_LoopHead
(0,0): anon7_LoopBody
RealCompare.dfy(133,3): anon8_Else
(0,0): anon9_Then
-RealCompare.dfy(156,12): Error: assertion violation
+RealCompare.dfy(156,11): Error: assertion violation
Execution trace:
(0,0): anon0
RealCompare.dfy(147,3): anon9_LoopHead
diff --git a/Test/dafny0/RealTypes.dfy.expect b/Test/dafny0/RealTypes.dfy.expect
index 0d132948..0fce4634 100644
--- a/Test/dafny0/RealTypes.dfy.expect
+++ b/Test/dafny0/RealTypes.dfy.expect
@@ -1,22 +1,22 @@
-RealTypes.dfy(12,16): Error: the real-based number must be an integer (if you want truncation, apply .Trunc to the real-based number)
+RealTypes.dfy(12,15): Error: the real-based number must be an integer (if you want truncation, apply .Trunc to the real-based number)
Execution trace:
(0,0): anon0
(0,0): anon6_Then
-RealTypes.dfy(14,28): Error: assertion violation
+RealTypes.dfy(14,27): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon7_Then
-RealTypes.dfy(21,12): Error: possible division by zero
+RealTypes.dfy(21,11): Error: possible division by zero
Execution trace:
(0,0): anon0
RealTypes.dfy(20,23): anon3_Else
(0,0): anon2
-RealTypes.dfy(21,20): Error: assertion violation
+RealTypes.dfy(21,19): Error: assertion violation
Execution trace:
(0,0): anon0
RealTypes.dfy(20,23): anon3_Else
(0,0): anon2
-RealTypes.dfy(29,12): Error: assertion violation
+RealTypes.dfy(29,11): Error: assertion violation
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/Refinement.dfy.expect b/Test/dafny0/Refinement.dfy.expect
index 93d59873..339c86b4 100644
--- a/Test/dafny0/Refinement.dfy.expect
+++ b/Test/dafny0/Refinement.dfy.expect
@@ -1,40 +1,40 @@
-Refinement.dfy(15,5): Error BP5003: A postcondition might not hold on this return path.
-Refinement.dfy(14,17): Related location: This is the postcondition that might not hold.
+Refinement.dfy(15,4): Error BP5003: A postcondition might not hold on this return path.
+Refinement.dfy(14,16): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-Refinement.dfy[B](15,5): Error BP5003: A postcondition might not hold on this return path.
-Refinement.dfy(33,20): Related location: This is the postcondition that might not hold.
+Refinement.dfy[B](15,4): Error BP5003: A postcondition might not hold on this return path.
+Refinement.dfy(33,19): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-Refinement.dfy(69,16): Error: assertion violation
+Refinement.dfy(69,15): Error: assertion violation
Execution trace:
(0,0): anon0
-Refinement.dfy(80,17): Error: assertion violation
+Refinement.dfy(80,16): Error: assertion violation
Execution trace:
(0,0): anon0
-Refinement.dfy(99,12): Error BP5003: A postcondition might not hold on this return path.
-Refinement.dfy(78,15): Related location: This is the postcondition that might not hold.
+Refinement.dfy(99,11): Error BP5003: A postcondition might not hold on this return path.
+Refinement.dfy(78,14): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-Refinement.dfy(102,3): Error BP5003: A postcondition might not hold on this return path.
-Refinement.dfy(83,15): Related location: This is the postcondition that might not hold.
+ (0,0): anon4_Else
+Refinement.dfy(102,2): Error BP5003: A postcondition might not hold on this return path.
+Refinement.dfy(83,14): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-Refinement.dfy(189,5): Error BP5003: A postcondition might not hold on this return path.
-Refinement.dfy[IncorrectConcrete](121,15): Related location: This is the postcondition that might not hold.
-Refinement.dfy(186,9): Related location
+Refinement.dfy(189,4): Error BP5003: A postcondition might not hold on this return path.
+Refinement.dfy[IncorrectConcrete](121,14): Related location: This is the postcondition that might not hold.
+Refinement.dfy(186,8): Related location
Execution trace:
(0,0): anon0
-Refinement.dfy(193,5): Error BP5003: A postcondition might not hold on this return path.
-Refinement.dfy[IncorrectConcrete](129,15): Related location: This is the postcondition that might not hold.
-Refinement.dfy(186,9): Related location
+Refinement.dfy(193,4): Error BP5003: A postcondition might not hold on this return path.
+Refinement.dfy[IncorrectConcrete](129,14): Related location: This is the postcondition that might not hold.
+Refinement.dfy(186,8): Related location
Execution trace:
(0,0): anon0
(0,0): anon4_Then
(0,0): anon3
-Refinement.dfy(199,7): Error: assertion violation
-Refinement.dfy[IncorrectConcrete](137,24): Related location
+Refinement.dfy(199,6): Error: assertion violation
+Refinement.dfy[IncorrectConcrete](137,23): Related location
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/RefinementErrors.dfy b/Test/dafny0/RefinementErrors.dfy
index 121b33aa..8d60a8e4 100644
--- a/Test/dafny0/RefinementErrors.dfy
+++ b/Test/dafny0/RefinementErrors.dfy
@@ -59,3 +59,40 @@ module BB refines B {
{ 10 }
}
}
+
+module Forall0 {
+ class C {
+ var a: int
+ method M()
+ modifies this
+ {
+ }
+ lemma Lemma(x: int)
+ {
+ }
+ }
+}
+module Forall1 refines Forall0 {
+ class C {
+ var b: int
+ method M...
+ {
+ forall x { Lemma(x); } // allowed
+ var s := {4};
+ forall x | x in s ensures x == 4 { } // allowed
+ forall x { // allowed
+ calc {
+ x in s;
+ ==
+ x == 4;
+ }
+ }
+ forall c | c in {this} {
+ c.b := 17; // allowed
+ }
+ forall c | c in {this} {
+ c.a := 17; // error: not allowed to update previously defined field
+ }
+ }
+ }
+}
diff --git a/Test/dafny0/RefinementErrors.dfy.expect b/Test/dafny0/RefinementErrors.dfy.expect
index 40cdb081..bac6612d 100644
--- a/Test/dafny0/RefinementErrors.dfy.expect
+++ b/Test/dafny0/RefinementErrors.dfy.expect
@@ -9,4 +9,5 @@ RefinementErrors.dfy(38,13): Error: type parameters are not allowed to be rename
RefinementErrors.dfy(39,23): Error: the type of parameter 'z' is different from the type of the same parameter in the corresponding function in the module it refines ('seq<C>' instead of 'set<C>')
RefinementErrors.dfy(40,9): Error: there is a difference in name of parameter 3 ('k' versus 'b') of function F compared to corresponding function in the module it refines
RefinementErrors.dfy(57,20): Error: a function can be changed into a function method in a refining module only if the function has not yet been given a body: G
-11 resolution/type errors detected in RefinementErrors.dfy
+RefinementErrors.dfy(94,10): Error: refinement method cannot assign to a field defined in parent module ('a')
+12 resolution/type errors detected in RefinementErrors.dfy
diff --git a/Test/dafny0/ResolutionErrors.dfy b/Test/dafny0/ResolutionErrors.dfy
index 761cffa0..8dceb6ba 100644
--- a/Test/dafny0/ResolutionErrors.dfy
+++ b/Test/dafny0/ResolutionErrors.dfy
@@ -9,9 +9,9 @@ method GhostDivergentLoop()
a[1] := -1;
ghost var i := 0;
while (i < 2)
- decreases *; // error: not allowed on a ghost loop
- invariant i <= 2;
- invariant (forall j :: 0 <= j && j < i ==> a[j] > 0);
+ decreases * // error: not allowed on a ghost loop
+ invariant i <= 2
+ invariant (forall j :: 0 <= j && j < i ==> a[j] > 0)
{
i := 0;
}
@@ -91,9 +91,9 @@ class EE {
var b3 := Benny;
var d0 := David(20); // error: constructor name David is ambiguous
var d1 := David; // error: constructor name David is ambiguous (never mind that the signature does
- // not match either of them)
+ // not match either of them)
var d2 := David(20, 40); // error: constructor name Davis is ambiguous (never mind that the given
- // parameters match the signature of only one of those constructors)
+ // parameters match the signature of only one of those constructors)
var d3 := Abc.David(20, 40); // error: wrong number of parameters
var d4 := Rst.David(20, 40);
var e := Eleanor; // this resolves to the field, not the Abc datatype constructor
@@ -102,7 +102,7 @@ class EE {
}
// --------------- ghost tests -------------------------------------
-
+module HereAreMoreGhostTests {
datatype GhostDt =
Nil(ghost extraInfo: int) |
Cons(data: int, tail: GhostDt, ghost moreInfo: int)
@@ -150,14 +150,6 @@ class GhostTests {
r := r + g; // fine, for the same reason
r := N(20, 20); // error: call to non-ghost method from ghost method is not okay
}
- ghost method NiceTry()
- ensures false;
- {
- while (true)
- decreases *; // error: not allowed in ghost context
- {
- }
- }
ghost method BreaksAreFineHere(t: int)
{
var n := 0;
@@ -195,6 +187,57 @@ class GhostTests {
decreases 112 - n;
{
label MyStructure: {
+ k := k + 1;
+ }
+ label MyOtherStructure:
+ if (k % 17 == 0) {
+ break MyOtherStructure; // this break is fine
+ } else {
+ k := k + 1;
+ }
+
+ var dontKnow;
+ if (n == 112) {
+ ghost var m := 0;
+ label LoopLabel0:
+ label LoopLabel1:
+ while (m < 200) {
+ if (m % 103 == 0) {
+ if {
+ case true => break; // fine, since this breaks out of the enclosing ghost loop
+ case true => break LoopLabel0; // fine
+ case true => break LoopLabel1; // fine
+ }
+ } else if (m % 101 == 0) {
+ }
+ m := m + 3;
+ }
+ break;
+ } else if (dontKnow == 708) {
+ var q := 0;
+ while (q < 1) {
+ label IfNest:
+ if (p == 67) {
+ break break; // fine, since this is not a ghost context
+ }
+ q := q + 1;
+ }
+ } else if (n == t) {
+ }
+ n := n + 1;
+ p := p + 1;
+ }
+ }
+ method BreakMayNotBeFineHere_Ghost(ghost t: int)
+ {
+ var n := 0;
+ ghost var k := 0;
+ var p := 0;
+ while (true)
+ invariant n <= 112;
+ decreases 112 - n;
+ {
+ label MyStructure: {
if (k % 17 == 0) { break MyStructure; } // error: break from ghost to non-ghost point
k := k + 1;
}
@@ -230,8 +273,6 @@ class GhostTests {
if (p == 67) {
break break; // fine, since this is not a ghost context
} else if (*) {
- break break break; // error: tries to break out of more loop levels than there are
- } else if (*) {
break break; // fine, since this is not a ghost context
} else if (k == 67) {
break break; // error, because this is a ghost context
@@ -246,7 +287,7 @@ class GhostTests {
}
}
}
-
+} //HereAreMoreGhostTests
method DuplicateLabels(n: int) {
var x;
if (n < 7) {
@@ -310,18 +351,17 @@ method DatatypeDestructors(d: DTD_List) {
assert d.DTD_Cons? == d.Car; // type error
assert d == DTD_Cons(hd, tl, 5);
ghost var g0 := d.g; // fine
- var g1 := d.g; // error: cannot use ghost member in non-ghost code
}
}
// ------------------- print statements ---------------------------------------
-
+module GhostPrintAttempts {
method PrintOnlyNonGhosts(a: int, ghost b: int)
{
print "a: ", a, "\n";
print "b: ", b, "\n"; // error: print statement cannot take ghosts
}
-
+}
// ------------------- auto-added type arguments ------------------------------
class GenericClass<T> { var data: T; }
@@ -381,48 +421,45 @@ method TestCalc(m: int, n: int, a: bool, b: bool)
n + m + 1;
==> n + m + 2; // error: ==> operator requires boolean lines
}
- calc {
- n + m;
- { print n + m; } // error: non-ghost statements are not allowed in hints
- m + n;
- }
}
-class SideEffectChecks {
- ghost var ycalc: int;
+module MyOwnModule {
+ class SideEffectChecks {
+ ghost var ycalc: int;
- ghost method Mod(a: int)
- modifies this;
- ensures ycalc == a;
- {
- ycalc := a;
- }
+ ghost method Mod(a: int)
+ modifies this;
+ ensures ycalc == a;
+ {
+ ycalc := a;
+ }
- ghost method Bad()
- modifies this;
- ensures 0 == 1;
- {
- var x: int;
- calc {
- 0;
- { Mod(0); } // methods with side-effects are not allowed
- ycalc;
- { ycalc := 1; } // heap updates are not allowed
- 1;
- { x := 1; } // updates to locals defined outside of the hint are not allowed
- x;
- {
- var x: int;
- x := 1; // this is OK
+ ghost method Bad()
+ modifies this;
+ ensures 0 == 1;
+ {
+ var x: int;
+ calc {
+ 0;
+ { Mod(0); } // error: methods with side-effects are not allowed
+ ycalc;
+ { ycalc := 1; } // error: heap updates are not allowed
+ 1;
+ { x := 1; } // error: updates to locals defined outside of the hint are not allowed
+ x;
+ {
+ var x: int;
+ x := 1; // this is OK
+ }
+ 1;
}
- 1;
}
}
}
-
+
// ------------------- nameless constructors ------------------------------
-class YHWH {
+class Y {
var data: int;
constructor (x: int)
modifies this;
@@ -433,22 +470,22 @@ class YHWH {
{
}
method Test() {
- var IAmWhoIAm := new YHWH(5);
- IAmWhoIAm := new YHWH._ctor(7); // but, in fact, it is also possible to use the underlying name
- IAmWhoIAm := new YHWH; // error: the class has a constructor, so one must be used
- var s := new Lucifer.Init(5);
- s := new Lucifer.FromArray(null);
- s := new Lucifer(false);
- s := new Lucifer._ctor(false);
- s := new Lucifer.M(); // error: there is a constructor, so one must be called
- s := new Lucifer; // error: there is a constructor, so one must be called
+ var i := new Y(5);
+ i := new Y._ctor(7); // but, in fact, it is also possible to use the underlying name
+ i := new Y; // error: the class has a constructor, so one must be used
+ var s := new Luci.Init(5);
+ s := new Luci.FromArray(null);
+ s := new Luci(false);
+ s := new Luci._ctor(false);
+ s := new Luci.M(); // error: there is a constructor, so one must be called
+ s := new Luci; // error: there is a constructor, so one must be called
var l := new Lamb;
l := new Lamb(); // error: there is no default constructor
l := new Lamb.Gwen();
}
}
-class Lucifer {
+class Luci {
constructor Init(y: int) { }
constructor (nameless: bool) { }
constructor FromArray(a: array<int>) { }
@@ -456,7 +493,7 @@ class Lucifer {
}
class Lamb {
- method Jesus() { }
+ method Jess() { }
method Gwen() { }
}
@@ -467,14 +504,10 @@ method AssignSuchThatFromGhost()
var x: int;
ghost var g: int;
- x := g; // error: ghost cannot flow into non-ghost
-
x := *;
assume x == g; // this mix of ghosts and non-ghosts is cool (but, of course,
// the compiler will complain)
- x :| x == g; // error: left-side has non-ghost, so RHS must be non-ghost as well
-
x :| assume x == g; // this is cool, since it's an assume (but, of course, the
// compiler will complain)
@@ -543,8 +576,6 @@ method LetSuchThat(ghost z: int, n: nat)
var x: int;
x := var y :| y < 0; y; // fine for the resolver (but would give a verification error for not being deterministic)
- x := var y :| y < z; y; // error: contraint depend on ghost (z)
-
x := var w :| w == 2*w; w; // fine (even for the verifier, this one)
x := var w := 2*w; w; // error: the 'w' in the RHS of the assignment is not in scope
ghost var xg := var w :| w == 2*w; w;
@@ -555,16 +586,16 @@ method LetSuchThat(ghost z: int, n: nat)
module NonInferredType {
predicate P<T>(x: T)
- method NonInferredType0(x: int)
+ method InferredType(x: int)
{
var t;
- assume forall z :: P(z) && z == t; // It would be nice to allow the following example, but the implementation calls DiscoverBounds before CheckInference for quantifiers.
+ assume forall z :: P(z) && z == t;
assume t == x; // this statement determines the type of t and z
}
- method NonInferredType1(x: int)
+ method NonInferredType(x: int)
{
- var t;
+ var t; // error: the type of t is not determined
assume forall z :: P(z) && z == t; // error: the type of z is not determined
}
}
@@ -582,20 +613,7 @@ module GhostAllocationTests {
p := new G; // error: ditto
}
- method GhostNew1(n: nat)
- {
- var a := new G[n];
- forall i | 0 <= i < n {
- a[i] := new G; // error: 'new' is currently not supported in forall statements
- }
- forall i | 0 <= i < n
- ensures true; // this makes the whole 'forall' statement into a ghost statement
- {
- a[i] := new G; // error: 'new' not allowed in ghost contexts, and proof-forall cannot update state
- }
- }
-
- method GhostNew2(n: nat, ghost g: int) returns (t: G, z: int)
+ method GhostNew1(n: nat, ghost g: int) returns (t: G, z: int)
{
if n < 0 {
z, t := 5, new G; // fine
@@ -605,33 +623,45 @@ module GhostAllocationTests {
}
}
- method GhostNew3(ghost b: bool)
+ method GhostNew2(ghost b: bool)
{
if (b) {
var y := new GIter(); // error: 'new' not allowed in ghost contexts (and a non-ghost method is not allowed to be called here either)
}
}
- method GhostNew4(n: nat)
+ method GhostNew3(n: nat)
{
var g := new G;
calc {
5;
{ var y := new G; } // error: 'new' not allowed in ghost contexts
2 + 3;
- { if n != 0 { GhostNew4(n-1); } } // error: cannot call non-ghost method in a ghost context
- 1 + 4;
- { GhostNew5(g); } // error: cannot call method with nonempty modifies
- -5 + 10;
}
}
- ghost method GhostNew5(g: G)
+ ghost method GhostNew4(g: G)
modifies g;
{
}
}
+module NewForall {
+ class G { }
+ method NewForallTest(n: nat)
+ {
+ var a := new G[n];
+ forall i | 0 <= i < n {
+ a[i] := new G; // error: 'new' is currently not supported in forall statements
+ }
+ forall i | 0 <= i < n
+ ensures true; // this makes the whole 'forall' statement into a ghost statement
+ {
+ a[i] := new G; // error: 'new' not allowed in ghost contexts, and proof-forall cannot update state
+ }
+ }
+}
+
// ------------------------- underspecified types ------------------------------
module UnderspecifiedTypes {
@@ -672,46 +702,31 @@ module StatementsInExpressions {
{
}
- ghost method M()
- modifies this;
- {
- calc {
- 5;
- { SideEffect(); } // error: cannot call method with side effects
- 5;
- }
- }
-
function F(): int
{
calc {
- 6;
- { assert 6 < 8; }
- { NonGhostMethod(); } // error: cannot call non-ghost method
- { var x := 8;
- while x != 0
- decreases *; // error: cannot use 'decreases *' in a ghost context
- {
- x := x - 1;
- }
- }
- { var x := 8;
- while x != 0
- {
- x := x - 1;
- }
- }
- { MyField := 12; } // error: cannot assign to a field
- { MyGhostField := 12; } // error: cannot assign to any field
- { SideEffect(); } // error: cannot call (ghost) method with a modifies clause
- { var x := 8;
- while x != 0
- modifies this; // error: cannot use a modifies clause on a loop
- {
- x := x - 1;
- }
- }
- 6;
+ 6;
+ { assert 6 < 8; }
+ { var x := 8;
+ while x != 0
+ decreases * // error: cannot use 'decreases *' here
+ {
+ x := x - 1;
+ }
+ }
+ { var x := 8;
+ while x != 0
+ {
+ x := x - 1;
+ }
+ }
+ { var x := 8;
+ while x != 0
+ {
+ x := x - 1;
+ }
+ }
+ 6;
}
5
}
@@ -723,33 +738,28 @@ module StatementsInExpressions {
{
var y :=
calc {
- 6;
- { assert 6 < 8; }
- { NonGhostMethod(); } // error: cannot call non-ghost method
- { var x := 8;
- while x != 0
- decreases *; // error: cannot use 'decreases *' in a ghost context
- {
- x := x - 1;
- }
- }
- { MyField := 12; } // error: cannot assign to a field
- { MyGhostField := 12; } // error: cannot assign to any field
- { M(); } // error: cannot call (ghost) method with a modifies clause
- { var x := 8;
- while x != 0
- modifies this; // error: cannot use a modifies clause on a loop
- {
- x := x - 1;
- }
- }
- { var x := 8;
- while x != 0
- {
- x := x - 1;
- }
- }
- 6;
+ 6;
+ { assert 6 < 8; }
+ { var x := 8;
+ while x != 0
+ decreases * // error: cannot use 'decreases *' here
+ {
+ x := x - 1;
+ }
+ }
+ { var x := 8;
+ while x != 0
+ {
+ x := x - 1;
+ }
+ }
+ { var x := 8;
+ while x != 0
+ {
+ x := x - 1;
+ }
+ }
+ 6;
}
5;
}
@@ -764,7 +774,6 @@ module StatementsInExpressions {
{
MyLemma();
MyGhostMethod(); // error: modifi2es state
- OrdinaryMethod(); // error: not a ghost
OutParamMethod(); // error: has out-parameters
10
}
@@ -846,40 +855,48 @@ class ModifyStatementClass {
ghost method G0()
modifies `g;
modifies `x; // error: non-ghost field mentioned in ghost context
- {
- modify `g;
- modify `x; // error: non-ghost field mentioned in ghost context
- }
- method G1()
- modifies this;
- {
- modify `x;
- if g < 100 {
- // we are now in a ghost context
+}
+module ModifyStatementClass_More {
+ class C {
+ var x: int;
+ ghost var g: int;
+ ghost method G0()
+ modifies `g;
+ {
+ modify `g;
modify `x; // error: non-ghost field mentioned in ghost context
}
- }
- method G2(y: nat)
- modifies this;
- {
- if g < 100 {
- // we're now in a ghost context
- var n := 0;
- while n < y
- modifies `x; // error: non-ghost field mentioned in ghost context
- {
- if * {
- g := g + 1; // if we got as far as verification, this would be flagged as an error too
- }
- n := n + 1;
+ method G1()
+ modifies this;
+ {
+ modify `x;
+ if g < 100 {
+ // we are now in a ghost context
+ modify `x; // error: non-ghost field mentioned in ghost context
}
}
- modify `x; // fine
- ghost var i := 0;
- while i < y
- modifies `x; // error: non-ghost field mentioned in ghost context
+ method G2(y: nat)
+ modifies this;
{
- i := i + 1;
+ if g < 100 {
+ // we're now in a ghost context
+ var n := 0;
+ while n < y
+ modifies `x; // error: non-ghost field mentioned in ghost context
+ {
+ if * {
+ g := g + 1; // if we got as far as verification, this would be flagged as an error too
+ }
+ n := n + 1;
+ }
+ }
+ modify `x; // fine
+ ghost var i := 0;
+ while i < y
+ modifies `x; // error: non-ghost field mentioned in ghost context
+ {
+ i := i + 1;
+ }
}
}
}
@@ -1109,15 +1126,15 @@ method TraitSynonym()
// ----- set comprehensions where the term type is finite -----
module ObjectSetComprehensions {
- // allowed in non-ghost context:
- function A() : set<object> { set o : object | true :: o }
+ // the following set comprehensions are known to be finite
+ function A() : set<object> { set o : object | true :: o } // error: a function is not allowed to depend on the allocated state
- lemma B() { var x := set o : object | true :: o; }
+ function method B() : set<object> { set o : object | true :: o } // error: a function is not allowed to depend on the allocated state
- // not allowed in non-ghost context:
- function method C() : set<object> { set o : object | true :: o }
+ // outside functions, the comprehension is permitted, but it cannot be compiled
+ lemma C() { var x := set o : object | true :: o; }
- method D() { var x := set o : object | true :: o; }
+ method D() { var x := set o : object | true :: o; } // error: not (easily) compilable
}
// ------ regression test for type checking of integer division -----
@@ -1211,9 +1228,9 @@ module NonInferredTypeVariables {
method BadClient(n: nat)
{
var p := P(n); // error: cannot infer the type argument for P
- ghost var q := Q(n); // error: cannot infer the type argument for Q
+ ghost var q := Q(n); // error: cannot infer the type argument for Q (and thus q's type cannot be determined either)
M(n); // error: cannot infer the type argument for M
- var x := N(n); // error: cannot infer the type argument for N
+ var x := N(n); // error: cannot infer the type argument for N (and thus x's type cannot be determined either)
var a := new array; // error: cannot infer the type argument for 'array'
var c := new C; // error: cannot infer the type argument for 'C'
var s: set; // type argument for 'set'
@@ -1231,7 +1248,7 @@ module NonInferredTypeVariables {
ghost var d0 := forall s :: s == {7} ==> s != {};
var d1 := forall s: set :: s in S ==> s == {};
var ggcc0: C;
- var ggcc1: C;
+ var ggcc1: C; // error: full type cannot be determined
ghost var d2 := forall c: C :: c != null ==> c.f == 10;
ghost var d2' := forall c :: c == ggcc0 && c != null ==> c.f == 10;
ghost var d2'' := forall c :: c == ggcc1 && c != null ==> c.f == c.f; // error: here, type of c is not determined
@@ -1253,14 +1270,14 @@ module SignatureCompletion {
datatype Dt = Ctor(X -> Dt) // error: X is not a declared type
datatype Et<Y> = Ctor(X -> Et, Y) // error: X is not a declared type
- // For methods and functions, signatures can auto-declare type parameters
- method My0(s: set, x: A -> B)
- method My1(x: A -> B, s: set)
+
+ method My0<A,B>(s: set, x: A -> B)
+ method My1<A,B>(x: A -> B, s: set)
method My2<A,B>(s: set, x: A -> B)
method My3<A,B>(x: A -> B, s: set)
- function F0(s: set, x: A -> B): int
- function F1(x: A -> B, s: set): int
+ function F0<A,B>(s: set, x: A -> B): int
+ function F1<A,B>(x: A -> B, s: set): int
function F2<A,B>(s: set, x: A -> B): int
function F3<A,B>(x: A -> B, s: set): int
}
@@ -1292,7 +1309,7 @@ module FrameTargetFields {
modifies `z // cool
{
}
-
+} } module FrameTargetFields_More { class C { var x: int var y: int ghost var z: int
method P()
modifies this
{
@@ -1349,3 +1366,349 @@ module TupleEqualitySupport {
datatype GoodRecord = GoodRecord(set<(int,int)>)
datatype BadRecord = BadRecord(set<(int, int->bool)>) // error: this tuple type does not support equality
}
+
+// ------------------- non-type variable names -------------------
+
+module NonTypeVariableNames {
+ type X = int
+
+ module Y { }
+
+ method M(m: map<real,string>)
+ {
+ assert X == X; // error (x2): type name used as variable
+ assert Y == Y; // error (x2): module name used as variable
+ assert X in m; // error (x2): type name used as variable
+ assert Y in m; // error (x2): module name used as variable
+ }
+
+ method N(k: int)
+ {
+ assert k == X; // error (x2): type name used as variable
+ assert k == Y; // error (x2): module name used as variable
+ X := k; // error: type name used as variable
+ Y := k; // error: module name used as variable
+ }
+}
+
+// ------------------- assign-such-that and let-such-that -------------------
+
+module SuchThat {
+ method M() {
+ var x: int;
+ x :| 5 + 7; // error: constraint should be boolean
+ x :| x; // error: constraint should be boolean
+ var y :| 4; // error: constraint should be boolean
+ }
+ function F(): int {
+ var w :| 6 + 8; // error: constraint should be boolean
+ w
+ }
+}
+
+// ---------------------- NEW STUFF ----------------------------------------
+
+module GhostTests {
+ class G { }
+
+ method GhostNew3(n: nat)
+ {
+ var g := new G;
+ calc {
+ 5;
+ 2 + 3;
+ { if n != 0 { GhostNew3(n-1); } } // error: cannot call non-ghost method in a ghost context
+ 1 + 4;
+ { GhostNew4(g); } // error: cannot call method with nonempty modifies
+ -5 + 10;
+ }
+ }
+
+ ghost method GhostNew4(g: G)
+ modifies g;
+ {
+ }
+
+ class MyClass {
+ ghost method SideEffect()
+ modifies this;
+ {
+ }
+
+ method NonGhostMethod()
+ {
+ }
+
+ ghost method M()
+ modifies this;
+ {
+ calc {
+ 5;
+ { SideEffect(); } // error: cannot call method with side effects
+ 5;
+ }
+ }
+ function F(): int
+ {
+ calc {
+ 6;
+ { assert 6 < 8; }
+ { NonGhostMethod(); } // error: cannot call non-ghost method
+ { var x := 8;
+ while x != 0
+ {
+ x := x - 1;
+ }
+ }
+ { var x := 8;
+ while x != 0
+ {
+ x := x - 1;
+ }
+ }
+ { MyField := 12; } // error: cannot assign to a field, and especially not a non-ghost field
+ { MyGhostField := 12; } // error: cannot assign to any field
+ { SideEffect(); } // error: cannot call (ghost) method with a modifies clause
+ { var x := 8;
+ while x != 0
+ modifies this; // error: cannot use a modifies clause on a loop
+ {
+ x := x - 1;
+ }
+ }
+ 6;
+ }
+ 5
+ }
+ var MyField: int;
+ ghost var MyGhostField: int;
+ method N()
+ {
+ var y :=
+ calc {
+ 6;
+ { assert 6 < 8; }
+ { NonGhostMethod(); } // error: cannot call non-ghost method
+ { var x := 8;
+ while x != 0
+ {
+ x := x - 1;
+ }
+ }
+ { MyField := 12; } // error: cannot assign to a field, and especially not a non-ghost field
+ { MyGhostField := 12; } // error: cannot assign to any field
+ { M(); } // error: cannot call (ghost) method with a modifies clause
+ { var x := 8;
+ while x != 0
+ modifies this; // error: cannot use a modifies clause on a loop
+ {
+ x := x - 1;
+ }
+ }
+ { var x := 8;
+ while x != 0
+ {
+ x := x - 1;
+ }
+ }
+ 6;
+ }
+ 5;
+ }
+ ghost method MyLemma()
+ ghost method MyGhostMethod()
+ modifies this;
+ method OrdinaryMethod()
+ ghost method OutParamMethod() returns (y: int)
+
+ function UseLemma(): int
+ {
+ MyLemma();
+ OrdinaryMethod(); // error: not a ghost
+ 10
+ }
+ }
+}
+
+module EvenMoreGhostTests {
+ ghost method NiceTry()
+ ensures false;
+ {
+ while (true)
+ decreases * // error: not allowed here
+ {
+ }
+ }
+ method BreakMayNotBeFineHere()
+ {
+ var n := 0;
+ var p := 0;
+ while (true)
+ {
+ var dontKnow;
+ if (n == 112) {
+ } else if (dontKnow == 708) {
+ while * {
+ label IfNest:
+ if (p == 67) {
+ break break; // fine, since this is not a ghost context
+ } else if (*) {
+ break break break; // error: tries to break out of more loop levels than there are
+ }
+ }
+ }
+ }
+ }
+}
+
+module BadGhostTransfer {
+ datatype DTD_List = DTD_Nil | DTD_Cons(Car: int, Cdr: DTD_List, ghost g: int)
+
+ method DatatypeDestructors_Ghost(d: DTD_List) {
+ var g1 := d.g; // error: cannot use ghost member in non-ghost code
+ }
+ method AssignSuchThatFromGhost()
+ {
+ var x: int;
+ ghost var g: int;
+
+ x := g; // error: ghost cannot flow into non-ghost
+
+ x := *;
+ assume x == g; // this mix of ghosts and non-ghosts is cool (but, of course,
+ // the compiler will complain)
+
+ x :| x == g; // error: left-side has non-ghost, so RHS must be non-ghost as well
+
+ x :| assume x == g; // this is cool, since it's an assume (but, of course, the
+ // compiler will complain)
+
+ x :| x == 5;
+ g :| g <= g;
+ g :| assume g < g; // the compiler will complain here, despite the LHS being
+ // ghost -- and rightly so, since an assume is used
+ }
+}
+
+module MoreGhostPrintAttempts {
+ method TestCalc_Ghost(m: int, n: int, a: bool, b: bool)
+ {
+ calc {
+ n + m;
+ { print n + m; } // error: non-ghost statements are not allowed in hints
+ m + n;
+ }
+ }
+}
+
+module MoreLetSuchThatExpr {
+ method LetSuchThat_Ghost(ghost z: int, n: nat)
+ {
+ var x := var y :| y < z; y; // error: contraint depend on ghost (z)
+ }
+}
+
+module UnderspecifiedTypedShouldBeResolvedOnlyOnce {
+ method CalcTest0(s: seq<int>) {
+ calc {
+ 2;
+ var t :| true; 2; // error: type of 't' is underspecified
+ }
+ }
+}
+
+module LoopResolutionTests {
+ class C {
+ var x: int
+ ghost var y: int
+ }
+
+ ghost method M(c: C)
+ requires c != null
+ modifies c
+ {
+ var n := 0;
+ while n < 100
+ modifies c`y
+ modifies c`x // error: not allowed to mention non-ghost field in modifies clause of ghost loops
+ {
+ c.x := c.x + 1; // error: assignment to non-ghost field not allowed here
+ }
+ }
+
+ method MM(c: C)
+ requires c != null
+ modifies c
+ {
+ var n := 0;
+ while
+ invariant n <= 100
+ modifies c // regression test
+ {
+ case n < 100 => n := n + 1;
+ }
+ }
+
+ method MMX(c: C, ghost g: int)
+ requires c != null
+ modifies c
+ {
+ var n := 0;
+ while
+ invariant n <= 100
+ modifies c`y
+ modifies c`x // error: not allowed to mention non-ghost field in modifies clause of ghost loops
+ {
+ case n < 100 => n := n + 1; // error: cannot assign to non-ghost in a ghost loop
+ case g < 56 && n != 100 => n := n + 1; // error: cannot assign to non-ghost in a ghost loop
+ }
+ }
+
+ method MD0(c: C, ghost g: nat)
+ requires c != null
+ modifies c
+ decreases *
+ {
+ var n := 0;
+ while n + g < 100
+ invariant n <= 100
+ decreases * // error: disallowed on ghost loops
+ {
+ n := n + 1; // error: cannot assign to non-ghost in a ghost loop
+ }
+ }
+
+ method MD1(c: C, ghost g: nat)
+ requires c != null
+ modifies c
+ decreases *
+ {
+ var n := 0;
+ while
+ invariant n <= 100
+ decreases * // error: disallowed on ghost loops
+ {
+ case n + g < 100 => n := n + 1; // error: cannot assign to non-ghost in a ghost loop
+ }
+ }
+}
+
+module UnderspecifiedTypesInAttributes {
+ function method P<T>(x: T): int
+ method M() {
+ var {:myattr var u :| true; 6} v: int; // error: type of u is underspecified
+ var j {:myattr var u :| true; 6} :| 0 <= j < 100; // error: type of u is underspecified
+
+ var a := new int[100];
+ forall lp {:myattr var u :| true; 6} | 0 <= lp < 100 { // error: type of u is underspecified
+ a[lp] := 0;
+ }
+
+ modify {:myattr P(10)} {:myattr var u :| true; 6} a; // error: type of u is underspecified
+
+ calc {:myattr P(10)} {:myattr var u :| true; 6} // error: type of u is underspecified
+ {
+ 5;
+ }
+ }
+}
diff --git a/Test/dafny0/ResolutionErrors.dfy.expect b/Test/dafny0/ResolutionErrors.dfy.expect
index c215d354..d1d826f4 100644
--- a/Test/dafny0/ResolutionErrors.dfy.expect
+++ b/Test/dafny0/ResolutionErrors.dfy.expect
@@ -1,102 +1,3 @@
-ResolutionErrors.dfy(502,7): Error: RHS (of type List<A>) not assignable to LHS (of type List<B>)
-ResolutionErrors.dfy(507,7): Error: RHS (of type List<A>) not assignable to LHS (of type List<B>)
-ResolutionErrors.dfy(521,23): Error: type of case bodies do not agree (found Tree<_T1,_T0>, previous types Tree<_T0,_T1>)
-ResolutionErrors.dfy(533,24): Error: Wrong number of type arguments (0 instead of 2) passed to datatype: Tree
-ResolutionErrors.dfy(561,25): Error: the type of this variable is underspecified
-ResolutionErrors.dfy(561,23): Error: type variable 'T' in the function call to 'P' could not be determined
-ResolutionErrors.dfy(568,25): Error: the type of this variable is underspecified
-ResolutionErrors.dfy(568,23): Error: type variable 'T' in the function call to 'P' could not be determined
-ResolutionErrors.dfy(581,13): Error: 'new' is not allowed in ghost contexts
-ResolutionErrors.dfy(582,9): Error: 'new' is not allowed in ghost contexts
-ResolutionErrors.dfy(589,14): Error: new allocation not supported in forall statements
-ResolutionErrors.dfy(594,11): Error: the body of the enclosing forall statement is not allowed to update heap locations
-ResolutionErrors.dfy(594,14): Error: new allocation not allowed in ghost context
-ResolutionErrors.dfy(604,23): Error: 'new' is not allowed in ghost contexts
-ResolutionErrors.dfy(611,15): Error: 'new' is not allowed in ghost contexts
-ResolutionErrors.dfy(611,15): Error: only ghost methods can be called from this context
-ResolutionErrors.dfy(620,17): Error: 'new' is not allowed in ghost contexts
-ResolutionErrors.dfy(622,29): Error: only ghost methods can be called from this context
-ResolutionErrors.dfy(624,17): Error: calls to methods with side-effects are not allowed inside a hint
-ResolutionErrors.dfy(642,21): Error: the type of this variable is underspecified
-ResolutionErrors.dfy(680,13): Error: calls to methods with side-effects are not allowed inside a hint
-ResolutionErrors.dfy(690,17): Error: only ghost methods can be called from this context
-ResolutionErrors.dfy(693,15): Error: 'decreases *' is not allowed on ghost loops
-ResolutionErrors.dfy(704,11): Error: Assignment to non-ghost field is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
-ResolutionErrors.dfy(704,11): Error: a hint is not allowed to update heap locations
-ResolutionErrors.dfy(705,16): Error: a hint is not allowed to update heap locations
-ResolutionErrors.dfy(706,13): Error: calls to methods with side-effects are not allowed inside a hint
-ResolutionErrors.dfy(709,14): Error: a while statement used inside a hint is not allowed to have a modifies clause
-ResolutionErrors.dfy(728,17): Error: only ghost methods can be called from this context
-ResolutionErrors.dfy(731,15): Error: 'decreases *' is not allowed on ghost loops
-ResolutionErrors.dfy(736,11): Error: Assignment to non-ghost field is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
-ResolutionErrors.dfy(736,11): Error: a hint is not allowed to update heap locations
-ResolutionErrors.dfy(737,16): Error: a hint is not allowed to update heap locations
-ResolutionErrors.dfy(738,4): Error: calls to methods with side-effects are not allowed inside a hint
-ResolutionErrors.dfy(741,14): Error: a while statement used inside a hint is not allowed to have a modifies clause
-ResolutionErrors.dfy(766,19): Error: calls to methods with side-effects are not allowed inside a statement expression
-ResolutionErrors.dfy(767,20): Error: only ghost methods can be called from this context
-ResolutionErrors.dfy(768,20): Error: wrong number of method result arguments (got 0, expected 1)
-ResolutionErrors.dfy(780,23): Error: function calls are allowed only in specification contexts (consider declaring the function a 'function method')
-ResolutionErrors.dfy(790,4): Error: ghost variables are allowed only in specification contexts
-ResolutionErrors.dfy(801,36): Error: ghost variables are allowed only in specification contexts
-ResolutionErrors.dfy(810,17): Error: function calls are allowed only in specification contexts (consider declaring the function a 'function method')
-ResolutionErrors.dfy(824,6): Error: RHS (of type B) not assignable to LHS (of type object)
-ResolutionErrors.dfy(825,6): Error: RHS (of type int) not assignable to LHS (of type object)
-ResolutionErrors.dfy(826,6): Error: RHS (of type B) not assignable to LHS (of type object)
-ResolutionErrors.dfy(831,6): Error: RHS (of type G) not assignable to LHS (of type object)
-ResolutionErrors.dfy(832,6): Error: RHS (of type Dt) not assignable to LHS (of type object)
-ResolutionErrors.dfy(833,6): Error: RHS (of type CoDt) not assignable to LHS (of type object)
-ResolutionErrors.dfy(895,4): Error: LHS of array assignment must denote an array element (found seq<int>)
-ResolutionErrors.dfy(896,4): Error: LHS of array assignment must denote an array element (found seq<int>)
-ResolutionErrors.dfy(901,10): Error: LHS of assignment must denote a mutable field
-ResolutionErrors.dfy(902,10): Error: LHS of assignment must denote a mutable field
-ResolutionErrors.dfy(903,9): Error: cannot assign to a range of array elements (try the 'forall' statement)
-ResolutionErrors.dfy(904,9): Error: cannot assign to a range of array elements (try the 'forall' statement)
-ResolutionErrors.dfy(905,5): Error: cannot assign to a range of array elements (try the 'forall' statement)
-ResolutionErrors.dfy(906,5): Error: cannot assign to a range of array elements (try the 'forall' statement)
-ResolutionErrors.dfy(987,11): Error: Wrong number of type arguments (2 instead of 1) passed to array type: array3
-ResolutionErrors.dfy(988,11): Error: Wrong number of type arguments (2 instead of 1) passed to class: C
-ResolutionErrors.dfy(999,7): Error: Duplicate name of top-level declaration: BadSyn2
-ResolutionErrors.dfy(996,17): Error: Wrong number of type arguments (0 instead of 1) passed to datatype: List
-ResolutionErrors.dfy(997,17): Error: Undeclared top-level type or type parameter: badName (did you forget to qualify a name?)
-ResolutionErrors.dfy(998,22): Error: Undeclared top-level type or type parameter: X (did you forget to qualify a name?)
-ResolutionErrors.dfy(1005,7): Error: Cycle among redirecting types (newtypes, type synonyms): A -> A
-ResolutionErrors.dfy(1008,7): Error: Cycle among redirecting types (newtypes, type synonyms): A -> B -> A
-ResolutionErrors.dfy(1012,7): Error: Cycle among redirecting types (newtypes, type synonyms): A -> B -> A
-ResolutionErrors.dfy(1021,11): Error: because of cyclic dependencies among constructor argument types, no instances of datatype 'D' can be constructed
-ResolutionErrors.dfy(1024,7): Error: Cycle among redirecting types (newtypes, type synonyms): A -> B -> A
-ResolutionErrors.dfy(1029,7): Error: Cycle among redirecting types (newtypes, type synonyms): A -> B -> A
-ResolutionErrors.dfy(1048,21): Error: unresolved identifier: x
-ResolutionErrors.dfy(1055,35): Error: Wrong number of type arguments (2 instead of 1) passed to opaque type: P
-ResolutionErrors.dfy(1067,13): Error: Undeclared top-level type or type parameter: BX (did you forget to qualify a name?)
-ResolutionErrors.dfy(1077,6): Error: RHS (of type P<int>) not assignable to LHS (of type P<bool>)
-ResolutionErrors.dfy(1082,6): Error: RHS (of type P<A>) not assignable to LHS (of type P<B>)
-ResolutionErrors.dfy(1087,6): Error: RHS (of type P<A>) not assignable to LHS (of type P<int>)
-ResolutionErrors.dfy(1088,6): Error: RHS (of type P<int>) not assignable to LHS (of type P<A>)
-ResolutionErrors.dfy(1093,13): Error: arguments must have the same type (got P<int> and P<X>)
-ResolutionErrors.dfy(1094,13): Error: arguments must have the same type (got P<bool> and P<X>)
-ResolutionErrors.dfy(1095,13): Error: arguments must have the same type (got P<int> and P<bool>)
-ResolutionErrors.dfy(1118,38): Error: a set comprehension must produce a finite set, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'o'
-ResolutionErrors.dfy(1120,24): Error: a set comprehension must produce a finite set, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'o'
-ResolutionErrors.dfy(1225,26): Error: the type of this variable is underspecified
-ResolutionErrors.dfy(1226,31): Error: the type of this variable is underspecified
-ResolutionErrors.dfy(1227,29): Error: the type of this variable is underspecified
-ResolutionErrors.dfy(1237,34): Error: the type of this variable is underspecified
-ResolutionErrors.dfy(1253,21): Error: Undeclared top-level type or type parameter: X (did you forget to qualify a name?)
-ResolutionErrors.dfy(1254,24): Error: Undeclared top-level type or type parameter: X (did you forget to qualify a name?)
-ResolutionErrors.dfy(1291,16): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (y)
-ResolutionErrors.dfy(1301,18): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (x)
-ResolutionErrors.dfy(1329,15): Error: The name Inner ambiguously refers to a type in one of the modules A, B (try qualifying the type name with the module name)
-ResolutionErrors.dfy(1339,29): Error: ghost variables are allowed only in specification contexts
-ResolutionErrors.dfy(1341,49): Error: ghost variables are allowed only in specification contexts
-ResolutionErrors.dfy(1341,54): Error: ghost variables are allowed only in specification contexts
-ResolutionErrors.dfy(432,2): Error: More than one anonymous constructor
-ResolutionErrors.dfy(50,13): Error: 'this' is not allowed in a 'static' context
-ResolutionErrors.dfy(87,14): Error: the name 'Benny' denotes a datatype constructor, but does not do so uniquely; add an explicit qualification (for example, 'Abc.Benny')
-ResolutionErrors.dfy(92,14): Error: the name 'David' denotes a datatype constructor, but does not do so uniquely; add an explicit qualification (for example, 'Abc.David')
-ResolutionErrors.dfy(93,14): Error: the name 'David' denotes a datatype constructor, but does not do so uniquely; add an explicit qualification (for example, 'Abc.David')
-ResolutionErrors.dfy(95,14): Error: the name 'David' denotes a datatype constructor, but does not do so uniquely; add an explicit qualification (for example, 'Abc.David')
-ResolutionErrors.dfy(97,18): Error: wrong number of arguments to datatype constructor David (found 2, expected 1)
ResolutionErrors.dfy(113,9): Error: ghost variables are allowed only in specification contexts
ResolutionErrors.dfy(114,9): Error: function calls are allowed only in specification contexts (consider declaring the function a 'function method')
ResolutionErrors.dfy(118,11): Error: ghost variables are allowed only in specification contexts
@@ -107,31 +8,183 @@ ResolutionErrors.dfy(137,4): Error: ghost variables are allowed only in specific
ResolutionErrors.dfy(141,21): Error: ghost variables are allowed only in specification contexts
ResolutionErrors.dfy(142,35): Error: ghost variables are allowed only in specification contexts
ResolutionErrors.dfy(151,10): Error: only ghost methods can be called from this context
-ResolutionErrors.dfy(157,16): Error: 'decreases *' is not allowed on ghost loops
-ResolutionErrors.dfy(198,27): Error: ghost-context break statement is not allowed to break out of non-ghost structure
-ResolutionErrors.dfy(221,12): Error: ghost-context break statement is not allowed to break out of non-ghost loop
-ResolutionErrors.dfy(233,12): Error: trying to break out of more loop levels than there are enclosing loops
-ResolutionErrors.dfy(237,12): Error: ghost-context break statement is not allowed to break out of non-ghost loop
-ResolutionErrors.dfy(242,8): Error: return statement is not allowed in this context (because it is guarded by a specification-only expression)
-ResolutionErrors.dfy(408,11): Error: calls to methods with side-effects are not allowed inside a hint
-ResolutionErrors.dfy(410,14): Error: a hint is not allowed to update heap locations
-ResolutionErrors.dfy(412,10): Error: a hint is not allowed to update a variable declared outside the hint
-ResolutionErrors.dfy(438,14): Error: when allocating an object of type 'YHWH', one of its constructor methods must be called
-ResolutionErrors.dfy(443,6): Error: when allocating an object of type 'Lucifer', one of its constructor methods must be called
-ResolutionErrors.dfy(444,6): Error: when allocating an object of type 'Lucifer', one of its constructor methods must be called
-ResolutionErrors.dfy(446,9): Error: class Lamb does not have an anonymous constructor
-ResolutionErrors.dfy(844,11): Error: a modifies-clause expression must denote an object or a collection of objects (instead got int)
-ResolutionErrors.dfy(848,14): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (x)
-ResolutionErrors.dfy(851,12): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (x)
-ResolutionErrors.dfy(859,14): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (x)
-ResolutionErrors.dfy(869,18): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (x)
-ResolutionErrors.dfy(880,16): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (x)
-ResolutionErrors.dfy(1036,23): Error: unresolved identifier: x
-ResolutionErrors.dfy(1039,20): Error: unresolved identifier: x
-ResolutionErrors.dfy(1042,23): Error: unresolved identifier: x
-ResolutionErrors.dfy(1044,19): Error: unresolved identifier: x
-ResolutionErrors.dfy(1046,19): Error: unresolved identifier: x
-ResolutionErrors.dfy(12,16): Error: 'decreases *' is not allowed on ghost loops
+ResolutionErrors.dfy(241,27): Error: ghost-context break statement is not allowed to break out of non-ghost structure
+ResolutionErrors.dfy(264,12): Error: ghost-context break statement is not allowed to break out of non-ghost loop
+ResolutionErrors.dfy(278,12): Error: ghost-context break statement is not allowed to break out of non-ghost loop
+ResolutionErrors.dfy(283,8): Error: return statement is not allowed in this context (because it is guarded by a specification-only expression)
+ResolutionErrors.dfy(362,15): Error: ghost variables are allowed only in specification contexts
+ResolutionErrors.dfy(444,13): Error: calls to methods with side-effects are not allowed inside a hint
+ResolutionErrors.dfy(446,16): Error: a hint is not allowed to update heap locations
+ResolutionErrors.dfy(448,12): Error: a hint is not allowed to update a variable declared outside the hint
+ResolutionErrors.dfy(535,7): Error: RHS (of type List<A>) not assignable to LHS (of type List<B>)
+ResolutionErrors.dfy(540,7): Error: RHS (of type List<A>) not assignable to LHS (of type List<B>)
+ResolutionErrors.dfy(554,23): Error: type of case bodies do not agree (found Tree<_T1,_T0>, previous types Tree<_T0,_T1>)
+ResolutionErrors.dfy(566,24): Error: Wrong number of type arguments (0 instead of 2) passed to datatype: Tree
+ResolutionErrors.dfy(598,8): Error: the type of this local variable is underspecified
+ResolutionErrors.dfy(599,23): Error: type variable 'T' in the function call to 'P' could not be determined
+ResolutionErrors.dfy(599,18): Error: type of bound variable 'z' could not be determined; please specify the type explicitly
+ResolutionErrors.dfy(612,13): Error: 'new' is not allowed in ghost contexts
+ResolutionErrors.dfy(613,9): Error: 'new' is not allowed in ghost contexts
+ResolutionErrors.dfy(622,23): Error: 'new' is not allowed in ghost contexts
+ResolutionErrors.dfy(629,15): Error: 'new' is not allowed in ghost contexts
+ResolutionErrors.dfy(638,17): Error: 'new' is not allowed in ghost contexts
+ResolutionErrors.dfy(655,14): Error: new allocation not supported in forall statements
+ResolutionErrors.dfy(660,11): Error: the body of the enclosing forall statement is not allowed to update heap locations
+ResolutionErrors.dfy(660,14): Error: new allocation not allowed in ghost context
+ResolutionErrors.dfy(672,21): Error: the type of this variable is underspecified
+ResolutionErrors.dfy(712,22): Error: a possibly infinite loop is allowed only if the enclosing method is declared (with 'decreases *') to be possibly non-terminating
+ResolutionErrors.dfy(745,22): Error: a possibly infinite loop is allowed only if the enclosing method is declared (with 'decreases *') to be possibly non-terminating
+ResolutionErrors.dfy(776,19): Error: calls to methods with side-effects are not allowed inside a statement expression
+ResolutionErrors.dfy(777,20): Error: wrong number of method result arguments (got 0, expected 1)
+ResolutionErrors.dfy(789,23): Error: function calls are allowed only in specification contexts (consider declaring the function a 'function method')
+ResolutionErrors.dfy(799,4): Error: ghost variables are allowed only in specification contexts
+ResolutionErrors.dfy(810,36): Error: ghost variables are allowed only in specification contexts
+ResolutionErrors.dfy(819,17): Error: function calls are allowed only in specification contexts (consider declaring the function a 'function method')
+ResolutionErrors.dfy(833,6): Error: RHS (of type B) not assignable to LHS (of type object)
+ResolutionErrors.dfy(834,6): Error: RHS (of type int) not assignable to LHS (of type object)
+ResolutionErrors.dfy(835,6): Error: RHS (of type B) not assignable to LHS (of type object)
+ResolutionErrors.dfy(840,6): Error: RHS (of type G) not assignable to LHS (of type object)
+ResolutionErrors.dfy(841,6): Error: RHS (of type Dt) not assignable to LHS (of type object)
+ResolutionErrors.dfy(842,6): Error: RHS (of type CoDt) not assignable to LHS (of type object)
+ResolutionErrors.dfy(867,14): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (x)
+ResolutionErrors.dfy(875,16): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (x)
+ResolutionErrors.dfy(885,20): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (x)
+ResolutionErrors.dfy(896,18): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (x)
+ResolutionErrors.dfy(912,4): Error: LHS of array assignment must denote an array element (found seq<int>)
+ResolutionErrors.dfy(913,4): Error: LHS of array assignment must denote an array element (found seq<int>)
+ResolutionErrors.dfy(918,10): Error: LHS of assignment must denote a mutable field
+ResolutionErrors.dfy(919,10): Error: LHS of assignment must denote a mutable field
+ResolutionErrors.dfy(920,9): Error: cannot assign to a range of array elements (try the 'forall' statement)
+ResolutionErrors.dfy(921,9): Error: cannot assign to a range of array elements (try the 'forall' statement)
+ResolutionErrors.dfy(922,5): Error: cannot assign to a range of array elements (try the 'forall' statement)
+ResolutionErrors.dfy(923,5): Error: cannot assign to a range of array elements (try the 'forall' statement)
+ResolutionErrors.dfy(1004,11): Error: Wrong number of type arguments (2 instead of 1) passed to array type: array3
+ResolutionErrors.dfy(1005,11): Error: Wrong number of type arguments (2 instead of 1) passed to class: C
+ResolutionErrors.dfy(1016,7): Error: Duplicate name of top-level declaration: BadSyn2
+ResolutionErrors.dfy(1013,17): Error: Wrong number of type arguments (0 instead of 1) passed to datatype: List
+ResolutionErrors.dfy(1014,17): Error: Undeclared top-level type or type parameter: badName (did you forget to qualify a name or declare a module import 'opened?')
+ResolutionErrors.dfy(1015,22): Error: Undeclared top-level type or type parameter: X (did you forget to qualify a name or declare a module import 'opened?')
+ResolutionErrors.dfy(1022,7): Error: Cycle among redirecting types (newtypes, type synonyms): A -> A
+ResolutionErrors.dfy(1025,7): Error: Cycle among redirecting types (newtypes, type synonyms): A -> B -> A
+ResolutionErrors.dfy(1029,7): Error: Cycle among redirecting types (newtypes, type synonyms): A -> B -> A
+ResolutionErrors.dfy(1038,11): Error: because of cyclic dependencies among constructor argument types, no instances of datatype 'D' can be constructed
+ResolutionErrors.dfy(1041,7): Error: Cycle among redirecting types (newtypes, type synonyms): A -> B -> A
+ResolutionErrors.dfy(1046,7): Error: Cycle among redirecting types (newtypes, type synonyms): A -> B -> A
+ResolutionErrors.dfy(1065,21): Error: unresolved identifier: x
+ResolutionErrors.dfy(1072,35): Error: Wrong number of type arguments (2 instead of 1) passed to opaque type: P
+ResolutionErrors.dfy(1084,13): Error: Undeclared top-level type or type parameter: BX (did you forget to qualify a name or declare a module import 'opened?')
+ResolutionErrors.dfy(1094,6): Error: RHS (of type P<int>) not assignable to LHS (of type P<bool>)
+ResolutionErrors.dfy(1099,6): Error: RHS (of type P<A>) not assignable to LHS (of type P<B>)
+ResolutionErrors.dfy(1104,6): Error: RHS (of type P<A>) not assignable to LHS (of type P<int>)
+ResolutionErrors.dfy(1105,6): Error: RHS (of type P<int>) not assignable to LHS (of type P<A>)
+ResolutionErrors.dfy(1110,13): Error: arguments must have the same type (got P<int> and P<X>)
+ResolutionErrors.dfy(1111,13): Error: arguments must have the same type (got P<bool> and P<X>)
+ResolutionErrors.dfy(1112,13): Error: arguments must have the same type (got P<int> and P<bool>)
+ResolutionErrors.dfy(1130,31): Error: a set comprehension involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'o'
+ResolutionErrors.dfy(1132,38): Error: a set comprehension involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'o'
+ResolutionErrors.dfy(1137,24): Error: set comprehensions in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce or compile a bounded set of values for 'o'
+ResolutionErrors.dfy(1230,13): Error: type variable 'PT' in the function call to 'P' could not be determined
+ResolutionErrors.dfy(1231,14): Error: the type of this variable is underspecified
+ResolutionErrors.dfy(1231,19): Error: type variable 'QT' in the function call to 'Q' could not be determined
+ResolutionErrors.dfy(1232,4): Error: type '?' to the method 'M' is not determined
+ResolutionErrors.dfy(1233,8): Error: the type of this variable is underspecified
+ResolutionErrors.dfy(1233,13): Error: type '?' to the method 'N' is not determined
+ResolutionErrors.dfy(1234,8): Error: the type of this variable is underspecified
+ResolutionErrors.dfy(1235,8): Error: the type of this variable is underspecified
+ResolutionErrors.dfy(1236,8): Error: the type of this local variable is underspecified
+ResolutionErrors.dfy(1237,8): Error: the type of this variable is underspecified
+ResolutionErrors.dfy(1238,8): Error: the type of this local variable is underspecified
+ResolutionErrors.dfy(1242,26): Error: the type of this variable is underspecified
+ResolutionErrors.dfy(1242,21): Error: type of bound variable 's' could not be determined; please specify the type explicitly
+ResolutionErrors.dfy(1243,31): Error: the type of this variable is underspecified
+ResolutionErrors.dfy(1243,21): Error: type of bound variable 's' could not be determined; please specify the type explicitly
+ResolutionErrors.dfy(1244,29): Error: the type of this variable is underspecified
+ResolutionErrors.dfy(1244,21): Error: type of bound variable 'c' could not be determined; please specify the type explicitly
+ResolutionErrors.dfy(1251,8): Error: the type of this local variable is underspecified
+ResolutionErrors.dfy(1254,29): Error: type of bound variable 'c' could not be determined; please specify the type explicitly
+ResolutionErrors.dfy(1270,21): Error: Undeclared top-level type or type parameter: X (did you forget to qualify a name or declare a module import 'opened?')
+ResolutionErrors.dfy(1271,24): Error: Undeclared top-level type or type parameter: X (did you forget to qualify a name or declare a module import 'opened?')
+ResolutionErrors.dfy(1308,16): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (y)
+ResolutionErrors.dfy(1318,18): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (x)
+ResolutionErrors.dfy(1346,15): Error: The name Inner ambiguously refers to a type in one of the modules A, B (try qualifying the type name with the module name)
+ResolutionErrors.dfy(1356,29): Error: ghost variables are allowed only in specification contexts
+ResolutionErrors.dfy(1358,49): Error: ghost variables are allowed only in specification contexts
+ResolutionErrors.dfy(1358,54): Error: ghost variables are allowed only in specification contexts
+ResolutionErrors.dfy(1379,11): Error: name of type (X) is used as a variable
+ResolutionErrors.dfy(1379,16): Error: name of type (X) is used as a variable
+ResolutionErrors.dfy(1380,11): Error: name of module (Y) is used as a variable
+ResolutionErrors.dfy(1380,16): Error: name of module (Y) is used as a variable
+ResolutionErrors.dfy(1381,11): Error: name of type (X) is used as a variable
+ResolutionErrors.dfy(1381,13): Error: second argument to "in" must be a set, multiset, or sequence with elements of type #type, or a map with domain #type (instead got map<real, string>)
+ResolutionErrors.dfy(1382,11): Error: name of module (Y) is used as a variable
+ResolutionErrors.dfy(1382,13): Error: second argument to "in" must be a set, multiset, or sequence with elements of type #module, or a map with domain #module (instead got map<real, string>)
+ResolutionErrors.dfy(1387,16): Error: name of type (X) is used as a variable
+ResolutionErrors.dfy(1387,13): Error: arguments must have the same type (got int and #type)
+ResolutionErrors.dfy(1388,16): Error: name of module (Y) is used as a variable
+ResolutionErrors.dfy(1388,13): Error: arguments must have the same type (got int and #module)
+ResolutionErrors.dfy(1389,4): Error: name of type (X) is used as a variable
+ResolutionErrors.dfy(1390,4): Error: name of module (Y) is used as a variable
+ResolutionErrors.dfy(1399,11): Error: type of RHS of assign-such-that statement must be boolean (got int)
+ResolutionErrors.dfy(1400,9): Error: type of RHS of assign-such-that statement must be boolean (got int)
+ResolutionErrors.dfy(1401,13): Error: type of RHS of assign-such-that statement must be boolean (got int)
+ResolutionErrors.dfy(1404,15): Error: type of RHS of let-such-that expression must be boolean (got int)
+ResolutionErrors.dfy(1447,20): Error: calls to methods with side-effects are not allowed inside a hint
+ResolutionErrors.dfy(1469,18): Error: a hint is not allowed to update heap locations
+ResolutionErrors.dfy(1470,23): Error: a hint is not allowed to update heap locations
+ResolutionErrors.dfy(1471,20): Error: calls to methods with side-effects are not allowed inside a hint
+ResolutionErrors.dfy(1474,21): Error: a while statement used inside a hint is not allowed to have a modifies clause
+ResolutionErrors.dfy(1456,24): Error: only ghost methods can be called from this context
+ResolutionErrors.dfy(1469,18): Error: Assignment to non-ghost field is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+ResolutionErrors.dfy(1498,18): Error: a hint is not allowed to update heap locations
+ResolutionErrors.dfy(1499,23): Error: a hint is not allowed to update heap locations
+ResolutionErrors.dfy(1500,11): Error: calls to methods with side-effects are not allowed inside a hint
+ResolutionErrors.dfy(1503,21): Error: a while statement used inside a hint is not allowed to have a modifies clause
+ResolutionErrors.dfy(1491,24): Error: only ghost methods can be called from this context
+ResolutionErrors.dfy(1498,18): Error: Assignment to non-ghost field is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+ResolutionErrors.dfy(1527,20): Error: only ghost methods can be called from this context
+ResolutionErrors.dfy(1420,29): Error: only ghost methods can be called from this context
+ResolutionErrors.dfy(1422,17): Error: calls to methods with side-effects are not allowed inside a hint
+ResolutionErrors.dfy(1538,16): Error: a possibly infinite loop is allowed only if the enclosing method is declared (with 'decreases *') to be possibly non-terminating
+ResolutionErrors.dfy(1556,12): Error: trying to break out of more loop levels than there are enclosing loops
+ResolutionErrors.dfy(1568,16): Error: ghost fields are allowed only in specification contexts
+ResolutionErrors.dfy(1575,9): Error: ghost variables are allowed only in specification contexts
+ResolutionErrors.dfy(1581,4): Error: non-ghost variable cannot be assigned a value that depends on a ghost
+ResolutionErrors.dfy(1598,8): Error: print statement is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+ResolutionErrors.dfy(1607,26): Error: ghost variables are allowed only in specification contexts
+ResolutionErrors.dfy(1615,6): Error: the type of the bound variable 't' could not be determined
+ResolutionErrors.dfy(1633,15): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (x)
+ResolutionErrors.dfy(1635,10): Error: Assignment to non-ghost field is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+ResolutionErrors.dfy(1660,15): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (x)
+ResolutionErrors.dfy(1662,25): Error: Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+ResolutionErrors.dfy(1663,35): Error: Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+ResolutionErrors.dfy(1673,4): Error: 'decreases *' is not allowed on ghost loops
+ResolutionErrors.dfy(1677,8): Error: Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+ResolutionErrors.dfy(1687,4): Error: 'decreases *' is not allowed on ghost loops
+ResolutionErrors.dfy(1691,29): Error: Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+ResolutionErrors.dfy(1699,17): Error: the type of the bound variable 'u' could not be determined
+ResolutionErrors.dfy(1700,19): Error: the type of the bound variable 'u' could not be determined
+ResolutionErrors.dfy(1703,23): Error: the type of the bound variable 'u' could not be determined
+ResolutionErrors.dfy(1707,36): Error: the type of the bound variable 'u' could not be determined
+ResolutionErrors.dfy(1709,34): Error: the type of the bound variable 'u' could not be determined
+ResolutionErrors.dfy(469,2): Error: More than one anonymous constructor
+ResolutionErrors.dfy(50,13): Error: 'this' is not allowed in a 'static' context
+ResolutionErrors.dfy(87,14): Error: the name 'Benny' denotes a datatype constructor, but does not do so uniquely; add an explicit qualification (for example, 'Abc.Benny')
+ResolutionErrors.dfy(92,14): Error: the name 'David' denotes a datatype constructor, but does not do so uniquely; add an explicit qualification (for example, 'Abc.David')
+ResolutionErrors.dfy(93,14): Error: the name 'David' denotes a datatype constructor, but does not do so uniquely; add an explicit qualification (for example, 'Abc.David')
+ResolutionErrors.dfy(95,14): Error: the name 'David' denotes a datatype constructor, but does not do so uniquely; add an explicit qualification (for example, 'Abc.David')
+ResolutionErrors.dfy(97,18): Error: wrong number of arguments to datatype constructor David (found 2, expected 1)
+ResolutionErrors.dfy(475,6): Error: when allocating an object of type 'Y', one of its constructor methods must be called
+ResolutionErrors.dfy(480,6): Error: when allocating an object of type 'Luci', one of its constructor methods must be called
+ResolutionErrors.dfy(481,6): Error: when allocating an object of type 'Luci', one of its constructor methods must be called
+ResolutionErrors.dfy(483,9): Error: class Lamb does not have an anonymous constructor
+ResolutionErrors.dfy(853,11): Error: a modifies-clause expression must denote an object or a collection of objects (instead got int)
+ResolutionErrors.dfy(857,14): Error: in a ghost context, only ghost fields can be mentioned as modifies frame targets (x)
+ResolutionErrors.dfy(1053,23): Error: unresolved identifier: x
+ResolutionErrors.dfy(1056,20): Error: unresolved identifier: x
+ResolutionErrors.dfy(1059,23): Error: unresolved identifier: x
+ResolutionErrors.dfy(1061,19): Error: unresolved identifier: x
+ResolutionErrors.dfy(1063,19): Error: unresolved identifier: x
+ResolutionErrors.dfy(12,16): Error: a possibly infinite loop is allowed only if the enclosing method is declared (with 'decreases *') to be possibly non-terminating
ResolutionErrors.dfy(24,11): Error: array selection requires an array2 (got array3<T>)
ResolutionErrors.dfy(25,12): Error: sequence/array/multiset/map selection requires a sequence, array, multiset, or map (got array3<T>)
ResolutionErrors.dfy(26,11): Error: array selection requires an array4 (got array<T>)
@@ -144,42 +197,36 @@ ResolutionErrors.dfy(62,14): Error: accessing member 'M' requires an instance ex
ResolutionErrors.dfy(63,7): Error: unresolved identifier: N
ResolutionErrors.dfy(66,8): Error: non-function expression (of type int) is called with parameters
ResolutionErrors.dfy(67,14): Error: member 'z' does not exist in type 'Global'
-ResolutionErrors.dfy(260,4): Error: label shadows an enclosing label
-ResolutionErrors.dfy(265,2): Error: duplicate label
-ResolutionErrors.dfy(291,4): Error: when allocating an object of type 'ClassWithConstructor', one of its constructor methods must be called
-ResolutionErrors.dfy(292,4): Error: when allocating an object of type 'ClassWithConstructor', one of its constructor methods must be called
-ResolutionErrors.dfy(294,9): Error: a constructor is allowed to be called only when an object is being allocated
-ResolutionErrors.dfy(308,16): Error: arguments must have the same type (got int and DTD_List)
-ResolutionErrors.dfy(309,16): Error: arguments must have the same type (got DTD_List and int)
-ResolutionErrors.dfy(310,25): Error: arguments must have the same type (got bool and int)
-ResolutionErrors.dfy(313,18): Error: ghost fields are allowed only in specification contexts
-ResolutionErrors.dfy(322,15): Error: ghost variables are allowed only in specification contexts
-ResolutionErrors.dfy(347,5): Error: incorrect type of method in-parameter 1 (expected GenericClass<int>, got GenericClass<bool>)
-ResolutionErrors.dfy(359,18): Error: incorrect type of datatype constructor argument (found GList<_T0>, expected GList<int>)
-ResolutionErrors.dfy(367,6): Error: arguments to + must be of a numeric type or a collection type (instead got bool)
-ResolutionErrors.dfy(372,6): Error: all lines in a calculation must have the same type (got int after bool)
-ResolutionErrors.dfy(375,6): Error: first argument to ==> must be of type bool (instead got int)
-ResolutionErrors.dfy(375,6): Error: second argument to ==> must be of type bool (instead got int)
-ResolutionErrors.dfy(376,10): Error: first argument to ==> must be of type bool (instead got int)
-ResolutionErrors.dfy(376,10): Error: second argument to ==> must be of type bool (instead got int)
-ResolutionErrors.dfy(381,10): Error: first argument to ==> must be of type bool (instead got int)
-ResolutionErrors.dfy(381,10): Error: second argument to ==> must be of type bool (instead got int)
-ResolutionErrors.dfy(386,6): Error: print statement is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
-ResolutionErrors.dfy(470,7): Error: ghost variables are allowed only in specification contexts
-ResolutionErrors.dfy(476,12): Error: ghost variables are allowed only in specification contexts
-ResolutionErrors.dfy(546,20): Error: ghost variables are allowed only in specification contexts
-ResolutionErrors.dfy(549,18): Error: unresolved identifier: w
-ResolutionErrors.dfy(656,11): Error: lemmas are not allowed to have modifies clauses
-ResolutionErrors.dfy(918,9): Error: unresolved identifier: s
-ResolutionErrors.dfy(929,32): Error: RHS (of type (int,int,real)) not assignable to LHS (of type (int,real,int))
-ResolutionErrors.dfy(930,37): Error: RHS (of type (int,real,int)) not assignable to LHS (of type (int,real,int,real))
-ResolutionErrors.dfy(936,16): Error: condition is expected to be of type bool, but is int
-ResolutionErrors.dfy(937,16): Error: member 3 does not exist in datatype _tuple#3
-ResolutionErrors.dfy(937,26): Error: member x does not exist in datatype _tuple#2
-ResolutionErrors.dfy(960,15): Error: arguments to / must have the same type (got real and int)
-ResolutionErrors.dfy(961,10): Error: second argument to % must be of type int (instead got real)
-ResolutionErrors.dfy(1106,8): Error: new cannot be applied to a trait
-ResolutionErrors.dfy(1127,13): Error: first argument to / must be of numeric type (instead got set<bool>)
-ResolutionErrors.dfy(1134,18): Error: a call to a possibly non-terminating method is allowed only if the calling method is also declared (with 'decreases *') to be possibly non-terminating
-ResolutionErrors.dfy(1149,14): Error: a possibly infinite loop is allowed only if the enclosing method is declared (with 'decreases *') to be possibly non-terminating
-184 resolution/type errors detected in ResolutionErrors.dfy
+ResolutionErrors.dfy(301,4): Error: label shadows an enclosing label
+ResolutionErrors.dfy(306,2): Error: duplicate label
+ResolutionErrors.dfy(332,4): Error: when allocating an object of type 'ClassWithConstructor', one of its constructor methods must be called
+ResolutionErrors.dfy(333,4): Error: when allocating an object of type 'ClassWithConstructor', one of its constructor methods must be called
+ResolutionErrors.dfy(335,9): Error: a constructor is allowed to be called only when an object is being allocated
+ResolutionErrors.dfy(349,16): Error: arguments must have the same type (got int and DTD_List)
+ResolutionErrors.dfy(350,16): Error: arguments must have the same type (got DTD_List and int)
+ResolutionErrors.dfy(351,25): Error: arguments must have the same type (got bool and int)
+ResolutionErrors.dfy(387,5): Error: incorrect type of method in-parameter 1 (expected GenericClass<int>, got GenericClass<bool>)
+ResolutionErrors.dfy(399,18): Error: incorrect type of datatype constructor argument (found GList<_T0>, expected GList<int>)
+ResolutionErrors.dfy(407,6): Error: arguments to + must be of a numeric type or a collection type (instead got bool)
+ResolutionErrors.dfy(412,6): Error: all lines in a calculation must have the same type (got int after bool)
+ResolutionErrors.dfy(415,6): Error: first argument to ==> must be of type bool (instead got int)
+ResolutionErrors.dfy(415,6): Error: second argument to ==> must be of type bool (instead got int)
+ResolutionErrors.dfy(416,10): Error: first argument to ==> must be of type bool (instead got int)
+ResolutionErrors.dfy(416,10): Error: second argument to ==> must be of type bool (instead got int)
+ResolutionErrors.dfy(421,10): Error: first argument to ==> must be of type bool (instead got int)
+ResolutionErrors.dfy(421,10): Error: second argument to ==> must be of type bool (instead got int)
+ResolutionErrors.dfy(580,18): Error: unresolved identifier: w
+ResolutionErrors.dfy(686,11): Error: lemmas are not allowed to have modifies clauses
+ResolutionErrors.dfy(935,9): Error: unresolved identifier: s
+ResolutionErrors.dfy(946,32): Error: RHS (of type (int,int,real)) not assignable to LHS (of type (int,real,int))
+ResolutionErrors.dfy(947,37): Error: RHS (of type (int,real,int)) not assignable to LHS (of type (int,real,int,real))
+ResolutionErrors.dfy(953,16): Error: condition is expected to be of type bool, but is int
+ResolutionErrors.dfy(954,16): Error: member 3 does not exist in datatype _tuple#3
+ResolutionErrors.dfy(954,26): Error: member x does not exist in datatype _tuple#2
+ResolutionErrors.dfy(977,15): Error: arguments to / must have the same type (got real and int)
+ResolutionErrors.dfy(978,10): Error: second argument to % must be of type int (instead got real)
+ResolutionErrors.dfy(1123,8): Error: new cannot be applied to a trait
+ResolutionErrors.dfy(1144,13): Error: first argument to / must be of numeric type (instead got set<bool>)
+ResolutionErrors.dfy(1151,18): Error: a call to a possibly non-terminating method is allowed only if the calling method is also declared (with 'decreases *') to be possibly non-terminating
+ResolutionErrors.dfy(1166,14): Error: a possibly infinite loop is allowed only if the enclosing method is declared (with 'decreases *') to be possibly non-terminating
+231 resolution/type errors detected in ResolutionErrors.dfy
diff --git a/Test/dafny0/SeqFromArray.dfy b/Test/dafny0/SeqFromArray.dfy
index aa131f98..cf889804 100644
--- a/Test/dafny0/SeqFromArray.dfy
+++ b/Test/dafny0/SeqFromArray.dfy
@@ -1,6 +1,8 @@
-// RUN: %dafny /compile:3 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:3 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
+// /autoTriggers:1 added to suppress instabilities
+
method Main() { }
method H(a: array<int>, c: array<int>, n: nat, j: nat)
@@ -51,7 +53,7 @@ method L(a: array<int>, c: array<int>, n: nat)
case A == C =>
assert forall i :: 0 <= i < h ==> A[i] == C[i];
case A == C =>
- assert forall i :: 0 <= i < h ==> a[n+i] == c[n+i];
+ assert forall i :: n <= i < n + h ==> a[i] == c[i];
case true =>
}
}
@@ -71,20 +73,24 @@ method M(a: array<int>, c: array<int>, m: nat, n: nat, k: nat, l: nat)
} else if * {
assert forall i :: 0 <= i < n ==> A[i] == C[i];
} else if * {
- assert forall i :: k <= i < k+n ==> A[i-k] == C[i-k];
+ assert forall i {:nowarn} :: k <= i < k+n ==> A[i-k] == C[i-k];
} else if * {
assert forall i :: 0 <= i < n ==> A[i] == a[k+i];
} else if * {
assert forall i :: 0 <= i < n ==> C[i] == c[l+i];
} else if * {
- assert forall i :: 0 <= i < n ==> a[k+i] == c[l+i];
+ assert forall i {:nowarn} :: 0 <= i < n ==> a[k+i] == c[l+i];
}
}
case l+m <= c.Length && forall i :: 0 <= i < m ==> a[i] == c[l+i] =>
assert a[..m] == c[l..l+m];
case l+a.Length <= c.Length && forall i :: k <= i < a.Length ==> a[i] == c[l+i] =>
- assert a[k..] == c[l+k..l+a.Length];
+ assert a[k..] == c[l+k..l+a.Length];
case l+k+m <= c.Length && forall i :: k <= i < k+m ==> a[i] == c[l+i] =>
- assert a[k..k+m] == c[l+k..l+k+m];
+ assert a[k..k+m] == c[l+k..l+k+m];
}
}
+
+// Local Variables:
+// dafny-prover-local-args: ("/autoTriggers:1")
+// End:
diff --git a/Test/dafny0/Shadows.dfy b/Test/dafny0/Shadows.dfy
new file mode 100644
index 00000000..da1e74d6
--- /dev/null
+++ b/Test/dafny0/Shadows.dfy
@@ -0,0 +1,42 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /warnShadowing "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+module Module0 {
+ class C<alpha> {
+ method M<beta, beta>(x: beta) // error: duplicate type parameter
+ method P<alpha>(x: alpha) // shadowed type parameter
+ function F<beta, beta>(x: beta): int // error: duplicate type parameter
+ function G<alpha>(x: alpha): int // shadowed type parameter
+
+ method Q0(x: int) returns (x: int) // error: duplicate variable name
+ }
+}
+module Module1 {
+ class D {
+ method Q1(x: int) returns (y: int)
+ {
+ var x; // shadowed
+ var y; // error: duplicate
+ }
+
+ var f: int
+ method R()
+ {
+ var f; // okay
+ var f; // error: duplicate
+ }
+ method S()
+ {
+ var x;
+ {
+ var x; // shadow
+ }
+ }
+ method T()
+ {
+ var x;
+ ghost var b := forall x :: x < 10; // shadow
+ ghost var c := forall y :: forall y :: y != y + 1; // shadow
+ }
+ }
+}
diff --git a/Test/dafny0/Shadows.dfy.expect b/Test/dafny0/Shadows.dfy.expect
new file mode 100644
index 00000000..5083ac64
--- /dev/null
+++ b/Test/dafny0/Shadows.dfy.expect
@@ -0,0 +1,12 @@
+Shadows.dfy(6,19): Error: Duplicate type-parameter name: beta
+Shadows.dfy(7,13): Warning: Shadowed type-parameter name: alpha
+Shadows.dfy(8,21): Error: Duplicate type-parameter name: beta
+Shadows.dfy(9,15): Warning: Shadowed type-parameter name: alpha
+Shadows.dfy(11,31): Error: Duplicate parameter name: x
+Shadows.dfy(18,10): Warning: Shadowed local-variable name: x
+Shadows.dfy(19,10): Error: Duplicate local-variable name: y
+Shadows.dfy(26,10): Error: Duplicate local-variable name: f
+Shadows.dfy(32,12): Warning: Shadowed local-variable name: x
+Shadows.dfy(38,28): Warning: Shadowed bound-variable name: x
+Shadows.dfy(39,40): Warning: Shadowed bound-variable name: y
+5 resolution/type errors detected in Shadows.dfy
diff --git a/Test/dafny0/Simple.dfy b/Test/dafny0/Simple.dfy
index f7bfcb70..0b6a620e 100644
--- a/Test/dafny0/Simple.dfy
+++ b/Test/dafny0/Simple.dfy
@@ -74,3 +74,30 @@ class CF {
static protected function method I(): real
protected static predicate method J()
}
+
+// test printing of various if statements, including with omitted guards
+module A {
+ method P(x: int, y: int) {
+ if x==2 {
+ } else if * {
+ }
+ if x==10 {
+ }
+ if y==0 {
+ } else if y==1 {
+ } else if * {
+ } else if y==2 {
+ } else if (*) {
+ } else if y == 3 {
+ } else {
+ }
+ }
+}
+module B refines A {
+ method P... {
+ if ... {
+ } else if x==3 {
+ }
+ ...;
+ }
+}
diff --git a/Test/dafny0/Simple.dfy.expect b/Test/dafny0/Simple.dfy.expect
index e6647c8a..d5eb6722 100644
--- a/Test/dafny0/Simple.dfy.expect
+++ b/Test/dafny0/Simple.dfy.expect
@@ -67,6 +67,35 @@ class CF {
static protected predicate method J()
}
+module A {
+ method P(x: int, y: int)
+ {
+ if x == 2 {
+ } else if * {
+ }
+ if x == 10 {
+ }
+ if y == 0 {
+ } else if y == 1 {
+ } else if * {
+ } else if y == 2 {
+ } else if * {
+ } else if y == 3 {
+ } else {
+ }
+ }
+}
+
+module B refines A {
+ method P ...
+ {
+ if ... {
+ } else if x == 3 {
+ }
+ ...;
+ }
+}
+
lemma M(x: int)
ensures x < 8
{
diff --git a/Test/dafny0/Skeletons.dfy.expect b/Test/dafny0/Skeletons.dfy.expect
index 43b372c3..4b48bad0 100644
--- a/Test/dafny0/Skeletons.dfy.expect
+++ b/Test/dafny0/Skeletons.dfy.expect
@@ -1,5 +1,5 @@
-Skeletons.dfy(45,3): Error BP5003: A postcondition might not hold on this return path.
-Skeletons.dfy(44,15): Related location: This is the postcondition that might not hold.
+Skeletons.dfy(45,2): Error BP5003: A postcondition might not hold on this return path.
+Skeletons.dfy(44,14): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
Skeletons.dfy[C0](32,5): anon11_LoopHead
diff --git a/Test/dafny0/SmallTests.dfy b/Test/dafny0/SmallTests.dfy
index 65db7f7f..ba009b83 100644
--- a/Test/dafny0/SmallTests.dfy
+++ b/Test/dafny0/SmallTests.dfy
@@ -1,4 +1,5 @@
-// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint.dfy" "%s" > "%t"; %dafny /noVerify /compile:0 "%t.dprint.dfy" >> "%t"
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint.dfy" /autoTriggers:1 "%s" > "%t"
+// RUN: %dafny /noVerify /compile:0 "%t.dprint.dfy" >> "%t"
// RUN: %diff "%s.expect" "%t"
class Node {
@@ -34,11 +35,11 @@ class Node {
}
method Sequence(s: seq<bool>, j: int, b: bool, c: bool) returns (t: seq<bool>)
- requires 10 <= |s|;
- requires 8 <= j && j < |s|;
- ensures |t| == |s|;
- ensures t[8] == s[8] || t[9] == s[9];
- ensures t[j] == b;
+ requires 10 <= |s|
+ requires 8 <= j < |s|
+ ensures |t| == |s|
+ ensures t[8] == s[8] || t[9] == s[9]
+ ensures t[j] == b
{
if (c) {
t := s[j := b];
@@ -48,14 +49,14 @@ class Node {
}
method Max0(x: int, y: int) returns (r: int)
- ensures r == (if x < y then y else x);
+ ensures r == (if x < y then y else x)
{
if (x < y) { r := y; } else { r := x; }
}
method Max1(x: int, y: int) returns (r: int)
- ensures r == x || r == y;
- ensures x <= r && y <= r;
+ ensures r == x || r == y
+ ensures x <= r && y <= r
{
r := if x < y then y else x;
}
@@ -121,12 +122,12 @@ class Modifies {
method C(b: bool)
modifies this;
- ensures !b ==> x == old(x) && next == old(next);
+ ensures !b ==> x == old(x) && next == old(next)
{
}
method D(p: Modifies, y: int)
- requires p != null;
+ requires p != null
{
if (y == 3) {
p.C(true); // error: may violate modifies clause
@@ -229,15 +230,15 @@ class InitCalls {
method Init(y: int)
modifies this;
- ensures z == y;
+ ensures z == y
{
z := y;
}
method InitFromReference(q: InitCalls)
- requires q != null && 15 <= q.z;
+ requires q != null && 15 <= q.z
modifies this;
- ensures p == q;
+ ensures p == q
{
p := q;
}
@@ -264,35 +265,35 @@ class InitCalls {
// --------------- some tests with quantifiers and ranges ----------------------
method QuantifierRange0<T>(a: seq<T>, x: T, y: T, N: int)
- requires 0 <= N && N <= |a|;
- requires forall k | 0 <= k && k < N :: a[k] != x;
- requires exists k | 0 <= k && k < N :: a[k] == y;
- ensures forall k :: 0 <= k && k < N ==> a[k] != x; // same as the precondition, but using ==> instead of |
- ensures exists k :: 0 <= k && k < N && a[k] == y; // same as the precondition, but using && instead of |
+ requires 0 <= N <= |a|
+ requires forall k | 0 <= k < N :: a[k] != x
+ requires exists k | 0 <= k < N :: a[k] == y
+ ensures forall k :: 0 <= k < N ==> a[k] != x; // same as the precondition, but using ==> instead of |
+ ensures exists k :: 0 <= k < N && a[k] == y; // same as the precondition, but using && instead of |
{
assert x != y;
}
method QuantifierRange1<T>(a: seq<T>, x: T, y: T, N: int)
- requires 0 <= N && N <= |a|;
- requires forall k :: 0 <= k && k < N ==> a[k] != x;
- requires exists k :: 0 <= k && k < N && a[k] == y;
- ensures forall k | 0 <= k && k < N :: a[k] != x; // same as the precondition, but using | instead of ==>
- ensures exists k | 0 <= k && k < N :: a[k] == y; // same as the precondition, but using | instead of &&
+ requires 0 <= N <= |a|
+ requires forall k :: 0 <= k < N ==> a[k] != x
+ requires exists k :: 0 <= k < N && a[k] == y
+ ensures forall k | 0 <= k < N :: a[k] != x; // same as the precondition, but using | instead of ==>
+ ensures exists k | 0 <= k < N :: a[k] == y; // same as the precondition, but using | instead of &&
{
assert x != y;
}
method QuantifierRange2<T(==)>(a: seq<T>, x: T, y: T, N: int)
- requires 0 <= N && N <= |a|;
- requires exists k | 0 <= k && k < N :: a[k] == y;
- ensures forall k | 0 <= k && k < N :: a[k] == y; // error
+ requires 0 <= N <= |a|
+ requires exists k | 0 <= k < N :: a[k] == y
+ ensures forall k | 0 <= k < N :: a[k] == y; // error
{
assert N != 0;
if (N == 1) {
- assert forall k | a[if 0 <= k && k < N then k else 0] != y :: k < 0 || N <= k; // in this case, the precondition holds trivially
+ assert forall k {:nowarn} | a[if 0 <= k < N then k else 0] != y :: k < 0 || N <= k; // in this case, the precondition holds trivially
}
- if (forall k | 0 <= k && k < N :: a[k] == x) {
+ if (forall k | 0 <= k < N :: a[k] == x) {
assert x == y;
}
}
@@ -300,8 +301,8 @@ method QuantifierRange2<T(==)>(a: seq<T>, x: T, y: T, N: int)
// ----------------------- tests that involve sequences of boxes --------
ghost method M(zeros: seq<bool>, Z: bool)
- requires 1 <= |zeros| && Z == false;
- requires forall k :: 0 <= k && k < |zeros| ==> zeros[k] == Z;
+ requires 1 <= |zeros| && Z == false
+ requires forall k :: 0 <= k < |zeros| ==> zeros[k] == Z
{
var x := [Z];
assert zeros[0..1] == [Z];
@@ -311,7 +312,7 @@ class SomeType
{
var x: int;
method DoIt(stack: seq<SomeType>)
- requires null !in stack;
+ requires null !in stack
modifies stack;
{
forall n | n in stack {
@@ -331,7 +332,8 @@ method TestSequences0()
assert 1 !in s;
} else {
assert 2 in s;
- assert exists n :: n in s && -3 <= n && n < 2;
+ assert 0 in s;
+ assert exists n :: n in s && -3 <= n < 2;
}
assert 7 in s; // error
}
@@ -397,7 +399,7 @@ class Test {
function F(b: bool): int
// The if-then-else in the following line was once translated incorrectly,
// incorrectly causing the postcondition to verify
- ensures if b then F(b) == 5 else F(b) == 6;
+ ensures if b then F(b) == 5 else F(b) == 6
{
5
}
@@ -428,10 +430,10 @@ class AttributeTests {
}
method testAttributes0() returns (r: AttributeTests)
- ensures {:boolAttr true} true;
- ensures {:boolAttr false} true;
- ensures {:intAttr 0} true;
- ensures {:intAttr 1} true;
+ ensures {:boolAttr true} true
+ ensures {:boolAttr false} true
+ ensures {:intAttr 0} true
+ ensures {:intAttr 1} true
modifies {:boolAttr true} this`f;
modifies {:boolAttr false} this`f;
modifies {:intAttr 0} this`f;
@@ -539,7 +541,7 @@ method TestNotNot()
// ----------------------- Assign-such-that statements -------
method AssignSuchThat0(a: int, b: int) returns (x: int, y: int)
- ensures x == a && y == b;
+ ensures x == a && y == b
{
if (*) {
x, y :| a <= x < a + 1 && b + a <= y + a && y <= b;
@@ -633,7 +635,7 @@ method AssignSuchThat9() returns (q: QuiteFinite)
function method LetSuchThat_P(x: int): bool
method LetSuchThat0(ghost g: int)
- requires LetSuchThat_P(g);
+ requires LetSuchThat_P(g)
{
var t :| LetSuchThat_P(t); // assign-such-that statement
ghost var u := var q :| LetSuchThat_P(q); q + 1; // let-such-that expression
@@ -708,10 +710,10 @@ class GT {
{
if (*) {
P0();
- assert forall x: GT :: x != null ==> !fresh(x); // error: method P2 may have allocated stuff
+ assert forall x: GT {:nowarn} :: x != null ==> !fresh(x); // error: method P2 may have allocated stuff
} else {
P1();
- assert forall x: GT :: x != null ==> !fresh(x); // fine, because the ghost method does not allocate anything
+ assert forall x: GT {:nowarn} :: x != null ==> !fresh(x); // fine, because the ghost method does not allocate anything
}
}
}
@@ -775,20 +777,20 @@ module GenericPick {
var x :| x in s; x
}
function SeqPick3<U>(s: seq<U>): U
- requires exists i :: 0 <= i < |s|
+ requires exists i {:nowarn} :: 0 <= i < |s|
{
EquivalentWaysOfSayingSequenceIsNonempty(s); // I wish this wasn't needed; see comment near Seq#Length axioms in DafnyPrelude.bpl
var x :| x in s; x
}
function SeqPick4<U>(s: seq<U>): U
- requires exists i :: 0 <= i < |s|
+ requires exists i {:nowarn} :: 0 <= i < |s|
{
var i :| 0 <= i < |s|; s[i]
}
lemma EquivalentWaysOfSayingSequenceIsNonempty<U>(s: seq<U>)
requires s != []
|| |s| != 0
- || exists i :: 0 <= i < |s|
+ || exists i {:nowarn} :: 0 <= i < |s|
ensures exists x :: x in s
{
assert s[0] in s;
diff --git a/Test/dafny0/SmallTests.dfy.expect b/Test/dafny0/SmallTests.dfy.expect
index 5f766cd6..746e978a 100644
--- a/Test/dafny0/SmallTests.dfy.expect
+++ b/Test/dafny0/SmallTests.dfy.expect
@@ -1,43 +1,42 @@
-SmallTests.dfy(33,11): Error: index out of range
+SmallTests.dfy(507,4): Warning: /!\ No trigger covering all quantified variables found.
+SmallTests.dfy(34,10): Error: index out of range
Execution trace:
(0,0): anon0
-SmallTests.dfy(64,36): Error: possible division by zero
+SmallTests.dfy(65,35): Error: possible division by zero
Execution trace:
(0,0): anon0
- (0,0): anon12_Then
-SmallTests.dfy(65,51): Error: possible division by zero
+ (0,0): anon13_Then
+SmallTests.dfy(66,50): Error: possible division by zero
Execution trace:
(0,0): anon0
- (0,0): anon12_Else
- (0,0): anon3
(0,0): anon13_Else
-SmallTests.dfy(66,22): Error: target object may be null
+ (0,0): anon14_Else
+SmallTests.dfy(67,21): Error: target object may be null
Execution trace:
(0,0): anon0
- (0,0): anon12_Then
- (0,0): anon3
(0,0): anon13_Then
- (0,0): anon6
-SmallTests.dfy(85,24): Error: target object may be null
+ (0,0): anon14_Then
+ (0,0): anon15_Then
+SmallTests.dfy(86,23): Error: target object may be null
Execution trace:
(0,0): anon0
- SmallTests.dfy(84,5): anon8_LoopHead
+ SmallTests.dfy(85,5): anon8_LoopHead
(0,0): anon8_LoopBody
(0,0): anon9_Then
-SmallTests.dfy(119,6): Error: call may violate context's modifies clause
+SmallTests.dfy(120,5): Error: call may violate context's modifies clause
Execution trace:
(0,0): anon0
(0,0): anon4_Else
(0,0): anon3
-SmallTests.dfy(132,10): Error: call may violate context's modifies clause
+SmallTests.dfy(133,9): Error: call may violate context's modifies clause
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-SmallTests.dfy(134,10): Error: call may violate context's modifies clause
+SmallTests.dfy(135,9): Error: call may violate context's modifies clause
Execution trace:
(0,0): anon0
(0,0): anon3_Else
-SmallTests.dfy(174,9): Error: assignment may update an object field not in the enclosing context's modifies clause
+SmallTests.dfy(175,8): Error: assignment may update an object field not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
(0,0): anon22_Else
@@ -46,23 +45,23 @@ Execution trace:
(0,0): anon28_Then
(0,0): anon29_Then
(0,0): anon19
-SmallTests.dfy(198,14): Error: assertion violation
+SmallTests.dfy(199,13): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon9_Then
-SmallTests.dfy(205,14): Error: assertion violation
+SmallTests.dfy(206,13): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon9_Else
(0,0): anon3
(0,0): anon10_Then
-SmallTests.dfy(207,14): Error: assertion violation
+SmallTests.dfy(208,13): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon9_Else
(0,0): anon3
(0,0): anon10_Else
-SmallTests.dfy(212,14): Error: assertion violation
+SmallTests.dfy(213,13): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon9_Else
@@ -70,7 +69,7 @@ Execution trace:
(0,0): anon10_Then
(0,0): anon6
(0,0): anon11_Then
-SmallTests.dfy(214,14): Error: assertion violation
+SmallTests.dfy(215,13): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon9_Else
@@ -78,37 +77,38 @@ Execution trace:
(0,0): anon10_Then
(0,0): anon6
(0,0): anon11_Else
-SmallTests.dfy(260,24): Error BP5002: A precondition for this call might not hold.
-SmallTests.dfy(238,30): Related location: This is the precondition that might not hold.
+SmallTests.dfy(261,23): Error BP5002: A precondition for this call might not hold.
+SmallTests.dfy(239,29): Related location: This is the precondition that might not hold.
Execution trace:
(0,0): anon0
- SmallTests.dfy(255,19): anon3_Else
+ SmallTests.dfy(256,19): anon3_Else
(0,0): anon2
-SmallTests.dfy(365,12): Error: assertion violation
+SmallTests.dfy(367,11): Error: assertion violation
Execution trace:
(0,0): anon0
-SmallTests.dfy(375,12): Error: assertion violation
+SmallTests.dfy(377,11): Error: assertion violation
Execution trace:
(0,0): anon0
-SmallTests.dfy(385,6): Error: cannot prove termination; try supplying a decreases clause
+SmallTests.dfy(387,5): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-SmallTests.dfy(690,14): Error: assertion violation
+ (0,0): anon4_Else
+SmallTests.dfy(692,13): Error: assertion violation
Execution trace:
(0,0): anon0
- SmallTests.dfy(687,5): anon7_LoopHead
+ SmallTests.dfy(689,5): anon7_LoopHead
(0,0): anon7_LoopBody
- SmallTests.dfy(687,5): anon8_Else
+ SmallTests.dfy(689,5): anon8_Else
(0,0): anon9_Then
-SmallTests.dfy(711,14): Error: assertion violation
+SmallTests.dfy(713,13): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon7_Then
(0,0): anon8_Then
(0,0): anon3
-SmallTests.dfy(295,3): Error BP5003: A postcondition might not hold on this return path.
-SmallTests.dfy(289,11): Related location: This is the postcondition that might not hold.
+SmallTests.dfy(296,2): Error BP5003: A postcondition might not hold on this return path.
+SmallTests.dfy(290,10): Related location: This is the postcondition that might not hold.
+SmallTests.dfy(290,40): Related location
Execution trace:
(0,0): anon0
(0,0): anon18_Else
@@ -116,29 +116,29 @@ Execution trace:
(0,0): anon24_Then
(0,0): anon15
(0,0): anon25_Else
-SmallTests.dfy(336,12): Error: assertion violation
+SmallTests.dfy(338,11): Error: assertion violation
Execution trace:
(0,0): anon0
- (0,0): anon8_Then
- (0,0): anon7
-SmallTests.dfy(343,10): Error: assertion violation
+ (0,0): anon7_Then
+ (0,0): anon6
+SmallTests.dfy(345,9): Error: assertion violation
Execution trace:
(0,0): anon0
-SmallTests.dfy(353,4): Error: cannot prove termination; try supplying a decreases clause
+SmallTests.dfy(355,3): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-SmallTests.dfy(397,10): Error BP5003: A postcondition might not hold on this return path.
-SmallTests.dfy(400,41): Related location: This is the postcondition that might not hold.
+ (0,0): anon4_Else
+SmallTests.dfy(399,9): Error BP5003: A postcondition might not hold on this return path.
+SmallTests.dfy(402,40): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
- (0,0): anon6_Else
-SmallTests.dfy(561,12): Error: assertion violation
+ (0,0): anon7_Else
+SmallTests.dfy(563,11): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Then
(0,0): anon2
-SmallTests.dfy(575,20): Error: left-hand sides 0 and 1 may refer to the same location
+SmallTests.dfy(577,19): Error: left-hand sides 0 and 1 may refer to the same location
Execution trace:
(0,0): anon0
(0,0): anon27_Then
@@ -150,11 +150,11 @@ Execution trace:
(0,0): anon31_Then
(0,0): anon32_Then
(0,0): anon12
-SmallTests.dfy(577,15): Error: left-hand sides 1 and 2 may refer to the same location
+SmallTests.dfy(579,14): Error: left-hand sides 1 and 2 may refer to the same location
Execution trace:
(0,0): anon0
(0,0): anon27_Then
- SmallTests.dfy(570,18): anon28_Else
+ SmallTests.dfy(572,18): anon28_Else
(0,0): anon4
(0,0): anon29_Else
(0,0): anon30_Then
@@ -165,16 +165,16 @@ Execution trace:
(0,0): anon37_Then
(0,0): anon22
(0,0): anon38_Then
-SmallTests.dfy(584,25): Error: target object may be null
+SmallTests.dfy(586,24): Error: target object may be null
Execution trace:
(0,0): anon0
-SmallTests.dfy(597,10): Error: assertion violation
+SmallTests.dfy(599,9): Error: assertion violation
Execution trace:
(0,0): anon0
-SmallTests.dfy(621,5): Error: cannot establish the existence of LHS values that satisfy the such-that predicate
+SmallTests.dfy(623,4): Error: cannot establish the existence of LHS values that satisfy the such-that predicate
Execution trace:
(0,0): anon0
-SmallTests.dfy(644,23): Error: assertion violation
+SmallTests.dfy(646,22): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon8_Then
@@ -182,20 +182,21 @@ Execution trace:
(0,0): anon4
(0,0): anon10_Then
(0,0): anon7
-SmallTests.dfy(658,10): Error: cannot establish the existence of LHS values that satisfy the such-that predicate
+SmallTests.dfy(660,9): Error: cannot establish the existence of LHS values that satisfy the such-that predicate
Execution trace:
(0,0): anon0
(0,0): anon5_Then
(0,0): anon6_Then
(0,0): anon3
-SmallTests.dfy(660,10): Error: cannot establish the existence of LHS values that satisfy the such-that predicate
+SmallTests.dfy(662,9): Error: cannot establish the existence of LHS values that satisfy the such-that predicate
Execution trace:
(0,0): anon0
(0,0): anon5_Else
-SmallTests.dfy(673,9): Error: cannot establish the existence of LHS values that satisfy the such-that predicate
+SmallTests.dfy(675,8): Error: cannot establish the existence of LHS values that satisfy the such-that predicate
Execution trace:
(0,0): anon0
Dafny program verifier finished with 104 verified, 35 errors
+SmallTests.dfy.tmp.dprint.dfy(369,4): Warning: /!\ No trigger covering all quantified variables found.
Dafny program verifier finished with 0 verified, 0 errors
diff --git a/Test/dafny0/SplitExpr.dfy.expect b/Test/dafny0/SplitExpr.dfy.expect
index b7ef524f..29dd6eda 100644
--- a/Test/dafny0/SplitExpr.dfy.expect
+++ b/Test/dafny0/SplitExpr.dfy.expect
@@ -1,5 +1,5 @@
-SplitExpr.dfy(92,15): Error: loop invariant violation
-SplitExpr.dfy(86,44): Related location
+SplitExpr.dfy(92,14): Error: loop invariant violation
+SplitExpr.dfy(86,43): Related location
Execution trace:
SplitExpr.dfy(91,3): anon7_LoopHead
diff --git a/Test/dafny0/StatementExpressions.dfy.expect b/Test/dafny0/StatementExpressions.dfy.expect
index 313c8884..936a3954 100644
--- a/Test/dafny0/StatementExpressions.dfy.expect
+++ b/Test/dafny0/StatementExpressions.dfy.expect
@@ -1,22 +1,22 @@
-StatementExpressions.dfy(55,12): Error: cannot prove termination; try supplying a decreases clause
+StatementExpressions.dfy(55,11): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
(0,0): anon6_Then
(0,0): anon8_Then
-StatementExpressions.dfy(59,14): Error: assertion violation
+StatementExpressions.dfy(59,13): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon6_Then
StatementExpressions.dfy(53,7): anon8_Else
-StatementExpressions.dfy(77,6): Error: possible division by zero
+StatementExpressions.dfy(77,5): Error: possible division by zero
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-StatementExpressions.dfy(88,5): Error: value assigned to a nat must be non-negative
+ (0,0): anon4_Else
+StatementExpressions.dfy(88,4): Error: value assigned to a nat must be non-negative
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-StatementExpressions.dfy(98,18): Error: cannot prove termination; try supplying a decreases clause
+ (0,0): anon4_Else
+StatementExpressions.dfy(98,17): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
(0,0): anon6_Then
diff --git a/Test/dafny0/Superposition.dfy.expect b/Test/dafny0/Superposition.dfy.expect
index 4b8e354f..04ec2f7d 100644
--- a/Test/dafny0/Superposition.dfy.expect
+++ b/Test/dafny0/Superposition.dfy.expect
@@ -10,19 +10,19 @@ Verifying CheckWellformed$$_0_M0.C.P ...
Verifying CheckWellformed$$_0_M0.C.Q ...
[5 proof obligations] error
-Superposition.dfy(27,15): Error BP5003: A postcondition might not hold on this return path.
-Superposition.dfy(28,26): Related location: This is the postcondition that might not hold.
+Superposition.dfy(27,14): Error BP5003: A postcondition might not hold on this return path.
+Superposition.dfy(28,25): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
+ (0,0): anon7_Else
Verifying CheckWellformed$$_0_M0.C.R ...
[5 proof obligations] error
-Superposition.dfy(33,15): Error BP5003: A postcondition might not hold on this return path.
-Superposition.dfy(34,26): Related location: This is the postcondition that might not hold.
+Superposition.dfy(33,14): Error BP5003: A postcondition might not hold on this return path.
+Superposition.dfy(34,25): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
+ (0,0): anon7_Else
Verifying CheckWellformed$$_1_M1.C.M ...
[0 proof obligations] verified
@@ -32,13 +32,13 @@ Verifying Impl$$_1_M1.C.M ...
Verifying CheckWellformed$$_1_M1.C.P ...
[2 proof obligations] error
-Superposition.dfy(50,25): Error BP5003: A postcondition might not hold on this return path.
-Superposition.dfy[M1](22,26): Related location: This is the postcondition that might not hold.
+Superposition.dfy(50,24): Error BP5003: A postcondition might not hold on this return path.
+Superposition.dfy[M1](22,25): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
- (0,0): anon7_Else
- (0,0): anon9_Then
- (0,0): anon6
+ (0,0): anon9_Else
+ (0,0): anon11_Then
+ (0,0): anon8
Verifying CheckWellformed$$_1_M1.C.Q ...
[0 proof obligations] verified
diff --git a/Test/dafny0/Termination.dfy.expect b/Test/dafny0/Termination.dfy.expect
index 98aa0cd8..69cb360d 100644
--- a/Test/dafny0/Termination.dfy.expect
+++ b/Test/dafny0/Termination.dfy.expect
@@ -1,20 +1,20 @@
-Termination.dfy[TerminationRefinement1](441,6): Error: failure to decrease termination measure
+Termination.dfy[TerminationRefinement1](441,5): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
-Termination.dfy(361,47): Error: failure to decrease termination measure
+Termination.dfy(361,46): Error: failure to decrease termination measure
Execution trace:
(0,0): anon0
- (0,0): anon7_Else
- (0,0): anon8_Then
(0,0): anon9_Else
-Termination.dfy(108,3): Error: cannot prove termination; try supplying a decreases clause for the loop
+ (0,0): anon10_Then
+ (0,0): anon11_Else
+Termination.dfy(108,2): Error: cannot prove termination; try supplying a decreases clause for the loop
Execution trace:
(0,0): anon0
Termination.dfy(108,3): anon6_LoopHead
(0,0): anon6_LoopBody
Termination.dfy(108,3): anon7_Else
Termination.dfy(108,3): anon8_Else
-Termination.dfy(116,3): Error: cannot prove termination; try supplying a decreases clause for the loop
+Termination.dfy(116,2): Error: cannot prove termination; try supplying a decreases clause for the loop
Execution trace:
(0,0): anon0
Termination.dfy(116,3): anon8_LoopHead
@@ -23,7 +23,7 @@ Execution trace:
(0,0): anon10_Then
(0,0): anon5
Termination.dfy(116,3): anon11_Else
-Termination.dfy(125,3): Error: decreases expression might not decrease
+Termination.dfy(125,2): Error: decreases expression might not decrease
Execution trace:
(0,0): anon0
Termination.dfy(125,3): anon8_LoopHead
@@ -32,7 +32,7 @@ Execution trace:
(0,0): anon10_Then
(0,0): anon5
Termination.dfy(125,3): anon11_Else
-Termination.dfy(126,17): Error: decreases expression must be bounded below by 0 at end of loop iteration
+Termination.dfy(126,16): Error: decreases expression must be bounded below by 0 at end of loop iteration
Execution trace:
(0,0): anon0
Termination.dfy(125,3): anon8_LoopHead
@@ -41,13 +41,13 @@ Execution trace:
(0,0): anon10_Then
(0,0): anon5
Termination.dfy(125,3): anon11_Else
-Termination.dfy(255,35): Error: cannot prove termination; try supplying a decreases clause
+Termination.dfy(255,34): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon6_Else
- (0,0): anon7_Else
- (0,0): anon8_Then
-Termination.dfy(296,3): Error: decreases expression might not decrease
+ (0,0): anon8_Else
+ (0,0): anon9_Else
+ (0,0): anon10_Then
+Termination.dfy(296,2): Error: decreases expression might not decrease
Execution trace:
Termination.dfy(296,3): anon9_LoopHead
(0,0): anon9_LoopBody
diff --git a/Test/dafny0/Trait/TraitBasix.dfy.expect b/Test/dafny0/Trait/TraitBasix.dfy.expect
index 69af0dc5..dbb11c21 100644
--- a/Test/dafny0/Trait/TraitBasix.dfy.expect
+++ b/Test/dafny0/Trait/TraitBasix.dfy.expect
@@ -1,4 +1,4 @@
-TraitBasix.dfy(91,24): Error: Undeclared top-level type or type parameter: IX (did you forget to qualify a name?)
+TraitBasix.dfy(91,24): Error: Undeclared top-level type or type parameter: IX (did you forget to qualify a name or declare a module import 'opened?')
TraitBasix.dfy(77,8): Error: field 'x' is inherited from trait 'I2' and is not allowed to be re-declared
TraitBasix.dfy(70,8): Error: class 'I0Child' does not implement trait method 'I2.Customizable'
TraitBasix.dfy(80,8): Error: class 'I0Child2' does not implement trait function 'I2.F'
diff --git a/Test/dafny0/Trait/TraitExample.dfy b/Test/dafny0/Trait/TraitExample.dfy
index be38bfe5..9474c7ba 100644
--- a/Test/dafny0/Trait/TraitExample.dfy
+++ b/Test/dafny0/Trait/TraitExample.dfy
@@ -4,79 +4,148 @@
trait Automobile {
ghost var Repr: set<object>
predicate Valid()
- reads this //, Repr
+ reads this, Repr
ensures Valid() ==> this in Repr
function method Brand(): string
var position: int
method Drive()
requires Valid()
- modifies this // Repr
+ modifies Repr
+ ensures Valid() && fresh(Repr - old(Repr))
ensures old(position) <= position
}
+class Fiat extends Automobile {
+ predicate Valid()
+ reads this, Repr
+ ensures Valid() ==> this in Repr
+ {
+ this in Repr && null !in Repr && position <= 100
+ }
+ constructor (pos: int)
+ requires pos <= 100
+ modifies this
+ ensures Valid() && fresh(Repr - {this}) && position == pos
+ {
+ position, Repr := pos, {this};
+ }
+ function method Brand(): string {
+ "Fiat"
+ }
+ method Drive()
+ requires Valid()
+ modifies Repr
+ ensures Valid() && fresh(Repr - old(Repr))
+ ensures old(position) <= position
+ {
+ position := if position < 97 then position + 3 else 100;
+ }
+}
+
class Volvo extends Automobile {
+ var odometer: Odometer
predicate Valid()
- reads this //, Repr
+ reads this, Repr
ensures Valid() ==> this in Repr
{
- this in Repr
+ this in Repr && null !in Repr && odometer in Repr &&
+ position % 10 == 0 && // position is always a multiple of 10
+ odometer.value == position
}
- constructor()
+ constructor ()
modifies this
- ensures Valid()
+ ensures Valid() && fresh(Repr - {this})
{
- Repr := {this};
+ position, Repr := 0, {this};
+ odometer := new Odometer();
+ Repr := Repr + {odometer};
}
function method Brand(): string {
"Volvo"
}
method Drive()
-// requires Valid()
- modifies this // Repr
- ensures old(position) <= position
+ requires Valid()
+ modifies Repr
+ ensures Valid() && fresh(Repr - old(Repr))
+ ensures old(position) < position // always promises to make a move
{
position := position + 10;
+ odometer.Advance(10);
}
}
-class Fiat extends Automobile {
+class Odometer {
+ var value: int
+ constructor ()
+ modifies this
+ ensures value == 0
+ {
+ value := 0;
+ }
+ method Advance(d: int)
+ requires 0 <= d
+ modifies this
+ ensures value == old(value) + d
+ {
+ value := value + d;
+ }
+}
+
+class Catacar extends Automobile {
+ var f: Fiat
+ var v: Volvo
predicate Valid()
- reads this // , Repr
+ reads this, Repr
ensures Valid() ==> this in Repr
{
- this in Repr
+ this in Repr && null !in Repr &&
+ f in Repr && this !in f.Repr && f.Repr <= Repr && f.Valid() &&
+ v in Repr && this !in v.Repr && v.Repr <= Repr && v.Valid() &&
+ f.Repr !! v.Repr &&
+ position == f.position + v.position
}
- constructor()
+ constructor ()
modifies this
- ensures Valid()
+ ensures Valid() && fresh(Repr - {this})
{
Repr := {this};
+ f := new Fiat(0); Repr := Repr + f.Repr;
+ v := new Volvo(); Repr := Repr + v.Repr;
+ position := v.position;
}
function method Brand(): string {
- "Fiat"
+ "Catacar"
}
method Drive()
-// requires Valid()
- modifies this // Repr
+ requires Valid()
+ modifies Repr
+ ensures Valid() && fresh(Repr - old(Repr))
ensures old(position) <= position
{
- position := position + 3;
+ f := new Fiat(f.position);
+ f.Drive(); v.Drive();
+ Repr := Repr + v.Repr + f.Repr;
+ position := f.position + v.position;
}
}
method Main() {
var auto: Automobile;
+ auto := new Fiat(0);
+ WorkIt(auto);
auto := new Volvo();
WorkIt(auto);
- auto := new Fiat();
+ auto := new Catacar();
WorkIt(auto);
}
method WorkIt(auto: Automobile)
requires auto != null && auto.Valid()
- modifies auto // auto.Repr
+ modifies auto.Repr
{
auto.Drive();
+ auto.Drive();
+ assert old(auto.position) <= auto.position;
print auto.Brand(), ": ", auto.position, "\n";
- auto.position := 0;
+ auto.position := 18; // note, this may destroy the automobile's consistency condition (given by Valid)
}
diff --git a/Test/dafny0/Trait/TraitExample.dfy.expect b/Test/dafny0/Trait/TraitExample.dfy.expect
index 4fc71fb5..337b8f2f 100644
--- a/Test/dafny0/Trait/TraitExample.dfy.expect
+++ b/Test/dafny0/Trait/TraitExample.dfy.expect
@@ -1,7 +1,8 @@
-Dafny program verifier finished with 25 verified, 0 errors
+Dafny program verifier finished with 38 verified, 0 errors
Program compiled successfully
Running...
-Volvo: 10
-Fiat: 3
+Fiat: 6
+Volvo: 20
+Catacar: 26
diff --git a/Test/dafny0/Trait/TraitUsingParentMembers.dfy.expect b/Test/dafny0/Trait/TraitUsingParentMembers.dfy.expect
index 9960c1d9..1517dee4 100644
--- a/Test/dafny0/Trait/TraitUsingParentMembers.dfy.expect
+++ b/Test/dafny0/Trait/TraitUsingParentMembers.dfy.expect
@@ -1,4 +1,4 @@
-TraitUsingParentMembers.dfy(10,8): Error: assignment may update an array element not in the enclosing context's modifies clause
+TraitUsingParentMembers.dfy(10,7): Error: assignment may update an array element not in the enclosing context's modifies clause
Execution trace:
(0,0): anon0
(0,0): anon5_Then
diff --git a/Test/dafny0/Trait/TraitsDecreases.dfy b/Test/dafny0/Trait/TraitsDecreases.dfy
index 53ce28be..8ab3672a 100644
--- a/Test/dafny0/Trait/TraitsDecreases.dfy
+++ b/Test/dafny0/Trait/TraitsDecreases.dfy
@@ -106,3 +106,49 @@ class CC extends TT {
decreases *
{ }
}
+
+
+// The following module contains various regression tests
+module More {
+ trait A0 {
+ predicate P() decreases 5
+ }
+ class B0 extends A0 {
+ predicate P() // error: rank is not lower
+ }
+
+ trait A1 {
+ predicate P() decreases 5
+ }
+ class B1 extends A1 {
+ predicate P() reads this // error: rank is not lower
+ }
+
+ trait A2 {
+ predicate P(x: int)
+ }
+ class B2 extends A2 {
+ predicate P(x: int) reads this // error: rank is not lower
+ }
+
+ trait A3 {
+ predicate P() reads this
+ }
+ class B3 extends A3 {
+ predicate P() // error: rank is not lower
+ }
+
+ trait A4 {
+ predicate P(x: int) decreases 5
+ }
+ class B4 extends A4 {
+ predicate P(x: int) // error: rank is not lower
+ }
+
+ trait A5 {
+ method M(x: int) decreases 5
+ }
+ class B5 extends A5 {
+ method M(x: int) // error: rank is not lower
+ }
+}
diff --git a/Test/dafny0/Trait/TraitsDecreases.dfy.expect b/Test/dafny0/Trait/TraitsDecreases.dfy.expect
index 6c76f9a8..7d646bd1 100644
--- a/Test/dafny0/Trait/TraitsDecreases.dfy.expect
+++ b/Test/dafny0/Trait/TraitsDecreases.dfy.expect
@@ -1,17 +1,35 @@
-TraitsDecreases.dfy(57,10): Error: method's decreases clause must be below or equal to that in the trait
+TraitsDecreases.dfy(117,14): Error: predicate's decreases clause must be below or equal to that in the trait
Execution trace:
(0,0): anon0
-TraitsDecreases.dfy(69,10): Error: method's decreases clause must be below or equal to that in the trait
+TraitsDecreases.dfy(124,14): Error: predicate's decreases clause must be below or equal to that in the trait
Execution trace:
(0,0): anon0
-TraitsDecreases.dfy(72,10): Error: method's decreases clause must be below or equal to that in the trait
+TraitsDecreases.dfy(131,14): Error: predicate's decreases clause must be below or equal to that in the trait
Execution trace:
(0,0): anon0
-TraitsDecreases.dfy(78,10): Error: method's decreases clause must be below or equal to that in the trait
+TraitsDecreases.dfy(138,14): Error: predicate's decreases clause must be below or equal to that in the trait
Execution trace:
(0,0): anon0
-TraitsDecreases.dfy(88,10): Error: method's decreases clause must be below or equal to that in the trait
+TraitsDecreases.dfy(145,14): Error: predicate's decreases clause must be below or equal to that in the trait
+Execution trace:
+ (0,0): anon0
+TraitsDecreases.dfy(152,11): Error: method's decreases clause must be below or equal to that in the trait
+Execution trace:
+ (0,0): anon0
+TraitsDecreases.dfy(57,9): Error: method's decreases clause must be below or equal to that in the trait
+Execution trace:
+ (0,0): anon0
+TraitsDecreases.dfy(69,9): Error: method's decreases clause must be below or equal to that in the trait
+Execution trace:
+ (0,0): anon0
+TraitsDecreases.dfy(72,9): Error: method's decreases clause must be below or equal to that in the trait
+Execution trace:
+ (0,0): anon0
+TraitsDecreases.dfy(78,9): Error: method's decreases clause must be below or equal to that in the trait
+Execution trace:
+ (0,0): anon0
+TraitsDecreases.dfy(88,9): Error: method's decreases clause must be below or equal to that in the trait
Execution trace:
(0,0): anon0
-Dafny program verifier finished with 63 verified, 5 errors
+Dafny program verifier finished with 75 verified, 11 errors
diff --git a/Test/dafny0/TriggerInPredicate.dfy b/Test/dafny0/TriggerInPredicate.dfy
new file mode 100644
index 00000000..b9c372dc
--- /dev/null
+++ b/Test/dafny0/TriggerInPredicate.dfy
@@ -0,0 +1,19 @@
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+predicate A(x: bool, y: bool) { x }
+
+predicate B(x: bool, z: bool) { forall y {:trigger A(x, y)} :: A(x, y) && z }
+
+// Inlining is disabled here to prevent pollution of the trigger in B
+method C() requires B(true || false, true) {}
+
+// Inlining should work fine here
+method C'() requires B(true, true) {}
+
+// Inlining should work fine here
+method C''() requires B(true, true && false) {}
+
+// Local Variables:
+// dafny-prover-local-args: ("/autoTriggers:1")
+// End:
diff --git a/Test/dafny0/TriggerInPredicate.dfy.expect b/Test/dafny0/TriggerInPredicate.dfy.expect
new file mode 100644
index 00000000..b3d4ff34
--- /dev/null
+++ b/Test/dafny0/TriggerInPredicate.dfy.expect
@@ -0,0 +1,7 @@
+TriggerInPredicate.dfy(6,32): Info: Not generating triggers for "A(x, y)".
+TriggerInPredicate.dfy(6,32): Info: Not generating triggers for "z".
+TriggerInPredicate.dfy(9,20): Info: Some instances of this call cannot safely be inlined.
+TriggerInPredicate.dfy(9,20): Info: Some instances of this call cannot safely be inlined.
+TriggerInPredicate.dfy(9,20): Info: Some instances of this call cannot safely be inlined.
+
+Dafny program verifier finished with 8 verified, 0 errors
diff --git a/Test/dafny0/Tuples.dfy.expect b/Test/dafny0/Tuples.dfy.expect
index 13c706d3..9b5f3a83 100644
--- a/Test/dafny0/Tuples.dfy.expect
+++ b/Test/dafny0/Tuples.dfy.expect
@@ -1,7 +1,7 @@
-Tuples.dfy(22,19): Error: assertion violation
+Tuples.dfy(22,18): Error: assertion violation
Execution trace:
(0,0): anon0
-Tuples.dfy(24,21): Error: possible division by zero
+Tuples.dfy(24,20): Error: possible division by zero
Execution trace:
(0,0): anon0
diff --git a/Test/dafny0/TypeAntecedents.dfy.expect b/Test/dafny0/TypeAntecedents.dfy.expect
index d6eb08e4..2e2f606d 100644
--- a/Test/dafny0/TypeAntecedents.dfy.expect
+++ b/Test/dafny0/TypeAntecedents.dfy.expect
@@ -1,8 +1,8 @@
-TypeAntecedents.dfy(35,13): Error: assertion violation
+TypeAntecedents.dfy(35,12): Error: assertion violation
Execution trace:
(0,0): anon0
-TypeAntecedents.dfy(58,1): Error BP5003: A postcondition might not hold on this return path.
-TypeAntecedents.dfy(57,15): Related location: This is the postcondition that might not hold.
+TypeAntecedents.dfy(58,0): Error BP5003: A postcondition might not hold on this return path.
+TypeAntecedents.dfy(57,14): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
(0,0): anon25_Then
@@ -16,7 +16,7 @@ Execution trace:
(0,0): anon34_Then
(0,0): anon35_Then
(0,0): anon24
-TypeAntecedents.dfy(66,16): Error: assertion violation
+TypeAntecedents.dfy(66,15): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon25_Else
diff --git a/Test/dafny0/TypeParameters.dfy.expect b/Test/dafny0/TypeParameters.dfy.expect
index 3d00e89a..aca0694d 100644
--- a/Test/dafny0/TypeParameters.dfy.expect
+++ b/Test/dafny0/TypeParameters.dfy.expect
@@ -1,43 +1,43 @@
-TypeParameters.dfy(47,22): Error: assertion violation
+TypeParameters.dfy(47,21): Error: assertion violation
Execution trace:
(0,0): anon0
-TypeParameters.dfy(69,27): Error: assertion violation
+TypeParameters.dfy(69,26): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon3_Then
(0,0): anon2
-TypeParameters.dfy(156,12): Error: assertion violation
-TypeParameters.dfy(156,28): Related location
+TypeParameters.dfy(156,11): Error: assertion violation
+TypeParameters.dfy(156,27): Related location
Execution trace:
(0,0): anon0
(0,0): anon20_Then
TypeParameters.dfy(156,32): anon21_Else
(0,0): anon5
-TypeParameters.dfy(158,12): Error: assertion violation
-TypeParameters.dfy(158,33): Related location
+TypeParameters.dfy(158,11): Error: assertion violation
+TypeParameters.dfy(158,32): Related location
Execution trace:
(0,0): anon0
(0,0): anon23_Then
TypeParameters.dfy(158,37): anon24_Else
(0,0): anon11
-TypeParameters.dfy(160,12): Error: assertion violation
-TypeParameters.dfy(160,20): Related location
+TypeParameters.dfy(160,11): Error: assertion violation
+TypeParameters.dfy(160,19): Related location
Execution trace:
(0,0): anon0
(0,0): anon25_Then
-TypeParameters.dfy(162,12): Error: assertion violation
-TypeParameters.dfy(147,5): Related location
-TypeParameters.dfy(162,21): Related location
+TypeParameters.dfy(162,11): Error: assertion violation
+TypeParameters.dfy(147,4): Related location
+TypeParameters.dfy(162,20): Related location
Execution trace:
(0,0): anon0
(0,0): anon26_Then
-TypeParameters.dfy(164,12): Error: assertion violation
-TypeParameters.dfy(149,8): Related location
+TypeParameters.dfy(164,11): Error: assertion violation
+TypeParameters.dfy(149,7): Related location
Execution trace:
(0,0): anon0
(0,0): anon27_Then
-TypeParameters.dfy(178,15): Error BP5005: This loop invariant might not be maintained by the loop.
-TypeParameters.dfy(178,38): Related location
+TypeParameters.dfy(178,14): Error BP5005: This loop invariant might not be maintained by the loop.
+TypeParameters.dfy(178,37): Related location
Execution trace:
(0,0): anon0
TypeParameters.dfy(171,3): anon16_LoopHead
diff --git a/Test/dafny0/TypeTests.dfy b/Test/dafny0/TypeTests.dfy
index b44f4d68..a9d473f6 100644
--- a/Test/dafny0/TypeTests.dfy
+++ b/Test/dafny0/TypeTests.dfy
@@ -39,7 +39,7 @@ datatype ReverseOrder_TheCounterpart<T> =
// ---------------------
-class ArrayTests {
+module ArrayTests {
ghost method G(a: array<int>)
requires a != null && 10 <= a.Length;
modifies a;
@@ -167,31 +167,33 @@ module Expl_Module {
// --------------------- more ghost tests, for assign-such-that statements
-method M()
-{
- ghost var b: bool;
- ghost var k: int, l: int;
- var m: int;
-
- k :| k < 10;
- k, m :| 0 <= k < m; // error: LHS has non-ghost and RHS has ghost
- m :| m < 10;
-
- // Because of the ghost guard, these 'if' statements are ghost contexts, so only
- // assignments to ghosts are allowed.
- if (b) {
- k :| k < 10; // should be allowed
- k, l :| 0 <= k < l; // ditto
- }
- if (b) {
- m :| m < 10; // error: not allowed in ghost context
- k, m :| 0 <= k < m; // error: not allowed in ghost context
+module MoreGhostTests {
+ method M()
+ {
+ ghost var b: bool;
+ ghost var k: int, l: int;
+ var m: int;
+
+ k :| k < 10;
+ k, m :| 0 <= k < m; // error: LHS has non-ghost and RHS has ghost
+ m :| m < 10;
+
+ // Because of the ghost guard, these 'if' statements are ghost contexts, so only
+ // assignments to ghosts are allowed.
+ if (b) {
+ k :| k < 10; // should be allowed
+ k, l :| 0 <= k < l; // ditto
+ }
+ if (b) {
+ m :| m < 10; // error: not allowed in ghost context
+ k, m :| 0 <= k < m; // error: not allowed in ghost context
+ }
}
-}
-ghost method GhostM() returns (x: int)
-{
- x :| true; // no problem (but there once was a problem with this case, where an error was generated for no reason)
+ ghost method GhostM() returns (x: int)
+ {
+ x :| true; // no problem (but there once was a problem with this case, where an error was generated for no reason)
+ }
}
// ------------------ cycles that could arise from proxy assignments ---------
diff --git a/Test/dafny0/TypeTests.dfy.expect b/Test/dafny0/TypeTests.dfy.expect
index 500b1af9..de0bfbed 100644
--- a/Test/dafny0/TypeTests.dfy.expect
+++ b/Test/dafny0/TypeTests.dfy.expect
@@ -1,6 +1,10 @@
-TypeTests.dfy(205,15): Error: incorrect type of datatype constructor argument (found ? -> ?, expected ? -> Dt<?>)
-TypeTests.dfy(211,15): Error: incorrect type of datatype constructor argument (found ? -> ?, expected ? -> Dt<?>)
-TypeTests.dfy(218,6): Error: RHS (of type set<?>) not assignable to LHS (of type ?)
+TypeTests.dfy(47,9): Error: Assignment to array element is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+TypeTests.dfy(178,7): Error: non-ghost variable cannot be assigned a value that depends on a ghost
+TypeTests.dfy(188,6): Error: cannot assign to non-ghost variable in a ghost context
+TypeTests.dfy(189,9): Error: cannot assign to non-ghost variable in a ghost context
+TypeTests.dfy(207,15): Error: incorrect type of datatype constructor argument (found ? -> ?, expected ? -> Dt<?>)
+TypeTests.dfy(213,15): Error: incorrect type of datatype constructor argument (found ? -> ?, expected ? -> Dt<?>)
+TypeTests.dfy(220,6): Error: RHS (of type set<?>) not assignable to LHS (of type ?)
TypeTests.dfy(7,17): Error: type mismatch for argument 0 (function expects C, got D)
TypeTests.dfy(7,20): Error: type mismatch for argument 1 (function expects D, got C)
TypeTests.dfy(8,15): Error: type mismatch for argument 0 (function expects C, got int)
@@ -8,7 +12,6 @@ TypeTests.dfy(8,18): Error: type mismatch for argument 1 (function expects D, go
TypeTests.dfy(14,16): Error: incorrect type of method in-parameter 0 (expected int, got bool)
TypeTests.dfy(15,12): Error: incorrect type of method out-parameter 0 (expected int, got C)
TypeTests.dfy(15,12): Error: incorrect type of method out-parameter 1 (expected C, got int)
-TypeTests.dfy(47,9): Error: Assignment to array element is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
TypeTests.dfy(56,6): Error: Duplicate local-variable name: z
TypeTests.dfy(58,6): Error: Duplicate local-variable name: x
TypeTests.dfy(61,8): Error: Duplicate local-variable name: x
@@ -56,8 +59,5 @@ TypeTests.dfy(151,13): Error: sorry, cannot instantiate type parameter with a su
TypeTests.dfy(152,2): Error: sorry, cannot instantiate type parameter with a subrange type
TypeTests.dfy(153,16): Error: sorry, cannot instantiate type parameter with a subrange type
TypeTests.dfy(154,14): Error: sorry, cannot instantiate type parameter with a subrange type
-TypeTests.dfy(177,15): Error: ghost variables are allowed only in specification contexts
-TypeTests.dfy(187,4): Error: cannot assign to non-ghost variable in a ghost context
-TypeTests.dfy(188,7): Error: cannot assign to non-ghost variable in a ghost context
TypeTests.dfy(21,9): Error: because of cyclic dependencies among constructor argument types, no instances of datatype 'NeverendingList' can be constructed
62 resolution/type errors detected in TypeTests.dfy
diff --git a/Test/dafny0/UnfoldingPerformance.dfy b/Test/dafny0/UnfoldingPerformance.dfy
new file mode 100644
index 00000000..3eed689a
--- /dev/null
+++ b/Test/dafny0/UnfoldingPerformance.dfy
@@ -0,0 +1,61 @@
+// RUN: %dafny /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+class C {
+ var x: nat
+ function method IgnoreFuel(): nat
+ reads this
+ {
+ x
+ }
+}
+
+function method Fib(n: int): int
+{
+ if n < 2 then n else Fib(n-2) + Fib(n-1)
+}
+
+method Test0() {
+ var c := new C;
+ var f := Fib(c.IgnoreFuel());
+ // with the bug, the following wwould take a long time before it reports an error
+ // after the bug fix, this still fails, but quickly
+ assert 0 <= f;
+}
+
+method Test1() {
+ var c := new C;
+ var f := Fib(c.x);
+ // the following assert will also fail, but quickly
+ assert 0 <= f;
+}
+
+method Test2() {
+ var c := new C;
+ c.x := 10;
+ var f := Fib(c.IgnoreFuel());
+ assert 0 <= f; // passes
+}
+
+method Test3() {
+ var c := new C;
+ c.x := 10;
+ var f := Fib(c.x);
+ assert 0 <= f; // passes
+}
+
+method Test4() {
+ var c := new C;
+ c.x := 10;
+ var f := Fib(c.x - 2);
+ assert 0 <= f; // fails
+}
+
+method Test5(x: int)
+ requires 9 <= x - 1 && x + 1 <= 11
+{
+ var c := new C;
+ c.x := x;
+ var f := Fib(c.x);
+ assert 0 <= f; // succeeds?
+}
diff --git a/Test/dafny0/UnfoldingPerformance.dfy.expect b/Test/dafny0/UnfoldingPerformance.dfy.expect
new file mode 100644
index 00000000..220fecc5
--- /dev/null
+++ b/Test/dafny0/UnfoldingPerformance.dfy.expect
@@ -0,0 +1,11 @@
+UnfoldingPerformance.dfy(23,11): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+UnfoldingPerformance.dfy(30,11): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+UnfoldingPerformance.dfy(51,11): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 11 verified, 3 errors
diff --git a/Test/dafny0/UserSpecifiedTypeParameters.dfy.expect b/Test/dafny0/UserSpecifiedTypeParameters.dfy.expect
index 2504fbfb..347252aa 100644
--- a/Test/dafny0/UserSpecifiedTypeParameters.dfy.expect
+++ b/Test/dafny0/UserSpecifiedTypeParameters.dfy.expect
@@ -1,8 +1,8 @@
UserSpecifiedTypeParameters.dfy(27,12): Error: the type of this variable is underspecified
UserSpecifiedTypeParameters.dfy(27,26): Error: type variable 'T' in the function call to 'H' could not be determined
UserSpecifiedTypeParameters.dfy(27,26): Error: type variable 'U' in the function call to 'H' could not be determined
-UserSpecifiedTypeParameters.dfy(48,22): Error: Undeclared top-level type or type parameter: b (did you forget to qualify a name?)
-UserSpecifiedTypeParameters.dfy(48,26): Error: Undeclared top-level type or type parameter: c (did you forget to qualify a name?)
+UserSpecifiedTypeParameters.dfy(48,22): Error: Undeclared top-level type or type parameter: b (did you forget to qualify a name or declare a module import 'opened?')
+UserSpecifiedTypeParameters.dfy(48,26): Error: Undeclared top-level type or type parameter: c (did you forget to qualify a name or declare a module import 'opened?')
UserSpecifiedTypeParameters.dfy(48,18): Error: variable 'a' does not take any type parameters
UserSpecifiedTypeParameters.dfy(48,30): Error: non-function expression (of type int) is called with parameters
UserSpecifiedTypeParameters.dfy(48,16): Error: wrong number of arguments to function application (function 'F' expects 2, got 1)
diff --git a/Test/dafny0/columns.dfy b/Test/dafny0/columns.dfy
new file mode 100644
index 00000000..72c9ab81
--- /dev/null
+++ b/Test/dafny0/columns.dfy
@@ -0,0 +1,12 @@
+// RUN: %dafny "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// Dafny counts columns from 0, but Boogie from one, so for a while there were small bugs with that.
+
+predicate P(x: int)
+
+static method A(x:int) requires x > 0 { // error os 's'
+ assert (forall y: int :: P(y)); // error on '('
+ assert x != 1; // error on '!'
+ assert x in {}; // error on 'i'
+}
diff --git a/Test/dafny0/columns.dfy.expect b/Test/dafny0/columns.dfy.expect
new file mode 100644
index 00000000..0a99be69
--- /dev/null
+++ b/Test/dafny0/columns.dfy.expect
@@ -0,0 +1,12 @@
+columns.dfy(8,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+columns.dfy(9,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+columns.dfy(10,11): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+columns.dfy(11,11): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 2 verified, 3 errors
diff --git a/Test/dafny0/fun-with-slices.dfy b/Test/dafny0/fun-with-slices.dfy
new file mode 100644
index 00000000..3d8da242
--- /dev/null
+++ b/Test/dafny0/fun-with-slices.dfy
@@ -0,0 +1,19 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This test was contributed by Bryan. It has shown some instabilities in the past.
+
+method seqIntoArray<A>(s: seq<A>, a: array<A>, index: nat)
+ requires a != null
+ requires index + |s| <= a.Length
+ modifies a
+ ensures a[..] == old(a[0..index]) + s + old(a[index + |s|..]) {
+ var i := index;
+
+ while i < index + |s|
+ invariant index <= i <= index + |s| <= a.Length
+ invariant a[..] == old(a[0..index]) + s[0..(i-index)] + old(a[i..]) {
+ a[i] := s[i - index];
+ i := i + 1;
+ }
+}
diff --git a/Test/dafny0/fun-with-slices.dfy.expect b/Test/dafny0/fun-with-slices.dfy.expect
new file mode 100644
index 00000000..069e7767
--- /dev/null
+++ b/Test/dafny0/fun-with-slices.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/dafny0/one-message-per-failed-precondition.dfy b/Test/dafny0/one-message-per-failed-precondition.dfy
new file mode 100644
index 00000000..ef4f5bd6
--- /dev/null
+++ b/Test/dafny0/one-message-per-failed-precondition.dfy
@@ -0,0 +1,20 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// When a function call violates two preconditions at the same time, it causes
+// two errors to be reported for the same token
+
+method A(x: int)
+ requires x > 0
+ requires x < 0
+{}
+
+method B(x: int) {
+ A(x);
+}
+
+function fA(x: int): int
+ requires x > 0
+ requires x < 0 { 1 }
+
+function fB(x: int): int { fA(x) }
diff --git a/Test/dafny0/one-message-per-failed-precondition.dfy.expect b/Test/dafny0/one-message-per-failed-precondition.dfy.expect
new file mode 100644
index 00000000..0a76965e
--- /dev/null
+++ b/Test/dafny0/one-message-per-failed-precondition.dfy.expect
@@ -0,0 +1,20 @@
+one-message-per-failed-precondition.dfy(13,3): Error BP5002: A precondition for this call might not hold.
+one-message-per-failed-precondition.dfy(9,13): Related location: This is the precondition that might not hold.
+Execution trace:
+ (0,0): anon0
+one-message-per-failed-precondition.dfy(13,3): Error BP5002: A precondition for this call might not hold.
+one-message-per-failed-precondition.dfy(8,13): Related location: This is the precondition that might not hold.
+Execution trace:
+ (0,0): anon0
+one-message-per-failed-precondition.dfy(20,27): Error: possible violation of function precondition
+one-message-per-failed-precondition.dfy(18,13): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon4_Else
+one-message-per-failed-precondition.dfy(20,27): Error: possible violation of function precondition
+one-message-per-failed-precondition.dfy(17,13): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon4_Else
+
+Dafny program verifier finished with 4 verified, 4 errors
diff --git a/Test/dafny0/snapshots/Snapshots0.v0.dfy b/Test/dafny0/snapshots/Inputs/Snapshots0.v0.dfy
index 73db9f9c..73db9f9c 100644
--- a/Test/dafny0/snapshots/Snapshots0.v0.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots0.v0.dfy
diff --git a/Test/dafny0/snapshots/Snapshots0.v1.dfy b/Test/dafny0/snapshots/Inputs/Snapshots0.v1.dfy
index db9fc01a..db9fc01a 100644
--- a/Test/dafny0/snapshots/Snapshots0.v1.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots0.v1.dfy
diff --git a/Test/dafny0/snapshots/Snapshots1.v0.dfy b/Test/dafny0/snapshots/Inputs/Snapshots1.v0.dfy
index 34d066c3..34d066c3 100644
--- a/Test/dafny0/snapshots/Snapshots1.v0.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots1.v0.dfy
diff --git a/Test/dafny0/snapshots/Snapshots1.v1.dfy b/Test/dafny0/snapshots/Inputs/Snapshots1.v1.dfy
index 184ac65d..184ac65d 100644
--- a/Test/dafny0/snapshots/Snapshots1.v1.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots1.v1.dfy
diff --git a/Test/dafny0/snapshots/Snapshots2.v0.dfy b/Test/dafny0/snapshots/Inputs/Snapshots2.v0.dfy
index 727e177d..727e177d 100644
--- a/Test/dafny0/snapshots/Snapshots2.v0.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots2.v0.dfy
diff --git a/Test/dafny0/snapshots/Snapshots2.v1.dfy b/Test/dafny0/snapshots/Inputs/Snapshots2.v1.dfy
index 02a91b52..02a91b52 100644
--- a/Test/dafny0/snapshots/Snapshots2.v1.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots2.v1.dfy
diff --git a/Test/dafny0/snapshots/Snapshots3.v0.dfy b/Test/dafny0/snapshots/Inputs/Snapshots3.v0.dfy
index 72607412..72607412 100644
--- a/Test/dafny0/snapshots/Snapshots3.v0.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots3.v0.dfy
diff --git a/Test/dafny0/snapshots/Snapshots3.v1.dfy b/Test/dafny0/snapshots/Inputs/Snapshots3.v1.dfy
index 3b186318..3b186318 100644
--- a/Test/dafny0/snapshots/Snapshots3.v1.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots3.v1.dfy
diff --git a/Test/dafny0/snapshots/Snapshots4.v0.dfy b/Test/dafny0/snapshots/Inputs/Snapshots4.v0.dfy
index beaadfeb..beaadfeb 100644
--- a/Test/dafny0/snapshots/Snapshots4.v0.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots4.v0.dfy
diff --git a/Test/dafny0/snapshots/Snapshots4.v1.dfy b/Test/dafny0/snapshots/Inputs/Snapshots4.v1.dfy
index cf9ae753..cf9ae753 100644
--- a/Test/dafny0/snapshots/Snapshots4.v1.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots4.v1.dfy
diff --git a/Test/dafny0/snapshots/Snapshots5.v0.dfy b/Test/dafny0/snapshots/Inputs/Snapshots5.v0.dfy
index b81c1a2b..b81c1a2b 100644
--- a/Test/dafny0/snapshots/Snapshots5.v0.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots5.v0.dfy
diff --git a/Test/dafny0/snapshots/Snapshots5.v1.dfy b/Test/dafny0/snapshots/Inputs/Snapshots5.v1.dfy
index 05dbced0..7b207d74 100644
--- a/Test/dafny0/snapshots/Snapshots5.v1.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots5.v1.dfy
@@ -17,9 +17,9 @@ method M()
}
else
{
- assert (exists b: bool :: b || !b) || 4 != 4;
+ assert (exists b: bool :: true) || 4 != 4;
}
- assert (exists b: bool :: b || !b) || 5 != 5;
+ assert (exists b: bool :: true) || 5 != 5;
}
diff --git a/Test/dafny0/snapshots/Snapshots6.v0.dfy b/Test/dafny0/snapshots/Inputs/Snapshots6.v0.dfy
index c3742f4b..c3742f4b 100644
--- a/Test/dafny0/snapshots/Snapshots6.v0.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots6.v0.dfy
diff --git a/Test/dafny0/snapshots/Snapshots6.v1.dfy b/Test/dafny0/snapshots/Inputs/Snapshots6.v1.dfy
index aeb520cb..aeb520cb 100644
--- a/Test/dafny0/snapshots/Snapshots6.v1.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots6.v1.dfy
diff --git a/Test/dafny0/snapshots/Snapshots7.v0.dfy b/Test/dafny0/snapshots/Inputs/Snapshots7.v0.dfy
index 27c7da5f..27c7da5f 100644
--- a/Test/dafny0/snapshots/Snapshots7.v0.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots7.v0.dfy
diff --git a/Test/dafny0/snapshots/Snapshots7.v1.dfy b/Test/dafny0/snapshots/Inputs/Snapshots7.v1.dfy
index b45dfe78..b45dfe78 100644
--- a/Test/dafny0/snapshots/Snapshots7.v1.dfy
+++ b/Test/dafny0/snapshots/Inputs/Snapshots7.v1.dfy
diff --git a/Test/dafny0/snapshots/Inputs/Snapshots8.v0.dfy b/Test/dafny0/snapshots/Inputs/Snapshots8.v0.dfy
new file mode 100644
index 00000000..97fcfccb
--- /dev/null
+++ b/Test/dafny0/snapshots/Inputs/Snapshots8.v0.dfy
@@ -0,0 +1,29 @@
+method M(x: int)
+{ assert x < 20 || 10 <= x; // always true
+ assert x < 10; // error
+ Other(x); // error: precondition violation
+}
+
+method Other(y: int)
+ requires 0 <= y
+{
+}
+
+method Posty() returns (z: int)
+ ensures 2 <= z // error: postcondition violation
+{
+ var t := 20;
+ if t < z {
+ } else { // the postcondition violation occurs on this 'else' branch
+ }
+}
+
+method NoChangeWhazzoeva(u: int)
+{
+ assert u != 53; // error
+}
+
+method NoChangeAndCorrect()
+{
+ assert true;
+}
diff --git a/Test/dafny0/snapshots/Inputs/Snapshots8.v1.dfy b/Test/dafny0/snapshots/Inputs/Snapshots8.v1.dfy
new file mode 100644
index 00000000..8d8b215b
--- /dev/null
+++ b/Test/dafny0/snapshots/Inputs/Snapshots8.v1.dfy
@@ -0,0 +1,33 @@
+method M(x: int)
+{
+assert x < 20 || 10 <= x; // always true
+
+ assert x < 10; // error
+ Other(x); // error: precondition violation
+ assert x == 7; // error: this is a new error in v1
+}
+
+
+ method Other(y: int)
+ requires 0 <= y
+ {
+ }
+
+
+
+method Posty() returns (z: int)
+ ensures 2 <= z // error: postcondition violation
+{
+ var t := 20;
+ if t < z {
+ assert true; // this is a new assert
+ } else { // the postcondition violation occurs on this 'else' branch
+ }
+}
+
+ method NoChangeWhazzoeva(u: int)
+ {
+ assert u != 53; // error
+ }
+
+method NoChangeAndCorrect() { assert true; }
diff --git a/Test/dafny0/snapshots/Snapshots0.run.dfy b/Test/dafny0/snapshots/Snapshots0.run.dfy
new file mode 100644
index 00000000..5e016c12
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots0.run.dfy
@@ -0,0 +1,2 @@
+// RUN: %dafny /compile:0 /verifySnapshots:2 /traceCaching:1 "%S/Inputs/Snapshots0.dfy" > "%t"
+// RUN: %diff "%s.expect" "%t"
diff --git a/Test/dafny0/snapshots/Snapshots0.run.dfy.expect b/Test/dafny0/snapshots/Snapshots0.run.dfy.expect
new file mode 100644
index 00000000..bf7388cf
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots0.run.dfy.expect
@@ -0,0 +1,25 @@
+Processing command (at Snapshots0.v0.dfy(3,6)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
+ >>> DoNothingToAssert
+Processing command (at Snapshots0.v0.dfy(4,10)) assert false;
+ >>> DoNothingToAssert
+
+Dafny program verifier finished with 3 verified, 0 errors
+Processing implementation CheckWellformed$$_module.__default.bar (at Snapshots0.v1.dfy(7,8)):
+ >>> added axiom: ##extracted_function##1() == (0 == $ModuleContextHeight && 0 == $FunctionContextHeight)
+ >>> added after assuming the current precondition: a##cached##0 := a##cached##0 && ##extracted_function##1();
+Processing call to procedure IntraModuleCall$$_module.__default.bar in implementation Impl$$_module.__default.foo (at Snapshots0.v1.dfy(3,6)):
+ >>> added axiom: (forall call0old#AT#$Heap: Heap, $Heap: Heap :: {:weight 30} { ##extracted_function##2(call0old#AT#$Heap, $Heap) } ##extracted_function##2(call0old#AT#$Heap, $Heap) == (true && Lit(false) && (forall<alpha> $o: ref, $f: Field alpha :: { read($Heap, $o, $f) } $o != null && read(call0old#AT#$Heap, $o, alloc) ==> read($Heap, $o, $f) == read(call0old#AT#$Heap, $o, $f)) && $HeapSucc(call0old#AT#$Heap, $Heap)))
+ >>> added after: a##cached##0 := a##cached##0 && ##extracted_function##2(call0old#AT#$Heap, $Heap);
+Processing command (at <unknown location>) a##cached##0 := a##cached##0 && ##extracted_function##1();
+ >>> AssumeNegationOfAssumptionVariable
+Processing command (at Snapshots0.v1.dfy(3,6)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
+ >>> MarkAsFullyVerified
+Processing command (at <unknown location>) a##cached##0 := a##cached##0 && ##extracted_function##2(call0old#AT#$Heap, $Heap);
+ >>> AssumeNegationOfAssumptionVariable
+Processing command (at Snapshots0.v1.dfy(4,10)) assert false;
+ >>> MarkAsPartiallyVerified
+Snapshots0.v1.dfy(4,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 2 verified, 1 error
diff --git a/Test/dafny0/snapshots/Snapshots1.run.dfy b/Test/dafny0/snapshots/Snapshots1.run.dfy
new file mode 100644
index 00000000..1907f4a0
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots1.run.dfy
@@ -0,0 +1,2 @@
+// RUN: %dafny /compile:0 /verifySnapshots:2 /traceCaching:1 "%S/Inputs/Snapshots1.dfy" > "%t"
+// RUN: %diff "%s.expect" "%t"
diff --git a/Test/dafny0/snapshots/Snapshots1.run.dfy.expect b/Test/dafny0/snapshots/Snapshots1.run.dfy.expect
new file mode 100644
index 00000000..1b5c8d24
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots1.run.dfy.expect
@@ -0,0 +1,21 @@
+Processing command (at Snapshots1.v0.dfy(3,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
+ >>> DoNothingToAssert
+Processing command (at Snapshots1.v0.dfy(4,10)) assert false;
+ >>> DoNothingToAssert
+Processing command (at Snapshots1.v0.dfy(12,3)) assert true;
+ >>> DoNothingToAssert
+
+Dafny program verifier finished with 4 verified, 0 errors
+Processing call to procedure IntraModuleCall$$_module.__default.N in implementation Impl$$_module.__default.M (at Snapshots1.v1.dfy(3,4)):
+ >>> added after: a##cached##0 := a##cached##0 && false;
+Processing command (at Snapshots1.v1.dfy(12,3)) assert true;
+ >>> MarkAsFullyVerified
+Processing command (at Snapshots1.v1.dfy(3,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
+ >>> MarkAsFullyVerified
+Processing command (at Snapshots1.v1.dfy(4,10)) assert false;
+ >>> DoNothingToAssert
+Snapshots1.v1.dfy(4,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 3 verified, 1 error
diff --git a/Test/dafny0/snapshots/Snapshots2.run.dfy b/Test/dafny0/snapshots/Snapshots2.run.dfy
new file mode 100644
index 00000000..71f3e18a
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots2.run.dfy
@@ -0,0 +1,2 @@
+// RUN: %dafny /compile:0 /verifySnapshots:2 /traceCaching:1 "%S/Inputs/Snapshots2.dfy" > "%t"
+// RUN: %diff "%s.expect" "%t"
diff --git a/Test/dafny0/snapshots/Snapshots2.run.dfy.expect b/Test/dafny0/snapshots/Snapshots2.run.dfy.expect
new file mode 100644
index 00000000..949ecec9
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots2.run.dfy.expect
@@ -0,0 +1,41 @@
+Processing command (at Snapshots2.v0.dfy(3,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
+ >>> DoNothingToAssert
+Processing command (at Snapshots2.v0.dfy(4,10)) assert false;
+ >>> DoNothingToAssert
+Processing command (at Snapshots2.v0.dfy(11,11)) assert true;
+ >>> DoNothingToAssert
+Processing command (at Snapshots2.v0.dfy(11,15)) assert _module.__default.P($LS($LS($LZ)), $Heap) <==> _module.__default.Q($LS($LS($LZ)), $Heap);
+ >>> DoNothingToAssert
+Processing command (at Snapshots2.v0.dfy(14,11)) assert true;
+ >>> DoNothingToAssert
+Processing command (at Snapshots2.v0.dfy(14,15)) assert _module.__default.Q($LS($LS($LZ)), $Heap) <==> Lit(_module.__default.R($Heap));
+ >>> DoNothingToAssert
+Processing command (at Snapshots2.v0.dfy(18,3)) assert true;
+ >>> DoNothingToAssert
+
+Dafny program verifier finished with 6 verified, 0 errors
+Processing call to procedure IntraModuleCall$$_module.__default.N in implementation Impl$$_module.__default.M (at Snapshots2.v1.dfy(3,4)):
+ >>> added after: a##cached##0 := a##cached##0 && false;
+Processing implementation CheckWellformed$$_module.__default.P (at Snapshots2.v1.dfy(10,11)):
+ >>> added after assuming the current precondition: a##cached##0 := a##cached##0 && false;
+Processing implementation CheckWellformed$$_module.__default.Q (at Snapshots2.v1.dfy(13,11)):
+ >>> added after assuming the current precondition: a##cached##0 := a##cached##0 && false;
+Processing command (at Snapshots2.v1.dfy(18,3)) assert true;
+ >>> MarkAsFullyVerified
+Processing command (at Snapshots2.v1.dfy(3,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
+ >>> MarkAsFullyVerified
+Processing command (at Snapshots2.v1.dfy(4,10)) assert false;
+ >>> DoNothingToAssert
+Snapshots2.v1.dfy(4,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Processing command (at Snapshots2.v1.dfy(11,11)) assert true;
+ >>> DoNothingToAssert
+Processing command (at Snapshots2.v1.dfy(11,15)) assert _module.__default.P($LS($LS($LZ)), $Heap) <==> _module.__default.Q($LS($LS($LZ)), $Heap);
+ >>> DoNothingToAssert
+Processing command (at Snapshots2.v1.dfy(14,11)) assert true;
+ >>> DoNothingToAssert
+Processing command (at Snapshots2.v1.dfy(14,15)) assert _module.__default.Q($LS($LS($LZ)), $Heap) <==> Lit(_module.__default.R($Heap));
+ >>> DoNothingToAssert
+
+Dafny program verifier finished with 5 verified, 1 error
diff --git a/Test/dafny0/snapshots/Snapshots3.run.dfy b/Test/dafny0/snapshots/Snapshots3.run.dfy
new file mode 100644
index 00000000..40dd1012
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots3.run.dfy
@@ -0,0 +1,2 @@
+// RUN: %dafny /compile:0 /verifySnapshots:2 /traceCaching:1 "%S/Inputs/Snapshots3.dfy" > "%t"
+// RUN: %diff "%s.expect" "%t"
diff --git a/Test/dafny0/snapshots/Snapshots3.run.dfy.expect b/Test/dafny0/snapshots/Snapshots3.run.dfy.expect
new file mode 100644
index 00000000..a7f05a68
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots3.run.dfy.expect
@@ -0,0 +1,18 @@
+Processing command (at Snapshots3.v0.dfy(9,14)) assert 0 != 0;
+ >>> DoNothingToAssert
+Snapshots3.v0.dfy(9,13): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Else
+
+Dafny program verifier finished with 1 verified, 1 error
+Processing command (at Snapshots3.v1.dfy(5,12)) assert true;
+ >>> DoNothingToAssert
+Processing command (at Snapshots3.v1.dfy(9,14)) assert 0 != 0;
+ >>> RecycleError
+Snapshots3.v0.dfy(9,13): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Else
+
+Dafny program verifier finished with 1 verified, 1 error
diff --git a/Test/dafny0/snapshots/Snapshots4.run.dfy b/Test/dafny0/snapshots/Snapshots4.run.dfy
new file mode 100644
index 00000000..803403cf
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots4.run.dfy
@@ -0,0 +1,2 @@
+// RUN: %dafny /compile:0 /verifySnapshots:2 /traceCaching:1 "%S/Inputs/Snapshots4.dfy" > "%t"
+// RUN: %diff "%s.expect" "%t"
diff --git a/Test/dafny0/snapshots/Snapshots4.run.dfy.expect b/Test/dafny0/snapshots/Snapshots4.run.dfy.expect
new file mode 100644
index 00000000..e0f07849
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots4.run.dfy.expect
@@ -0,0 +1,20 @@
+Processing command (at Snapshots4.v0.dfy(9,14)) assert LitInt(0) == LitInt(0);
+ >>> DoNothingToAssert
+
+Dafny program verifier finished with 2 verified, 0 errors
+Processing command (at Snapshots4.v1.dfy(5,14)) assert 1 != 1;
+ >>> DoNothingToAssert
+Processing command (at Snapshots4.v1.dfy(9,14)) assert LitInt(0) == LitInt(0);
+ >>> MarkAsFullyVerified
+Processing command (at Snapshots4.v1.dfy(10,14)) assert 2 != 2;
+ >>> DoNothingToAssert
+Snapshots4.v1.dfy(5,13): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Then
+Snapshots4.v1.dfy(10,13): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Else
+
+Dafny program verifier finished with 1 verified, 2 errors
diff --git a/Test/dafny0/snapshots/Snapshots5.run.dfy b/Test/dafny0/snapshots/Snapshots5.run.dfy
new file mode 100644
index 00000000..096df53c
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots5.run.dfy
@@ -0,0 +1,2 @@
+// RUN: %dafny /compile:0 /verifySnapshots:2 /traceCaching:1 "%S/Inputs/Snapshots5.dfy" /autoTriggers:1 > "%t"
+// RUN: %diff "%s.expect" "%t"
diff --git a/Test/dafny0/snapshots/Snapshots5.run.dfy.expect b/Test/dafny0/snapshots/Snapshots5.run.dfy.expect
new file mode 100644
index 00000000..8cc44882
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots5.run.dfy.expect
@@ -0,0 +1,35 @@
+Snapshots5.v0.dfy(10,12): Warning: /!\ No terms found to trigger on.
+Snapshots5.v0.dfy(13,10): Warning: /!\ No terms found to trigger on.
+Snapshots5.v0.dfy(20,12): Warning: /!\ No terms found to trigger on.
+Snapshots5.v0.dfy(26,11): Warning: /!\ No terms found to trigger on.
+Processing command (at Snapshots5.v0.dfy(3,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
+ >>> DoNothingToAssert
+Processing command (at Snapshots5.v0.dfy(10,40)) assert (forall b#1: bool :: true ==> b#1 || !b#1) || 0 != 0;
+ >>> DoNothingToAssert
+Processing command (at Snapshots5.v0.dfy(12,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
+ >>> DoNothingToAssert
+Processing command (at Snapshots5.v0.dfy(13,38)) assert (forall b#3: bool :: true ==> b#3 || !b#3) || 3 != 3;
+ >>> DoNothingToAssert
+Processing command (at Snapshots5.v0.dfy(20,40)) assert (forall b#5: bool :: true ==> b#5 || !b#5) || 1 != 1;
+ >>> DoNothingToAssert
+
+Dafny program verifier finished with 3 verified, 0 errors
+Snapshots5.v1.dfy(10,12): Warning: /!\ No terms found to trigger on.
+Snapshots5.v1.dfy(13,10): Warning: /!\ No terms found to trigger on.
+Snapshots5.v1.dfy(20,12): Warning: /!\ No terms found to trigger on.
+Snapshots5.v1.dfy(22,10): Warning: /!\ No terms found to trigger on.
+Snapshots5.v1.dfy(27,11): Warning: /!\ No terms found to trigger on.
+Processing command (at Snapshots5.v1.dfy(3,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
+ >>> MarkAsFullyVerified
+Processing command (at Snapshots5.v1.dfy(10,40)) assert (forall b#1: bool :: true ==> b#1 || !b#1) || 0 != 0;
+ >>> MarkAsFullyVerified
+Processing command (at Snapshots5.v1.dfy(12,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
+ >>> MarkAsFullyVerified
+Processing command (at Snapshots5.v1.dfy(13,38)) assert (forall b#3: bool :: true ==> b#3 || !b#3) || 3 != 3;
+ >>> MarkAsFullyVerified
+Processing command (at Snapshots5.v1.dfy(20,37)) assert (exists b#5: bool :: Lit(true)) || 4 != 4;
+ >>> DoNothingToAssert
+Processing command (at Snapshots5.v1.dfy(22,35)) assert (exists b#7: bool :: Lit(true)) || 5 != 5;
+ >>> DoNothingToAssert
+
+Dafny program verifier finished with 3 verified, 0 errors
diff --git a/Test/dafny0/snapshots/Snapshots6.run.dfy b/Test/dafny0/snapshots/Snapshots6.run.dfy
new file mode 100644
index 00000000..8f958cb9
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots6.run.dfy
@@ -0,0 +1,2 @@
+// RUN: %dafny /compile:0 /verifySnapshots:2 /traceCaching:1 "%S/Inputs/Snapshots6.dfy" > "%t"
+// RUN: %diff "%s.expect" "%t"
diff --git a/Test/dafny0/snapshots/Snapshots6.run.dfy.expect b/Test/dafny0/snapshots/Snapshots6.run.dfy.expect
new file mode 100644
index 00000000..cdb942bb
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots6.run.dfy.expect
@@ -0,0 +1,11 @@
+Processing command (at Snapshots6.v0.dfy(20,14)) assert false;
+ >>> DoNothingToAssert
+
+Dafny program verifier finished with 4 verified, 0 errors
+Processing command (at Snapshots6.v1.dfy(20,14)) assert false;
+ >>> DoNothingToAssert
+Snapshots6.v1.dfy(20,13): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 3 verified, 1 error
diff --git a/Test/dafny0/snapshots/Snapshots7.run.dfy b/Test/dafny0/snapshots/Snapshots7.run.dfy
new file mode 100644
index 00000000..c84c41d2
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots7.run.dfy
@@ -0,0 +1,2 @@
+// RUN: %dafny /compile:0 /verifySnapshots:2 /traceCaching:1 "%S/Inputs/Snapshots7.dfy" > "%t"
+// RUN: %diff "%s.expect" "%t"
diff --git a/Test/dafny0/snapshots/Snapshots7.run.dfy.expect b/Test/dafny0/snapshots/Snapshots7.run.dfy.expect
new file mode 100644
index 00000000..a08b32c6
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots7.run.dfy.expect
@@ -0,0 +1,31 @@
+Processing command (at Snapshots7.v0.dfy(19,14)) assert false;
+ >>> DoNothingToAssert
+
+Dafny program verifier finished with 4 verified, 0 errors
+Processing implementation CheckWellformed$$_0_M0.C.Foo (at Snapshots7.v1.dfy(5,12)):
+ >>> added axiom: ##extracted_function##1() == (0 == $ModuleContextHeight && 0 == $FunctionContextHeight)
+ >>> added after assuming the current precondition: a##cached##0 := a##cached##0 && ##extracted_function##1();
+Processing implementation Impl$$_0_M0.C.Foo (at Snapshots7.v1.dfy(5,12)):
+ >>> added axiom: ##extracted_function##2() == (0 == $ModuleContextHeight && 0 == $FunctionContextHeight && Lit(false))
+ >>> added after assuming the current precondition: a##cached##0 := a##cached##0 && ##extracted_function##2();
+Processing implementation CheckWellformed$$_1_M1.C.Foo (at Snapshots7.v1.dfy[M1](5,12)):
+ >>> added axiom: ##extracted_function##3() == (1 == $ModuleContextHeight && 0 == $FunctionContextHeight)
+ >>> added after assuming the current precondition: a##cached##0 := a##cached##0 && ##extracted_function##3();
+Processing implementation Impl$$_1_M1.C.Foo (at Snapshots7.v1.dfy[M1](5,12)):
+ >>> added axiom: ##extracted_function##4() == (1 == $ModuleContextHeight && 0 == $FunctionContextHeight && Lit(false))
+ >>> added after assuming the current precondition: a##cached##0 := a##cached##0 && ##extracted_function##4();
+Processing command (at <unknown location>) a##cached##0 := a##cached##0 && ##extracted_function##1();
+ >>> AssumeNegationOfAssumptionVariable
+Processing command (at <unknown location>) a##cached##0 := a##cached##0 && ##extracted_function##2();
+ >>> AssumeNegationOfAssumptionVariable
+Processing command (at <unknown location>) a##cached##0 := a##cached##0 && ##extracted_function##3();
+ >>> AssumeNegationOfAssumptionVariable
+Processing command (at <unknown location>) a##cached##0 := a##cached##0 && ##extracted_function##4();
+ >>> AssumeNegationOfAssumptionVariable
+Processing command (at Snapshots7.v1.dfy(19,14)) assert false;
+ >>> MarkAsPartiallyVerified
+Snapshots7.v1.dfy(19,13): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 3 verified, 1 error
diff --git a/Test/dafny0/snapshots/Snapshots8.run.dfy b/Test/dafny0/snapshots/Snapshots8.run.dfy
new file mode 100644
index 00000000..00d20f91
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots8.run.dfy
@@ -0,0 +1,2 @@
+// RUN: %dafny /compile:0 /verifySnapshots:3 /traceCaching:1 /errorTrace:0 "%S/Inputs/Snapshots8.dfy" > "%t"
+// RUN: %diff "%s.expect" "%t"
diff --git a/Test/dafny0/snapshots/Snapshots8.run.dfy.expect b/Test/dafny0/snapshots/Snapshots8.run.dfy.expect
new file mode 100644
index 00000000..e1cbdbe0
--- /dev/null
+++ b/Test/dafny0/snapshots/Snapshots8.run.dfy.expect
@@ -0,0 +1,55 @@
+Processing command (at Snapshots8.v0.dfy(2,37)) assert x#0 < 20 || LitInt(10) <= x#0;
+ >>> DoNothingToAssert
+Processing command (at Snapshots8.v0.dfy(3,12)) assert x#0 < 10;
+ >>> DoNothingToAssert
+Processing command (at Snapshots8.v0.dfy(4,9)) assert true;
+ >>> DoNothingToAssert
+Processing command (at Snapshots8.v0.dfy(4,8)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
+ >>> DoNothingToAssert
+Processing command (at Snapshots8.v0.dfy(4,8)) assert LitInt(0) <= call0formal#AT#y#0;
+ >>> DoNothingToAssert
+Snapshots8.v0.dfy(3,11): Error: assertion violation
+Snapshots8.v0.dfy(4,7): Error BP5002: A precondition for this call might not hold.
+Snapshots8.v0.dfy(8,13): Related location: This is the precondition that might not hold.
+Processing command (at Snapshots8.v0.dfy(15,12)) assert true;
+ >>> DoNothingToAssert
+Processing command (at Snapshots8.v0.dfy(13,13)) assert LitInt(2) <= z#0;
+ >>> DoNothingToAssert
+Snapshots8.v0.dfy(17,9): Error BP5003: A postcondition might not hold on this return path.
+Snapshots8.v0.dfy(13,12): Related location: This is the postcondition that might not hold.
+Processing command (at Snapshots8.v0.dfy(23,12)) assert u#0 != 53;
+ >>> DoNothingToAssert
+Snapshots8.v0.dfy(23,11): Error: assertion violation
+Processing command (at Snapshots8.v0.dfy(28,10)) assert true;
+ >>> DoNothingToAssert
+
+Dafny program verifier finished with 7 verified, 4 errors
+Processing command (at Snapshots8.v1.dfy(30,17)) assert u#0 != 53;
+ >>> RecycleError
+Snapshots8.v1.dfy(30,16): Error: assertion violation
+Processing command (at Snapshots8.v1.dfy(3,15)) assert x#0 < 20 || LitInt(10) <= x#0;
+ >>> MarkAsFullyVerified
+Processing command (at Snapshots8.v1.dfy(5,17)) assert x#0 < 10;
+ >>> RecycleError
+Processing command (at Snapshots8.v1.dfy(6,9)) assert true;
+ >>> MarkAsFullyVerified
+Processing command (at Snapshots8.v1.dfy(6,8)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
+ >>> MarkAsFullyVerified
+Processing command (at Snapshots8.v1.dfy(6,8)) assert LitInt(0) <= call0formal#AT#y#0;
+ >>> RecycleError
+Processing command (at Snapshots8.v1.dfy(7,12)) assert x#0 == LitInt(7);
+ >>> DoNothingToAssert
+Snapshots8.v1.dfy(5,16): Error: assertion violation
+Snapshots8.v1.dfy(6,7): Error BP5002: A precondition for this call might not hold.
+Snapshots8.v1.dfy(12,20): Related location: This is the precondition that might not hold.
+Snapshots8.v1.dfy(7,11): Error: assertion violation
+Processing command (at Snapshots8.v1.dfy(21,12)) assert true;
+ >>> MarkAsFullyVerified
+Processing command (at Snapshots8.v1.dfy(23,12)) assert true;
+ >>> DoNothingToAssert
+Processing command (at Snapshots8.v1.dfy(19,13)) assert LitInt(2) <= z#0;
+ >>> DoNothingToAssert
+Snapshots8.v1.dfy(24,9): Error BP5003: A postcondition might not hold on this return path.
+Snapshots8.v1.dfy(19,12): Related location: This is the postcondition that might not hold.
+
+Dafny program verifier finished with 7 verified, 5 errors
diff --git a/Test/dafny0/snapshots/lit.local.cfg b/Test/dafny0/snapshots/lit.local.cfg
deleted file mode 100644
index 07cb869f..00000000
--- a/Test/dafny0/snapshots/lit.local.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-# This test is unusual in that we don't use the .bpl files
-# directly on the command line. So instead we'll invoke
-# files in this directory with extension '.snapshot'. There
-# will only be one for now
-config.suffixes = ['.snapshot']
diff --git a/Test/dafny0/snapshots/runtest.snapshot b/Test/dafny0/snapshots/runtest.snapshot
deleted file mode 100644
index 62ccabb3..00000000
--- a/Test/dafny0/snapshots/runtest.snapshot
+++ /dev/null
@@ -1,2 +0,0 @@
-// RUN: %dafny /compile:0 /verifySnapshots:2 /traceCaching:1 /verifySeparately Snapshots0.dfy Snapshots1.dfy Snapshots2.dfy Snapshots3.dfy Snapshots4.dfy Snapshots5.dfy Snapshots6.dfy Snapshots7.dfy > "%t"
-// RUN: %diff "%s.expect" "%t"
diff --git a/Test/dafny0/snapshots/runtest.snapshot.expect b/Test/dafny0/snapshots/runtest.snapshot.expect
deleted file mode 100644
index 8ad86f3b..00000000
--- a/Test/dafny0/snapshots/runtest.snapshot.expect
+++ /dev/null
@@ -1,180 +0,0 @@
-
--------------------- Snapshots0.dfy --------------------
-Processing command (at Snapshots0.v0.dfy(3,6)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
- >>> DoNothingToAssert
-Processing command (at Snapshots0.v0.dfy(4,10)) assert Lit(false);
- >>> DoNothingToAssert
-
-Dafny program verifier finished with 3 verified, 0 errors
-Processing call to procedure IntraModuleCall$$_module.__default.bar in implementation Impl$$_module.__default.foo (at Snapshots0.v1.dfy(3,6)):
- >>> added axiom: (forall call0old#AT#$Heap: Heap, $Heap: Heap :: {:weight 30} { ##extracted_function##1(call0old#AT#$Heap, $Heap) } ##extracted_function##1(call0old#AT#$Heap, $Heap) == (true && Lit(false) && (forall<alpha> $o: ref, $f: Field alpha :: { read($Heap, $o, $f) } $o != null && read(call0old#AT#$Heap, $o, alloc) ==> read($Heap, $o, $f) == read(call0old#AT#$Heap, $o, $f)) && $HeapSucc(call0old#AT#$Heap, $Heap)))
- >>> added after: a##post##0 := a##post##0 && ##extracted_function##1(call0old#AT#$Heap, $Heap);
-Processing command (at Snapshots0.v1.dfy(3,6)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
- >>> MarkAsFullyVerified
-Processing command (at <unknown location>) a##post##0 := a##post##0 && ##extracted_function##1(call0old#AT#$Heap, $Heap);
- >>> AssumeNegationOfAssumptionVariable
-Processing command (at Snapshots0.v1.dfy(4,10)) assert Lit(false);
- >>> MarkAsPartiallyVerified
-Snapshots0.v1.dfy(4,10): Error: assertion violation
-Execution trace:
- (0,0): anon0
-
-Dafny program verifier finished with 2 verified, 1 error
-
--------------------- Snapshots1.dfy --------------------
-Processing command (at Snapshots1.v0.dfy(3,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
- >>> DoNothingToAssert
-Processing command (at Snapshots1.v0.dfy(4,10)) assert Lit(false);
- >>> DoNothingToAssert
-Processing command (at Snapshots1.v0.dfy(12,3)) assert true;
- >>> DoNothingToAssert
-
-Dafny program verifier finished with 4 verified, 0 errors
-Processing call to procedure IntraModuleCall$$_module.__default.N in implementation Impl$$_module.__default.M (at Snapshots1.v1.dfy(3,4)):
- >>> added after: a##post##0 := a##post##0 && false;
-Processing command (at Snapshots1.v1.dfy(12,3)) assert true;
- >>> MarkAsFullyVerified
-Processing command (at Snapshots1.v1.dfy(3,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
- >>> MarkAsFullyVerified
-Processing command (at Snapshots1.v1.dfy(4,10)) assert Lit(false);
- >>> DoNothingToAssert
-Snapshots1.v1.dfy(4,10): Error: assertion violation
-Execution trace:
- (0,0): anon0
-
-Dafny program verifier finished with 3 verified, 1 error
-
--------------------- Snapshots2.dfy --------------------
-Processing command (at Snapshots2.v0.dfy(3,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
- >>> DoNothingToAssert
-Processing command (at Snapshots2.v0.dfy(4,10)) assert Lit(false);
- >>> DoNothingToAssert
-Processing command (at Snapshots2.v0.dfy(11,11)) assert true;
- >>> DoNothingToAssert
-Processing command (at Snapshots2.v0.dfy(11,15)) assert _module.__default.P($LS($LS($LZ)), $Heap) <==> _module.__default.Q($LS($LS($LZ)), $Heap);
- >>> DoNothingToAssert
-Processing command (at Snapshots2.v0.dfy(14,11)) assert true;
- >>> DoNothingToAssert
-Processing command (at Snapshots2.v0.dfy(14,15)) assert _module.__default.Q($LS($LS($LZ)), $Heap) <==> Lit(_module.__default.R($Heap));
- >>> DoNothingToAssert
-Processing command (at Snapshots2.v0.dfy(18,3)) assert true;
- >>> DoNothingToAssert
-
-Dafny program verifier finished with 6 verified, 0 errors
-Processing call to procedure IntraModuleCall$$_module.__default.N in implementation Impl$$_module.__default.M (at Snapshots2.v1.dfy(3,4)):
- >>> added after: a##post##0 := a##post##0 && false;
-Processing command (at Snapshots2.v1.dfy(18,3)) assert true;
- >>> MarkAsFullyVerified
-Processing command (at Snapshots2.v1.dfy(3,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
- >>> MarkAsFullyVerified
-Processing command (at Snapshots2.v1.dfy(4,10)) assert Lit(false);
- >>> DoNothingToAssert
-Snapshots2.v1.dfy(4,10): Error: assertion violation
-Execution trace:
- (0,0): anon0
-Processing command (at Snapshots2.v1.dfy(11,11)) assert true;
- >>> MarkAsFullyVerified
-Processing command (at Snapshots2.v1.dfy(11,15)) assert _module.__default.P($LS($LS($LZ)), $Heap) <==> _module.__default.Q($LS($LS($LZ)), $Heap);
- >>> DoNothingToAssert
-Processing command (at Snapshots2.v1.dfy(14,11)) assert true;
- >>> MarkAsFullyVerified
-Processing command (at Snapshots2.v1.dfy(14,15)) assert _module.__default.Q($LS($LS($LZ)), $Heap) <==> Lit(_module.__default.R($Heap));
- >>> DoNothingToAssert
-
-Dafny program verifier finished with 5 verified, 1 error
-
--------------------- Snapshots3.dfy --------------------
-Processing command (at Snapshots3.v0.dfy(9,14)) assert Lit(0 != 0);
- >>> DoNothingToAssert
-Snapshots3.v0.dfy(9,14): Error: assertion violation
-Execution trace:
- (0,0): anon0
- (0,0): anon3_Else
-
-Dafny program verifier finished with 1 verified, 1 error
-Processing command (at Snapshots3.v1.dfy(5,12)) assert Lit(true);
- >>> DoNothingToAssert
-Processing command (at Snapshots3.v1.dfy(9,14)) assert Lit(0 != 0);
- >>> RecycleError
-Snapshots3.v0.dfy(9,14): Error: assertion violation
-Execution trace:
- (0,0): anon0
- (0,0): anon3_Else
-
-Dafny program verifier finished with 1 verified, 1 error
-
--------------------- Snapshots4.dfy --------------------
-Processing command (at Snapshots4.v0.dfy(9,14)) assert LitInt(0) == LitInt(0);
- >>> DoNothingToAssert
-
-Dafny program verifier finished with 2 verified, 0 errors
-Processing command (at Snapshots4.v1.dfy(5,14)) assert Lit(1 != 1);
- >>> DoNothingToAssert
-Processing command (at Snapshots4.v1.dfy(9,14)) assert LitInt(0) == LitInt(0);
- >>> MarkAsFullyVerified
-Processing command (at Snapshots4.v1.dfy(10,14)) assert Lit(2 != 2);
- >>> DoNothingToAssert
-Snapshots4.v1.dfy(5,14): Error: assertion violation
-Execution trace:
- (0,0): anon0
- (0,0): anon3_Then
-Snapshots4.v1.dfy(10,14): Error: assertion violation
-Execution trace:
- (0,0): anon0
- (0,0): anon3_Else
-
-Dafny program verifier finished with 1 verified, 2 errors
-
--------------------- Snapshots5.dfy --------------------
-Processing command (at Snapshots5.v0.dfy(3,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
- >>> DoNothingToAssert
-Processing command (at Snapshots5.v0.dfy(10,40)) assert (forall b#1: bool :: true ==> b#1 || !b#1) || 0 != 0;
- >>> DoNothingToAssert
-Processing command (at Snapshots5.v0.dfy(12,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
- >>> DoNothingToAssert
-Processing command (at Snapshots5.v0.dfy(13,38)) assert (forall b#3: bool :: true ==> b#3 || !b#3) || 3 != 3;
- >>> DoNothingToAssert
-Processing command (at Snapshots5.v0.dfy(20,40)) assert (forall b#5: bool :: true ==> b#5 || !b#5) || 1 != 1;
- >>> DoNothingToAssert
-
-Dafny program verifier finished with 3 verified, 0 errors
-Processing command (at Snapshots5.v1.dfy(3,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
- >>> MarkAsFullyVerified
-Processing command (at Snapshots5.v1.dfy(10,40)) assert (forall b#1: bool :: true ==> b#1 || !b#1) || 0 != 0;
- >>> MarkAsFullyVerified
-Processing command (at Snapshots5.v1.dfy(12,4)) assert (forall<alpha> $o: ref, $f: Field alpha :: false ==> $_Frame[$o, $f]);
- >>> MarkAsFullyVerified
-Processing command (at Snapshots5.v1.dfy(13,38)) assert (forall b#3: bool :: true ==> b#3 || !b#3) || 3 != 3;
- >>> MarkAsFullyVerified
-Processing command (at Snapshots5.v1.dfy(20,40)) assert (exists b#5: bool :: b#5 || !b#5) || 4 != 4;
- >>> DoNothingToAssert
-Processing command (at Snapshots5.v1.dfy(22,38)) assert (exists b#7: bool :: b#7 || !b#7) || 5 != 5;
- >>> DoNothingToAssert
-
-Dafny program verifier finished with 3 verified, 0 errors
-
--------------------- Snapshots6.dfy --------------------
-Processing command (at Snapshots6.v0.dfy(20,14)) assert Lit(false);
- >>> DoNothingToAssert
-
-Dafny program verifier finished with 4 verified, 0 errors
-Processing command (at Snapshots6.v1.dfy(20,14)) assert Lit(false);
- >>> DoNothingToAssert
-Snapshots6.v1.dfy(20,14): Error: assertion violation
-Execution trace:
- (0,0): anon0
-
-Dafny program verifier finished with 3 verified, 1 error
-
--------------------- Snapshots7.dfy --------------------
-Processing command (at Snapshots7.v0.dfy(19,14)) assert Lit(false);
- >>> DoNothingToAssert
-
-Dafny program verifier finished with 4 verified, 0 errors
-Processing command (at Snapshots7.v1.dfy(19,14)) assert Lit(false);
- >>> DoNothingToAssert
-Snapshots7.v1.dfy(19,14): Error: assertion violation
-Execution trace:
- (0,0): anon0
-
-Dafny program verifier finished with 3 verified, 1 error
diff --git a/Test/dafny1/BDD.dfy b/Test/dafny1/BDD.dfy
index 252164db..59dc3092 100644
--- a/Test/dafny1/BDD.dfy
+++ b/Test/dafny1/BDD.dfy
@@ -55,6 +55,7 @@ module SimpleBDD
node := if s[n-i] then node.t else node.f;
i := i - 1;
}
+ assert s[n-i..] == [];
b := node.b;
}
}
diff --git a/Test/dafny1/ExtensibleArrayAuto.dfy b/Test/dafny1/ExtensibleArrayAuto.dfy
index b2e5ecc4..01afdafd 100644
--- a/Test/dafny1/ExtensibleArrayAuto.dfy
+++ b/Test/dafny1/ExtensibleArrayAuto.dfy
@@ -2,12 +2,12 @@
// RUN: %diff "%s.expect" "%t"
class {:autocontracts} ExtensibleArray<T> {
- ghost var Contents: seq<T>;
+ ghost var Contents: seq<T>
- var elements: array<T>;
- var more: ExtensibleArray<array<T>>;
- var length: int;
- var M: int; // shorthand for: if more == null then 0 else 256 * |more.Contents|
+ var elements: array<T>
+ var more: ExtensibleArray<array<T>>
+ var length: int
+ var M: int // shorthand for: if more == null then 0 else 256 * |more.Contents|
predicate Valid()
{
@@ -35,7 +35,7 @@ class {:autocontracts} ExtensibleArray<T> {
}
constructor Init()
- ensures Contents == [];
+ ensures Contents == []
{
elements := new T[256];
more := null;
@@ -46,11 +46,11 @@ class {:autocontracts} ExtensibleArray<T> {
}
method Get(i: int) returns (t: T)
- requires 0 <= i < |Contents|;
- ensures t == Contents[i];
- decreases Repr;
+ requires 0 <= i < |Contents|
+ ensures t == Contents[i]
+ decreases Repr
{
- if (M <= i) {
+ if M <= i {
t := elements[i - M];
} else {
var arr := more.Get(i / 256);
@@ -59,10 +59,10 @@ class {:autocontracts} ExtensibleArray<T> {
}
method Set(i: int, t: T)
- requires 0 <= i < |Contents|;
- ensures Contents == old(Contents)[i := t];
+ requires 0 <= i < |Contents|
+ ensures Contents == old(Contents)[i := t]
{
- if (M <= i) {
+ if M <= i {
elements[i - M] := t;
} else {
var arr := more.Get(i / 256);
@@ -72,14 +72,14 @@ class {:autocontracts} ExtensibleArray<T> {
}
method Append(t: T)
- ensures Contents == old(Contents) + [t];
- decreases |Contents|;
+ ensures Contents == old(Contents) + [t]
+ decreases |Contents|
{
- if (length == 0 || length % 256 != 0) {
+ if length == 0 || length % 256 != 0 {
// there is room in "elements"
elements[length - M] := t;
} else {
- if (more == null) {
+ if more == null {
more := new ExtensibleArray<array<T>>.Init();
Repr := Repr + {more} + more.Repr;
}
@@ -99,7 +99,7 @@ class {:autocontracts} ExtensibleArray<T> {
method Main() {
var a := new ExtensibleArray<int>.Init();
var n := 0;
- while (n < 256*256+600)
+ while n < 256*256+600
invariant a.Valid() && fresh(a.Repr);
invariant |a.Contents| == n;
{
diff --git a/Test/dafny1/FindZero.dfy b/Test/dafny1/FindZero.dfy
index f0eb6a60..374555b0 100644
--- a/Test/dafny1/FindZero.dfy
+++ b/Test/dafny1/FindZero.dfy
@@ -3,7 +3,7 @@
method FindZero(a: array<int>) returns (r: int)
requires a != null && forall i :: 0 <= i < a.Length ==> 0 <= a[i];
- requires forall i :: 0 <= i && i+1 < a.Length ==> a[i]-1 <= a[i+1];
+ requires forall i {:nowarn} :: 0 <= i && i+1 < a.Length ==> a[i]-1 <= a[i+1];
ensures 0 <= r ==> r < a.Length && a[r] == 0;
ensures r < 0 ==> forall i :: 0 <= i < a.Length ==> a[i] != 0;
{
@@ -18,9 +18,9 @@ method FindZero(a: array<int>) returns (r: int)
r := -1;
}
-ghost method Lemma(a: array<int>, k: int, m: int)
+lemma Lemma(a: array<int>, k: int, m: int)
requires a != null && forall i :: 0 <= i < a.Length ==> 0 <= a[i];
- requires forall i :: 0 <= i && i+1 < a.Length ==> a[i]-1 <= a[i+1];
+ requires forall i {:nowarn} :: 0 <= i && i+1 < a.Length ==> a[i]-1 <= a[i+1];
requires 0 <= k;
requires k < a.Length ==> m <= a[k];
ensures forall i :: k <= i < k+m && i < a.Length ==> a[i] != 0;
@@ -36,7 +36,7 @@ ghost method Lemma(a: array<int>, k: int, m: int)
method FindZero_GhostLoop(a: array<int>) returns (r: int)
requires a != null && forall i :: 0 <= i < a.Length ==> 0 <= a[i];
- requires forall i :: 0 <= i && i+1 < a.Length ==> a[i]-1 <= a[i+1];
+ requires forall i {:nowarn} :: 0 <= i && i+1 < a.Length ==> a[i]-1 <= a[i+1];
ensures 0 <= r ==> r < a.Length && a[r] == 0;
ensures r < 0 ==> forall i :: 0 <= i < a.Length ==> a[i] != 0;
{
@@ -63,7 +63,7 @@ method FindZero_GhostLoop(a: array<int>) returns (r: int)
method FindZero_Assert(a: array<int>) returns (r: int)
requires a != null && forall i :: 0 <= i < a.Length ==> 0 <= a[i];
- requires forall i :: 0 <= i-1 && i < a.Length ==> a[i-1]-1 <= a[i];
+ requires forall i {:nowarn} :: 0 <= i-1 && i < a.Length ==> a[i-1]-1 <= a[i];
ensures 0 <= r ==> r < a.Length && a[r] == 0;
ensures r < 0 ==> forall i :: 0 <= i < a.Length ==> a[i] != 0;
{
diff --git a/Test/dafny1/Induction.dfy b/Test/dafny1/Induction.dfy
index 28171896..e2cd4ade 100644
--- a/Test/dafny1/Induction.dfy
+++ b/Test/dafny1/Induction.dfy
@@ -22,7 +22,7 @@ class IntegerInduction {
// Here is one proof. It uses a lemma, which is proved separately.
- ghost method Theorem0(n: int)
+ lemma Theorem0(n: int)
requires 0 <= n;
ensures SumOfCubes(n) == Gauss(n) * Gauss(n);
{
@@ -32,7 +32,7 @@ class IntegerInduction {
}
}
- ghost method Lemma(n: int)
+ lemma Lemma(n: int)
requires 0 <= n;
ensures 2 * Gauss(n) == n*(n+1);
{
@@ -42,7 +42,7 @@ class IntegerInduction {
// Here is another proof. It states the lemma as part of the theorem, and
// thus proves the two together.
- ghost method Theorem1(n: int)
+ lemma Theorem1(n: int)
requires 0 <= n;
ensures SumOfCubes(n) == Gauss(n) * Gauss(n);
ensures 2 * Gauss(n) == n*(n+1);
@@ -52,24 +52,24 @@ class IntegerInduction {
}
}
- ghost method DoItAllInOneGo()
- ensures (forall n :: 0 <= n ==>
+ lemma DoItAllInOneGo()
+ ensures (forall n {:split false} :: 0 <= n ==> // WISH reenable quantifier splitting here. This will only work once we generate induction hypotheses at the Dafny level.
SumOfCubes(n) == Gauss(n) * Gauss(n) &&
2 * Gauss(n) == n*(n+1));
{
}
- // The following two ghost methods are the same as the previous two, but
+ // The following two lemmas are the same as the previous two, but
// here no body is given--and the proof still goes through (thanks to
// Dafny's ghost-method induction tactic).
- ghost method Lemma_Auto(n: int)
+ lemma Lemma_Auto(n: int)
requires 0 <= n;
ensures 2 * Gauss(n) == n*(n+1);
{
}
- ghost method Theorem1_Auto(n: int)
+ lemma Theorem1_Auto(n: int)
requires 0 <= n;
ensures SumOfCubes(n) == Gauss(n) * Gauss(n);
ensures 2 * Gauss(n) == n*(n+1);
@@ -79,7 +79,7 @@ class IntegerInduction {
// Here is another proof. It makes use of Dafny's induction heuristics to
// prove the lemma.
- ghost method Theorem2(n: int)
+ lemma Theorem2(n: int)
requires 0 <= n;
ensures SumOfCubes(n) == Gauss(n) * Gauss(n);
{
@@ -90,7 +90,7 @@ class IntegerInduction {
}
}
- ghost method M(n: int)
+ lemma M(n: int)
requires 0 <= n;
{
assume (forall k :: 0 <= k && k < n ==> 2 * Gauss(k) == k*(k+1)); // manually assume the induction hypothesis
@@ -99,7 +99,7 @@ class IntegerInduction {
// Another way to prove the lemma is to supply a postcondition on the Gauss function
- ghost method Theorem3(n: int)
+ lemma Theorem3(n: int)
requires 0 <= n;
ensures SumOfCubes(n) == GaussWithPost(n) * GaussWithPost(n);
{
@@ -117,14 +117,14 @@ class IntegerInduction {
// Finally, with the postcondition of GaussWithPost, one can prove the entire theorem by induction
- ghost method Theorem4()
+ lemma Theorem4()
ensures (forall n :: 0 <= n ==>
SumOfCubes(n) == GaussWithPost(n) * GaussWithPost(n));
{
// look ma, no hints!
}
- ghost method Theorem5(n: int)
+ lemma Theorem5(n: int)
requires 0 <= n;
ensures SumOfCubes(n) == GaussWithPost(n) * GaussWithPost(n);
{
@@ -148,11 +148,11 @@ class IntegerInduction {
// Proving the "<==" case is simple; it's the "==>" case that requires induction.
// The example uses an attribute that requests induction on just "j". However, the proof also
// goes through by applying induction on both bound variables.
- function method IsSorted(s: seq<int>): bool
- ensures IsSorted(s) ==> (forall i,j {:induction j} :: 0 <= i && i < j && j < |s| ==> s[i] <= s[j]);
+ function method IsSorted(s: seq<int>): bool //WISH remove autotriggers false
+ ensures IsSorted(s) ==> (forall i,j {:induction j} {:autotriggers false} :: 0 <= i < j < |s| ==> s[i] <= s[j]);
ensures (forall i,j :: 0 <= i && i < j && j < |s| ==> s[i] <= s[j]) ==> IsSorted(s);
{
- (forall i :: 1 <= i && i < |s| ==> s[i-1] <= s[i])
+ (forall i {:nowarn} :: 1 <= i && i < |s| ==> s[i-1] <= s[i])
}
}
diff --git a/Test/dafny1/MoreInduction.dfy b/Test/dafny1/MoreInduction.dfy
index 41adcf50..2b5187a4 100644
--- a/Test/dafny1/MoreInduction.dfy
+++ b/Test/dafny1/MoreInduction.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
datatype List<X> = Nil | Cons(Node<X>, List<X>)
@@ -42,13 +42,13 @@ function ToSeq<X>(list: List<X>): seq<X>
case Nary(nn) => ToSeq(nn) + ToSeq(rest)
}
-ghost method Theorem<X>(list: List<X>)
+lemma Theorem<X>(list: List<X>)
ensures ToSeq(list) == ToSeq(FlattenMain(list));
{
Lemma(list, Nil);
}
-ghost method Lemma<X>(list: List<X>, ext: List<X>)
+lemma Lemma<X>(list: List<X>, ext: List<X>)
requires IsFlat(ext);
ensures ToSeq(list) + ToSeq(ext) == ToSeq(Flatten(list, ext));
{
@@ -73,27 +73,27 @@ function NegFac(n: int): int
if -1 <= n then -1 else - NegFac(n+1) * n
}
-ghost method LemmaAll()
+lemma LemmaAll()
ensures forall n :: NegFac(n) <= -1; // error: induction heuristic does not give a useful well-founded order, and thus this fails to verify
{
}
-ghost method LemmaOne(n: int)
+lemma LemmaOne(n: int)
ensures NegFac(n) <= -1; // error: induction heuristic does not give a useful well-founded order, and thus this fails to verify
{
}
-ghost method LemmaAll_Neg()
- ensures forall n :: NegFac(-n) <= -1; // error: fails to verify because of the minus in the trigger
+lemma LemmaAll_Neg() //FIXME I don't understand the comment below; what trigger?
+ ensures forall n {:nowarn} :: NegFac(-n) <= -1; // error: fails to verify because of the minus in the trigger
{
}
-ghost method LemmaOne_Neg(n: int)
+lemma LemmaOne_Neg(n: int) //FIXME What trigger?
ensures NegFac(-n) <= -1; // error: fails to verify because of the minus in the trigger
{
}
-ghost method LemmaOneWithDecreases(n: int)
+lemma LemmaOneWithDecreases(n: int)
ensures NegFac(n) <= -1; // here, the programmer gives a good well-founded order, so this verifies
decreases -n;
{
diff --git a/Test/dafny1/MoreInduction.dfy.expect b/Test/dafny1/MoreInduction.dfy.expect
index c8785e56..5de0ace6 100644
--- a/Test/dafny1/MoreInduction.dfy.expect
+++ b/Test/dafny1/MoreInduction.dfy.expect
@@ -1,17 +1,17 @@
-MoreInduction.dfy(78,1): Error BP5003: A postcondition might not hold on this return path.
-MoreInduction.dfy(77,11): Related location: This is the postcondition that might not hold.
+MoreInduction.dfy(78,0): Error BP5003: A postcondition might not hold on this return path.
+MoreInduction.dfy(77,10): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-MoreInduction.dfy(83,1): Error BP5003: A postcondition might not hold on this return path.
-MoreInduction.dfy(82,21): Related location: This is the postcondition that might not hold.
+MoreInduction.dfy(83,0): Error BP5003: A postcondition might not hold on this return path.
+MoreInduction.dfy(82,20): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-MoreInduction.dfy(88,1): Error BP5003: A postcondition might not hold on this return path.
-MoreInduction.dfy(87,11): Related location: This is the postcondition that might not hold.
+MoreInduction.dfy(88,0): Error BP5003: A postcondition might not hold on this return path.
+MoreInduction.dfy(87,10): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
-MoreInduction.dfy(93,1): Error BP5003: A postcondition might not hold on this return path.
-MoreInduction.dfy(92,22): Related location: This is the postcondition that might not hold.
+MoreInduction.dfy(93,0): Error BP5003: A postcondition might not hold on this return path.
+MoreInduction.dfy(92,21): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
diff --git a/Test/dafny1/PriorityQueue.dfy b/Test/dafny1/PriorityQueue.dfy
index 94223cba..3d2a5d78 100644
--- a/Test/dafny1/PriorityQueue.dfy
+++ b/Test/dafny1/PriorityQueue.dfy
@@ -12,7 +12,7 @@ class PriorityQueue {
reads this, Repr;
{
MostlyValid() &&
- (forall j :: 2 <= j && j <= n ==> a[j/2] <= a[j])
+ (forall j {:nowarn} :: 2 <= j && j <= n ==> a[j/2] <= a[j])
}
predicate MostlyValid()
@@ -50,8 +50,8 @@ class PriorityQueue {
method SiftUp(k: int)
requires 1 <= k && k <= n;
requires MostlyValid();
- requires (forall j :: 2 <= j && j <= n && j != k ==> a[j/2] <= a[j]);
- requires (forall j :: 1 <= j && j <= n ==> j/2 != k); // k is a leaf
+ requires (forall j {:nowarn} :: 2 <= j && j <= n && j != k ==> a[j/2] <= a[j]);
+ requires (forall j {:nowarn} :: 1 <= j && j <= n ==> j/2 != k); // k is a leaf
modifies a;
ensures Valid();
{
@@ -59,8 +59,8 @@ class PriorityQueue {
assert MostlyValid();
while (1 < i)
invariant i <= k && MostlyValid();
- invariant (forall j :: 2 <= j && j <= n && j != i ==> a[j/2] <= a[j]);
- invariant (forall j :: 1 <= j/2/2 && j/2 == i && j <= n ==> a[j/2/2] <= a[j]);
+ invariant (forall j {:nowarn} :: 2 <= j && j <= n && j != i ==> a[j/2] <= a[j]);
+ invariant (forall j {:nowarn} :: 1 <= j/2/2 && j/2 == i && j <= n ==> a[j/2/2] <= a[j]);
{
if (a[i/2] <= a[i]) {
return;
@@ -85,8 +85,8 @@ class PriorityQueue {
method SiftDown(k: int)
requires 1 <= k;
requires MostlyValid();
- requires (forall j :: 2 <= j && j <= n && j/2 != k ==> a[j/2] <= a[j]);
- requires (forall j :: 2 <= j && j <= n && 1 <= j/2/2 && j/2/2 != k ==> a[j/2/2] <= a[j]);
+ requires (forall j {:nowarn} :: 2 <= j && j <= n && j/2 != k ==> a[j/2] <= a[j]);
+ requires (forall j {:nowarn} :: 2 <= j && j <= n && 1 <= j/2/2 && j/2/2 != k ==> a[j/2/2] <= a[j]);
// Alternatively, the line above can be expressed as:
// requires (forall j :: 1 <= k/2 && j/2 == k && j <= n ==> a[j/2/2] <= a[j]);
modifies a;
@@ -95,8 +95,8 @@ class PriorityQueue {
var i := k;
while (2*i <= n) // while i is not a leaf
invariant 1 <= i && MostlyValid();
- invariant (forall j :: 2 <= j && j <= n && j/2 != i ==> a[j/2] <= a[j]);
- invariant (forall j :: 2 <= j && j <= n && 1 <= j/2/2 && j/2/2 != i ==> a[j/2/2] <= a[j]);
+ invariant (forall j {:nowarn} :: 2 <= j && j <= n && j/2 != i ==> a[j/2] <= a[j]);
+ invariant (forall j {:nowarn} :: 2 <= j && j <= n && 1 <= j/2/2 && j/2/2 != i ==> a[j/2/2] <= a[j]);
{
var smallestChild;
if (2*i + 1 <= n && a[2*i + 1] < a[2*i]) {
@@ -127,7 +127,7 @@ class PriorityQueue_Alternative {
reads this, Repr;
{
MostlyValid() &&
- (forall j :: 2 <= j && j <= n ==> a[j/2] <= a[j])
+ (forall j {:nowarn} :: 2 <= j && j <= n ==> a[j/2] <= a[j])
}
predicate MostlyValid()
@@ -164,7 +164,7 @@ class PriorityQueue_Alternative {
method SiftUp()
requires MostlyValid();
- requires (forall j :: 2 <= j && j <= n && j != n ==> a[j/2] <= a[j]);
+ requires (forall j {:nowarn} :: 2 <= j && j <= n && j != n ==> a[j/2] <= a[j]);
modifies a;
ensures Valid();
{
@@ -172,8 +172,8 @@ class PriorityQueue_Alternative {
assert MostlyValid();
while (1 < i)
invariant i <= n && MostlyValid();
- invariant (forall j :: 2 <= j && j <= n && j != i ==> a[j/2] <= a[j]);
- invariant (forall j :: 1 <= j/2/2 && j/2 == i && j <= n ==> a[j/2/2] <= a[j]);
+ invariant (forall j {:nowarn} :: 2 <= j && j <= n && j != i ==> a[j/2] <= a[j]);
+ invariant (forall j {:nowarn} :: 1 <= j/2/2 && j/2 == i && j <= n ==> a[j/2/2] <= a[j]);
{
if (a[i/2] <= a[i]) {
return;
@@ -197,15 +197,15 @@ class PriorityQueue_Alternative {
method SiftDown()
requires MostlyValid();
- requires (forall j :: 4 <= j && j <= n ==> a[j/2] <= a[j]);
+ requires (forall j {:nowarn} :: 4 <= j && j <= n ==> a[j/2] <= a[j]);
modifies a;
ensures Valid();
{
var i := 1;
while (2*i <= n) // while i is not a leaf
invariant 1 <= i && MostlyValid();
- invariant (forall j :: 2 <= j && j <= n && j/2 != i ==> a[j/2] <= a[j]);
- invariant (forall j :: 1 <= j/2/2 && j/2 == i && j <= n ==> a[j/2/2] <= a[j]);
+ invariant (forall j {:nowarn} :: 2 <= j && j <= n && j/2 != i ==> a[j/2] <= a[j]);
+ invariant (forall j {:nowarn} :: 1 <= j/2/2 && j/2 == i && j <= n ==> a[j/2/2] <= a[j]);
{
var smallestChild;
if (2*i + 1 <= n && a[2*i + 1] < a[2*i]) {
diff --git a/Test/dafny1/Rippling.dfy b/Test/dafny1/Rippling.dfy
index 55701a93..d888a5cc 100644
--- a/Test/dafny1/Rippling.dfy
+++ b/Test/dafny1/Rippling.dfy
@@ -300,244 +300,244 @@ function AlwaysTrueFunction(): FunctionValue
// The theorems to be proved
// -----------------------------------------------------------------------------------
-ghost method P1()
+lemma P1()
ensures forall n, xs :: concat(take(n, xs), drop(n, xs)) == xs;
{
}
-ghost method P2()
+lemma P2()
ensures forall n, xs, ys :: add(count(n, xs), count(n, ys)) == count(n, concat(xs, ys));
{
}
-ghost method P3()
+lemma P3()
ensures forall n, xs, ys :: leq(count(n, xs), count(n, concat(xs, ys))) == True;
{
}
-ghost method P4()
+lemma P4()
ensures forall n, xs :: add(Suc(Zero), count(n, xs)) == count(n, Cons(n, xs));
{
}
-ghost method P5()
+lemma P5()
ensures forall n, xs, x ::
add(Suc(Zero), count(n, xs)) == count(n, Cons(x, xs))
==> n == x;
{
}
-ghost method P6()
+lemma P6()
ensures forall m, n :: minus(n, add(n, m)) == Zero;
{
}
-ghost method P7()
+lemma P7()
ensures forall m, n :: minus(add(n, m), n) == m;
{
}
-ghost method P8()
+lemma P8()
ensures forall k, m, n :: minus(add(k, m), add(k, n)) == minus(m, n);
{
}
-ghost method P9()
+lemma P9()
ensures forall i, j, k :: minus(minus(i, j), k) == minus(i, add(j, k));
{
}
-ghost method P10()
+lemma P10()
ensures forall m :: minus(m, m) == Zero;
{
}
-ghost method P11()
+lemma P11()
ensures forall xs :: drop(Zero, xs) == xs;
{
}
-ghost method P12()
+lemma P12()
ensures forall n, xs, f :: drop(n, apply(f, xs)) == apply(f, drop(n, xs));
{
}
-ghost method P13()
+lemma P13()
ensures forall n, x, xs :: drop(Suc(n), Cons(x, xs)) == drop(n, xs);
{
}
-ghost method P14()
+lemma P14()
ensures forall xs, ys, p :: filter(p, concat(xs, ys)) == concat(filter(p, xs), filter(p, ys));
{
}
-ghost method P15()
+lemma P15()
ensures forall x, xs :: len(ins(x, xs)) == Suc(len(xs));
{
}
-ghost method P16()
+lemma P16()
ensures forall x, xs :: xs == Nil ==> last(Cons(x, xs)) == x;
{
}
-ghost method P17()
+lemma P17()
ensures forall n :: leq(n, Zero) == True <==> n == Zero;
{
}
-ghost method P18()
+lemma P18()
ensures forall i, m :: less(i, Suc(add(i, m))) == True;
{
}
-ghost method P19()
+lemma P19()
ensures forall n, xs :: len(drop(n, xs)) == minus(len(xs), n);
{
}
-ghost method P20()
+lemma P20()
ensures forall xs :: len(sort(xs)) == len(xs);
{
// the proof of this theorem requires a lemma about "insort"
assert forall x, xs :: len(insort(x, xs)) == Suc(len(xs));
}
-ghost method P21()
+lemma P21()
ensures forall n, m :: leq(n, add(n, m)) == True;
{
}
-ghost method P22()
+lemma P22()
ensures forall a, b, c :: max(max(a, b), c) == max(a, max(b, c));
{
}
-ghost method P23()
+lemma P23()
ensures forall a, b :: max(a, b) == max(b, a);
{
}
-ghost method P24()
+lemma P24()
ensures forall a, b :: max(a, b) == a <==> leq(b, a) == True;
{
}
-ghost method P25()
+lemma P25()
ensures forall a, b :: max(a, b) == b <==> leq(a, b) == True;
{
}
-ghost method P26()
+lemma P26()
ensures forall x, xs, ys :: mem(x, xs) == True ==> mem(x, concat(xs, ys)) == True;
{
}
-ghost method P27()
+lemma P27()
ensures forall x, xs, ys :: mem(x, ys) == True ==> mem(x, concat(xs, ys)) == True;
{
}
-ghost method P28()
+lemma P28()
ensures forall x, xs :: mem(x, concat(xs, Cons(x, Nil))) == True;
{
}
-ghost method P29()
+lemma P29()
ensures forall x, xs :: mem(x, ins1(x, xs)) == True;
{
}
-ghost method P30()
+lemma P30()
ensures forall x, xs :: mem(x, ins(x, xs)) == True;
{
}
-ghost method P31()
+lemma P31()
ensures forall a, b, c :: min(min(a, b), c) == min(a, min(b, c));
{
}
-ghost method P32()
+lemma P32()
ensures forall a, b :: min(a, b) == min(b, a);
{
}
-ghost method P33()
+lemma P33()
ensures forall a, b :: min(a, b) == a <==> leq(a, b) == True;
{
}
-ghost method P34()
+lemma P34()
ensures forall a, b :: min(a, b) == b <==> leq(b, a) == True;
{
}
-ghost method P35()
+lemma P35()
ensures forall xs :: dropWhileAlways(AlwaysFalseFunction(), xs) == xs;
{
}
-ghost method P36()
+lemma P36()
ensures forall xs :: takeWhileAlways(AlwaysTrueFunction(), xs) == xs;
{
}
-ghost method P37()
+lemma P37()
ensures forall x, xs :: not(mem(x, delete(x, xs))) == True;
{
}
-ghost method P38()
+lemma P38()
ensures forall n, xs :: count(n, concat(xs, Cons(n, Nil))) == Suc(count(n, xs));
{
}
-ghost method P39()
+lemma P39()
ensures forall n, x, xs ::
add(count(n, Cons(x, Nil)), count(n, xs)) == count(n, Cons(x, xs));
{
}
-ghost method P40()
+lemma P40()
ensures forall xs :: take(Zero, xs) == Nil;
{
}
-ghost method P41()
+lemma P41()
ensures forall n, xs, f :: take(n, apply(f, xs)) == apply(f, take(n, xs));
{
}
-ghost method P42()
+lemma P42()
ensures forall n, x, xs :: take(Suc(n), Cons(x, xs)) == Cons(x, take(n, xs));
{
}
-ghost method P43(p: FunctionValue)
+lemma P43(p: FunctionValue)
ensures forall xs :: concat(takeWhileAlways(p, xs), dropWhileAlways(p, xs)) == xs;
{
}
-ghost method P44()
+lemma P44()
ensures forall x, xs, ys :: zip(Cons(x, xs), ys) == zipConcat(x, xs, ys);
{
}
-ghost method P45()
+lemma P45()
ensures forall x, xs, y, ys ::
zip(Cons(x, xs), Cons(y, ys)) ==
PCons(Pair.Pair(x, y), zip(xs, ys));
{
}
-ghost method P46()
+lemma P46()
ensures forall ys :: zip(Nil, ys) == PNil;
{
}
-ghost method P47()
+lemma P47()
ensures forall a :: height(mirror(a)) == height(a);
{
// proving this theorem requires a previously proved lemma:
@@ -546,20 +546,20 @@ ghost method P47()
// ...
-ghost method P54()
+lemma P54()
ensures forall m, n :: minus(add(m, n), n) == m;
{
// the proof of this theorem follows from two lemmas:
- assert forall m, n :: minus(add(n, m), n) == m;
+ assert forall m, n {:autotriggers false} :: minus(add(n, m), n) == m; // FIXME: Why does Autotriggers false make things verify?
assert forall m, n :: add(m, n) == add(n, m);
}
-ghost method P65()
+lemma P65()
ensures forall i, m :: less(i, Suc(add(m, i))) == True;
{
if (*) {
// the proof of this theorem follows from two lemmas:
- assert forall i, m :: less(i, Suc(add(i, m))) == True;
+ assert forall i, m {:autotriggers false} :: less(i, Suc(add(i, m))) == True; // FIXME: Why does Autotriggers false make things verify?
assert forall m, n :: add(m, n) == add(n, m);
} else {
// a different way to prove it uses the following lemma:
@@ -567,12 +567,12 @@ ghost method P65()
}
}
-ghost method P67()
+lemma P67()
ensures forall m, n :: leq(n, add(m, n)) == True;
{
if (*) {
// the proof of this theorem follows from two lemmas:
- assert forall m, n :: leq(n, add(n, m)) == True;
+ assert forall m, n {:autotriggers false} :: leq(n, add(n, m)) == True; // FIXME: Why does Autotriggers false make things verify?
assert forall m, n :: add(m, n) == add(n, m);
} else {
// a different way to prove it uses the following lemma:
@@ -583,19 +583,19 @@ ghost method P67()
// ---------
// Here is a alternate way of writing down the proof obligations:
-ghost method P1_alt(n: Nat, xs: List)
+lemma P1_alt(n: Nat, xs: List)
ensures concat(take(n, xs), drop(n, xs)) == xs;
{
}
-ghost method P2_alt(n: Nat, xs: List, ys: List)
+lemma P2_alt(n: Nat, xs: List, ys: List)
ensures add(count(n, xs), count(n, ys)) == count(n, (concat(xs, ys)));
{
}
// ---------
-ghost method Lemma_RevConcat(xs: List, ys: List)
+lemma Lemma_RevConcat(xs: List, ys: List)
ensures reverse(concat(xs, ys)) == concat(reverse(ys), reverse(xs));
{
match (xs) {
@@ -606,7 +606,7 @@ ghost method Lemma_RevConcat(xs: List, ys: List)
}
}
-ghost method Theorem(xs: List)
+lemma Theorem(xs: List)
ensures reverse(reverse(xs)) == xs;
{
match (xs) {
diff --git a/Test/dafny1/SchorrWaite-stages.dfy b/Test/dafny1/SchorrWaite-stages.dfy
index 0eaed68c..a6e5e3aa 100644
--- a/Test/dafny1/SchorrWaite-stages.dfy
+++ b/Test/dafny1/SchorrWaite-stages.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// Schorr-Waite algorithms, written and verified in Dafny.
diff --git a/Test/dafny1/SchorrWaite.dfy b/Test/dafny1/SchorrWaite.dfy
index b29a6829..b0877f9f 100644
--- a/Test/dafny1/SchorrWaite.dfy
+++ b/Test/dafny1/SchorrWaite.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// Rustan Leino
@@ -180,7 +180,7 @@ class Main {
ensures forall n :: n in S && n.marked ==>
forall ch :: ch in n.children && ch != null ==> ch.marked
// every marked node was reachable from 'root' in the pre-state:
- ensures forall n :: n in S && n.marked ==> old(Reachable(root, n, S))
+ ensures forall n {:autotriggers false} :: n in S && n.marked ==> old(Reachable(root, n, S))
// the structure of the graph has not changed:
ensures forall n :: n in S ==>
n.childrenVisited == old(n.childrenVisited) &&
@@ -207,7 +207,7 @@ class Main {
forall j :: 0 <= j < n.childrenVisited ==>
n.children[j] == null || n.children[j].marked
invariant forall n :: n in stackNodes ==> n.childrenVisited < |n.children|
- invariant forall n :: n in S && n.marked && n !in stackNodes && n != t ==>
+ invariant forall n {:autotriggers false} :: n in S && n.marked && n !in stackNodes && n != t ==>
forall ch :: ch in n.children && ch != null ==> ch.marked
invariant forall n :: n in S && n !in stackNodes && n != t ==>
n.childrenVisited == old(n.childrenVisited)
@@ -219,7 +219,7 @@ class Main {
// every marked node is reachable:
invariant !fresh(path); // needed to show 'path' worthy as argument to old(Reachable(...))
invariant old(ReachableVia(root, path, t, S));
- invariant forall n, pth :: n in S && n.marked && pth == n.pathFromRoot ==> !fresh(pth)
+ invariant forall n, pth {:nowarn} :: n in S && n.marked && pth == n.pathFromRoot ==> !fresh(pth)
invariant forall n, pth :: n in S && n.marked && pth == n.pathFromRoot ==>
old(ReachableVia(root, pth, n, S))
invariant forall n :: n in S && n.marked ==> old(Reachable(root, n, S))
diff --git a/Test/dafny1/Substitution.dfy b/Test/dafny1/Substitution.dfy
index da64d004..b9c83aff 100644
--- a/Test/dafny1/Substitution.dfy
+++ b/Test/dafny1/Substitution.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
datatype List = Nil | Cons(Expr, List)
diff --git a/Test/dafny1/UltraFilter.dfy b/Test/dafny1/UltraFilter.dfy
index a32e6e0b..7ac4e749 100644
--- a/Test/dafny1/UltraFilter.dfy
+++ b/Test/dafny1/UltraFilter.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// ultra filter
diff --git a/Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy b/Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy
index c752bd38..f691384c 100644
--- a/Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy
+++ b/Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy
@@ -117,6 +117,11 @@ class Tree {
Repr := lft.Repr + {this} + rgt.Repr;
}
+ lemma exists_intro<T>(P: T -> bool, x: T)
+ requires P.requires(x)
+ requires P(x)
+ ensures exists y :: P.requires(y) && P(y) { }
+
method ComputeMax() returns (mx: int)
requires Valid() && !IsEmpty();
ensures forall x :: x in Contents ==> x <= mx;
@@ -124,13 +129,17 @@ class Tree {
decreases Repr;
{
mx := value;
+
if (!left.IsEmpty()) {
var m := left.ComputeMax();
mx := if mx < m then m else mx;
}
+
if (!right.IsEmpty()) {
var m := right.ComputeMax();
mx := if mx < m then m else mx;
}
+
+ exists_intro(x reads this => x in Contents && x == mx, mx);
}
}
diff --git a/Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy.expect b/Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy.expect
index 42fd56a5..c87e2af2 100644
--- a/Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy.expect
+++ b/Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy.expect
@@ -1,2 +1,2 @@
-Dafny program verifier finished with 8 verified, 0 errors
+Dafny program verifier finished with 10 verified, 0 errors
diff --git a/Test/dafny2/COST-verif-comp-2011-3-TwoDuplicates.dfy b/Test/dafny2/COST-verif-comp-2011-3-TwoDuplicates.dfy
index 72a22cfd..4c702674 100644
--- a/Test/dafny2/COST-verif-comp-2011-3-TwoDuplicates.dfy
+++ b/Test/dafny2/COST-verif-comp-2011-3-TwoDuplicates.dfy
@@ -93,8 +93,8 @@ method Search(a: array<int>) returns (p: int, q: int)
invariant forall j :: 0 <= j < d.Length ==>
(d[j] == -1 && forall k :: 0 <= k < i ==> a[k] != j) ||
(0 <= d[j] < i && a[d[j]] == j);
- invariant p == q ==> IsDuplicate(a, p);
- invariant forall k :: 0 <= k < i && IsPrefixDuplicate(a, i, a[k]) ==> p == q == a[k];
+ invariant p == q ==> IsDuplicate(a, p); //WISH remove the trigger on the next line
+ invariant forall k {:trigger old(a[k])} :: 0 <= k < i && IsPrefixDuplicate(a, i, a[k]) ==> p == q == a[k];
decreases a.Length - i;
{
var k := d[a[i]];
diff --git a/Test/dafny2/COST-verif-comp-2011-4-FloydCycleDetect.dfy b/Test/dafny2/COST-verif-comp-2011-4-FloydCycleDetect.dfy
index 2aa14db7..72250f99 100644
--- a/Test/dafny2/COST-verif-comp-2011-4-FloydCycleDetect.dfy
+++ b/Test/dafny2/COST-verif-comp-2011-4-FloydCycleDetect.dfy
@@ -164,7 +164,7 @@ class Node {
invariant 0 <= t < h && Nexxxt(t, S) == tortoise && Nexxxt(h, S) == hare;
// What follows of the invariant is for proving termination:
invariant h == 1 + 2*t && t <= A + B;
- invariant forall k :: 0 <= k < t ==> Nexxxt(k, S) != Nexxxt(1+2*k, S);
+ invariant forall k {:nowarn} :: 0 <= k < t ==> Nexxxt(k, S) != Nexxxt(1+2*k, S);
decreases A + B - t;
{
if hare == null || hare.next == null {
@@ -225,7 +225,7 @@ class Node {
requires 0 <= a && 1 <= b;
requires forall k,l :: 0 <= k < l < a ==> Nexxxt(k, S) != Nexxxt(l, S);
requires Nexxxt(a, S) == null || Nexxxt(a, S).Nexxxt(b, S) == Nexxxt(a, S);
- ensures exists T :: 0 <= T < a+b && Nexxxt(T, S) == Nexxxt(1+2*T, S);
+ ensures exists T {:nowarn} :: 0 <= T < a+b && Nexxxt(T, S) == Nexxxt(1+2*T, S);
{
if Nexxxt(a, S) == null {
Lemma_NullIsTerminal(1+2*a, S);
diff --git a/Test/dafny2/Calculations.dfy b/Test/dafny2/Calculations.dfy
index 8af0afe9..3870490f 100644
--- a/Test/dafny2/Calculations.dfy
+++ b/Test/dafny2/Calculations.dfy
@@ -41,12 +41,12 @@ function qreverse(l: List): List
// Here are two lemmas about the List functions.
-ghost method Lemma_ConcatNil(xs : List)
+lemma Lemma_ConcatNil(xs : List)
ensures concat(xs, Nil) == xs;
{
}
-ghost method Lemma_RevCatCommute(xs : List)
+lemma Lemma_RevCatCommute(xs : List)
ensures forall ys, zs :: revacc(xs, concat(ys, zs)) == concat(revacc(xs, ys), zs);
{
}
@@ -55,7 +55,7 @@ ghost method Lemma_RevCatCommute(xs : List)
// is given in a calculational style. The proof is not minimal--some lines can be omitted
// and Dafny will still fill in the details.
-ghost method Theorem_QReverseIsCorrect_Calc(l: List)
+lemma Theorem_QReverseIsCorrect_Calc(l: List)
ensures qreverse(l) == reverse(l);
{
calc {
@@ -69,7 +69,7 @@ ghost method Theorem_QReverseIsCorrect_Calc(l: List)
}
}
-ghost method Lemma_Revacc_calc(xs: List, ys: List)
+lemma Lemma_Revacc_calc(xs: List, ys: List)
ensures revacc(xs, ys) == concat(reverse(xs), ys);
{
match (xs) {
@@ -93,7 +93,7 @@ ghost method Lemma_Revacc_calc(xs: List, ys: List)
// Here is a version of the same proof, as it was constructed before Dafny's "calc" construct.
-ghost method Theorem_QReverseIsCorrect(l: List)
+lemma Theorem_QReverseIsCorrect(l: List)
ensures qreverse(l) == reverse(l);
{
assert qreverse(l)
@@ -105,7 +105,7 @@ ghost method Theorem_QReverseIsCorrect(l: List)
Lemma_ConcatNil(reverse(l));
}
-ghost method Lemma_Revacc(xs: List, ys: List)
+lemma Lemma_Revacc(xs: List, ys: List)
ensures revacc(xs, ys) == concat(reverse(xs), ys);
{
match (xs) {
@@ -140,7 +140,7 @@ function Fib(n: nat): nat
if n < 2 then n else Fib(n - 2) + Fib(n - 1)
}
-ghost method Lemma_Fib()
+lemma Lemma_Fib()
ensures Fib(5) < 6;
{
calc {
@@ -160,11 +160,11 @@ ghost method Lemma_Fib()
/* List length */
// Here are some proofs that show the use of nested calculations.
-ghost method Lemma_Concat_Length(xs: List, ys: List)
+lemma Lemma_Concat_Length(xs: List, ys: List)
ensures length(concat(xs, ys)) == length(xs) + length(ys);
{}
-ghost method Lemma_Reverse_Length(xs: List)
+lemma Lemma_Reverse_Length(xs: List)
ensures length(xs) == length(reverse(xs));
{
match (xs) {
@@ -193,7 +193,7 @@ ghost method Lemma_Reverse_Length(xs: List)
}
}
-ghost method Window(xs: List, ys: List)
+lemma Window(xs: List, ys: List)
ensures length(xs) == length(ys) ==> length(reverse(xs)) == length(reverse(ys));
{
calc {
@@ -221,11 +221,11 @@ function ith<a>(xs: List, i: nat): a
case Cons(x, xrest) => if i == 0 then x else ith(xrest, i - 1)
}
-ghost method lemma_zero_length(xs: List)
+lemma lemma_zero_length(xs: List)
ensures length(xs) == 0 <==> xs.Nil?;
{}
-ghost method lemma_extensionality(xs: List, ys: List)
+lemma lemma_extensionality(xs: List, ys: List)
requires length(xs) == length(ys); // (0)
requires forall i: nat | i < length(xs) :: ith(xs, i) == ith(ys, i); // (1)
ensures xs == ys;
diff --git a/Test/dafny2/MajorityVote.dfy b/Test/dafny2/MajorityVote.dfy
index 51e5b968..f1c3b485 100644
--- a/Test/dafny2/MajorityVote.dfy
+++ b/Test/dafny2/MajorityVote.dfy
@@ -165,7 +165,7 @@ method SearchForWinner<Candidate(==)>(a: seq<Candidate>, ghost hasWinner: bool,
// Here are two lemmas about Count that are used in the methods above.
-ghost method Lemma_Split<T>(a: seq<T>, s: int, t: int, u: int, x: T)
+lemma Lemma_Split<T>(a: seq<T>, s: int, t: int, u: int, x: T)
requires 0 <= s <= t <= u <= |a|;
ensures Count(a, s, t, x) + Count(a, t, u, x) == Count(a, s, u, x);
{
@@ -178,7 +178,7 @@ ghost method Lemma_Split<T>(a: seq<T>, s: int, t: int, u: int, x: T)
*/
}
-ghost method Lemma_Unique<T>(a: seq<T>, s: int, t: int, x: T, y: T)
+lemma Lemma_Unique<T>(a: seq<T>, s: int, t: int, x: T, y: T)
requires 0 <= s <= t <= |a|;
ensures x != y ==> Count(a, s, t, x) + Count(a, s, t, y) <= t - s;
{
diff --git a/Test/dafny2/SnapshotableTrees.dfy b/Test/dafny2/SnapshotableTrees.dfy
index 2bdfb83b..033c5db0 100644
--- a/Test/dafny2/SnapshotableTrees.dfy
+++ b/Test/dafny2/SnapshotableTrees.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:2 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:2 /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// Rustan Leino, September 2011.
diff --git a/Test/dafny2/SnapshotableTrees.dfy.expect b/Test/dafny2/SnapshotableTrees.dfy.expect
index 849b9e38..68b4ff73 100644
--- a/Test/dafny2/SnapshotableTrees.dfy.expect
+++ b/Test/dafny2/SnapshotableTrees.dfy.expect
@@ -1,8 +1,15 @@
-SnapshotableTrees.dfy(68,24): Error BP5002: A precondition for this call might not hold.
-SnapshotableTrees.dfy(648,16): Related location: This is the precondition that might not hold.
+SnapshotableTrees.dfy(68,23): Error BP5002: A precondition for this call might not hold.
+SnapshotableTrees.dfy(648,15): Related location: This is the precondition that might not hold.
+SnapshotableTrees.dfy(545,15): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Then
+SnapshotableTrees.dfy(68,23): Error BP5002: A precondition for this call might not hold.
+SnapshotableTrees.dfy(648,15): Related location: This is the precondition that might not hold.
+SnapshotableTrees.dfy(548,18): Related location
Execution trace:
(0,0): anon0
(0,0): anon3_Then
-Dafny program verifier finished with 65 verified, 1 error
+Dafny program verifier finished with 65 verified, 2 errors
Compiled assembly into SnapshotableTrees.exe
diff --git a/Test/dafny3/CachedContainer.dfy.expect b/Test/dafny3/CachedContainer.dfy.expect
index c6c90498..0185aacd 100644
--- a/Test/dafny3/CachedContainer.dfy.expect
+++ b/Test/dafny3/CachedContainer.dfy.expect
@@ -1,2 +1,3 @@
+CachedContainer.dfy(120,25): Warning: "import A as B" has been deprecated; in the new syntax, it is "import A:B"
Dafny program verifier finished with 47 verified, 0 errors
diff --git a/Test/dafny3/CalcExample.dfy b/Test/dafny3/CalcExample.dfy
index 2782d049..b9d3260b 100644
--- a/Test/dafny3/CalcExample.dfy
+++ b/Test/dafny3/CalcExample.dfy
@@ -3,14 +3,14 @@
function f(x: int, y: int): int
-ghost method Associativity(x: int, y: int, z: int)
+lemma Associativity(x: int, y: int, z: int)
ensures f(x, f(y, z)) == f(f(x, y), z);
-ghost method Monotonicity(y: int, z: int)
+lemma Monotonicity(y: int, z: int)
requires y <= z;
ensures forall x :: f(x, y) <= f(x, z);
-ghost method DiagonalIdentity(x: int)
+lemma DiagonalIdentity(x: int)
ensures f(x, x) == x;
method M(a: int, b: int, c: int, x: int)
diff --git a/Test/dafny3/Dijkstra.dfy b/Test/dafny3/Dijkstra.dfy
index 1fbd9b7c..56719180 100644
--- a/Test/dafny3/Dijkstra.dfy
+++ b/Test/dafny3/Dijkstra.dfy
@@ -3,7 +3,7 @@
// Example taken from:
// Edsger W. Dijkstra: Heuristics for a Calculational Proof. Inf. Process. Lett. (IPL) 53(3):141-143 (1995)
-// Transcribed into Dafny by Valentin Wüstholz and Nadia Polikarpova.
+// Transcribed into Dafny by Valentin Wüstholz and Nadia Polikarpova.
// f is an arbitrary function on the natural numbers
function f(n: nat) : nat
@@ -56,7 +56,7 @@ lemma lemma_ping(j: nat, n: nat)
}
}
-// The other directorion: f(n) <= n
+// The other direction: f(n) <= n
lemma lemma_pong(n: nat)
requires P()
ensures f(n) <= n
diff --git a/Test/dafny3/Filter.dfy b/Test/dafny3/Filter.dfy
index 24c8e94e..7473a580 100644
--- a/Test/dafny3/Filter.dfy
+++ b/Test/dafny3/Filter.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
codatatype Stream<T> = Cons(head: T, tail: Stream)
@@ -35,7 +35,7 @@ lemma Lemma_TailSubStreamK(s: Stream, u: Stream, k: nat) // this lemma could ha
{
if k != 0 {
Lemma_InTail(s.head, u);
- Lemma_TailSubStreamK(s.tail, u, k-1);
+ //Lemma_TailSubStreamK(s.tail, u, k-1);
}
}
lemma Lemma_InSubStream<T>(x: T, s: Stream<T>, u: Stream<T>)
@@ -53,104 +53,119 @@ lemma Lemma_InSubStream<T>(x: T, s: Stream<T>, u: Stream<T>)
}
}
-type PredicateHandle
-predicate P<T>(x: T, h: PredicateHandle)
+type Predicate<T> = T -> bool
-copredicate AllP(s: Stream, h: PredicateHandle)
+predicate Total<T,U>(f: T -> U)
+ reads f.reads
{
- P(s.head, h) && AllP(s.tail, h)
+ forall t :: f.reads(t) == {} && f.requires(t)
}
-lemma Lemma_InAllP<T>(x: T, s: Stream<T>, h: PredicateHandle)
- requires In(x, s) && AllP(s, h);
- ensures P(x, h);
+
+copredicate AllP(s: Stream, P: Predicate)
+ requires Total(P)
+{
+ P(s.head) && AllP(s.tail, P)
+}
+lemma Lemma_InAllP<T>(x: T, s: Stream<T>, P: Predicate)
+ requires Total(P)
+ requires In(x, s) && AllP(s, P)
+ ensures P(x)
{
var n :| 0 <= n && Tail(s, n).head == x;
var t := s;
while n != 0
- invariant 0 <= n;
- invariant Tail(t, n).head == x;
- invariant AllP(t, h);
+ invariant 0 <= n
+ invariant Tail(t, n).head == x
+ invariant AllP(t, P)
{
t, n := t.tail, n - 1;
}
}
-predicate IsAnother(s: Stream, h: PredicateHandle)
+predicate IsAnother(s: Stream, P: Predicate)
+ requires Total(P)
{
- exists n :: 0 <= n && P(Tail(s, n).head, h)
+ exists n :: 0 <= n && P(Tail(s, n).head)
}
-copredicate AlwaysAnother(s: Stream, h: PredicateHandle)
+copredicate AlwaysAnother(s: Stream, P: Predicate)
+ requires Total(P)
{
- IsAnother(s, h) && AlwaysAnother(s.tail, h)
+ IsAnother(s, P) && AlwaysAnother(s.tail, P)
}
-colemma Lemma_AllImpliesAlwaysAnother(s: Stream, h: PredicateHandle)
- requires AllP(s, h);
- ensures AlwaysAnother(s, h);
+colemma Lemma_AllImpliesAlwaysAnother(s: Stream, P: Predicate)
+ requires Total(P)
+ requires AllP(s, P)
+ ensures AlwaysAnother(s, P)
{
assert Tail(s, 0) == s;
}
-function Next(s: Stream, h: PredicateHandle): nat
- requires AlwaysAnother(s, h);
- ensures P(Tail(s, Next(s, h)).head, h);
- ensures forall i :: 0 <= i < Next(s, h) ==> !P(Tail(s, i).head, h);
+function Next(s: Stream, P: Predicate): nat
+ requires Total(P)
+ requires AlwaysAnother(s, P)
+ ensures P(Tail(s, Next(s, P)).head)
+ ensures forall i :: 0 <= i < Next(s, P) ==> !P(Tail(s, i).head)
{
- var n :| 0 <= n && P(Tail(s, n).head, h);
- NextMinimizer(s, h, n)
+ var n :| 0 <= n && P(Tail(s, n).head);
+ NextMinimizer(s, P, n)
}
// the following is an auxiliary function of the definition of Next
-function NextMinimizer(s: Stream, h: PredicateHandle, n: nat): nat
- requires P(Tail(s, n).head, h);
- ensures P(Tail(s, NextMinimizer(s, h, n)).head, h);
- ensures forall i :: 0 <= i < NextMinimizer(s, h, n) ==> !P(Tail(s, i).head, h);
+function NextMinimizer(s: Stream, P: Predicate, n: nat): nat
+ requires Total(P)
+ requires P(Tail(s, n).head)
+ ensures P(Tail(s, NextMinimizer(s, P, n)).head)
+ ensures forall i :: 0 <= i < NextMinimizer(s, P, n) ==> !P(Tail(s, i).head)
{
- if forall i :: 0 <= i < n ==> !P(Tail(s, i).head, h) then
+ if forall i :: 0 <= i < n ==> !P(Tail(s, i).head) then
n
else
- var k :| 0 <= k < n && P(Tail(s, k).head, h);
- NextMinimizer(s, h, k)
+ var k :| 0 <= k < n && P(Tail(s, k).head);
+ NextMinimizer(s, P, k)
}
-function Filter(s: Stream, h: PredicateHandle): Stream
- requires AlwaysAnother(s, h);
- decreases Next(s, h);
+function Filter(s: Stream, P: Predicate): Stream
+ requires Total(P)
+ requires AlwaysAnother(s, P)
+ decreases Next(s, P)
{
- if P(s.head, h) then
- Cons(s.head, Filter(s.tail, h))
+ if P(s.head) then
+ Cons(s.head, Filter(s.tail, P))
else
- Filter(s.tail, h)
+ Filter(s.tail, P)
}
// properties about Filter
-colemma Filter_AlwaysAnother(s: Stream, h: PredicateHandle)
- requires AlwaysAnother(s, h);
- ensures AllP(Filter(s, h), h);
- decreases Next(s, h);
+colemma Filter_AlwaysAnother(s: Stream, P: Predicate)
+ requires Total(P)
+ requires AlwaysAnother(s, P)
+ ensures AllP(Filter(s, P), P)
+ decreases Next(s, P)
{
- if P(s.head, h) {
- Filter_AlwaysAnother(s.tail, h);
+ if P(s.head) {
+ Filter_AlwaysAnother(s.tail, P);
} else {
- Filter_AlwaysAnother#[_k](s.tail, h);
+ Filter_AlwaysAnother#[_k](s.tail, P);
}
}
-colemma Filter_IsSubStream(s: Stream, h: PredicateHandle)
- requires AlwaysAnother(s, h);
- ensures IsSubStream(Filter(s, h), s);
- decreases Next(s, h);
+colemma Filter_IsSubStream(s: Stream, P: Predicate)
+ requires Total(P)
+ requires AlwaysAnother(s, P)
+ ensures IsSubStream(Filter(s, P), s)
+ decreases Next(s, P)
{
- if P(s.head, h) {
+ if P(s.head) {
// To prove IsSubStream#[_k](Filter(s, h), s), we prove the two conjuncts from the definition
calc {
true;
- == { Filter_IsSubStream(s.tail, h); } // induction hypothesis
- IsSubStream#[_k-1](Filter(s.tail, h), s.tail);
+ == { Filter_IsSubStream(s.tail, P); } // induction hypothesis
+ IsSubStream(Filter(s.tail, P), s.tail);
== // { assert Filter(s.tail, h) == Filter(s, h).tail; }
- IsSubStream#[_k-1](Filter(s, h).tail, s.tail);
- ==> { Lemma_TailSubStreamK(Filter(s, h).tail, s, _k-1); }
- IsSubStream#[_k-1](Filter(s, h).tail, s);
+ IsSubStream(Filter(s, P).tail, s.tail);
+ ==> { Lemma_TailSubStreamK(Filter(s, P).tail, s, _k-1); }
+ IsSubStream(Filter(s, P).tail, s);
}
calc {
- In(Filter(s, h).head, s);
- == { assert Filter(s, h) == Cons(s.head, Filter(s.tail, h)); }
+ In(Filter(s, P).head, s);
+ == { assert Filter(s, P) == Cons(s.head, Filter(s.tail, P)); }
In(s.head, s);
== { assert Tail(s, 0) == s;
assert exists n :: 0 <= n && Tail(s, n).head == s.head;
@@ -158,105 +173,114 @@ colemma Filter_IsSubStream(s: Stream, h: PredicateHandle)
true;
}
} else {
- Lemma_TailSubStreamK(Filter(s.tail, h), s, _k);
+ Lemma_TailSubStreamK(Filter(s.tail, P), s, _k);
}
}
// The following says nothing about the order of the elements in the stream
-lemma Theorem_Filter<T>(s: Stream<T>, h: PredicateHandle)
- requires AlwaysAnother(s, h);
- ensures forall x :: In(x, Filter(s, h)) <==> In(x, s) && P(x, h);
+lemma Theorem_Filter<T>(s: Stream<T>, P: Predicate)
+ requires Total(P)
+ requires AlwaysAnother(s, P)
+ ensures forall x :: In(x, Filter(s, P)) <==> In(x, s) && P(x)
{
forall x
- ensures In(x, Filter(s, h)) <==> In(x, s) && P(x, h);
+ ensures In(x, Filter(s, P)) <==> In(x, s) && P(x)
{
- if In(x, Filter(s, h)) {
- FS_Ping(s, h, x);
+ if In(x, Filter(s, P)) {
+ FS_Ping(s, P, x);
}
- if In(x, s) && P(x, h) {
+ if In(x, s) && P(x) {
var k :| 0 <= k && Tail(s, k).head == x;
- FS_Pong(s, h, x, k);
+ FS_Pong(s, P, x, k);
}
}
}
-lemma FS_Ping<T>(s: Stream<T>, h: PredicateHandle, x: T)
- requires AlwaysAnother(s, h) && In(x, Filter(s, h));
- ensures In(x, s) && P(x, h);
+lemma FS_Ping<T>(s: Stream<T>, P: Predicate, x: T)
+ requires Total(P)
+ requires AlwaysAnother(s, P) && In(x, Filter(s, P));
+ ensures In(x, s) && P(x);
{
- Filter_IsSubStream(s, h);
- Lemma_InSubStream(x, Filter(s, h), s);
+ Filter_IsSubStream(s, P);
+ Lemma_InSubStream(x, Filter(s, P), s);
- Filter_AlwaysAnother(s, h);
- assert AllP(Filter(s, h), h);
- Lemma_InAllP(x, Filter(s, h), h);
+ Filter_AlwaysAnother(s, P);
+ assert AllP(Filter(s, P), P);
+ Lemma_InAllP(x, Filter(s, P), P);
}
-lemma FS_Pong<T>(s: Stream<T>, h: PredicateHandle, x: T, k: nat)
- requires AlwaysAnother(s, h) && In(x, s) && P(x, h);
- requires Tail(s, k).head == x;
- ensures In(x, Filter(s, h));
- decreases k;
+lemma FS_Pong<T>(s: Stream<T>, P: Predicate, x: T, k: nat)
+ requires Total(P)
+ requires AlwaysAnother(s, P) && In(x, s) && P(x)
+ requires Tail(s, k).head == x
+ ensures In(x, Filter(s, P))
+ decreases k
{
- var fs := Filter(s, h);
+ var fs := Filter(s, P);
if s.head == x {
assert Tail(fs, 0) == fs;
- } else if P(s.head, h) {
- assert fs == Cons(s.head, Filter(s.tail, h)); // reminder of where we are
+ } else if P(s.head) {
+ assert fs == Cons(s.head, Filter(s.tail, P)); // reminder of where we are
calc {
true;
- == { FS_Pong(s.tail, h, x, k-1); }
- In(x, Filter(s.tail, h));
+ //== { FS_Pong(s.tail, h, x, k-1); }
+ In(x, Filter(s.tail, P));
==> { assert fs.head != x; Lemma_InTail(x, fs); }
In(x, fs);
}
} else {
- assert fs == Filter(s.tail, h); // reminder of where we are
- FS_Pong(s.tail, h, x, k-1);
+ //assert fs == Filter(s.tail, h); // reminder of where we are
+ //FS_Pong(s.tail, h, x, k-1);
}
}
// ----- orderings ------
-function Ord<T>(x: T, ord: PredicateHandle): int
+type Ord<T> = T -> int
-copredicate Increasing(s: Stream, ord: PredicateHandle)
+copredicate Increasing(s: Stream, ord: Ord)
+ requires Total(ord)
{
- Ord(s.head, ord) < Ord(s.tail.head, ord) && Increasing(s.tail, ord)
+ ord(s.head) < ord(s.tail.head) && Increasing(s.tail, ord)
}
-copredicate IncrFrom(s: Stream, low: int, ord: PredicateHandle)
+copredicate IncrFrom(s: Stream, low: int, ord: Ord)
+ requires Total(ord)
{
- low <= Ord(s.head, ord) && IncrFrom(s.tail, Ord(s.head, ord) + 1, ord)
+ low <= ord(s.head) && IncrFrom(s.tail, ord(s.head) + 1, ord)
}
-colemma Lemma_Incr0(s: Stream, low: int, ord: PredicateHandle)
- requires IncrFrom(s, low, ord);
- ensures Increasing(s, ord);
+colemma Lemma_Incr0(s: Stream, low: int, ord: Ord)
+ requires Total(ord)
+ requires IncrFrom(s, low, ord)
+ ensures Increasing(s, ord)
{
}
-colemma Lemma_Incr1(s: Stream, ord: PredicateHandle)
+colemma Lemma_Incr1(s: Stream, ord: Ord)
+ requires Total(ord)
requires Increasing(s, ord);
- ensures IncrFrom(s, Ord(s.head, ord), ord);
+ ensures IncrFrom(s, ord(s.head), ord);
{
Lemma_Incr1(s.tail, ord);
}
-lemma Theorem_FilterPreservesOrdering(s: Stream, h: PredicateHandle, ord: PredicateHandle)
- requires Increasing(s, ord) && AlwaysAnother(s, h);
- ensures Increasing(Filter(s, h), ord);
+lemma Theorem_FilterPreservesOrdering(s: Stream, P: Predicate, ord: Ord)
+ requires Total(P) && Total(ord)
+ requires Increasing(s, ord) && AlwaysAnother(s, P)
+ ensures Increasing(Filter(s, P), ord)
{
Lemma_Incr1(s, ord);
- Lemma_FilterPreservesIncrFrom(s, h, Ord(s.head, ord), ord);
- Lemma_Incr0(Filter(s, h), Ord(s.head, ord), ord);
+ Lemma_FilterPreservesIncrFrom(s, P, ord(s.head), ord);
+ Lemma_Incr0(Filter(s, P), ord(s.head), ord);
}
-colemma Lemma_FilterPreservesIncrFrom(s: Stream, h: PredicateHandle, low: int, ord: PredicateHandle)
- requires IncrFrom(s, low, ord) && AlwaysAnother(s, h) && low <= Ord(s.head, ord);
- ensures IncrFrom(Filter(s, h), low, ord);
- decreases Next(s, h);
+colemma Lemma_FilterPreservesIncrFrom(s: Stream, P: Predicate, low: int, ord: Ord)
+ requires Total(P) && Total(ord)
+ requires IncrFrom(s, low, ord) && AlwaysAnother(s, P) && low <= ord(s.head)
+ ensures IncrFrom(Filter(s, P), low, ord)
+ decreases Next(s, P)
{
- if P(s.head, h) {
- Lemma_FilterPreservesIncrFrom(s.tail, h, Ord(s.head, ord)+1, ord);
+ if P(s.head) {
+ Lemma_FilterPreservesIncrFrom(s.tail, P, ord(s.head)+1, ord);
} else {
- Lemma_FilterPreservesIncrFrom#[_k](s.tail, h, low, ord);
+ Lemma_FilterPreservesIncrFrom#[_k](s.tail, P, low, ord);
}
}
diff --git a/Test/dafny3/Filter.dfy.expect b/Test/dafny3/Filter.dfy.expect
index 91aa9b47..6ba9b9bc 100644
--- a/Test/dafny3/Filter.dfy.expect
+++ b/Test/dafny3/Filter.dfy.expect
@@ -1,2 +1,2 @@
-Dafny program verifier finished with 43 verified, 0 errors
+Dafny program verifier finished with 42 verified, 0 errors
diff --git a/Test/dafny3/GenericSort.dfy b/Test/dafny3/GenericSort.dfy
index 7ea038be..7555817c 100644
--- a/Test/dafny3/GenericSort.dfy
+++ b/Test/dafny3/GenericSort.dfy
@@ -7,25 +7,25 @@ abstract module TotalOrder {
// Three properties of total orders. Here, they are given as unproved
// lemmas, that is, as axioms.
lemma Antisymmetry(a: T, b: T)
- requires Leq(a, b) && Leq(b, a);
- ensures a == b;
+ requires Leq(a, b) && Leq(b, a)
+ ensures a == b
lemma Transitivity(a: T, b: T, c: T)
- requires Leq(a, b) && Leq(b, c);
- ensures Leq(a, c);
+ requires Leq(a, b) && Leq(b, c)
+ ensures Leq(a, c)
lemma Totality(a: T, b: T)
- ensures Leq(a, b) || Leq(b, a);
+ ensures Leq(a, b) || Leq(b, a)
}
abstract module Sort {
- import O as TotalOrder // let O denote some module that has the members of TotalOrder
+ import O : TotalOrder // let O denote some module that has the members of TotalOrder
predicate Sorted(a: array<O.T>, low: int, high: int)
- requires a != null && 0 <= low <= high <= a.Length;
- reads a;
+ requires a != null && 0 <= low <= high <= a.Length
+ reads a
// The body of the predicate is hidden outside the module, but the postcondition is
// "exported" (that is, visible, known) outside the module. Here, we choose the
// export the following property:
- ensures Sorted(a, low, high) ==> forall i, j :: low <= i < j < high ==> O.Leq(a[i], a[j]);
+ ensures Sorted(a, low, high) ==> forall i, j :: low <= i < j < high ==> O.Leq(a[i], a[j])
{
forall i, j :: low <= i < j < high ==> O.Leq(a[i], a[j])
}
@@ -33,18 +33,18 @@ abstract module Sort {
// In the insertion sort routine below, it's more convenient to keep track of only that
// neighboring elements of the array are sorted...
predicate NeighborSorted(a: array<O.T>, low: int, high: int)
- requires a != null && 0 <= low <= high <= a.Length;
- reads a;
+ requires a != null && 0 <= low <= high <= a.Length
+ reads a
{
- forall i :: low < i < high ==> O.Leq(a[i-1], a[i])
+ forall i {:nowarn} :: low < i < high ==> O.Leq(a[i-1], a[i])
}
// ...but we show that property to imply all pairs to be sorted. The proof of this
// lemma uses the transitivity property.
lemma NeighborSorted_implies_Sorted(a: array<O.T>, low: int, high: int)
- requires a != null && 0 <= low <= high <= a.Length;
- requires NeighborSorted(a, low, high);
- ensures Sorted(a, low, high);
- decreases high - low;
+ requires a != null && 0 <= low <= high <= a.Length
+ requires NeighborSorted(a, low, high)
+ ensures Sorted(a, low, high)
+ decreases high - low
{
if low != high {
NeighborSorted_implies_Sorted(a, low+1, high);
@@ -57,25 +57,25 @@ abstract module Sort {
// Standard insertion sort method
method InsertionSort(a: array<O.T>)
- requires a != null;
- modifies a;
- ensures Sorted(a, 0, a.Length);
- ensures multiset(a[..]) == old(multiset(a[..]));
+ requires a != null
+ modifies a
+ ensures Sorted(a, 0, a.Length)
+ ensures multiset(a[..]) == old(multiset(a[..]))
{
if a.Length == 0 { return; }
var i := 1;
while i < a.Length
- invariant 0 < i <= a.Length;
- invariant NeighborSorted(a, 0, i);
- invariant multiset(a[..]) == old(multiset(a[..]));
+ invariant 0 < i <= a.Length
+ invariant NeighborSorted(a, 0, i)
+ invariant multiset(a[..]) == old(multiset(a[..]))
{
var j := i;
while 0 < j && !O.Leq(a[j-1], a[j])
- invariant 0 <= j <= i;
- invariant NeighborSorted(a, 0, j);
- invariant NeighborSorted(a, j, i+1);
- invariant 0 < j < i ==> O.Leq(a[j-1], a[j+1]);
- invariant multiset(a[..]) == old(multiset(a[..]));
+ invariant 0 <= j <= i
+ invariant NeighborSorted(a, 0, j)
+ invariant NeighborSorted(a, j, i+1)
+ invariant 0 < j < i ==> O.Leq(a[j-1], a[j+1])
+ invariant multiset(a[..]) == old(multiset(a[..]))
{
// The proof of correctness uses the totality property here.
// It implies that if two elements are not previously in
@@ -97,7 +97,7 @@ module IntOrder refines TotalOrder {
datatype T = Int(i: int)
// Define the ordering on these integers
predicate method Leq ...
- ensures Leq(a, b) ==> a.i <= b.i;
+ ensures Leq(a, b) ==> a.i <= b.i
{
a.i <= b.i
}
@@ -156,7 +156,7 @@ module intOrder refines TotalOrder {
type T = int
// Define the ordering on these integers
predicate method Leq ...
- ensures Leq(a, b) ==> a <= b;
+ ensures Leq(a, b) ==> a <= b
{
a <= b
}
diff --git a/Test/dafny3/InductionVsCoinduction.dfy b/Test/dafny3/InductionVsCoinduction.dfy
index 89fa6cc8..0074b742 100644
--- a/Test/dafny3/InductionVsCoinduction.dfy
+++ b/Test/dafny3/InductionVsCoinduction.dfy
@@ -80,7 +80,7 @@ lemma SAppendIsAssociative(a:Stream, b:Stream, c:Stream)
{
forall k:nat { SAppendIsAssociativeK(k, a, b, c); }
// assert for clarity only, postcondition follows directly from it
- assert (forall k:nat :: SAppend(SAppend(a, b), c) ==#[k] SAppend(a, SAppend(b, c)));
+ assert (forall k:nat {:autotriggers false} :: SAppend(SAppend(a, b), c) ==#[k] SAppend(a, SAppend(b, c))); //FIXME: Should Dafny generate a trigger here? If so then which one?
}
// Equivalent proof using the colemma syntax.
diff --git a/Test/dafny3/InfiniteTrees.dfy b/Test/dafny3/InfiniteTrees.dfy
index 516a9e4e..85f73bc3 100644
--- a/Test/dafny3/InfiniteTrees.dfy
+++ b/Test/dafny3/InfiniteTrees.dfy
@@ -286,7 +286,7 @@ lemma Theorem1_Lemma(t: Tree, n: nat, p: Stream<int>)
LowerThan(ch, n);
==> // def. LowerThan
LowerThan(ch.head.children, n-1);
- ==> { Theorem1_Lemma(ch.head, n-1, tail); }
+ ==> //{ Theorem1_Lemma(ch.head, n-1, tail); }
!IsNeverEndingStream(tail);
==> // def. IsNeverEndingStream
!IsNeverEndingStream(p);
@@ -374,30 +374,30 @@ lemma Proposition3b()
}
}
lemma Proposition3b_Lemma(t: Tree, h: nat, p: Stream<int>)
- requires LowerThan(t.children, h) && ValidPath(t, p);
- ensures !IsNeverEndingStream(p);
- decreases h;
+ requires LowerThan(t.children, h) && ValidPath(t, p)
+ ensures !IsNeverEndingStream(p)
+ decreases h
{
match p {
case Nil =>
case Cons(index, tail) =>
// From the definition of ValidPath(t, p), we get the following:
var ch := Tail(t.children, index);
- assert ch.Cons? && ValidPath(ch.head, tail);
+ // assert ch.Cons? && ValidPath(ch.head, tail);
// From the definition of LowerThan(t.children, h), we get the following:
match t.children {
case Nil =>
ValidPath_Lemma(p);
assert false; // absurd case
case Cons(_, _) =>
- assert 1 <= h;
+ // assert 1 <= h;
LowerThan_Lemma(t.children, index, h);
- assert LowerThan(ch, h);
+ // assert LowerThan(ch, h);
}
// Putting these together, by ch.Cons? and the definition of LowerThan(ch, h), we get:
- assert LowerThan(ch.head.children, h-1);
+ // assert LowerThan(ch.head.children, h-1);
// And now we can invoke the induction hypothesis:
- Proposition3b_Lemma(ch.head, h-1, tail);
+ // Proposition3b_Lemma(ch.head, h-1, tail);
}
}
@@ -627,30 +627,10 @@ colemma Path_Lemma2'(p: Stream<int>)
}
}
colemma Path_Lemma2''(p: Stream<int>, n: nat, tail: Stream<int>)
- requires IsNeverEndingStream(p) && p.tail == tail;
- ensures InfinitePath'(S2N'(n, tail));
+ requires IsNeverEndingStream(p) && p.tail == tail
+ ensures InfinitePath'(S2N'(n, tail))
{
- if n <= 0 {
- calc {
- InfinitePath'#[_k](S2N'(n, tail));
- // def. S2N'
- InfinitePath'#[_k](Zero(S2N(tail)));
- // def. InfinitePath'
- InfinitePath#[_k-1](S2N(tail));
- { Path_Lemma2'(tail); }
- true;
- }
- } else {
- calc {
- InfinitePath'#[_k](S2N'(n, tail));
- // def. S2N'
- InfinitePath'#[_k](Succ(S2N'(n-1, tail)));
- // def. InfinitePath'
- InfinitePath'#[_k-1](S2N'(n-1, tail));
- { Path_Lemma2''(p, n-1, tail); }
- true;
- }
- }
+ Path_Lemma2'(tail);
}
lemma Path_Lemma3(r: CoOption<Number>)
ensures InfinitePath(r) ==> IsNeverEndingStream(N2S(r));
diff --git a/Test/dafny3/SimpleInduction.dfy b/Test/dafny3/SimpleInduction.dfy
index 83ea6d14..8cf937e1 100644
--- a/Test/dafny3/SimpleInduction.dfy
+++ b/Test/dafny3/SimpleInduction.dfy
@@ -13,7 +13,7 @@ function Fib(n: nat): nat
decreases n;
{ if n < 2 then n else Fib(n-2) + Fib(n-1) }
-ghost method FibLemma(n: nat)
+lemma FibLemma(n: nat)
ensures Fib(n) % 2 == 0 <==> n % 3 == 0;
decreases n;
{
@@ -30,7 +30,7 @@ ghost method FibLemma(n: nat)
satisfying 0 <= k < n, and in the second example, to all non-negative n.
*/
-ghost method FibLemma_Alternative(n: nat)
+lemma FibLemma_Alternative(n: nat)
ensures Fib(n) % 2 == 0 <==> n % 3 == 0;
{
forall k | 0 <= k < n {
@@ -38,7 +38,7 @@ ghost method FibLemma_Alternative(n: nat)
}
}
-ghost method FibLemma_All()
+lemma FibLemma_All()
ensures forall n :: 0 <= n ==> (Fib(n) % 2 == 0 <==> n % 3 == 0);
{
forall n | 0 <= n {
@@ -48,8 +48,8 @@ ghost method FibLemma_All()
/*
A standard inductive definition of a generic List type and a function Append
- that concatenates two lists. The ghost method states the lemma that Append
- is associative, and its recursive body gives the inductive proof.
+ that concatenates two lists. The lemma states that Append is associative,
+ and its recursive body gives the inductive proof.
We omitted the explicit declaration and uses of the List type parameter in
the signature of the method, since in simple cases like this, Dafny is able
@@ -68,7 +68,7 @@ function Append<T>(xs: List<T>, ys: List<T>): List<T>
// The {:induction false} attribute disables automatic induction tactic,
// so we can make the proof explicit.
-ghost method {:induction false} AppendIsAssociative(xs: List, ys: List, zs: List)
+lemma {:induction false} AppendIsAssociative(xs: List, ys: List, zs: List)
ensures Append(Append(xs, ys), zs) == Append(xs, Append(ys, zs));
decreases xs;
{
@@ -81,7 +81,7 @@ ghost method {:induction false} AppendIsAssociative(xs: List, ys: List, zs: List
// Here the proof is fully automatic - the body of the method is empty,
// yet still verifies.
-ghost method AppendIsAssociative_Auto(xs: List, ys: List, zs: List)
+lemma AppendIsAssociative_Auto(xs: List, ys: List, zs: List)
ensures Append(Append(xs, ys), zs) == Append(xs, Append(ys, zs));
{
}
diff --git a/Test/dafny4/ACL2-extractor.dfy b/Test/dafny4/ACL2-extractor.dfy
index 8fe98531..bd2c9d83 100644
--- a/Test/dafny4/ACL2-extractor.dfy
+++ b/Test/dafny4/ACL2-extractor.dfy
@@ -116,9 +116,9 @@ lemma RevLength(xs: List)
// you can prove two lists equal by proving their elements equal
lemma EqualElementsMakeEqualLists(xs: List, ys: List)
- requires length(xs) == length(ys);
- requires forall i :: 0 <= i < length(xs) ==> nth(i, xs) == nth(i, ys);
- ensures xs == ys;
+ requires length(xs) == length(ys)
+ requires forall i :: 0 <= i < length(xs) ==> nth(i, xs) == nth(i, ys)
+ ensures xs == ys
{
match xs {
case Nil =>
@@ -132,7 +132,7 @@ lemma EqualElementsMakeEqualLists(xs: List, ys: List)
nth(i+1, xs) == nth(i+1, ys);
}
}
- EqualElementsMakeEqualLists(xs.tail, ys.tail);
+ // EqualElementsMakeEqualLists(xs.tail, ys.tail);
}
}
diff --git a/Test/dafny4/Ackermann.dfy b/Test/dafny4/Ackermann.dfy
new file mode 100644
index 00000000..7ab686e0
--- /dev/null
+++ b/Test/dafny4/Ackermann.dfy
@@ -0,0 +1,235 @@
+// RUN: %dafny /compile:3 /rprint:"%t.rprint" /autoTriggers:1 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// Rustan Leino, 8 Sep 2015.
+// This file proves that the Ackermann function is monotonic in each argument
+
+method Main() {
+ // Note, don't try much larger numbers unless you're prepared to wait!
+ print "Ack(3, 4) = ", Ack(3, 4), "\n";
+}
+
+// Here is the definition of the Ackermann function:
+function method Ack(m: nat, n: nat): nat
+{
+ if m == 0 then
+ n + 1
+ else if n == 0 then
+ Ack(m - 1, 1)
+ else
+ Ack(m - 1, Ack(m, n - 1))
+}
+
+// And here is the theorem that proves the desired result:
+lemma AckermannIsMonotonic(m: nat, n: nat, m': nat, n': nat)
+ requires m <= m' && n <= n'
+ ensures Ack(m, n) <= Ack(m', n')
+{
+ // This is the proof. It calls two lemmas, stated and proved below.
+ MonotonicN(m, n, n');
+ MonotonicM(m, n, m');
+}
+
+// --------------------------------------------------------
+// What follows are the supporting lemmas and their proofs.
+// --------------------------------------------------------
+
+// Proving that Ackermann is monotonic in its second argument is easy.
+lemma MonotonicN(m: nat, n: nat, n': nat)
+ requires n <= n'
+ ensures Ack(m, n) <= Ack(m, n')
+{
+ // In fact, Dafny completes this proof automatically.
+}
+
+// To prove the other direction, we consider an alternative formulation
+// of the Ackermann function, namely a curried form:
+function CurriedAckermann(m: int, n: int): int
+{
+ A(m)(n)
+}
+
+function A(m: int): int -> int
+{
+ if m <= 0 then
+ n => n + 1
+ else
+ n => Iter(A(m-1), n)
+}
+
+function Iter(f: int -> int, n: int): int
+ requires IsTotal(f)
+ decreases n
+{
+ if n <= 0 then
+ f(1)
+ else
+ f(Iter(f, n-1))
+}
+
+// In the 3-part definition above, function Iter needs to know that it can
+// apply its function parameter "f". Therefore, Iter's precondition says that
+// "f" must be total. We define totality of "f" by saying that its precondition
+// holds for any n and that it never reads the heap:
+predicate IsTotal(f: int -> int)
+ reads f.reads
+{
+ forall n :: f.requires(n) && f.reads(n) == {}
+}
+
+// Now, we can prove certain things about CurriedAckermann. The first thing we
+// prove is that it gives the same result as the Ack function above.
+
+lemma CurriedIsTheSame(m: nat, n: nat)
+ ensures CurriedAckermann(m, n) == Ack(m, n)
+{
+ // The proof considers 3 cases, following the 3 cases in the definition of Ack
+ if m == 0 {
+ // trivial
+ } else if n == 0 {
+ // trivial
+ } else {
+ // we help Dafny out with the following lemma:
+ assert A(m)(n) == A(m-1)(Iter(A(m-1), n-1));
+ }
+}
+
+// Monotonicity in the first argument of Ackermann now follows from the fact that,
+// for m <= m', A(m) is a function that is always below A(m')
+lemma MonotonicM(m: nat, n: nat, m': nat)
+ requires m <= m'
+ ensures Ack(m, n) <= Ack(m', n)
+{
+ CurriedIsTheSame(m, n);
+ CurriedIsTheSame(m', n);
+ ABelow(m, m');
+}
+
+// We must now prove ABelow. To do that, we will prove some properties of A and of
+// Iter. Let us define the three properties we will reason about.
+
+// The first property is a relation on functions. It is the property that above was referred
+// to as "f is a function that is always below g". The lemma ABelow(m, m') used above establishes
+// FunctionBelow(A(m), A(m')).
+predicate FunctionBelow(f: int -> int, g: int -> int)
+ requires IsTotal(f) && IsTotal(g)
+{
+ forall n :: f(n) <= g(n)
+}
+
+// The next property says that a function is monotonic.
+predicate FunctionMonotonic(f: int -> int)
+ requires IsTotal(f)
+{
+ forall n,n' :: n <= n' ==> f(n) <= f(n')
+}
+
+// The third property says that a function's return value is strictly greater than its argument.
+predicate Expanding(f: int -> int)
+ requires IsTotal(f)
+{
+ forall n :: n < f(n)
+}
+
+// We will prove that A(_) satisfies the properties FunctionBelow, FunctionMonotonic, and
+// FunctionExpanding. But first we prove three properties of Iter.
+
+// Provided that "f" is monotonic and expanding, Iter(f, _) is monotonic.
+lemma IterIsMonotonicN(f: int -> int, n: int, n': int)
+ requires IsTotal(f) && Expanding(f) && FunctionMonotonic(f) && n <= n'
+ ensures Iter(f, n) <= Iter(f, n')
+{
+ // This proof is a simple induction over n' and Dafny completes the proof automatically.
+}
+
+// Next, we prove that Iter(_, n) is monotonic. That is, given functions "f" and "g"
+// such that FunctionBelow(f, g), we have Iter(f, n) <= Iter(g, n). The lemma requires
+// "f" to be monotonic, but we don't have to state the same property for g.
+lemma IterIsMonotonicF(f: int -> int, g: int -> int, n: int)
+ requires IsTotal(f) && IsTotal(g) && FunctionMonotonic(f) && FunctionBelow(f, g)
+ ensures Iter(f, n) <= Iter(g, n)
+{
+ // This proof is a simple induction over n and Dafny completes the proof automatically.
+}
+
+// Finally, we shows that for any expanding function "f", Iter(f, _) is also expanding.
+lemma IterExpanding(f: int -> int, n: int)
+ requires IsTotal(f) && Expanding(f)
+ ensures n < Iter(f, n)
+{
+ // Here, too, the proof is a simple induction of n and Dafny completes it automatically.
+}
+
+// We complete the proof by showing that A(_) has the three properties we need.
+
+// Of the three properties we prove about A(_), we start by showing that A(m) returns a
+// function that is expanding.
+lemma AExp(m: int)
+ ensures Expanding(A(m))
+{
+ if m <= 0 {
+ // trivial
+ } else {
+ // This branch of the proof follows from the fact that Iter(A(m-1), _) is expanding.
+ forall n {
+ // The following lemma requires A(m-1) to be expanding, which is something that
+ // following from our induction hypothesis.
+ IterExpanding(A(m-1), n);
+ }
+ }
+}
+
+// Next, we show that A(m) returns a monotonic function.
+lemma Am(m: int)
+ ensures FunctionMonotonic(A(m))
+{
+ if m <= 0 {
+ // trivial
+ } else {
+ // We make use of the fact that A(m-1) is expanding:
+ AExp(m-1);
+ // and the fact that Iter(A(m-1), _) is monotonic:
+ forall n,n' | n <= n' {
+ // The following lemma requires A(m-1) to be expanding and monotonic.
+ // The former comes from the invocation of AExp(m-1) above, and the
+ // latter comes from our induction hypothesis.
+ IterIsMonotonicN(A(m-1), n, n');
+ }
+ }
+}
+
+// Our final property about A, which is the lemma we had used above to prove
+// that Ackermann is monotonic in its first argument, is stated and proved here:
+lemma ABelow(m: int, m': int)
+ requires m <= m'
+ ensures FunctionBelow(A(m), A(m'))
+{
+ if m' <= 0 {
+ // trivial
+ } else if m <= 0 {
+ forall n {
+ calc {
+ A(m)(n);
+ ==
+ n + 1;
+ <= { AExp(m'-1); IterExpanding(A(m'-1), n); }
+ Iter(A(m'-1), n);
+ ==
+ A(m')(n);
+ }
+ }
+ } else {
+ forall n {
+ calc {
+ A(m)(n);
+ ==
+ Iter(A(m-1), n);
+ <= { Am(m-1); ABelow(m-1, m'-1);
+ IterIsMonotonicF(A(m-1), A(m'-1), n); }
+ Iter(A(m'-1), n);
+ ==
+ A(m')(n);
+ }
+ }
+ }
+}
diff --git a/Test/dafny4/Ackermann.dfy.expect b/Test/dafny4/Ackermann.dfy.expect
new file mode 100644
index 00000000..158f2a48
--- /dev/null
+++ b/Test/dafny4/Ackermann.dfy.expect
@@ -0,0 +1,6 @@
+
+Dafny program verifier finished with 30 verified, 0 errors
+Program compiled successfully
+Running...
+
+Ack(3, 4) = 125
diff --git a/Test/dafny4/BinarySearch.dfy.expect b/Test/dafny4/BinarySearch.dfy.expect
index 944f677a..a9f834b7 100644
--- a/Test/dafny4/BinarySearch.dfy.expect
+++ b/Test/dafny4/BinarySearch.dfy.expect
@@ -1,4 +1,4 @@
-BinarySearch.dfy(44,20): Error: result of operation might violate newtype constraint
+BinarySearch.dfy(44,19): Error: result of operation might violate newtype constraint
Execution trace:
(0,0): anon0
BinarySearch.dfy(40,3): anon18_LoopHead
diff --git a/Test/dafny4/Bug100.dfy b/Test/dafny4/Bug100.dfy
new file mode 100644
index 00000000..0c971e82
--- /dev/null
+++ b/Test/dafny4/Bug100.dfy
@@ -0,0 +1,23 @@
+// RUN: %dafny /compile:0 /autoTriggers:1 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+lemma lemma_ensures(x:int, RefineInt:int->int)
+ requires forall y :: RefineInt.requires(y);
+ ensures forall y :: RefineInt(y) + x == RefineInt(x) + y;
+
+function Identity(z:int) : int
+
+lemma test()
+{
+ var v,w:int;
+ lemma_ensures(w, Identity);
+ //var RefineInt := Identity;
+ //assert RefineInt(v) == Identity(v);
+ assert Identity(v) + w == Identity(w) + v;
+}
+
+
+
+
+
+
diff --git a/Test/dafny4/Bug100.dfy.expect b/Test/dafny4/Bug100.dfy.expect
new file mode 100644
index 00000000..73ba063c
--- /dev/null
+++ b/Test/dafny4/Bug100.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 4 verified, 0 errors
diff --git a/Test/dafny4/Bug101.dfy b/Test/dafny4/Bug101.dfy
new file mode 100644
index 00000000..878ed57a
--- /dev/null
+++ b/Test/dafny4/Bug101.dfy
@@ -0,0 +1,19 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+predicate P(i:int) { true }
+
+lemma Tester()
+{
+// forall i ensures false ==> P(i) {}
+ forall i ensures P(i) <== false {}
+ assert forall i :: P(i) ==> false;
+ assert P(0);
+ assert false;
+}
+
+
+
+
+
+
diff --git a/Test/dafny4/Bug101.dfy.expect b/Test/dafny4/Bug101.dfy.expect
new file mode 100644
index 00000000..a4e5f4b3
--- /dev/null
+++ b/Test/dafny4/Bug101.dfy.expect
@@ -0,0 +1,8 @@
+Bug101.dfy(10,11): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon6_Else
+ (0,0): anon7_Then
+ (0,0): anon5
+
+Dafny program verifier finished with 2 verified, 1 error
diff --git a/Test/dafny4/Bug103.dfy b/Test/dafny4/Bug103.dfy
new file mode 100644
index 00000000..559a361c
--- /dev/null
+++ b/Test/dafny4/Bug103.dfy
@@ -0,0 +1,20 @@
+// RUN: %dafny /compile:0 /autoTriggers:1 /print:"%t.print" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+predicate IsLessThanSuccesor(i:int)
+{
+ i < i + 1
+}
+
+lemma LemmaWithoutTriggerOnForallStatement()
+{
+ forall i
+ ensures IsLessThanSuccesor(i);
+ {
+ }
+}
+
+
+
+
+
diff --git a/Test/dafny4/Bug103.dfy.expect b/Test/dafny4/Bug103.dfy.expect
new file mode 100644
index 00000000..52595bf9
--- /dev/null
+++ b/Test/dafny4/Bug103.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 3 verified, 0 errors
diff --git a/Test/dafny4/Bug104.dfy b/Test/dafny4/Bug104.dfy
new file mode 100644
index 00000000..ffabbb92
--- /dev/null
+++ b/Test/dafny4/Bug104.dfy
@@ -0,0 +1,12 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+datatype PartRealPartGhost = PartRealPartGhost(x:int, ghost y:int)
+
+method UpdateField()
+{
+ var v := PartRealPartGhost(3, 4);
+ ghost var g := 5;
+ v := v[y := g];
+ v := v.(y := g);
+} \ No newline at end of file
diff --git a/Test/dafny4/Bug104.dfy.expect b/Test/dafny4/Bug104.dfy.expect
new file mode 100644
index 00000000..1cc43cbf
--- /dev/null
+++ b/Test/dafny4/Bug104.dfy.expect
@@ -0,0 +1,3 @@
+Bug104.dfy(10,7): Warning: datatype update syntax D[f := E] is deprecated; the new syntax is D.(f := E)
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/dafny4/Bug107.dfy b/Test/dafny4/Bug107.dfy
new file mode 100644
index 00000000..56965d92
--- /dev/null
+++ b/Test/dafny4/Bug107.dfy
@@ -0,0 +1,16 @@
+// RUN: %dafny /compile:3 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method Main()
+{
+ var f := Inc;
+ print(f(4));
+}
+
+function method Inc(x: int): int
+{
+ x + 2
+}
+
+
+
diff --git a/Test/dafny4/Bug107.dfy.expect b/Test/dafny4/Bug107.dfy.expect
new file mode 100644
index 00000000..eaa3aa54
--- /dev/null
+++ b/Test/dafny4/Bug107.dfy.expect
@@ -0,0 +1,6 @@
+
+Dafny program verifier finished with 3 verified, 0 errors
+Program compiled successfully
+Running...
+
+6 \ No newline at end of file
diff --git a/Test/dafny4/Bug108.dfy b/Test/dafny4/Bug108.dfy
new file mode 100644
index 00000000..17cb9f12
--- /dev/null
+++ b/Test/dafny4/Bug108.dfy
@@ -0,0 +1,11 @@
+// RUN: %dafny /compile:3 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method Main() {
+ var A := map[0 := 1];
+ var B := map x | x in (set y | y in A) :: A[x];
+ print A, "\n";
+ print B, "\n";
+}
+
+
diff --git a/Test/dafny4/Bug108.dfy.expect b/Test/dafny4/Bug108.dfy.expect
new file mode 100644
index 00000000..94e65ba2
--- /dev/null
+++ b/Test/dafny4/Bug108.dfy.expect
@@ -0,0 +1,7 @@
+
+Dafny program verifier finished with 2 verified, 0 errors
+Program compiled successfully
+Running...
+
+map[0 := 1]
+map[0 := 1]
diff --git a/Test/dafny4/Bug110.dfy b/Test/dafny4/Bug110.dfy
new file mode 100644
index 00000000..aa808669
--- /dev/null
+++ b/Test/dafny4/Bug110.dfy
@@ -0,0 +1,31 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+module Io {
+ predicate AdvanceTime(oldTime:int) { oldTime > 2 }
+ class Time
+ {
+ static method GetTime()
+ ensures AdvanceTime(1);
+ }
+
+ function MaxPacketSize() : int { 65507 }
+
+ class UdpClient
+ {
+ method Receive()
+ ensures AdvanceTime(3);
+
+ method Send() returns(ok:bool)
+ requires 0 <= MaxPacketSize();
+ }
+}
+
+abstract module Host {
+ import opened Io // Doesn't work.
+ //import Io // Works
+}
+
+abstract module Main {
+ import H : Host
+}
diff --git a/Test/dafny4/Bug110.dfy.expect b/Test/dafny4/Bug110.dfy.expect
new file mode 100644
index 00000000..42fd56a5
--- /dev/null
+++ b/Test/dafny4/Bug110.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 8 verified, 0 errors
diff --git a/Test/dafny4/Bug111.dfy b/Test/dafny4/Bug111.dfy
new file mode 100644
index 00000000..730d44d3
--- /dev/null
+++ b/Test/dafny4/Bug111.dfy
@@ -0,0 +1,18 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+datatype A = A(i:int)
+datatype B = B1(a1:A) | B2(a2:A)
+
+function f(b:B):int
+{
+ match b
+ {
+ case B1(A(i)) => i
+ case B2(A(j)) => j
+ }
+}
+
+
+
+
diff --git a/Test/dafny4/Bug111.dfy.expect b/Test/dafny4/Bug111.dfy.expect
new file mode 100644
index 00000000..c0c48e2b
--- /dev/null
+++ b/Test/dafny4/Bug111.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 1 verified, 0 errors
diff --git a/Test/dafny4/Bug113.dfy b/Test/dafny4/Bug113.dfy
new file mode 100644
index 00000000..8f5ddf9f
--- /dev/null
+++ b/Test/dafny4/Bug113.dfy
@@ -0,0 +1,10 @@
+// RUN: %dafny /compile:3 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+datatype D = D(q:int, r:int, s:int, t:int)
+
+method Main()
+{
+ print D(10, 20, 30, 40);
+ print "\n";
+} \ No newline at end of file
diff --git a/Test/dafny4/Bug113.dfy.expect b/Test/dafny4/Bug113.dfy.expect
new file mode 100644
index 00000000..c4be010e
--- /dev/null
+++ b/Test/dafny4/Bug113.dfy.expect
@@ -0,0 +1,6 @@
+
+Dafny program verifier finished with 2 verified, 0 errors
+Program compiled successfully
+Running...
+
+D.D(10, 20, 30, 40)
diff --git a/Test/dafny4/Bug114.dfy b/Test/dafny4/Bug114.dfy
new file mode 100644
index 00000000..1c0f0109
--- /dev/null
+++ b/Test/dafny4/Bug114.dfy
@@ -0,0 +1,10 @@
+// RUN: %dafny /compile:0 /autoTriggers:1 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+function f1(d:int):map<int,int>
+function f2(y:int, d:int):int
+
+method M(m:map<int,int>, d:int, x2:int)
+{
+ assert forall d :: f1(d) == (map x | x in m :: f2(x, d));
+} \ No newline at end of file
diff --git a/Test/dafny4/Bug114.dfy.expect b/Test/dafny4/Bug114.dfy.expect
new file mode 100644
index 00000000..8e671f90
--- /dev/null
+++ b/Test/dafny4/Bug114.dfy.expect
@@ -0,0 +1,7 @@
+Bug114.dfy(9,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Then
+ (0,0): anon2
+
+Dafny program verifier finished with 3 verified, 1 error
diff --git a/Test/dafny4/Bug116.dfy b/Test/dafny4/Bug116.dfy
new file mode 100644
index 00000000..9fd30597
--- /dev/null
+++ b/Test/dafny4/Bug116.dfy
@@ -0,0 +1,15 @@
+// RUN: %dafny "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+datatype struct = S // this is ok
+
+method Main()
+{
+ var s := S; // this line generates illegal C# code
+ print s;
+}
+
+
+
+
+
diff --git a/Test/dafny4/Bug116.dfy.expect b/Test/dafny4/Bug116.dfy.expect
new file mode 100644
index 00000000..b0cf7300
--- /dev/null
+++ b/Test/dafny4/Bug116.dfy.expect
@@ -0,0 +1,3 @@
+
+Dafny program verifier finished with 2 verified, 0 errors
+Compiled assembly into Bug116.exe
diff --git a/Test/dafny4/Bug117.dfy b/Test/dafny4/Bug117.dfy
new file mode 100644
index 00000000..418746cb
--- /dev/null
+++ b/Test/dafny4/Bug117.dfy
@@ -0,0 +1,37 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+abstract module AbstractModule1
+{
+ type AbstractType1
+}
+
+abstract module AbstractModule2
+{
+ import opened AM1 : AbstractModule1
+
+ datatype AbstractType2 = AbstractType2(x:AbstractType1)
+}
+
+abstract module AbstractModule3
+{
+ import AM1 : AbstractModule1
+
+ datatype AbstractType2 = AbstractType2(x:AM1.AbstractType1)
+}
+
+module ConcreteModule1
+{
+ type AbstractType1 = int
+}
+
+module ConcreteModule2 refines AbstractModule2
+{
+ import AM1 = ConcreteModule1 // error: must be declared "opened" to match AbstratctModule2
+}
+
+module ConcreteModule3 refines AbstractModule3
+{
+ import opened AM1 = ConcreteModule1 // error: can't be declared "opened" to match AbstractModule3
+}
+
diff --git a/Test/dafny4/Bug117.dfy.expect b/Test/dafny4/Bug117.dfy.expect
new file mode 100644
index 00000000..0c5a5445
--- /dev/null
+++ b/Test/dafny4/Bug117.dfy.expect
@@ -0,0 +1,3 @@
+Bug117.dfy(28,7): Error: AM1 in ConcreteModule2 must be imported with "opened" to match the corresponding import in its refinement base AbstractModule2.
+Bug117.dfy(33,7): Error: AM1 in ConcreteModule3 cannot be imported with "opened" because it does not match the corresponding import in the refinement base AbstractModule3
+2 resolution/type errors detected in Bug117.dfy
diff --git a/Test/dafny4/Bug118.dfy b/Test/dafny4/Bug118.dfy
new file mode 100644
index 00000000..1e2dddeb
--- /dev/null
+++ b/Test/dafny4/Bug118.dfy
@@ -0,0 +1,12 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+class Foo {
+ ghost var Repr: set<object>
+}
+
+function SeqRepr(s:seq<Foo>) : set<object>
+ reads set b | b in s
+{
+ set o,b | b in s && b != null && o in b.Repr :: o // Works if you say "set b,o | ..."
+} \ No newline at end of file
diff --git a/Test/dafny4/Bug118.dfy.expect b/Test/dafny4/Bug118.dfy.expect
new file mode 100644
index 00000000..c0c48e2b
--- /dev/null
+++ b/Test/dafny4/Bug118.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 1 verified, 0 errors
diff --git a/Test/dafny4/Bug120.dfy b/Test/dafny4/Bug120.dfy
new file mode 100644
index 00000000..73553f2a
--- /dev/null
+++ b/Test/dafny4/Bug120.dfy
@@ -0,0 +1,11 @@
+// RUN: %dafny /compile:0 /noNLarith "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+function G(n: nat): nat
+{
+ if n == 0 then 5 else G(n-1)
+}
+
+method Test() {
+ assert G(10) == 5;
+} \ No newline at end of file
diff --git a/Test/dafny4/Bug120.dfy.expect b/Test/dafny4/Bug120.dfy.expect
new file mode 100644
index 00000000..52595bf9
--- /dev/null
+++ b/Test/dafny4/Bug120.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 3 verified, 0 errors
diff --git a/Test/dafny4/Bug121.dfy b/Test/dafny4/Bug121.dfy
new file mode 100644
index 00000000..13798fa8
--- /dev/null
+++ b/Test/dafny4/Bug121.dfy
@@ -0,0 +1,18 @@
+// RUN: %dafny /compile:0 /autoTriggers:1 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method Try (a:int, b:int, c:int)
+{
+ forall
+ ensures a * c == a * c;
+ ensures b * c == b * c;
+ {
+ }
+}
+
+
+
+
+
+
+
diff --git a/Test/dafny4/Bug121.dfy.expect b/Test/dafny4/Bug121.dfy.expect
new file mode 100644
index 00000000..069e7767
--- /dev/null
+++ b/Test/dafny4/Bug121.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/dafny4/Bug122.dfy b/Test/dafny4/Bug122.dfy
new file mode 100644
index 00000000..adbee30d
--- /dev/null
+++ b/Test/dafny4/Bug122.dfy
@@ -0,0 +1,17 @@
+// RUN: %dafny /compile:0 /autoTriggers:1 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method Try (a:int)
+{
+ forall
+ ensures a == a;
+ {
+ }
+}
+
+
+
+
+
+
+
diff --git a/Test/dafny4/Bug122.dfy.expect b/Test/dafny4/Bug122.dfy.expect
new file mode 100644
index 00000000..069e7767
--- /dev/null
+++ b/Test/dafny4/Bug122.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/dafny4/Bug124.dfy b/Test/dafny4/Bug124.dfy
new file mode 100644
index 00000000..60f26a00
--- /dev/null
+++ b/Test/dafny4/Bug124.dfy
@@ -0,0 +1,14 @@
+// RUN: %dafny /compile:0 /autoTriggers:1 /noNLarith "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+function power(n:nat, e:nat) : int
+
+lemma lemma_power()
+ ensures forall n:nat, e:nat :: 0 <= n * e && power(n, e) == 5;
+{
+ forall n:nat, e:nat
+ ensures 0 <= n * e && power(n, e) == 5;
+ {
+ assume false;
+ }
+} \ No newline at end of file
diff --git a/Test/dafny4/Bug124.dfy.expect b/Test/dafny4/Bug124.dfy.expect
new file mode 100644
index 00000000..52595bf9
--- /dev/null
+++ b/Test/dafny4/Bug124.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 3 verified, 0 errors
diff --git a/Test/dafny4/Bug125.dfy b/Test/dafny4/Bug125.dfy
new file mode 100644
index 00000000..5dbdea6f
--- /dev/null
+++ b/Test/dafny4/Bug125.dfy
@@ -0,0 +1,58 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+abstract module AbstractModuleA
+{
+ type T
+}
+
+abstract module AbstractModuleB
+{
+ import opened AMA : AbstractModuleA
+
+ method Foo(t:T)
+}
+
+abstract module AbstractModuleC refines AbstractModuleB
+{
+ import opened AMA2 : AbstractModuleA
+}
+
+module LibA {
+ class G {
+ static function f(x:int) : bool {
+ x >= 10
+ }
+ }
+
+ function g() : bool {
+ true
+ }
+}
+
+module LibB {
+ class G {
+ static function f(x:int) : bool {
+ x < 10
+ }
+ }
+
+ function g() : bool {
+ false
+ }
+}
+
+module R {
+ import opened LibA
+}
+
+module S refines R {
+ import opened LibB
+ method m() {
+ assert g(); // should be LibA.g
+ }
+
+ method m1() {
+ assert G.f(20); // should be LibA.G.f
+ }
+}
diff --git a/Test/dafny4/Bug125.dfy.expect b/Test/dafny4/Bug125.dfy.expect
new file mode 100644
index 00000000..c87e2af2
--- /dev/null
+++ b/Test/dafny4/Bug125.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 10 verified, 0 errors
diff --git a/Test/dafny4/Bug128.dfy b/Test/dafny4/Bug128.dfy
new file mode 100644
index 00000000..b7220335
--- /dev/null
+++ b/Test/dafny4/Bug128.dfy
@@ -0,0 +1,13 @@
+// RUN: %dafny /noNLarith /z3opt:pi.warnings=true /proverWarnings:1 /compile:0 /autoTriggers:1 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+function GetIndexInSequence<T>(s:seq<T>, x:T) : int
+ requires x in s;
+ ensures 0 <= GetIndexInSequence(s, x) < |s|;
+ ensures s[GetIndexInSequence(s, x)] == x; {
+ var i :| 0 <= i < |s| && s[i] == x;
+ i
+ }
+
+
+
diff --git a/Test/dafny4/Bug128.dfy.expect b/Test/dafny4/Bug128.dfy.expect
new file mode 100644
index 00000000..c0c48e2b
--- /dev/null
+++ b/Test/dafny4/Bug128.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 1 verified, 0 errors
diff --git a/Test/dafny4/Bug129.dfy b/Test/dafny4/Bug129.dfy
new file mode 100644
index 00000000..f6cf0fe8
--- /dev/null
+++ b/Test/dafny4/Bug129.dfy
@@ -0,0 +1,12 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+datatype Maybe<T> = Some(v:T) | None
+datatype B = B(b:Maybe<B>)
+
+datatype List<T> = Nil | Cons(T, List<T>)
+datatype Tree<T> = Nodes(children: List<Tree<T>>)
+
+
+
+
diff --git a/Test/dafny4/Bug129.dfy.expect b/Test/dafny4/Bug129.dfy.expect
new file mode 100644
index 00000000..a1c1f7b9
--- /dev/null
+++ b/Test/dafny4/Bug129.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 0 verified, 0 errors
diff --git a/Test/dafny4/Bug131.dfy b/Test/dafny4/Bug131.dfy
new file mode 100644
index 00000000..5d01cf59
--- /dev/null
+++ b/Test/dafny4/Bug131.dfy
@@ -0,0 +1,11 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+class Cell {
+ method Test(c: Cell) {
+ assert c.F();
+ }
+}
+
+predicate F()
+
diff --git a/Test/dafny4/Bug131.dfy.expect b/Test/dafny4/Bug131.dfy.expect
new file mode 100644
index 00000000..b4c98652
--- /dev/null
+++ b/Test/dafny4/Bug131.dfy.expect
@@ -0,0 +1,2 @@
+Bug131.dfy(6,13): Error: member F does not exist in class Cell
+1 resolution/type errors detected in Bug131.dfy
diff --git a/Test/dafny4/Bug132.dfy b/Test/dafny4/Bug132.dfy
new file mode 100644
index 00000000..b2a26876
--- /dev/null
+++ b/Test/dafny4/Bug132.dfy
@@ -0,0 +1,45 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+class Cell {
+ var data: int
+
+ predicate P()
+ reads this
+ { data < 0 }
+
+ predicate Q(e: Cell)
+ reads this, e
+ { e != null ==> e.data == data }
+
+ method Test() {
+ ghost var b;
+ var c := new Cell;
+ if {
+ // In the current state, everything is allowed:
+ case true => b := this.P();
+ case true => b := c.P();
+ case true => b := this.Q(this);
+ case true => b := this.Q(c);
+ case true => b := c.Q(this);
+ case true => b := c.Q(c);
+
+ // 'this' was allocated already in the 'old' state, so all of these are fine:
+ case true => b := old(this.P());
+ case true => b := old(P()); // same as previous line, of course
+ case true => b := old(this.Q(this));
+
+ // 'c' is freshly allocaed in this method, so it cannot be used inside 'old'
+ case true => b := old(c.P()); // error: receiver argument must be allocated in the state in which the function is invoked
+ case true => b := old(c.Q(this)); // error: receiver argument must be allocated in the state in which the function is invoked
+
+ // The same rule should apply if 'c' is a non-receiver argument
+ case true => b := old(this.Q(c)); // BOGUS: this should also generate an error
+
+ // In the following, 'c' is used as both of the two arguments. It's not allowed as either argument. However, since the error
+ // about the receiver masks the error about the other parameter, only one error (about the receiver) should be reported.
+ case true => b := old(c.Q(c)); // BOGUS: this should generate an error about the receiver
+ }
+ }
+}
+
diff --git a/Test/dafny4/Bug132.dfy.expect b/Test/dafny4/Bug132.dfy.expect
new file mode 100644
index 00000000..0452f42d
--- /dev/null
+++ b/Test/dafny4/Bug132.dfy.expect
@@ -0,0 +1,18 @@
+Bug132.dfy(33,29): Error: receiver argument must be allocated in the state in which the function is invoked
+Execution trace:
+ (0,0): anon0
+ (0,0): anon24_Then
+Bug132.dfy(34,29): Error: receiver argument must be allocated in the state in which the function is invoked
+Execution trace:
+ (0,0): anon0
+ (0,0): anon25_Then
+Bug132.dfy(37,36): Error: argument must be allocated in the state in which the function is invoked
+Execution trace:
+ (0,0): anon0
+ (0,0): anon26_Then
+Bug132.dfy(41,29): Error: receiver argument must be allocated in the state in which the function is invoked
+Execution trace:
+ (0,0): anon0
+ (0,0): anon27_Then
+
+Dafny program verifier finished with 3 verified, 4 errors
diff --git a/Test/dafny4/Bug133.dfy b/Test/dafny4/Bug133.dfy
new file mode 100644
index 00000000..f7da133e
--- /dev/null
+++ b/Test/dafny4/Bug133.dfy
@@ -0,0 +1,18 @@
+// RUN: %dafny /noNLarith /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+module Math__div_def_i {
+ function my_div_pos(x:int, d:int) : int
+ requires d > 0;
+ decreases if x < 0 then (d - x) else x;
+ {
+ if x < 0 then
+ -1 + my_div_pos(x+d, d)
+ else if x < d then
+ 0
+ else
+ 1 + my_div_pos(x-d, d)
+ }
+}
+
+
diff --git a/Test/dafny4/Bug133.dfy.expect b/Test/dafny4/Bug133.dfy.expect
new file mode 100644
index 00000000..c0c48e2b
--- /dev/null
+++ b/Test/dafny4/Bug133.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 1 verified, 0 errors
diff --git a/Test/dafny4/Bug134.dfy b/Test/dafny4/Bug134.dfy
new file mode 100644
index 00000000..fff6c36a
--- /dev/null
+++ b/Test/dafny4/Bug134.dfy
@@ -0,0 +1,23 @@
+// RUN: %dafny /compile:0 /ironDafny "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+module NativeTypes {
+ newtype{:nativeType "ushort"} uint16 = i:int | 0 <= i < 0x10000
+}
+
+abstract module AbstractModuleA
+{
+ import opened NativeTypes
+ datatype T = T(i:uint16)
+}
+
+abstract module AbstractModuleB
+{
+ import opened A as AbstractModuleA
+}
+
+abstract module AbstractModuleC
+{
+ import opened B as AbstractModuleB
+}
+
diff --git a/Test/dafny4/Bug134.dfy.expect b/Test/dafny4/Bug134.dfy.expect
new file mode 100644
index 00000000..d5d7ae53
--- /dev/null
+++ b/Test/dafny4/Bug134.dfy.expect
@@ -0,0 +1,4 @@
+Bug134.dfy(16,20): Warning: "import A as B" has been deprecated; in the new syntax, it is "import A:B"
+Bug134.dfy(21,20): Warning: "import A as B" has been deprecated; in the new syntax, it is "import A:B"
+
+Dafny program verifier finished with 4 verified, 0 errors
diff --git a/Test/dafny4/Bug136.dfy b/Test/dafny4/Bug136.dfy
new file mode 100644
index 00000000..97c9e389
--- /dev/null
+++ b/Test/dafny4/Bug136.dfy
@@ -0,0 +1,12 @@
+// RUN: %dafny /compile:0 /print:"%t.print" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method test()
+{
+ assume false;
+ assert true;
+}
+
+
+
+
diff --git a/Test/dafny4/Bug136.dfy.expect b/Test/dafny4/Bug136.dfy.expect
new file mode 100644
index 00000000..069e7767
--- /dev/null
+++ b/Test/dafny4/Bug136.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/dafny4/Bug138.dfy b/Test/dafny4/Bug138.dfy
new file mode 100644
index 00000000..db0e54ef
--- /dev/null
+++ b/Test/dafny4/Bug138.dfy
@@ -0,0 +1,22 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+datatype List = Nil | Cons(int, List)
+
+method R(xs: List)
+{
+ match xs
+ case Nil() => // currently produces a parsing error, but shouldn't
+ case Cons(x, Nil()) => // currently allowed
+ case Cons(x, Cons(y, tail)) =>
+}
+
+function F(xs: List) : int
+{
+ match xs
+ case Nil() => 0 // currently produces a parsing error, but shouldn't
+ case Cons(x, Nil()) => 1 // currently allowed
+ case Cons(x, Cons(y, tail)) => 2
+}
+
+
diff --git a/Test/dafny4/Bug138.dfy.expect b/Test/dafny4/Bug138.dfy.expect
new file mode 100644
index 00000000..52595bf9
--- /dev/null
+++ b/Test/dafny4/Bug138.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 3 verified, 0 errors
diff --git a/Test/dafny4/Bug139.dfy b/Test/dafny4/Bug139.dfy
new file mode 100644
index 00000000..bd4ded73
--- /dev/null
+++ b/Test/dafny4/Bug139.dfy
@@ -0,0 +1,25 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+datatype List = Nil | Cons(int, List)
+
+method R(xs: List)
+{
+ var a: int;
+ var b: int;
+ match xs
+ case Nil =>
+ case Cons(a, Nil()) => // this 'a' is allowed
+ case Cons(x, Cons(b, tail)) => // this 'b' (which is in a nested position) generates an error
+}
+
+function F(xs: List): int
+{
+ var a := 4;
+ var b := 7;
+ match xs
+ case Nil => 0
+ case Cons(a, Nil()) => 1
+ case Cons(x, Cons(b, tail)) => 2
+}
+
diff --git a/Test/dafny4/Bug139.dfy.expect b/Test/dafny4/Bug139.dfy.expect
new file mode 100644
index 00000000..52595bf9
--- /dev/null
+++ b/Test/dafny4/Bug139.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 3 verified, 0 errors
diff --git a/Test/dafny4/Bug140.dfy b/Test/dafny4/Bug140.dfy
new file mode 100644
index 00000000..9a85e36c
--- /dev/null
+++ b/Test/dafny4/Bug140.dfy
@@ -0,0 +1,67 @@
+// RUN: %dafny /compile:3 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+class Node<T> {
+ ghost var List: seq<T>;
+ ghost var Repr: set<Node<T>>;
+
+ var data: T;
+ var next: Node<T>;
+
+ predicate Valid()
+ reads this, Repr
+ {
+ this in Repr && null !in Repr &&
+ (next == null ==> List == [data]) &&
+ (next != null ==>
+ next in Repr && next.Repr <= Repr &&
+ this !in next.Repr &&
+ List == [data] + next.List &&
+ next.Valid())
+ }
+
+ constructor (d: T)
+ modifies this
+ ensures Valid() && fresh(Repr - {this})
+ ensures List == [d]
+ {
+ data, next := d, null;
+ List, Repr := [d], {this};
+ }
+
+ constructor InitAsPredecessor(d: T, succ: Node<T>)
+ requires succ != null && succ.Valid() && this !in succ.Repr;
+ modifies this;
+ ensures Valid() && fresh(Repr - {this} - succ.Repr);
+ ensures List == [d] + succ.List;
+ {
+ data, next := d, succ;
+ List := [d] + succ.List;
+ Repr := {this} + succ.Repr;
+ }
+
+ method Prepend(d: T) returns (r: Node<T>)
+ requires Valid()
+ ensures r != null && r.Valid() && fresh(r.Repr - old(Repr))
+ ensures r.List == [d] + List
+ {
+ r := new Node.InitAsPredecessor(d, this);
+ }
+
+ method Print()
+ requires Valid()
+ decreases |List|
+ {
+ print data;
+ if (next != null) {
+ next.Print();
+ }
+ }
+}
+
+method Main()
+{
+ var l2 := new Node(2);
+ var l1 := l2.Prepend(1);
+ l1.Print();
+}
diff --git a/Test/dafny4/Bug140.dfy.expect b/Test/dafny4/Bug140.dfy.expect
new file mode 100644
index 00000000..00c7d129
--- /dev/null
+++ b/Test/dafny4/Bug140.dfy.expect
@@ -0,0 +1,6 @@
+
+Dafny program verifier finished with 11 verified, 0 errors
+Program compiled successfully
+Running...
+
+12 \ No newline at end of file
diff --git a/Test/dafny4/Bug148.dfy b/Test/dafny4/Bug148.dfy
new file mode 100644
index 00000000..b7a08952
--- /dev/null
+++ b/Test/dafny4/Bug148.dfy
@@ -0,0 +1,25 @@
+// RUN: %dafny /compile:3 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method Main()
+{
+ var zero : real := 0.0;
+ var three : real := 3.0;
+ var fifteen : real := 15.0;
+ var negone : real := -1.0;
+ var negthree : real := -3.0;
+
+ print zero <= fifteen, "\n"; // true
+ print fifteen <= zero, "\n"; // false
+ print negone <= zero, "\n"; // true
+ print zero <= negone, "\n"; // false
+ print negone <= fifteen, "\n"; // true
+ print fifteen <= negone, "\n"; // false
+
+ print zero >= fifteen, "\n"; // false
+ print fifteen >= zero, "\n"; // true
+ print negone >= zero, "\n"; // false
+ print zero >= negone, "\n"; // true
+ print negone >= fifteen, "\n"; // false
+ print fifteen >= negone, "\n"; // true
+}
diff --git a/Test/dafny4/Bug148.dfy.expect b/Test/dafny4/Bug148.dfy.expect
new file mode 100644
index 00000000..7acfb169
--- /dev/null
+++ b/Test/dafny4/Bug148.dfy.expect
@@ -0,0 +1,17 @@
+
+Dafny program verifier finished with 2 verified, 0 errors
+Program compiled successfully
+Running...
+
+True
+False
+True
+False
+True
+False
+False
+True
+False
+True
+False
+True
diff --git a/Test/dafny4/Bug49.dfy b/Test/dafny4/Bug49.dfy
new file mode 100644
index 00000000..887938d6
--- /dev/null
+++ b/Test/dafny4/Bug49.dfy
@@ -0,0 +1,74 @@
+// RUN: %dafny /compile:3 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method Main()
+{
+ print apply(i => i + 1, 5), "\n";
+ print mapply(map[5 := 6], 5), "\n";
+ var f;
+ print five(f), "\n";
+}
+
+// -----
+// test that the definition axiom for function "apply" is available
+
+function method apply(f:int->int, a:int): int
+ reads f.reads
+ requires f.requires(a)
+{
+ f(a)
+}
+
+lemma TestPost()
+ ensures apply(i => i + 1, 5) == 6
+{
+}
+
+lemma M() {
+ assert apply(i => i + 1, 5) == 6;
+}
+
+lemma TestPre()
+ requires apply(i => i + 1, 5) == 6
+{
+}
+
+lemma TestPreCaller()
+{
+ TestPre();
+}
+
+// -----
+// test that the above thing for arrows also works for maps
+
+function method mapply(m: map<int,int>, a:int): int
+ requires a in m
+{
+ m[a]
+}
+
+lemma TestMPost()
+ ensures mapply(map[5 := 6], 5) == 6
+{
+}
+
+lemma N() {
+ assert mapply(map[5 := 6], 5) == 6;
+}
+
+// -----
+// test that g's result is known to be $Is'ed and $IsAlloc'ed
+
+function method five(f:int->int): int { 5 }
+
+lemma P() {
+ var f := i => i + 1;
+ assert five(f) == 5;
+}
+
+lemma Q(g: real->int->int)
+ requires g.requires(0.0)
+{
+ var f := g(0.0);
+ assert five(f) == 5;
+}
diff --git a/Test/dafny4/Bug49.dfy.expect b/Test/dafny4/Bug49.dfy.expect
new file mode 100644
index 00000000..653dda07
--- /dev/null
+++ b/Test/dafny4/Bug49.dfy.expect
@@ -0,0 +1,8 @@
+
+Dafny program verifier finished with 21 verified, 0 errors
+Program compiled successfully
+Running...
+
+6
+6
+5
diff --git a/Test/dafny4/Bug60.dfy b/Test/dafny4/Bug60.dfy
index 5340ad6b..c433451c 100644
--- a/Test/dafny4/Bug60.dfy
+++ b/Test/dafny4/Bug60.dfy
@@ -9,5 +9,5 @@ method Main()
print (s, m), "\n";
print (|s|, |m|), "\n";
print(set s | s in m), "\n";
- print (forall x :: x in (map [1:=10, 2:=20]) ==> x > 0), "\n";
-} \ No newline at end of file
+ print (forall x {:nowarn} :: x in (map [1:=10, 2:=20]) ==> x > 0), "\n";
+}
diff --git a/Test/dafny4/Bug63.dfy b/Test/dafny4/Bug63.dfy
index 86aad232..39cbae1b 100644
--- a/Test/dafny4/Bug63.dfy
+++ b/Test/dafny4/Bug63.dfy
@@ -8,6 +8,6 @@ method M()
method Client()
{
- assume forall o: object :: o != null ==> false;
+ assume forall o: object {:nowarn} :: o != null ==> false;
M();
-} \ No newline at end of file
+}
diff --git a/Test/dafny4/Bug73.dfy.expect b/Test/dafny4/Bug73.dfy.expect
index 6cf5c156..8beaa18c 100644
--- a/Test/dafny4/Bug73.dfy.expect
+++ b/Test/dafny4/Bug73.dfy.expect
@@ -1,9 +1,9 @@
-Bug73.dfy(7,14): Error: assertion violation
+Bug73.dfy(7,13): Error: assertion violation
Execution trace:
(0,0): anon0
Bug73.dfy(7,19): anon3_Else
(0,0): anon2
-Bug73.dfy(13,14): Error: assertion violation
+Bug73.dfy(13,13): Error: assertion violation
Execution trace:
(0,0): anon0
Bug73.dfy(13,20): anon3_Else
diff --git a/Test/dafny4/Bug75.dfy b/Test/dafny4/Bug75.dfy
new file mode 100644
index 00000000..37d35f77
--- /dev/null
+++ b/Test/dafny4/Bug75.dfy
@@ -0,0 +1,50 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+predicate R1(x:int, y:int) { x > 0 ==> R2(x - 1) }
+predicate R2(x:int) { exists y :: R1(x, y) }
+
+lemma L1(x:int)
+{
+ assume R2(x);
+ assert exists y :: R1(x, y); // FAILS
+}
+
+lemma L2(x:int)
+ requires R2(x); // Oddly, adding this requires fixes the problem
+{
+ assume R2(x);
+ assert exists y :: R1(x, y); // SUCCEEDS
+}
+
+// this predicate says that the first "n" elements of "s"
+
+// are in strictly increasing order
+
+predicate method Increasing(s: seq<int>, n: nat)
+ requires n <= |s|
+{
+ n < 2 ||
+ (s[n-2] < s[n-1] && Increasing(s, n-1))
+}
+
+method Extend(s: seq<int>, n: nat) returns (n': nat)
+ requires n < |s|
+ requires forall i :: 0 <= i < n ==> Increasing(s, i)
+ ensures n <= n' <= |s|
+ ensures forall j :: 0 <= j < n' ==> Increasing(s, j)
+{
+ if 2 <= n && s[n-2] < s[n-1] {
+ n' := n + 1;
+ } else {
+ n' := n;
+ }
+}
+
+function pred(i:int):int { i - 1 }
+predicate f(a:int, s:int) { (a <= 0 || (exists s0 :: f(pred(a), s0))) }
+
+lemma Fuel1(a:int, s:int)
+{
+ assert f(a, s) <==> (a <= 0 || (exists s0 :: f(pred(a), s0))); // FAILS
+}
diff --git a/Test/dafny4/Bug75.dfy.expect b/Test/dafny4/Bug75.dfy.expect
new file mode 100644
index 00000000..aeb37948
--- /dev/null
+++ b/Test/dafny4/Bug75.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 13 verified, 0 errors
diff --git a/Test/dafny4/Bug79.dfy b/Test/dafny4/Bug79.dfy
new file mode 100644
index 00000000..49f2421b
--- /dev/null
+++ b/Test/dafny4/Bug79.dfy
@@ -0,0 +1,10 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+function foo(s:int) : (int, int)
+
+function bar(s:int) : bool
+{
+ var (x, rest) := foo(s);
+ x > 0
+} \ No newline at end of file
diff --git a/Test/dafny4/Bug79.dfy.expect b/Test/dafny4/Bug79.dfy.expect
new file mode 100644
index 00000000..069e7767
--- /dev/null
+++ b/Test/dafny4/Bug79.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/dafny4/Bug81.dfy b/Test/dafny4/Bug81.dfy
new file mode 100644
index 00000000..1992d666
--- /dev/null
+++ b/Test/dafny4/Bug81.dfy
@@ -0,0 +1,9 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+function {:opaque} RefineSeqToSeq<T,U>(s:seq<T>, refine_func:T->U) : seq<U>
+ reads refine_func.reads;
+{
+ if |s| == 0 then []
+ else RefineSeqToSeq(s[1..], refine_func)
+}
diff --git a/Test/dafny4/Bug81.dfy.expect b/Test/dafny4/Bug81.dfy.expect
new file mode 100644
index 00000000..069e7767
--- /dev/null
+++ b/Test/dafny4/Bug81.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/dafny4/Bug82.dfy b/Test/dafny4/Bug82.dfy
new file mode 100644
index 00000000..bc7ff321
--- /dev/null
+++ b/Test/dafny4/Bug82.dfy
@@ -0,0 +1,11 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+function {:opaque} Reverse(id:int) : int
+
+function RefineToMap(ReverseKey:int->int) : bool
+
+function RefineToMapOfSeqNums() : bool
+{
+ RefineToMap(Reverse)
+}
diff --git a/Test/dafny4/Bug82.dfy.expect b/Test/dafny4/Bug82.dfy.expect
new file mode 100644
index 00000000..73ba063c
--- /dev/null
+++ b/Test/dafny4/Bug82.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 4 verified, 0 errors
diff --git a/Test/dafny4/Bug88.dfy b/Test/dafny4/Bug88.dfy
new file mode 100644
index 00000000..cab2524a
--- /dev/null
+++ b/Test/dafny4/Bug88.dfy
@@ -0,0 +1,18 @@
+// RUN: %dafny "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+lemma T(a: int) returns (b: int)
+ ensures a == b
+{
+ calc {
+ a;
+ }
+}
+
+lemma A(i: int)
+ ensures false
+{
+ if * {
+ } else {
+ }
+} \ No newline at end of file
diff --git a/Test/dafny4/Bug88.dfy.expect b/Test/dafny4/Bug88.dfy.expect
new file mode 100644
index 00000000..3bd22329
--- /dev/null
+++ b/Test/dafny4/Bug88.dfy.expect
@@ -0,0 +1,11 @@
+Bug88.dfy(6,0): Error BP5003: A postcondition might not hold on this return path.
+Bug88.dfy(5,12): Related location: This is the postcondition that might not hold.
+Execution trace:
+ (0,0): anon0
+ Bug88.dfy(7,3): anon2_Else
+Bug88.dfy(14,0): Error BP5003: A postcondition might not hold on this return path.
+Bug88.dfy(13,10): Related location: This is the postcondition that might not hold.
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 2 verified, 2 errors
diff --git a/Test/dafny4/Bug89.dfy b/Test/dafny4/Bug89.dfy
new file mode 100644
index 00000000..12aec5f4
--- /dev/null
+++ b/Test/dafny4/Bug89.dfy
@@ -0,0 +1,15 @@
+// RUN: %dafny /compile:3 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method F() returns(x:int)
+ ensures x == 6;
+{
+ x := 5;
+ x := (var y := 1; y + x);
+}
+
+method Main()
+{
+ var x := F();
+ print x;
+} \ No newline at end of file
diff --git a/Test/dafny4/Bug89.dfy.expect b/Test/dafny4/Bug89.dfy.expect
new file mode 100644
index 00000000..5221a5d1
--- /dev/null
+++ b/Test/dafny4/Bug89.dfy.expect
@@ -0,0 +1,6 @@
+
+Dafny program verifier finished with 4 verified, 0 errors
+Program compiled successfully
+Running...
+
+6 \ No newline at end of file
diff --git a/Test/dafny4/Bug91.dfy b/Test/dafny4/Bug91.dfy
new file mode 100644
index 00000000..53e5d5b2
--- /dev/null
+++ b/Test/dafny4/Bug91.dfy
@@ -0,0 +1,40 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+type SendState = map<int, seq<int>>
+
+function UnAckedMessages(s:SendState) : set<int>
+{
+ set m,dst | dst in s && m in s[dst] :: m
+}
+
+function UnAckedMessagesForDst(s:SendState, dst:int) : set<int>
+ requires dst in s;
+{
+ set m | m in s[dst] :: m
+}
+
+function UnAckedMessages3(s:SendState) : set<int>
+{
+ set m,dst | dst in s && m in UnAckedMessagesForDst(s, dst) :: m
+}
+
+function SeqToSet<T>(s:seq<T>) : set<T>
+{
+ set i | i in s
+}
+
+function UnAckedMessages4(s:SendState) : set<int>
+{
+ set m,dst | dst in s && m in SeqToSet(s[dst]) :: m
+}
+
+function UnAckedLists(s:SendState) : set<seq<int>>
+{
+ set dst | dst in s :: s[dst]
+}
+
+function UnAckedMessages5(s:SendState) : set<int>
+{
+ set m, list | list in UnAckedLists(s) && m in list :: m
+} \ No newline at end of file
diff --git a/Test/dafny4/Bug91.dfy.expect b/Test/dafny4/Bug91.dfy.expect
new file mode 100644
index 00000000..76f19e0d
--- /dev/null
+++ b/Test/dafny4/Bug91.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 7 verified, 0 errors
diff --git a/Test/dafny4/Bug93.dfy b/Test/dafny4/Bug93.dfy
new file mode 100644
index 00000000..5a1dd27f
--- /dev/null
+++ b/Test/dafny4/Bug93.dfy
@@ -0,0 +1,37 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+module Fuel {
+ function FunctionA(x:int) : int
+ {
+ x + 2
+ }
+
+ function FunctionB(y:int) : int
+ {
+ FunctionA(y - 2)
+ }
+
+ method {:fuel FunctionA,0,0} MethodX(z:int)
+ {
+ assert FunctionB(z) == z; // error: Cannot see the body of FunctionA
+ }
+}
+
+module Opaque {
+ function {:opaque} FunctionA(x:int) : int
+ {
+ x + 2
+ }
+
+ function FunctionB(y:int) : int
+ {
+ FunctionA(y - 2)
+ }
+
+ method MethodX(z:int)
+ {
+ assert FunctionB(z) == z;
+ }
+}
+
diff --git a/Test/dafny4/Bug93.dfy.expect b/Test/dafny4/Bug93.dfy.expect
new file mode 100644
index 00000000..d0baf877
--- /dev/null
+++ b/Test/dafny4/Bug93.dfy.expect
@@ -0,0 +1,8 @@
+Bug93.dfy(17,28): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Bug93.dfy(34,28): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 7 verified, 2 errors
diff --git a/Test/dafny4/Bug94.dfy b/Test/dafny4/Bug94.dfy
new file mode 100644
index 00000000..2f437785
--- /dev/null
+++ b/Test/dafny4/Bug94.dfy
@@ -0,0 +1,35 @@
+// RUN: %dafny /compile:3 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+function foo() : (int, int)
+{
+ (5, 10)
+}
+
+function bar() : int
+{
+ var (x, y) := foo();
+ x + y
+}
+
+lemma test()
+{
+ var (x, y) := foo();
+}
+
+function method foo2() : (int,int)
+{
+ (5, 10)
+}
+
+method test2()
+{
+ var (x, y) := foo2();
+}
+
+method Main()
+{
+ var (x, y) := foo2();
+ assert (x+y == 15);
+ print(x+y);
+}
diff --git a/Test/dafny4/Bug94.dfy.expect b/Test/dafny4/Bug94.dfy.expect
new file mode 100644
index 00000000..6b337d5a
--- /dev/null
+++ b/Test/dafny4/Bug94.dfy.expect
@@ -0,0 +1,6 @@
+
+Dafny program verifier finished with 9 verified, 0 errors
+Program compiled successfully
+Running...
+
+15 \ No newline at end of file
diff --git a/Test/dafny4/Bug99.dfy b/Test/dafny4/Bug99.dfy
new file mode 100644
index 00000000..3f95ce9f
--- /dev/null
+++ b/Test/dafny4/Bug99.dfy
@@ -0,0 +1,11 @@
+// RUN: %dafny /autoTriggers:1 /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+predicate P(e:int, p:int) { true }
+predicate Q(i:int, t:int)
+
+lemma Tester(x:int)
+{
+ assert forall i :: Q(i, x) ==> (forall p {:trigger P(i, p)} :: P(i, p));
+
+}
diff --git a/Test/dafny4/Bug99.dfy.expect b/Test/dafny4/Bug99.dfy.expect
new file mode 100644
index 00000000..73ba063c
--- /dev/null
+++ b/Test/dafny4/Bug99.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 4 verified, 0 errors
diff --git a/Test/dafny4/Circ.dfy b/Test/dafny4/Circ.dfy
index e7609195..d110c05c 100644
--- a/Test/dafny4/Circ.dfy
+++ b/Test/dafny4/Circ.dfy
@@ -16,6 +16,7 @@ function zip(a: Stream, b: Stream): Stream { Cons(a.head, zip(b, a.tail)) }
colemma BlinkZipProperty()
ensures zip(zeros(), ones()) == blink();
{
+ BlinkZipProperty();
}
// ----- Thue-Morse sequence -----
@@ -75,6 +76,7 @@ colemma FProperty(s: Stream<Bit>)
// def. zip
Cons(s.head, Cons(not(s).head, zip(s.tail, not(s).tail)));
}
+ FProperty(s.tail);
}
// The fix-point theorem now follows easily.
diff --git a/Test/dafny4/CoqArt-InsertionSort.dfy b/Test/dafny4/CoqArt-InsertionSort.dfy
index efd01537..99e0f0b1 100644
--- a/Test/dafny4/CoqArt-InsertionSort.dfy
+++ b/Test/dafny4/CoqArt-InsertionSort.dfy
@@ -151,6 +151,7 @@ lemma existence_proof(l: List<int>)
{
match l {
case Nil =>
+ assert sorted(Nil);
case Cons(x, m) =>
existence_proof(m);
var m' :| equiv(m, m') && sorted(m');
diff --git a/Test/dafny4/FlyingRobots.dfy b/Test/dafny4/FlyingRobots.dfy
new file mode 100644
index 00000000..c80d310d
--- /dev/null
+++ b/Test/dafny4/FlyingRobots.dfy
@@ -0,0 +1,285 @@
+// RUN: %dafny /compile:3 /dprint:"%t.dprint" /autoTriggers:1 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// The flying robots examples from an F* tutorial. It demonstrates how to specify
+// mutable data structures in the heap.
+
+class Cell {
+ var val:int
+ constructor (v:int)
+ modifies this
+ ensures val == v
+ {
+ val := v;
+ }
+}
+
+class Point {
+ ghost var Value: (int, int, int)
+
+ ghost var Repr: set<object>
+ predicate Valid()
+ reads this, Repr
+ {
+ this in Repr && null !in Repr &&
+ {x,y,z} <= Repr &&
+ x != y && y != z && z != x &&
+ Value == (x.val, y.val, z.val)
+ }
+
+ var x:Cell, y:Cell, z:Cell
+
+ constructor (a:int, b:int, c:int)
+ modifies this
+ ensures Valid() && fresh(Repr - {this})
+ ensures Value == (a, b, c)
+ {
+ x := new Cell(a);
+ y := new Cell(b);
+ z := new Cell(c);
+ Repr := {this};
+ Repr := Repr + {x, y, z};
+ Value := (a, b, c);
+ }
+
+ method Mutate(a:int, b:int, c:int)
+ requires Valid()
+ modifies Repr
+ ensures Valid() && fresh(Repr - old(Repr))
+ ensures Value == (a, b, c)
+ {
+ x.val, y.val, z.val := a, b, c;
+ Value := (a, b, c);
+ }
+}
+
+class Arm {
+ ghost var Value: (int, int)
+
+ ghost var Repr: set<object>
+ predicate Valid()
+ reads this, Repr
+ {
+ this in Repr && null !in Repr &&
+ {polar, azim} <= Repr &&
+ polar != azim &&
+ Value == (polar.val, azim.val)
+ }
+
+ var polar:Cell
+ var azim:Cell
+
+ constructor (polar_in:int, azim_in:int)
+ modifies this
+ ensures Valid() && fresh(Repr - {this})
+ ensures Value == (polar_in, azim_in)
+ {
+ polar := new Cell(polar_in);
+ azim := new Cell(azim_in);
+ Repr := {this};
+ Repr := Repr + {polar, azim};
+ Value := (polar_in, azim_in);
+ }
+
+ method Mutate(polar_in:int, azim_in:int)
+ requires Valid()
+ modifies Repr
+ ensures Valid() && fresh(Repr - old(Repr))
+ ensures Value == (polar_in, azim_in)
+ {
+ polar.val, azim.val := polar_in, azim_in;
+ Value := (polar_in, azim_in);
+ }
+}
+
+class Bot {
+ ghost var Repr: set<object>
+ predicate {:opaque} Valid()
+ reads this, Repr
+ ensures Valid() ==> this in Repr && null !in Repr
+ {
+ this in Repr && null !in Repr &&
+ pos in Repr && {left, right} <= Repr &&
+ left != right &&
+ pos.Repr <= Repr && left.Repr <= Repr && right.Repr <= Repr &&
+ pos.Repr !! left.Repr !! right.Repr &&
+ pos.Valid() && left.Valid() && right.Valid()
+ }
+
+ var pos:Point
+ var left:Arm
+ var right:Arm
+
+ constructor ()
+ modifies this
+ ensures Valid() && fresh(Repr - {this})
+ {
+ pos := new Point(0, 0, 0);
+ left := new Arm(0, 0);
+ right := new Arm(0, 0);
+ Repr := {this};
+ Repr := Repr + pos.Repr + left.Repr + right.Repr;
+ reveal_Valid();
+ }
+
+ predicate flying()
+ requires (reveal_Valid(); Valid())
+ reads Repr
+ {
+ pos.z.val > 0
+ }
+
+ predicate arms_up()
+ requires (reveal_Valid(); Valid())
+ reads Repr
+ {
+ left.polar.val == right.polar.val == 0
+ }
+
+ predicate robot_inv()
+ requires (reveal_Valid(); Valid())
+ reads Repr
+ {
+ flying() ==> arms_up()
+ }
+
+ method Fly()
+ requires Valid()
+ modifies Repr
+ ensures Valid() && fresh(Repr - old(Repr))
+ ensures robot_inv() && flying()
+ {
+ reveal_Valid();
+ left.polar.val, right.polar.val := 0, 0;
+ pos.z.val := 100;
+ right.azim.val := 17;
+ pos.Value := (pos.Value.0, pos.Value.1, 100);
+ left.Value, right.Value := (0, left.Value.1), (0, 17);
+ reveal_Valid();
+ }
+}
+
+// This method tests that Fly operates independently on disjoint robots
+method FlyRobots(b0:Bot, b1:Bot)
+ requires b0 != null && b0.Valid()
+ requires b1 != null && b1.Valid()
+ requires b0 != b1 ==> b0.Repr !! b1.Repr
+ modifies b0.Repr, b1.Repr
+ ensures b0.Valid() && fresh(b0.Repr - old(b0.Repr))
+ ensures b1.Valid() && fresh(b1.Repr - old(b1.Repr))
+ ensures b0 != b1 ==> b0.Repr !! b1.Repr
+ ensures b0.robot_inv() && b1.robot_inv()
+ ensures b0.flying() && b1.flying()
+{
+ b0.Fly();
+ b1.Fly();
+}
+
+// ----- robot armies ----------
+
+// The union of .Repr for the robots in "bots"
+function ArmyRepr(bots:seq<Bot>) : set<object>
+ reads set b | b in bots
+{
+ set b,o | b in bots && b != null && o in b.Repr :: o
+}
+
+// An army is a sequence of disjoint, valid robots
+predicate ValidArmy(bots:seq<Bot>)
+ reads set b | b in bots
+ reads ArmyRepr(bots)
+{
+ (forall i :: 0 <= i < |bots| ==> bots[i] != null && bots[i].Valid())
+ && (forall i,j :: 0 <= i < j < |bots| ==> bots[i].Repr !! bots[j].Repr)
+}
+
+method FlyRobotArmy(bots:seq<Bot>)
+ requires ValidArmy(bots)
+ modifies ArmyRepr(bots)
+ ensures ValidArmy(bots) && fresh(ArmyRepr(bots) - old(ArmyRepr(bots)))
+ ensures forall b :: b in bots ==> b.Valid() && b.robot_inv() && b.flying()
+{
+ if * {
+ // fly recursively
+ FlyRobotArmy_Recursively(bots);
+ } else {
+ // fly iteratively
+ var n := 0;
+ while n < |bots|
+ invariant 0 <= n <= |bots|
+ invariant ValidArmy(bots)
+ invariant forall j :: 0 <= j < n ==> bots[j].Valid() && bots[j].robot_inv() && bots[j].flying()
+ invariant forall i :: 0 <= i < |bots| ==> fresh(bots[i].Repr - old(bots[i].Repr))
+ {
+ FlyOne(bots, n);
+ n := n + 1;
+ }
+ }
+}
+
+method FlyRobotArmy_Recursively(bots:seq<Bot>)
+ requires ValidArmy(bots)
+ modifies ArmyRepr(bots)
+ ensures ValidArmy(bots)
+ ensures forall i :: 0 <= i < |bots| ==> fresh(bots[i].Repr - old(bots[i].Repr))
+ ensures forall b :: b in bots ==> b.robot_inv() && b.flying()
+{
+ if bots != [] {
+ FlyOne(bots, 0);
+ FlyRobotArmy_Recursively(bots[1..]);
+ }
+}
+
+// This method is intended to be called in each loop iteration of FlyRobotArmy
+method FlyOne(bots:seq<Bot>, n:int)
+ requires 0 <= n < |bots|
+ requires forall j :: 0 <= j < |bots| ==> bots[j] != null && bots[j].Valid()
+ requires forall i,j :: 0 <= i < j < |bots| ==> bots[i].Repr !! bots[j].Repr
+ requires forall j :: 0 <= j < n ==> bots[j].robot_inv() && bots[j].flying()
+ modifies bots[n].Repr
+ ensures forall j :: 0 <= j < |bots| ==> bots[j].Valid()
+ ensures fresh(bots[n].Repr - old(bots[n].Repr))
+ ensures bots[n].robot_inv() && bots[n].flying()
+ ensures forall j :: 0 <= j < |bots| && j != n ==> bots[j].Repr == old(bots[j].Repr)
+ ensures forall j :: 0 <= j < n ==> bots[j].robot_inv() && bots[j].flying()
+{
+ bots[n].Fly();
+}
+
+// This method makes sure FlyRobotArmy is callable and callable again
+method FormArmy(b0:Bot, b1:Bot, b2:Bot)
+ requires null !in {b0, b1, b2}
+ requires b0.Valid() && b1.Valid() && b2.Valid()
+ requires b0.Repr !! b1.Repr !! b2.Repr
+ modifies b0.Repr, b1.Repr, b2.Repr
+ ensures b0.Valid() && b1.Valid() && b2.Valid()
+ ensures b0.Repr !! b1.Repr !! b2.Repr
+ ensures fresh(b0.Repr + b1.Repr + b2.Repr - old(b0.Repr + b1.Repr + b2.Repr))
+{
+ var army := [b0, b1, b2];
+ ArmyRepr3(army);
+ FlyRobotArmy(army);
+ FlyRobotArmy(army); // do it again
+ ArmyRepr3(army);
+}
+
+lemma ArmyRepr3(army:seq<Bot>)
+ requires null !in army && |army| == 3
+ ensures ArmyRepr(army) == army[0].Repr + army[1].Repr + army[2].Repr
+{
+}
+
+// ----- Make sure everything is callable ----------
+
+method Main()
+{
+ var b0 := new Bot();
+ var b1 := new Bot();
+ FlyRobots(b0, b1);
+ FlyRobots(b0, b1);
+ FlyRobots(b1, b0);
+
+ var b2 := new Bot();
+ FormArmy(b0, b1, b2);
+ FormArmy(b2, b0, b1);
+}
diff --git a/Test/dafny4/FlyingRobots.dfy.expect b/Test/dafny4/FlyingRobots.dfy.expect
new file mode 100644
index 00000000..99cdc3cb
--- /dev/null
+++ b/Test/dafny4/FlyingRobots.dfy.expect
@@ -0,0 +1,5 @@
+
+Dafny program verifier finished with 37 verified, 0 errors
+Program compiled successfully
+Running...
+
diff --git a/Test/dafny4/Fstar-QuickSort.dfy b/Test/dafny4/Fstar-QuickSort.dfy
index 4c5bc09b..d895ccf4 100644
--- a/Test/dafny4/Fstar-QuickSort.dfy
+++ b/Test/dafny4/Fstar-QuickSort.dfy
@@ -6,8 +6,6 @@
// Dafny needs help with a couple of lemmas in places where F* does not need them.
// Comments below show differences between the F* and Dafny versions.
-datatype Pair<T, U> = P(T, U)
-
datatype List<T> = Nil | Cons(T, List)
function length(list: List): nat // for termination proof
@@ -26,7 +24,7 @@ function In(x: int, list: List<int>): nat
}
predicate SortedRange(m: int, n: int, list: List<int>)
- decreases list; // for termination proof
+ decreases list // for termination proof
{
match list
case Nil => m <= n
@@ -34,45 +32,45 @@ predicate SortedRange(m: int, n: int, list: List<int>)
}
function append(n0: int, n1: int, n2: int, n3: int, i: List<int>, j: List<int>): List<int>
- requires n0 <= n1 <= n2 <= n3;
- requires SortedRange(n0, n1, i) && SortedRange(n2, n3, j);
- ensures SortedRange(n0, n3, append(n0, n1, n2, n3, i, j));
- ensures forall x :: In(x, append(n0, n1, n2, n3, i, j)) == In(x, i) + In(x, j);
- decreases i; // for termination proof
+ requires n0 <= n1 <= n2 <= n3
+ requires SortedRange(n0, n1, i) && SortedRange(n2, n3, j)
+ ensures SortedRange(n0, n3, append(n0, n1, n2, n3, i, j))
+ ensures forall x :: In(x, append(n0, n1, n2, n3, i, j)) == In(x, i) + In(x, j)
+ decreases i // for termination proof
{
match i
case Nil => j
case Cons(hd, tl) => Cons(hd, append(hd, n1, n2, n3, tl, j))
}
-function partition(x: int, l: List<int>): Pair<List<int>, List<int>>
- ensures var P(lo, hi) := partition(x, l);
+function partition(x: int, l: List<int>): (List<int>, List<int>)
+ ensures var (lo, hi) := partition(x, l);
(forall y :: In(y, lo) == if y <= x then In(y, l) else 0) &&
(forall y :: In(y, hi) == if x < y then In(y, l) else 0) &&
- length(l) == length(lo) + length(hi); // for termination proof
+ length(l) == length(lo) + length(hi) // for termination proof
{
match l
- case Nil => P(Nil, Nil)
+ case Nil => (Nil, Nil)
case Cons(hd, tl) =>
- var P(lo, hi) := partition(x, tl);
+ var (lo, hi) := partition(x, tl);
if hd <= x then
- P(Cons(hd, lo), hi)
+ (Cons(hd, lo), hi)
else
- P(lo, Cons(hd, hi))
+ (lo, Cons(hd, hi))
}
function sort(min: int, max: int, i: List<int>): List<int>
- requires min <= max;
- requires forall x :: In(x, i) != 0 ==> min <= x <= max;
- ensures SortedRange(min, max, sort(min, max, i));
- ensures forall x :: In(x, i) == In(x, sort(min, max, i));
- decreases length(i); // for termination proof
+ requires min <= max
+ requires forall x :: In(x, i) != 0 ==> min <= x <= max
+ ensures SortedRange(min, max, sort(min, max, i))
+ ensures forall x :: In(x, i) == In(x, sort(min, max, i))
+ decreases length(i) // for termination proof
{
match i
case Nil => Nil
case Cons(hd, tl) =>
assert In(hd, i) != 0; // this proof line not needed in F*
- var P(lo, hi) := partition(hd, tl);
+ var (lo, hi) := partition(hd, tl);
assert forall y :: In(y, lo) <= In(y, i); // this proof line not needed in F*
var i' := sort(min, hd, lo);
var j' := sort(hd, max, hi);
diff --git a/Test/dafny4/GHC-MergeSort.dfy b/Test/dafny4/GHC-MergeSort.dfy
index e06773eb..24903d87 100644
--- a/Test/dafny4/GHC-MergeSort.dfy
+++ b/Test/dafny4/GHC-MergeSort.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// Rustan Leino
@@ -412,11 +412,8 @@ lemma sorted_replaceSuffix(xs: List<G>, ys: List<G>, zs: List<G>)
match xs {
case Nil =>
case Cons(c, xs') =>
- forall a,b | a in multiset_of(xs') && b in multiset_of(Cons(c, zs))
- ensures Below(a, b);
- {
- sorted_reverse(xs', Cons(c, ys));
- }
+ sorted_reverse(xs, ys);
+ sorted_reverse(xs', Cons(c, ys));
sorted_replaceSuffix(xs', Cons(c, ys), Cons(c, zs));
}
}
diff --git a/Test/dafny4/KozenSilva.dfy b/Test/dafny4/KozenSilva.dfy
index af0cdc71..ef49b10f 100644
--- a/Test/dafny4/KozenSilva.dfy
+++ b/Test/dafny4/KozenSilva.dfy
@@ -25,8 +25,8 @@ copredicate LexLess(s: Stream<int>, t: Stream<int>)
// A co-lemma is used to establish the truth of a co-predicate.
colemma Theorem1_LexLess_Is_Transitive(s: Stream<int>, t: Stream<int>, u: Stream<int>)
- requires LexLess(s, t) && LexLess(t, u);
- ensures LexLess(s, u);
+ requires LexLess(s, t) && LexLess(t, u)
+ ensures LexLess(s, u)
{
// Here is the proof, which is actually a body of code. It lends itself to a
// simple, intuitive co-inductive reading. For a theorem this simple, this simple
@@ -38,6 +38,14 @@ colemma Theorem1_LexLess_Is_Transitive(s: Stream<int>, t: Stream<int>, u: Stream
}
}
+// Actually, Dafny can do the proof of the previous lemma completely automatically. Here it is:
+colemma Theorem1_LexLess_Is_Transitive_Automatic(s: Stream<int>, t: Stream<int>, u: Stream<int>)
+ requires LexLess(s, t) && LexLess(t, u)
+ ensures LexLess(s, u)
+{
+ // no manual proof needed, so the body of the co-lemma is empty
+}
+
// The following predicate captures the (inductively defined) negation of (the
// co-inductively defined) LexLess above.
predicate NotLexLess(s: Stream<int>, t: Stream<int>)
@@ -51,7 +59,7 @@ predicate NotLexLess'(k: nat, s: Stream<int>, t: Stream<int>)
}
lemma EquivalenceTheorem(s: Stream<int>, t: Stream<int>)
- ensures LexLess(s, t) <==> !NotLexLess(s, t);
+ ensures LexLess(s, t) <==> !NotLexLess(s, t)
{
if !NotLexLess(s, t) {
EquivalenceTheorem0(s, t);
@@ -61,8 +69,8 @@ lemma EquivalenceTheorem(s: Stream<int>, t: Stream<int>)
}
}
colemma EquivalenceTheorem0(s: Stream<int>, t: Stream<int>)
- requires !NotLexLess(s, t);
- ensures LexLess(s, t);
+ requires !NotLexLess(s, t)
+ ensures LexLess(s, t)
{
// Here, more needs to be said about the way Dafny handles co-lemmas.
// The way a co-lemma establishes a co-predicate is to prove, by induction,
@@ -74,14 +82,14 @@ colemma EquivalenceTheorem0(s: Stream<int>, t: Stream<int>)
// indicates a finite unrolling of a co-inductive predicate. In particular,
// LexLess#[k] refers to k unrollings of LexLess.
lemma EquivalenceTheorem0_Lemma(k: nat, s: Stream<int>, t: Stream<int>)
- requires !NotLexLess'(k, s, t);
- ensures LexLess#[k](s, t);
+ requires !NotLexLess'(k, s, t)
+ ensures LexLess#[k](s, t)
{
// This simple inductive proof is done completely automatically by Dafny.
}
lemma EquivalenceTheorem1(s: Stream<int>, t: Stream<int>)
- requires LexLess(s, t);
- ensures !NotLexLess(s, t);
+ requires LexLess(s, t)
+ ensures !NotLexLess(s, t)
{
// The forall statement in Dafny is used, here, as universal introduction:
// what EquivalenceTheorem1_Lemma establishes for one k, the forall
@@ -91,22 +99,22 @@ lemma EquivalenceTheorem1(s: Stream<int>, t: Stream<int>)
}
}
lemma EquivalenceTheorem1_Lemma(k: nat, s: Stream<int>, t: Stream<int>)
- requires LexLess(s, t);
- ensures !NotLexLess'(k, s, t);
+ requires LexLess(s, t)
+ ensures !NotLexLess'(k, s, t)
{
}
lemma Theorem1_Alt(s: Stream<int>, t: Stream<int>, u: Stream<int>)
- requires NotLexLess(s, u);
- ensures NotLexLess(s, t) || NotLexLess(t, u);
+ requires NotLexLess(s, u)
+ ensures NotLexLess(s, t) || NotLexLess(t, u)
{
forall k: nat | NotLexLess'(k, s, u) {
Theorem1_Alt_Lemma(k, s, t, u);
}
}
lemma Theorem1_Alt_Lemma(k: nat, s: Stream<int>, t: Stream<int>, u: Stream<int>)
- requires NotLexLess'(k, s, u);
- ensures NotLexLess'(k, s, t) || NotLexLess'(k, t, u);
+ requires NotLexLess'(k, s, u)
+ ensures NotLexLess'(k, s, t) || NotLexLess'(k, t, u)
{
}
@@ -116,8 +124,8 @@ function PointwiseAdd(s: Stream<int>, t: Stream<int>): Stream<int>
}
colemma Theorem2_Pointwise_Addition_Is_Monotone(s: Stream<int>, t: Stream<int>, u: Stream<int>, v: Stream<int>)
- requires LexLess(s, t) && LexLess(u, v);
- ensures LexLess(PointwiseAdd(s, u), PointwiseAdd(t, v));
+ requires LexLess(s, t) && LexLess(u, v)
+ ensures LexLess(PointwiseAdd(s, u), PointwiseAdd(t, v))
{
// The co-lemma will establish the co-inductive predicate by establishing
// all finite unrollings thereof. Each finite unrolling is proved by
@@ -148,15 +156,9 @@ copredicate Subtype(a: RecType, b: RecType)
}
colemma Theorem3_Subtype_Is_Transitive(a: RecType, b: RecType, c: RecType)
- requires Subtype(a, b) && Subtype(b, c);
- ensures Subtype(a, c);
-{
- if a == Bottom || c == Top {
- // done
- } else {
- Theorem3_Subtype_Is_Transitive(c.dom, b.dom, a.dom);
- Theorem3_Subtype_Is_Transitive(a.ran, b.ran, c.ran);
- }
+ requires Subtype(a, b) && Subtype(b, c)
+ ensures Subtype(a, c)
+{
}
// --------------------------------------------------------------------------
@@ -184,16 +186,16 @@ copredicate ValBelow(u: Val, v: Val)
}
colemma Theorem4a_ClEnvBelow_Is_Transitive(c: ClEnv, d: ClEnv, e: ClEnv)
- requires ClEnvBelow(c, d) && ClEnvBelow(d, e);
- ensures ClEnvBelow(c, e);
+ requires ClEnvBelow(c, d) && ClEnvBelow(d, e)
+ ensures ClEnvBelow(c, e)
{
forall y | y in c.m {
Theorem4b_ValBelow_Is_Transitive#[_k-1](c.m[y], d.m[y], e.m[y]);
}
}
colemma Theorem4b_ValBelow_Is_Transitive(u: Val, v: Val, w: Val)
- requires ValBelow(u, v) && ValBelow(v, w);
- ensures ValBelow(u, w);
+ requires ValBelow(u, v) && ValBelow(v, w)
+ ensures ValBelow(u, w)
{
if u.ValCl? {
Theorem4a_ClEnvBelow_Is_Transitive(u.cl.env, v.cl.env, w.cl.env);
@@ -209,7 +211,7 @@ predicate IsCapsule(cap: Capsule)
}
function ClosureConversion(cap: Capsule): Cl
- requires IsCapsule(cap);
+ requires IsCapsule(cap)
{
Closure(cap.e.abs, ClosureConvertedMap(cap.s))
// In the Kozen and Silva paper, there are more conditions, having to do with free variables,
@@ -229,8 +231,8 @@ predicate CapsuleEnvironmentBelow(s: map<Var, ConstOrAbs>, t: map<Var, ConstOrAb
}
colemma Theorem5_ClosureConversion_Is_Monotone(s: map<Var, ConstOrAbs>, t: map<Var, ConstOrAbs>)
- requires CapsuleEnvironmentBelow(s, t);
- ensures ClEnvBelow(ClosureConvertedMap(s), ClosureConvertedMap(t));
+ requires CapsuleEnvironmentBelow(s, t)
+ ensures ClEnvBelow(ClosureConvertedMap(s), ClosureConvertedMap(t))
{
}
@@ -251,8 +253,8 @@ copredicate Bisim(s: Stream, t: Stream)
}
colemma Theorem6_Bisim_Is_Symmetric(s: Stream, t: Stream)
- requires Bisim(s, t);
- ensures Bisim(t, s);
+ requires Bisim(s, t)
+ ensures Bisim(t, s)
{
// proof is automatic
}
@@ -270,8 +272,8 @@ function merge(s: Stream, t: Stream): Stream
// In general, the termination argument needs to be supplied explicitly in terms
// of a metric, rank, variant function, or whatever you want to call it--a
// "decreases" clause in Dafny. Dafny provides some help in making up "decreases"
-// clauses, and in this case it automatically adds "decreases 0;" to SplitLeft
-// and "decreases 1;" to SplitRight. With these "decreases" clauses, the
+// clauses, and in this case it automatically adds "decreases 0" to SplitLeft
+// and "decreases 1" to SplitRight. With these "decreases" clauses, the
// termination check of SplitRight's call to SplitLeft will simply be "0 < 1",
// which is trivial to check.
function SplitLeft(s: Stream): Stream
@@ -284,7 +286,7 @@ function SplitRight(s: Stream): Stream
}
colemma Theorem7_Merge_Is_Left_Inverse_Of_Split_Bisim(s: Stream)
- ensures Bisim(merge(SplitLeft(s), SplitRight(s)), s);
+ ensures Bisim(merge(SplitLeft(s), SplitRight(s)), s)
{
var LHS := merge(SplitLeft(s), SplitRight(s));
// The construct that follows is a "calc" statement. It gives a way to write an
@@ -318,7 +320,7 @@ colemma Theorem7_Merge_Is_Left_Inverse_Of_Split_Bisim(s: Stream)
}
colemma Theorem7_Merge_Is_Left_Inverse_Of_Split_Equal(s: Stream)
- ensures merge(SplitLeft(s), SplitRight(s)) == s;
+ ensures merge(SplitLeft(s), SplitRight(s)) == s
{
// The proof of this co-lemma is actually done completely automatically (so the
// body of this co-lemma can be empty). However, just to show what the calculations
diff --git a/Test/dafny4/KozenSilva.dfy.expect b/Test/dafny4/KozenSilva.dfy.expect
index c6c90498..90432af3 100644
--- a/Test/dafny4/KozenSilva.dfy.expect
+++ b/Test/dafny4/KozenSilva.dfy.expect
@@ -1,2 +1,2 @@
-Dafny program verifier finished with 47 verified, 0 errors
+Dafny program verifier finished with 49 verified, 0 errors
diff --git a/Test/dafny4/LargeConstants.dfy b/Test/dafny4/LargeConstants.dfy
new file mode 100644
index 00000000..18435c30
--- /dev/null
+++ b/Test/dafny4/LargeConstants.dfy
@@ -0,0 +1,14 @@
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+lemma largeIsLarge()
+ ensures 0x8000000000000000 > 0 {
+}
+
+lemma SmallIsSmall()
+ ensures -0x8000000000000000 < 0 {
+}
+
+lemma ShouldCancelOut()
+ ensures -0x8000000000000000 + 0x8000000000000000 == 0 {
+}
diff --git a/Test/dafny4/LargeConstants.dfy.expect b/Test/dafny4/LargeConstants.dfy.expect
new file mode 100644
index 00000000..4ef2de53
--- /dev/null
+++ b/Test/dafny4/LargeConstants.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 6 verified, 0 errors
diff --git a/Test/dafny4/Leq.dfy b/Test/dafny4/Leq.dfy
new file mode 100644
index 00000000..0491dd00
--- /dev/null
+++ b/Test/dafny4/Leq.dfy
@@ -0,0 +1,174 @@
+// RUN: %dafny /rprint:"%t.rprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// Rustan Leino, 22 Sep 2015.
+// This file considers two definitions of Leq on naturals+infinity. One
+// definition uses the least fixpoint, the other the greatest fixpoint.
+
+// Nat represents natural numbers extended with infinity
+codatatype Nat = Z | S(pred: Nat)
+
+function Num(n: nat): Nat
+{
+ if n == 0 then Z else S(Num(n-1))
+}
+
+predicate IsFinite(a: Nat)
+{
+ exists m:nat :: a == Num(m)
+}
+
+copredicate IsInfinity(a: Nat)
+{
+ a.S? && IsInfinity(a.pred)
+}
+
+lemma NatCases(a: Nat)
+ ensures IsFinite(a) || IsInfinity(a)
+{
+ if IsFinite(a) {
+ } else {
+ NatCasesAux(a);
+ }
+}
+colemma NatCasesAux(a: Nat)
+ requires !IsFinite(a)
+ ensures IsInfinity(a)
+{
+ assert a != Num(0);
+ if IsFinite(a.pred) {
+ // going for a contradiction
+ var m:nat :| a.pred == Num(m);
+ assert a == Num(m+1);
+ assert false; // the case is absurd
+ }
+ NatCasesAux(a.pred);
+}
+
+// ----------- inductive semantics (more precisely, a least-fixpoint definition of Leq)
+
+inductive predicate Leq(a: Nat, b: Nat)
+{
+ a == Z ||
+ (a.S? && b.S? && Leq(a.pred, b.pred))
+}
+
+lemma LeqTheorem(a: Nat, b: Nat)
+ ensures Leq(a, b) <==>
+ exists m:nat :: a == Num(m) &&
+ (IsInfinity(b) || exists n:nat :: b == Num(n) && m <= n)
+{
+ if exists m:nat,n:nat :: a == Num(m) && b == Num(n) && m <= n {
+ var m:nat,n:nat :| a == Num(m) && b == Num(n) && m <= n;
+ Leq0_finite(m, n);
+ }
+ if (exists m:nat :: a == Num(m)) && IsInfinity(b) {
+ var m:nat :| a == Num(m);
+ Leq0_infinite(m, b);
+ }
+ if Leq(a, b) {
+ var k:nat :| Leq#[k](a, b);
+ var m, n := Leq1(k, a, b);
+ }
+}
+
+lemma Leq0_finite(m: nat, n: nat)
+ requires m <= n
+ ensures Leq(Num(m), Num(n))
+{
+ // proof is automatic
+}
+
+lemma Leq0_infinite(m: nat, b: Nat)
+ requires IsInfinity(b)
+ ensures Leq(Num(m), b)
+{
+ // proof is automatic
+}
+
+lemma Leq1(k: nat, a: Nat, b: Nat) returns (m: nat, n: nat)
+ requires Leq#[k](a, b)
+ ensures a == Num(m)
+ ensures IsInfinity(b) || (b == Num(n) && m <= n)
+{
+ if a == Z {
+ m := 0;
+ NatCases(b);
+ if !IsInfinity(b) {
+ n :| b == Num(n);
+ }
+ } else {
+ assert a.S? && b.S? && Leq(a.pred, b.pred);
+ m,n := Leq1(k-1, a.pred, b.pred);
+ m, n := m + 1, n + 1;
+ }
+}
+
+// ----------- co-inductive semantics (more precisely, a greatest-fixpoint definition of Leq)
+
+copredicate CoLeq(a: Nat, b: Nat)
+{
+ a == Z ||
+ (a.S? && b.S? && CoLeq(a.pred, b.pred))
+}
+
+lemma CoLeqTheorem(a: Nat, b: Nat)
+ ensures CoLeq(a, b) <==>
+ IsInfinity(b) ||
+ exists m:nat,n:nat :: a == Num(m) && b == Num(n) && m <= n
+{
+ if IsInfinity(b) {
+ CoLeq0_infinite(a, b);
+ }
+ if exists m:nat,n:nat :: a == Num(m) && b == Num(n) && m <= n {
+ var m:nat,n:nat :| a == Num(m) && b == Num(n) && m <= n;
+ CoLeq0_finite(m, n);
+ }
+ if CoLeq(a, b) {
+ CoLeq1(a, b);
+ }
+}
+
+lemma CoLeq0_finite(m: nat, n: nat)
+ requires m <= n
+ ensures CoLeq(Num(m), Num(n))
+{
+ // proof is automatic
+}
+
+colemma CoLeq0_infinite(a: Nat, b: Nat)
+ requires IsInfinity(b)
+ ensures CoLeq(a, b)
+{
+ // proof is automatic
+}
+
+lemma CoLeq1(a: Nat, b: Nat)
+ requires CoLeq(a, b)
+ ensures IsInfinity(b) || exists m:nat,n:nat :: a == Num(m) && b == Num(n) && m <= n
+{
+ var m,n := CoLeq1'(a, b);
+}
+
+lemma CoLeq1'(a: Nat, b: Nat) returns (m: nat, n: nat)
+ requires CoLeq(a, b)
+ ensures IsInfinity(b) || (a == Num(m) && b == Num(n) && m <= n)
+{
+ if !IsInfinity(b) {
+ NatCases(b);
+ n :| b == Num(n);
+ m := CoLeq1Aux(a, n);
+ }
+}
+
+lemma CoLeq1Aux(a: Nat, n: nat) returns (m: nat)
+ requires CoLeq(a, Num(n))
+ ensures a == Num(m) && m <= n
+{
+ if a == Z {
+ m := 0;
+ } else {
+ m := CoLeq1Aux(a.pred, n-1);
+ m := m + 1;
+ }
+}
diff --git a/Test/dafny4/Leq.dfy.expect b/Test/dafny4/Leq.dfy.expect
new file mode 100644
index 00000000..754c1e55
--- /dev/null
+++ b/Test/dafny4/Leq.dfy.expect
@@ -0,0 +1,3 @@
+
+Dafny program verifier finished with 29 verified, 0 errors
+Compiled assembly into Leq.dll
diff --git a/Test/dafny4/McCarthy91.dfy b/Test/dafny4/McCarthy91.dfy
new file mode 100644
index 00000000..2e599f0d
--- /dev/null
+++ b/Test/dafny4/McCarthy91.dfy
@@ -0,0 +1,86 @@
+// RUN: %dafny /compile:3 /rprint:"%t.rprint" /autoTriggers:1 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+// The usual recursive method for computing McCarthy's 91 function
+
+method Main() {
+ var s := [3, 99, 100, 101, 1013];
+
+ var n := 0;
+ while n < |s| {
+ var m := M(s[n]);
+ print "M(", s[n], ") = ", m, "\n";
+ n := n + 1;
+ }
+
+ n := 0;
+ while n < |s| {
+ print "mc91(", s[n], ") = ", mc91(s[n]), "\n";
+ n := n + 1;
+ }
+
+ n := 0;
+ while n < |s| {
+ var m := Mc91(s[n]);
+ print "Mc91(", s[n], ") = ", m, "\n";
+ n := n + 1;
+ }
+
+ n := 0;
+ while n < 5 {
+ var m := iter(n, mc91, 40);
+ print "iter(", n, ", mc91, 40) = ", m, "\n";
+ n := n + 1;
+ }
+}
+
+method M(n: int) returns (r: int)
+ ensures r == if n <= 100 then 91 else n - 10
+ decreases 100 - n
+{
+ if n <= 100 {
+ r := M(n + 11);
+ r := M(r);
+ } else {
+ r := n - 10;
+ }
+}
+
+// Same as above, but as a function
+
+function method mc91(n: int): int
+ ensures n <= 100 ==> mc91(n) == 91
+ decreases 100 - n
+{
+ if n <= 100 then
+ mc91(mc91(n + 11))
+ else
+ n - 10
+}
+
+// Iterating a function f e times starting from n
+
+function method iter(e: nat, f: int -> int, n: int): int
+ requires forall x :: f.requires(x) && f.reads(x) == {}
+{
+ if e == 0 then n else iter(e-1, f, f(n))
+}
+
+// Iterative version of McCarthy's 91 function, following in lockstep
+// what the recursive version would do
+
+method Mc91(n0: int) returns (r: int)
+ ensures r == mc91(n0)
+{
+ var e, n := 1, n0;
+ while e > 0
+ invariant iter(e, mc91, n) == mc91(n0)
+ decreases 100 - n + 10 * e, e
+ {
+ if n <= 100 {
+ e, n := e+1, n+11;
+ } else {
+ e, n := e-1, n-10;
+ }
+ }
+ return n;
+}
diff --git a/Test/dafny4/McCarthy91.dfy.expect b/Test/dafny4/McCarthy91.dfy.expect
new file mode 100644
index 00000000..bbc91c35
--- /dev/null
+++ b/Test/dafny4/McCarthy91.dfy.expect
@@ -0,0 +1,25 @@
+
+Dafny program verifier finished with 8 verified, 0 errors
+Program compiled successfully
+Running...
+
+M(3) = 91
+M(99) = 91
+M(100) = 91
+M(101) = 91
+M(1013) = 1003
+mc91(3) = 91
+mc91(99) = 91
+mc91(100) = 91
+mc91(101) = 91
+mc91(1013) = 1003
+Mc91(3) = 91
+Mc91(99) = 91
+Mc91(100) = 91
+Mc91(101) = 91
+Mc91(1013) = 1003
+iter(0, mc91, 40) = 40
+iter(1, mc91, 40) = 91
+iter(2, mc91, 40) = 91
+iter(3, mc91, 40) = 91
+iter(4, mc91, 40) = 91
diff --git a/Test/dafny4/MonadicLaws.dfy b/Test/dafny4/MonadicLaws.dfy
new file mode 100644
index 00000000..b668ffb8
--- /dev/null
+++ b/Test/dafny4/MonadicLaws.dfy
@@ -0,0 +1,100 @@
+// RUN: %dafny /compile:0 /rprint:"%t.rprint" /autoTriggers:1 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// Monadic Laws
+// Niki Vazou and Rustan Leino
+// 28 March 2016
+
+datatype List<T> = Nil | Cons(head: T, tail: List)
+
+predicate Total<T,U>(p: T -> U)
+ reads p.reads
+{
+ forall x :: p.reads(x) == {} && p.requires(x)
+}
+
+function append(xs: List, ys: List): List
+{
+ match xs
+ case Nil => ys
+ case Cons(x, xs') => Cons(x, append(xs', ys))
+}
+
+lemma AppendNil(xs: List)
+ ensures append(xs, Nil) == xs
+{
+}
+
+lemma AppendAssoc(xs: List, ys: List, zs: List)
+ ensures append(append(xs, ys), zs) == append(xs, append(ys, zs));
+{
+}
+
+function Return<T>(a: T): List
+{
+ Cons(a, Nil)
+}
+
+function Bind<T,U>(xs: List<T>, f: T -> List<U>): List<U>
+ requires Total(f)
+{
+ match xs
+ case Nil => Nil
+ case Cons(x, xs') => append(f(x), Bind(xs', f))
+}
+
+lemma LeftIdentity<T>(a: T, f: T -> List)
+ requires Total(f)
+ ensures Bind(Return(a), f) == f(a)
+{
+ AppendNil(f(a));
+}
+
+lemma RightIdentity<T>(m: List)
+ ensures Bind(m, Return) == m
+{
+ match m
+ case Nil =>
+ assert Bind<T,T>(Nil, Return) == Nil;
+ case Cons(x, m') =>
+ calc {
+ Bind(Cons(x, m'), Return);
+ append(Return(x), Bind(m', Return));
+ Cons(x, Bind(m', Return));
+ }
+}
+
+lemma Associativity<T>(m: List, f: T -> List, g: T -> List)
+ requires Total(f) && Total(g)
+ ensures Bind(Bind(m, f), g) == Bind(m, x => Bind(f(x), g))
+{
+ match m
+ case Nil =>
+ assert Bind(m, x => Bind(f(x), g)) == Nil;
+ case Cons(x, xs) =>
+ match f(x)
+ case Nil =>
+ calc {
+ Bind(xs, y => Bind(f(y), g));
+ Bind(Cons(x, xs), y => Bind(f(y), g));
+ }
+ case Cons(y, ys) =>
+ calc {
+ append(g(y), Bind(append(ys, Bind(xs, f)), g));
+ { BindOverAppend(ys, Bind(xs, f), g); }
+ append(g(y), append(Bind(ys, g), Bind(Bind(xs, f), g)));
+ { AppendAssoc(g(y), Bind(ys, g), Bind(Bind(xs, f), g)); }
+ append(append(g(y), Bind(ys, g)), Bind(Bind(xs, f), g));
+ Bind(Cons(x, xs), z => Bind(f(z), g));
+ }
+}
+
+lemma BindOverAppend<T>(xs: List, ys: List, g: T -> List)
+ requires Total(g)
+ ensures Bind(append(xs, ys), g) == append(Bind(xs, g), Bind(ys, g))
+{
+ match xs
+ case Nil =>
+ case Cons(x, xs') =>
+ AppendAssoc(g(x), Bind(xs', g), Bind(ys, g));
+}
diff --git a/Test/dafny4/MonadicLaws.dfy.expect b/Test/dafny4/MonadicLaws.dfy.expect
new file mode 100644
index 00000000..d903c7c5
--- /dev/null
+++ b/Test/dafny4/MonadicLaws.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 16 verified, 0 errors
diff --git a/Test/dafny4/NipkowKlein-chapter3.dfy b/Test/dafny4/NipkowKlein-chapter3.dfy
index 6572359a..3de6a5fc 100644
--- a/Test/dafny4/NipkowKlein-chapter3.dfy
+++ b/Test/dafny4/NipkowKlein-chapter3.dfy
@@ -18,7 +18,7 @@ function append(xs: List, ys: List): List
// ----- arithmetic expressions -----
type vname = string // variable names
-datatype aexp = N(n: int) | V(x: vname) | Plus(0: aexp, 1: aexp) // arithmetic expressions
+datatype aexp = N(n: int) | V(vname) | Plus(aexp, aexp) // arithmetic expressions
type val = int
type state = vname -> val
@@ -131,9 +131,15 @@ lemma AsimpCorrect(a: aexp, s: state)
forall a' | a' < a { AsimpCorrect(a', s); }
}
+// The following lemma is not in the Nipkow and Klein book, but it's a fun one to prove.
+lemma ASimplInvolutive(a: aexp)
+ ensures asimp(asimp(a)) == asimp(a)
+{
+}
+
// ----- boolean expressions -----
-datatype bexp = Bc(v: bool) | Not(op: bexp) | And(0: bexp, 1: bexp) | Less(a0: aexp, a1: aexp)
+datatype bexp = Bc(v: bool) | Not(bexp) | And(bexp, bexp) | Less(aexp, aexp)
function bval(b: bexp, s: state): bool
reads s.reads
@@ -189,9 +195,12 @@ lemma BsimpCorrect(b: bexp, s: state)
ensures bval(bsimp(b), s) == bval(b, s)
{
/* Here is one proof, which uses the induction hypothesis any anything smaller than b and also invokes
- the lemma AsimpCorrect on anything smaller than b.
+ the lemma AsimpCorrect on every arithmetic expression.
forall b' | b' < b { BsimpCorrect(b', s); }
- forall a' | a' < b { AsimpCorrect(a', s); }
+ forall a { AsimpCorrect(a, s); }
+ Yet another possibility is to mark the lemma with {:induction b} and to use the following line in
+ the body:
+ forall a { AsimpCorrect(a, s); }
*/
// Here is another proof, which makes explicit the uses of the induction hypothesis and the other lemma.
match b
diff --git a/Test/dafny4/NipkowKlein-chapter3.dfy.expect b/Test/dafny4/NipkowKlein-chapter3.dfy.expect
index ab18d98e..bb45fee9 100644
--- a/Test/dafny4/NipkowKlein-chapter3.dfy.expect
+++ b/Test/dafny4/NipkowKlein-chapter3.dfy.expect
@@ -1,2 +1,2 @@
-Dafny program verifier finished with 28 verified, 0 errors
+Dafny program verifier finished with 30 verified, 0 errors
diff --git a/Test/dafny4/NipkowKlein-chapter7.dfy b/Test/dafny4/NipkowKlein-chapter7.dfy
index 33be9dd6..0c089895 100644
--- a/Test/dafny4/NipkowKlein-chapter7.dfy
+++ b/Test/dafny4/NipkowKlein-chapter7.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /rprint:"%t.rprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /rprint:"%t.rprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// This file is a Dafny encoding of chapter 7 from "Concrete Semantics: With Isabelle/HOL" by
@@ -10,25 +10,19 @@ datatype List<T> = Nil | Cons(head: T, tail: List<T>)
type vname = string // variable names
type val = int
-type state = imap<vname, val>
-predicate Total(s: state)
-{
- forall x :: x in s
-}
+type state = map<vname, val>
datatype aexp = N(n: int) | V(x: vname) | Plus(0: aexp, 1: aexp) // arithmetic expressions
function aval(a: aexp, s: state): val
- requires Total(s)
{
match a
case N(n) => n
- case V(x) => s[x]
+ case V(x) => if x in s then s[x] else 0
case Plus(a0, a1) => aval(a0,s ) + aval(a1, s)
}
datatype bexp = Bc(v: bool) | Not(op: bexp) | And(0: bexp, 1: bexp) | Less(a0: aexp, a1: aexp)
function bval(b: bexp, s: state): bool
- requires Total(s)
{
match b
case Bc(v) => v
@@ -44,7 +38,6 @@ datatype com = SKIP | Assign(vname, aexp) | Seq(com, com) | If(bexp, com, com) |
// ----- Big-step semantics -----
inductive predicate big_step(c: com, s: state, t: state)
- requires Total(s)
{
match c
case SKIP =>
@@ -53,7 +46,6 @@ inductive predicate big_step(c: com, s: state, t: state)
t == s[x := aval(a, s)]
case Seq(c0, c1) =>
exists s' ::
- Total(s') &&
big_step(c0, s, s') &&
big_step(c1, s', t)
case If(b, thn, els) =>
@@ -61,13 +53,11 @@ inductive predicate big_step(c: com, s: state, t: state)
case While(b, body) =>
(!bval(b, s) && s == t) ||
(bval(b, s) && exists s' ::
- Total(s') &&
big_step(body, s, s') &&
big_step(While(b, body), s', t))
}
lemma Example1(s: state, t: state)
- requires Total(s)
requires t == s["x" := 5]["y" := 5]
ensures big_step(Seq(Assign("x", N(5)), Assign("y", V("x"))), s, t)
{
@@ -83,29 +73,13 @@ lemma Example1(s: state, t: state)
}
lemma SemiAssociativity(c0: com, c1: com, c2: com, s: state, t: state)
- requires Total(s)
ensures big_step(Seq(Seq(c0, c1), c2), s, t) == big_step(Seq(c0, Seq(c1, c2)), s, t)
{
- calc {
- big_step(Seq(Seq(c0, c1), c2), s, t);
- // def. big_step
- exists s'' :: Total(s'') && big_step(Seq(c0, c1), s, s'') && big_step(c2, s'', t);
- // def. big_step
- exists s'' :: Total(s'') && (exists s' :: Total(s') && big_step(c0, s, s') && big_step(c1, s', s'')) && big_step(c2, s'', t);
- // logic
- exists s', s'' :: Total(s') && Total(s'') && big_step(c0, s, s') && big_step(c1, s', s'') && big_step(c2, s'', t);
- // logic
- exists s' :: Total(s') && big_step(c0, s, s') && exists s'' :: Total(s'') && big_step(c1, s', s'') && big_step(c2, s'', t);
- // def. big_step
- exists s' :: Total(s') && big_step(c0, s, s') && big_step(Seq(c1, c2), s', t);
- // def. big_step
- big_step(Seq(c0, Seq(c1, c2)), s, t);
- }
}
predicate equiv_c(c: com, c': com)
{
- forall s,t :: Total(s) ==> big_step(c, s, t) == big_step(c', s, t)
+ forall s,t :: big_step(c, s, t) == big_step(c', s, t)
}
lemma lemma_7_3(b: bexp, c: com)
@@ -122,7 +96,7 @@ lemma lemma_7_5(b: bexp, c: com, c': com)
requires equiv_c(c, c')
ensures equiv_c(While(b, c), While(b, c'))
{
- forall s,t | Total(s)
+ forall s,t
ensures big_step(While(b, c), s, t) == big_step(While(b, c'), s, t)
{
if big_step(While(b, c), s, t) {
@@ -135,15 +109,9 @@ lemma lemma_7_5(b: bexp, c: com, c': com)
}
inductive lemma lemma_7_6(b: bexp, c: com, c': com, s: state, t: state)
- requires Total(s) && big_step(While(b, c), s, t) && equiv_c(c, c')
+ requires big_step(While(b, c), s, t) && equiv_c(c, c')
ensures big_step(While(b, c'), s, t)
{
- if !bval(b, s) {
- // trivial
- } else {
- var s' :| Total(s') && big_step#[_k-1](c, s, s') && big_step#[_k-1](While(b, c), s', t);
- lemma_7_6(b, c, c', s', t); // induction hypothesis
- }
}
// equiv_c is an equivalence relation
@@ -161,36 +129,15 @@ lemma equiv_c_transitive(c: com, c': com, c'': com)
}
inductive lemma IMP_is_deterministic(c: com, s: state, t: state, t': state)
- requires Total(s) && big_step(c, s, t) && big_step(c, s, t')
+ requires big_step(c, s, t) && big_step(c, s, t')
ensures t == t'
{
- match c
- case SKIP =>
- // trivial
- case Assign(x, a) =>
- // trivial
- case Seq(c0, c1) =>
- var s' :| Total(s') && big_step#[_k-1](c0, s, s') && big_step#[_k-1](c1, s', t);
- var s'' :| Total(s'') && big_step#[_k-1](c0, s, s'') && big_step#[_k-1](c1, s'', t');
- IMP_is_deterministic(c0, s, s', s'');
- IMP_is_deterministic(c1, s', t, t');
- case If(b, thn, els) =>
- IMP_is_deterministic(if bval(b, s) then thn else els, s, t, t');
- case While(b, body) =>
- if !bval(b, s) {
- // trivial
- } else {
- var s' :| Total(s') && big_step#[_k-1](body, s, s') && big_step#[_k-1](While(b, body), s', t);
- var s'' :| Total(s'') && big_step#[_k-1](body, s, s'') && big_step#[_k-1](While(b, body), s'', t');
- IMP_is_deterministic(body, s, s', s'');
- IMP_is_deterministic(While(b, body), s', t, t');
- }
+ // Dafny totally rocks!
}
// ----- Small-step semantics -----
inductive predicate small_step(c: com, s: state, c': com, s': state)
- requires Total(s)
{
match c
case SKIP => false
@@ -206,7 +153,6 @@ inductive predicate small_step(c: com, s: state, c': com, s': state)
}
inductive lemma SmallStep_is_deterministic(cs: (com, state), cs': (com, state), cs'': (com, state))
- requires Total(cs.1)
requires small_step(cs.0, cs.1, cs'.0, cs'.1)
requires small_step(cs.0, cs.1, cs''.0, cs''.1)
ensures cs' == cs''
@@ -216,100 +162,59 @@ inductive lemma SmallStep_is_deterministic(cs: (com, state), cs': (com, state),
case Seq(c0, c1) =>
if c0 == SKIP {
} else {
- var c0' :| cs'.0 == Seq(c0', c1) && small_step#[_k-1](c0, cs.1, c0', cs'.1);
- var c0'' :| cs''.0 == Seq(c0'', c1) && small_step#[_k-1](c0, cs.1, c0'', cs''.1);
+ var c0' :| cs'.0 == Seq(c0', c1) && small_step(c0, cs.1, c0', cs'.1);
+ var c0'' :| cs''.0 == Seq(c0'', c1) && small_step(c0, cs.1, c0'', cs''.1);
SmallStep_is_deterministic((c0, cs.1), (c0', cs'.1), (c0'', cs''.1));
}
case If(b, thn, els) =>
case While(b, body) =>
}
-inductive lemma small_step_ends_in_Total_state(c: com, s: state, c': com, s': state)
- requires Total(s) && small_step(c, s, c', s')
- ensures Total(s')
-{
- match c
- case Assign(x, a) =>
- case Seq(c0, c1) =>
- if c0 != SKIP {
- var c0' :| c' == Seq(c0', c1) && small_step(c0, s, c0', s');
- small_step_ends_in_Total_state(c0, s, c0', s');
- }
- case If(b, thn, els) =>
- case While(b, body) =>
-}
-
inductive predicate small_step_star(c: com, s: state, c': com, s': state)
- requires Total(s)
{
(c == c' && s == s') ||
exists c'', s'' ::
- small_step(c, s, c'', s'') &&
- (small_step_ends_in_Total_state(c, s, c'', s''); small_step_star(c'', s'', c', s'))
-}
-
-inductive lemma small_step_star_ends_in_Total_state(c: com, s: state, c': com, s': state)
- requires Total(s) && small_step_star(c, s, c', s')
- ensures Total(s')
-{
- if c == c' && s == s' {
- } else {
- var c'', s'' :| small_step(c, s, c'', s'') &&
- (small_step_ends_in_Total_state(c, s, c'', s''); small_step_star#[_k-1](c'', s'', c', s'));
- small_step_star_ends_in_Total_state(c'', s'', c', s');
- }
+ small_step(c, s, c'', s'') && small_step_star(c'', s'', c', s')
}
lemma star_transitive(c0: com, s0: state, c1: com, s1: state, c2: com, s2: state)
- requires Total(s0) && Total(s1)
requires small_step_star(c0, s0, c1, s1) && small_step_star(c1, s1, c2, s2)
ensures small_step_star(c0, s0, c2, s2)
{
star_transitive_aux(c0, s0, c1, s1, c2, s2);
}
inductive lemma star_transitive_aux(c0: com, s0: state, c1: com, s1: state, c2: com, s2: state)
- requires Total(s0) && Total(s1)
requires small_step_star(c0, s0, c1, s1)
ensures small_step_star(c1, s1, c2, s2) ==> small_step_star(c0, s0, c2, s2)
{
- if c0 == c1 && s0 == s1 {
- } else {
- var c', s' :|
- small_step(c0, s0, c', s') &&
- (small_step_ends_in_Total_state(c0, s0, c', s'); small_step_star#[_k-1](c', s', c1, s1));
- star_transitive_aux(c', s', c1, s1, c2, s2);
- }
}
// The big-step semantics can be simulated by some number of small steps
inductive lemma BigStep_implies_SmallStepStar(c: com, s: state, t: state)
- requires Total(s) && big_step(c, s, t)
+ requires big_step(c, s, t)
ensures small_step_star(c, s, SKIP, t)
{
match c
case SKIP =>
// trivial
case Assign(x, a) =>
- assert t == s[x := aval(a, s)];
- assert small_step(c, s, SKIP, t);
assert small_step_star(SKIP, t, SKIP, t);
case Seq(c0, c1) =>
- var s' :| Total(s') && big_step#[_k-1](c0, s, s') && big_step#[_k-1](c1, s', t);
+ var s' :| big_step(c0, s, s') && big_step(c1, s', t);
calc <== {
small_step_star(c, s, SKIP, t);
{ star_transitive(Seq(c0, c1), s, Seq(SKIP, c1), s', SKIP, t); }
small_step_star(Seq(c0, c1), s, Seq(SKIP, c1), s') && small_step_star(Seq(SKIP, c1), s', SKIP, t);
{ lemma_7_13(c0, s, SKIP, s', c1); }
small_step_star(c0, s, SKIP, s') && small_step_star(Seq(SKIP, c1), s', SKIP, t);
- { BigStep_implies_SmallStepStar(c0, s, s'); }
+ //{ BigStep_implies_SmallStepStar(c0, s, s'); }
small_step_star(Seq(SKIP, c1), s', SKIP, t);
{ assert small_step(Seq(SKIP, c1), s', c1, s'); }
small_step_star(c1, s', SKIP, t);
- { BigStep_implies_SmallStepStar(c1, s', t); }
+ //{ BigStep_implies_SmallStepStar(c1, s', t); }
true;
}
case If(b, thn, els) =>
- BigStep_implies_SmallStepStar(if bval(b, s) then thn else els, s, t);
case While(b, body) =>
if !bval(b, s) && s == t {
calc <== {
@@ -321,7 +226,7 @@ inductive lemma BigStep_implies_SmallStepStar(c: com, s: state, t: state)
true;
}
} else {
- var s' :| Total(s') && big_step#[_k-1](body, s, s') && big_step#[_k-1](While(b, body), s', t);
+ var s' :| big_step(body, s, s') && big_step(While(b, body), s', t);
calc <== {
small_step_star(c, s, SKIP, t);
{ assert small_step(c, s, If(b, Seq(body, While(b, body)), SKIP), s); }
@@ -332,41 +237,40 @@ inductive lemma BigStep_implies_SmallStepStar(c: com, s: state, t: state)
small_step_star(Seq(body, While(b, body)), s, Seq(SKIP, While(b, body)), s') && small_step_star(Seq(SKIP, While(b, body)), s', SKIP, t);
{ lemma_7_13(body, s, SKIP, s', While(b, body)); }
small_step_star(body, s, SKIP, s') && small_step_star(Seq(SKIP, While(b, body)), s', SKIP, t);
- { BigStep_implies_SmallStepStar(body, s, s'); }
+ //{ BigStep_implies_SmallStepStar(body, s, s'); }
small_step_star(Seq(SKIP, While(b, body)), s', SKIP, t);
{ assert small_step(Seq(SKIP, While(b, body)), s', While(b, body), s'); }
small_step_star(While(b, body), s', SKIP, t);
- { BigStep_implies_SmallStepStar(While(b, body), s', t); }
+ //{ BigStep_implies_SmallStepStar(While(b, body), s', t); }
true;
}
}
}
inductive lemma lemma_7_13(c0: com, s0: state, c: com, t: state, c1: com)
- requires Total(s0) && small_step_star(c0, s0, c, t)
+ requires small_step_star(c0, s0, c, t)
ensures small_step_star(Seq(c0, c1), s0, Seq(c, c1), t)
{
if c0 == c && s0 == t {
} else {
- var c', s' :| small_step(c0, s0, c', s') && (small_step_ends_in_Total_state(c0, s0, c', s'); small_step_star#[_k-1](c', s', c, t));
+ var c', s' :| small_step(c0, s0, c', s') && small_step_star(c', s', c, t);
lemma_7_13(c', s', c, t, c1);
}
}
inductive lemma SmallStepStar_implies_BigStep(c: com, s: state, t: state)
- requires Total(s) && small_step_star(c, s, SKIP, t)
+ requires small_step_star(c, s, SKIP, t)
ensures big_step(c, s, t)
{
if c == SKIP && s == t {
} else {
- var c', s' :| small_step(c, s, c', s') && (small_step_ends_in_Total_state(c, s, c', s'); small_step_star#[_k-1](c', s', SKIP, t));
- SmallStepStar_implies_BigStep(c', s', t);
+ var c', s' :| small_step(c, s, c', s') && small_step_star(c', s', SKIP, t);
SmallStep_plus_BigStep(c, s, c', s', t);
}
}
inductive lemma SmallStep_plus_BigStep(c: com, s: state, c': com, s': state, t: state)
- requires Total(s) && Total(s') && small_step(c, s, c', s')
+ requires small_step(c, s, c', s')
ensures big_step(c', s', t) ==> big_step(c, s, t)
{
match c
@@ -376,9 +280,7 @@ inductive lemma SmallStep_plus_BigStep(c: com, s: state, c': com, s': state, t:
} else {
var c0' :| c' == Seq(c0', c1) && small_step(c0, s, c0', s');
if big_step(c', s', t) {
- var k: nat :| big_step#[k](Seq(c0', c1), s', t);
- var s'' :| Total(s'') && big_step(c0', s', s'') && big_step(c1, s'', t);
- SmallStep_plus_BigStep(c0, s, c0', s', s'');
+ var s'' :| big_step(c0', s', s'') && big_step(c1, s'', t);
}
}
case If(b, thn, els) =>
@@ -391,7 +293,6 @@ inductive lemma SmallStep_plus_BigStep(c: com, s: state, c': com, s': state, t:
// big-step and small-step semantics agree
lemma BigStep_SmallStepStar_Same(c: com, s: state, t: state)
- requires Total(s)
ensures big_step(c, s, t) <==> small_step_star(c, s, SKIP, t)
{
if big_step(c, s, t) {
@@ -403,14 +304,12 @@ lemma BigStep_SmallStepStar_Same(c: com, s: state, t: state)
}
predicate final(c: com, s: state)
- requires Total(s)
{
!exists c',s' :: small_step(c, s, c', s')
}
// lemma 7.17:
lemma final_is_skip(c: com, s: state)
- requires Total(s)
ensures final(c, s) <==> c == SKIP
{
if c == SKIP {
@@ -420,7 +319,7 @@ lemma final_is_skip(c: com, s: state)
}
}
lemma only_skip_has_no_next_state(c: com, s: state) returns (c': com, s': state)
- requires Total(s) && c != SKIP
+ requires c != SKIP
ensures small_step(c, s, c', s')
{
match c
@@ -441,15 +340,12 @@ lemma only_skip_has_no_next_state(c: com, s: state) returns (c': com, s': state)
}
lemma lemma_7_18(c: com, s: state)
- requires Total(s)
ensures (exists t :: big_step(c, s, t)) <==>
- (exists c',s' :: small_step_star(c, s, c', s') &&
- (small_step_star_ends_in_Total_state(c, s, c', s'); final(c', s')))
+ (exists c',s' :: small_step_star(c, s, c', s') && final(c', s'))
{
if exists t :: big_step(c, s, t) {
var t :| big_step(c, s, t);
BigStep_SmallStepStar_Same(c, s, t);
- small_step_star_ends_in_Total_state(c, s, SKIP, t);
calc ==> {
true;
big_step(c, s, t);
@@ -458,11 +354,11 @@ lemma lemma_7_18(c: com, s: state)
small_step_star(c, s, SKIP, t) && final(SKIP, t);
}
}
- if exists c',s' :: small_step_star(c, s, c', s') &&
- (small_step_star_ends_in_Total_state(c, s, c', s'); final(c', s')) {
- var c',s' :| small_step_star(c, s, c', s') &&
- (small_step_star_ends_in_Total_state(c, s, c', s'); final(c', s'));
+ if exists c',s' :: small_step_star(c, s, c', s') && final(c', s') {
+ var c',s' :| small_step_star(c, s, c', s') && final(c', s');
final_is_skip(c', s');
BigStep_SmallStepStar_Same(c, s, s');
}
}
+
+// Autotriggers:0 added as this file relies on proving a property of the form body(f) == f
diff --git a/Test/dafny4/NipkowKlein-chapter7.dfy.expect b/Test/dafny4/NipkowKlein-chapter7.dfy.expect
index e08b3632..90432af3 100644
--- a/Test/dafny4/NipkowKlein-chapter7.dfy.expect
+++ b/Test/dafny4/NipkowKlein-chapter7.dfy.expect
@@ -1,2 +1,2 @@
-Dafny program verifier finished with 54 verified, 0 errors
+Dafny program verifier finished with 49 verified, 0 errors
diff --git a/Test/dafny4/NumberRepresentations.dfy b/Test/dafny4/NumberRepresentations.dfy
index 1ebdf64c..c15f4987 100644
--- a/Test/dafny4/NumberRepresentations.dfy
+++ b/Test/dafny4/NumberRepresentations.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
// We consider a number representation that consists of a sequence of digits. The least
@@ -234,17 +234,16 @@ lemma UniqueRepresentation(a: seq<int>, b: seq<int>, lowDigit: int, base: nat)
}
lemma ZeroIsUnique(a: seq<int>, lowDigit: int, base: nat)
- requires 2 <= base && lowDigit <= 0 < lowDigit + base;
- requires a == trim(a);
- requires IsSkewNumber(a, lowDigit, base);
- requires eval(a, base) == 0;
- ensures a == [];
+ requires 2 <= base && lowDigit <= 0 < lowDigit + base
+ requires a == trim(a)
+ requires IsSkewNumber(a, lowDigit, base)
+ requires eval(a, base) == 0
+ ensures a == []
{
if a != [] {
- assert eval(a, base) == a[0] + base * eval(a[1..], base);
if eval(a[1..], base) == 0 {
TrimProperty(a);
- ZeroIsUnique(a[1..], lowDigit, base);
+ // ZeroIsUnique(a[1..], lowDigit, base);
}
assert false;
}
@@ -293,3 +292,7 @@ lemma MulInverse(x: int, a: int, b: int, y: int)
ensures a == b;
{
}
+
+// Local Variables:
+// dafny-prover-local-args: ("/vcsMaxKeepGoingSplits:5")
+// End:
diff --git a/Test/dafny4/Primes.dfy b/Test/dafny4/Primes.dfy
index 31e3a19b..0c2a64dd 100644
--- a/Test/dafny4/Primes.dfy
+++ b/Test/dafny4/Primes.dfy
@@ -1,9 +1,9 @@
-// RUN: %dafny /compile:0 /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
predicate IsPrime(n: int)
{
- 2 <= n && forall m :: 2 <= m < n ==> n % m != 0
+ 2 <= n && forall m {:nowarn} :: 2 <= m < n ==> n % m != 0 // WISH It would be great to think about the status of modulo as a trigger
}
// The following theorem shows that there is an infinite number of primes
@@ -110,6 +110,13 @@ lemma RemoveFactor(x: int, s: set<int>)
x * y * product(s - {y} - {x});
{ assert s - {y} - {x} == s - {x} - {y}; }
x * y * product(s - {x} - {y});
+ /* FIXME: This annotation wasn't needed before the introduction
+ * of auto-triggers. It's not needed if one adds {:no_trigger}
+ * to the forall y :: y in s ==> y <= x part of PickLargest, but that
+ * boils down to z3 picking $Box(...) as good trigger
+ */
+ // FIXME: the parens shouldn't be needed around (s - {x})
+ { assert y in (s - {x}); }
{ assert y == PickLargest(s - {x}); }
x * product(s - {x});
}
@@ -160,8 +167,8 @@ lemma Composite(c: int) returns (a: int, b: int)
calc {
true;
!IsPrime(c);
- !(2 <= c && forall m :: 2 <= m < c ==> c % m != 0);
- exists m :: 2 <= m < c && c % m == 0;
+ !(2 <= c && forall m {:nowarn} :: 2 <= m < c ==> c % m != 0);
+ exists m {:nowarn} :: 2 <= m < c && c % m == 0;
}
a :| 2 <= a < c && c % a == 0;
b := c / a;
@@ -187,7 +194,7 @@ lemma LargestElementExists(s: set<int>)
var s' := s;
while true
invariant s' != {} && s' <= s;
- invariant forall x,y :: x in s' && y in s - s' ==> y <= x;
+ invariant forall x,y {:nowarn} :: x in s' && y in s - s' ==> y <= x;
decreases s';
{
var x :| x in s'; // pick something
diff --git a/Test/dafny4/Regression0.dfy b/Test/dafny4/Regression0.dfy
new file mode 100644
index 00000000..666d9575
--- /dev/null
+++ b/Test/dafny4/Regression0.dfy
@@ -0,0 +1,13 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This once crashed Dafny
+
+method M() {
+ var s := [1, "2"]; // error: all elements must have the same type
+ if * {
+ assert exists n :: n in s && n != 1; // the type of n is inferred to be int
+ } else {
+ assert "2" in s; // error: since the type of s wasn't determined
+ }
+}
diff --git a/Test/dafny4/Regression0.dfy.expect b/Test/dafny4/Regression0.dfy.expect
new file mode 100644
index 00000000..566b3e3f
--- /dev/null
+++ b/Test/dafny4/Regression0.dfy.expect
@@ -0,0 +1,3 @@
+Regression0.dfy(7,15): Error: All elements of display must be of the same type (got string, but type of previous elements is int)
+Regression0.dfy(11,15): Error: second argument to "in" must be a set, multiset, or sequence with elements of type string, or a map with domain string (instead got ?)
+2 resolution/type errors detected in Regression0.dfy
diff --git a/Test/dafny4/Regression1.dfy b/Test/dafny4/Regression1.dfy
new file mode 100644
index 00000000..ebd8cf6d
--- /dev/null
+++ b/Test/dafny4/Regression1.dfy
@@ -0,0 +1,9 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+ghost method M() {
+ var x :=
+// In the following line, why are the range and term copied in Substitute?
+// var loo := 100; map y | 0 <= y < 100 :: y+1;
+ var loo := 100; imap y: int | true :: 3;
+}
diff --git a/Test/dafny4/Regression1.dfy.expect b/Test/dafny4/Regression1.dfy.expect
new file mode 100644
index 00000000..069e7767
--- /dev/null
+++ b/Test/dafny4/Regression1.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/dafny4/SoftwareFoundations-Basics.dfy.expect b/Test/dafny4/SoftwareFoundations-Basics.dfy.expect
index 0f9eb8d0..f07b068f 100644
--- a/Test/dafny4/SoftwareFoundations-Basics.dfy.expect
+++ b/Test/dafny4/SoftwareFoundations-Basics.dfy.expect
@@ -1,4 +1,4 @@
-SoftwareFoundations-Basics.dfy(41,12): Error: assertion violation
+SoftwareFoundations-Basics.dfy(41,11): Error: assertion violation
Execution trace:
(0,0): anon0
diff --git a/Test/dafny4/UnionFind.dfy b/Test/dafny4/UnionFind.dfy
new file mode 100644
index 00000000..6c4b4cfb
--- /dev/null
+++ b/Test/dafny4/UnionFind.dfy
@@ -0,0 +1,332 @@
+// RUN: %dafny /rprint:"%t.rprint" /autoTriggers:1 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+// Rustan Leino, Nov 2015
+
+// Module M0 gives the high-level specification of the UnionFind data structure
+abstract module M0 {
+ class Element { }
+
+ class {:autocontracts} UnionFind {
+ ghost var M: map<Element, Element>
+ protected predicate Valid()
+ reads this, Repr
+
+ constructor ()
+ ensures M == map[]
+ {
+ Repr, M:= {this}, map[];
+ }
+
+ method New() returns (e: Element)
+ ensures old(e !in M && forall e' :: e' in M ==> M[e'] != e)
+ ensures M == old(M)[e := e]
+
+ method Find(e: Element) returns (r: Element)
+ requires e in M
+ ensures M == old(M) && M[e] == r
+
+ method Union(e0: Element, e1: Element) returns (ghost r: Element)
+ requires e0 in M && e1 in M
+ ensures r in old(M) && old(M[r] == M[e0] || M[r] == M[e1])
+ ensures M == map e | e in old(M) :: old(if M[e] == M[e0] || M[e] == M[e1] then r else M[e])
+ }
+}
+
+// Module M1 gives the concrete data structure used in UnionFind, along with the invariant of
+// that data structure. It also implements the New method and, by declaring a new method Join,
+// the Union method.
+abstract module M1 refines M0 {
+ datatype Contents = Root(depth: nat) | Link(next: Element)
+ class Element {
+ var c: Contents
+ }
+
+ type CMap = map<Element, Contents>
+ predicate GoodCMap(C: CMap)
+ {
+ null !in C && forall f :: f in C && C[f].Link? ==> C[f].next in C
+ }
+
+ class UnionFind {
+ protected predicate Valid...
+ {
+ (forall e :: e in M ==> e in Repr && M[e] in M && M[M[e]] == M[e]) &&
+ (forall e :: e in M && e.c.Link? ==> e.c.next in M) &&
+ (forall e :: e in M ==> M[e].c.Root? && Reaches(M[e].c.depth, e, M[e], Collect()))
+ }
+
+ // This function returns a snapshot of the .c fields of the objects in the domain of M
+ function Collect(): CMap
+ requires null !in M && forall f :: f in M && f.c.Link? ==> f.c.next in M
+ reads this, set a | a in M
+ ensures GoodCMap(Collect())
+ {
+ map e | e in M :: e.c
+ }
+ predicate Reaches(d: nat, e: Element, r: Element, C: CMap)
+ requires GoodCMap(C)
+ requires e in C
+ {
+ match C[e]
+ case Root(_) => e == r
+ case Link(next) => d != 0 && Reaches(d-1, next, r, C)
+ }
+ lemma {:autocontracts false} Reaches_Monotonic(d: nat, e: Element, r: Element, C: CMap, C': CMap)
+ requires GoodCMap(C) && GoodCMap(C')
+ requires e in C
+ requires Reaches(d, e, r, C) && forall f :: f in C ==> f in C' && C[f] == C'[f]
+ ensures Reaches(d, e, r, C')
+ {
+ }
+
+ method New...
+ {
+ e := new Element;
+ e.c := Root(0);
+ Repr := Repr + {e};
+ M := M[e := e];
+ assert Reaches(0, e, e, Collect());
+ forall f | f in M
+ ensures M[f].c.Root? && Reaches(M[f].c.depth, f, M[f], Collect())
+ {
+ if f != e {
+ Reaches_Monotonic(M[f].c.depth, f, M[f], old(Collect()), Collect());
+ }
+ }
+ }
+
+ method Union...
+ {
+ var r0 := Find(e0);
+ var r1 := Find(e1);
+ r := Join(r0, r1);
+ }
+
+ method Join(r0: Element, r1: Element) returns (ghost r: Element)
+ requires r0 in M && r1 in M && M[r0] == r0 && M[r1] == r1
+ ensures r == r0 || r == r1
+ ensures M == map e | e in old(M) :: old(if M[e] == r0 || M[e] == r1 then r else M[e])
+ }
+
+ // stupid help lemma to get around boxing
+ lemma MapsEqual<D>(m: map<D, D>, n: map<D, D>)
+ requires forall d :: d in m <==> d in n;
+ requires forall d :: d in m ==> m[d] == n[d]
+ ensures m == n
+ {
+ }
+}
+
+// Module M2 adds the implementation of Find, together with the proofs needed for the verification.
+abstract module M2 refines M1 {
+ class UnionFind {
+ method Find...
+ {
+ r := FindAux(M[e].c.depth, e);
+ }
+
+ lemma NextReachesSame(e: Element)
+ requires e in M && e.c.Link?
+ ensures M[e] == M[e.c.next]
+ {
+ var next := e.c.next;
+ var d0, d1 := M[e].c.depth, M[next].c.depth;
+ assert Reaches(d0 - 1, next, M[e], Collect());
+ assert Reaches(d1, next, M[next], Collect());
+ Reaches_SinkIsFunctionOfStart(d0 - 1, d1, next, M[e], M[next], Collect());
+ }
+
+ lemma {:autocontracts false} Reaches_SinkIsFunctionOfStart(d0: nat, d1: nat, e: Element, r0: Element, r1: Element, C: CMap)
+ requires GoodCMap(C)
+ requires e in C
+ requires Reaches(d0, e, r0, C) && Reaches(d1, e, r1, C)
+ ensures r0 == r1
+ {
+ }
+
+ method FindAux(ghost d: nat, e: Element) returns (r: Element)
+ requires e in M && Reaches(d, e, M[e], Collect())
+ ensures M == old(M) && M[e] == r
+ ensures forall d: nat, e, r :: e in old(Collect()) && Reaches(d, e, r, old(Collect())) ==> Reaches(d, e, r, Collect())
+ {
+ match e.c
+ case Root(_) =>
+ r := e;
+ case Link(next) =>
+ NextReachesSame(e);
+ r := FindAux(d-1, next);
+ ghost var C := Collect(); // take a snapshot of all the .c fields
+ e.c := Link(r);
+ UpdateMaintainsReaches(d, e, r, C, Collect());
+ }
+
+ lemma {:autocontracts false} UpdateMaintainsReaches(td: nat, tt: Element, tm: Element, C: CMap, C': CMap)
+ requires GoodCMap(C)
+ requires tt in C && Reaches(td, tt, tm, C)
+ requires C' == C[tt := Link(tm)] && C'[tt].Link? && tm in C' && C'[tm].Root?
+ requires null !in C' && forall f :: f in C && C'[f].Link? ==> C'[f].next in C
+ ensures forall d: nat, e, r :: e in C && Reaches(d, e, r, C) ==> Reaches(d, e, r, C')
+ {
+ forall d: nat, e, r | e in C && Reaches(d, e, r, C)
+ ensures Reaches(d, e, r, C')
+ {
+ ConstructReach(d, e, r, C, td, tt, tm, C');
+ }
+ }
+
+ lemma {:autocontracts false} ConstructReach(d: nat, e: Element, r: Element, C: CMap, td: nat, tt: Element, tm: Element, C': CMap)
+ requires GoodCMap(C)
+ requires e in C
+ requires Reaches(d, e, r, C)
+ requires tt in C && Reaches(td, tt, tm, C);
+ requires C' == C[tt := Link(tm)] && C'[tt].Link? && tm in C' && C'[tm].Root?
+ requires GoodCMap(C')
+ ensures Reaches(d, e, r, C')
+ {
+ if e == tt {
+ Reaches_SinkIsFunctionOfStart(d, td, e, r, tm, C);
+ } else {
+ match C[e]
+ case Root(_) =>
+ case Link(next) =>
+ ConstructReach(d-1, next, r, C, td, tt, tm, C');
+ }
+ }
+ }
+}
+
+// Finally, module M3 adds the implementation of Join, along with what's required to
+// verify its correctness.
+module M3 refines M2 {
+ class UnionFind {
+ method Join...
+ {
+ if r0 == r1 {
+ r := r0;
+ MapsEqual(M, map e | e in M :: if M[e] == r0 || M[e] == r1 then r else M[e]);
+ return;
+ } else if r0.c.depth < r1.c.depth {
+ r0.c := Link(r1);
+ r := r1;
+ M := map e | e in M :: if M[e] == r0 || M[e] == r1 then r else M[e];
+ forall e | e in Collect()
+ ensures M[e].c.Root? && Reaches(M[e].c.depth, e, M[e], Collect())
+ {
+ JoinMaintainsReaches0(r0, r1, old(Collect()), Collect());
+ assert Reaches(old(M[e].c).depth, e, old(M)[e], old(Collect()));
+ }
+ } else if r1.c.depth < r0.c.depth {
+ r1.c := Link(r0);
+ r := r0;
+ M := map e | e in M :: if M[e] == r0 || M[e] == r1 then r else M[e];
+ forall e | e in Collect()
+ ensures M[e].c.Root? && Reaches(M[e].c.depth, e, M[e], Collect())
+ {
+ JoinMaintainsReaches0(r1, r0, old(Collect()), Collect());
+ assert Reaches(old(M[e].c).depth, e, old(M)[e], old(Collect()));
+ }
+ } else {
+ r0.c := Link(r1);
+ r1.c := Root(r1.c.depth + 1);
+ r := r1;
+ M := map e | e in M :: if M[e] == r0 || M[e] == r1 then r else M[e];
+ forall e | e in Collect()
+ ensures M[e].c.Root? && Reaches(M[e].c.depth, e, M[e], Collect())
+ {
+ JoinMaintainsReaches1(r0, r1, old(Collect()), Collect());
+ assert Reaches(old(M[e].c).depth, e, old(M)[e], old(Collect()));
+ }
+ }
+ }
+
+ lemma {:autocontracts false} JoinMaintainsReaches1(r0: Element, r1: Element, C: CMap, C': CMap)
+ requires GoodCMap(C)
+ requires r0 in C && r1 in C && C[r0].Root? && C[r1].Root? && C[r0].depth == C[r1].depth && r0 != r1
+ requires C' == C[r0 := Link(r1)][r1 := Root(C[r1].depth + 1)]
+ requires GoodCMap(C')
+ ensures forall d: nat, e, r :: e in C && Reaches(d, e, r, C) && r != r0 && r != r1 ==> Reaches(d, e, r, C') // proved automatically by induction
+ ensures forall e :: e in C && Reaches(C[r0].depth, e, r0, C) ==> Reaches(C'[r1].depth, e, r1, C')
+ ensures forall e :: e in C && Reaches(C[r1].depth, e, r1, C) ==> Reaches(C'[r1].depth, e, r1, C')
+ {
+ forall e | e in C && Reaches(C[r0].depth, e, r0, C)
+ ensures Reaches(C'[r1].depth, e, r1, C')
+ {
+ ExtendedReach'(e, C, C[r0].depth, C'[r1].depth, r0, r1, C');
+ }
+ forall e | e in C && Reaches(C[r1].depth, e, r1, C)
+ ensures Reaches(C'[r1].depth, e, r1, C')
+ {
+ ReachUnaffectedByChangeFromRoot'(C[r1].depth, e, r1, C, C[r0].depth, r0, r1, C');
+ }
+ }
+
+ lemma {:autocontracts false} ReachUnaffectedByChangeFromRoot'(d: nat, e: Element, r: Element, C: CMap, td: nat, r0: Element, r1: Element, C': CMap)
+ requires GoodCMap(C)
+ requires e in C && Reaches(d, e, r, C)
+ requires r0 in C && r1 in C && C[r0].Root? && C[r1].Root? && C[r0].depth == C[r1].depth && r0 != r1
+ requires C[r0].Root? && C' == C[r0 := Link(r1)][r1 := Root(C[r1].depth + 1)]
+ requires Reaches(td, r0, r0, C) && r0 != r
+ requires GoodCMap(C')
+ ensures Reaches(d+1, e, r, C')
+ {
+ }
+
+ lemma {:autocontracts false} ExtendedReach'(e: Element, C: CMap, d0: nat, d1: nat, r0: Element, r1: Element, C': CMap)
+ requires GoodCMap(C) && GoodCMap(C')
+ requires r0 in C && r1 in C && C[r0].Root? && C[r1].Root? && C[r0].depth == C[r1].depth && r0 != r1
+ requires C' == C[r0 := Link(r1)][r1 := Root(C[r1].depth + 1)]
+ requires C[r0].Root? && d0 <= C[r0].depth && C[r1].Root? && d1 <= C'[r1].depth && d0 < d1
+ requires e in C && Reaches(d0, e, r0, C)
+ ensures Reaches(d1, e, r1, C')
+ {
+ match C[e]
+ case Root(_) =>
+ case Link(next) =>
+ ExtendedReach'(next, C, d0-1, d1-1, r0, r1, C');
+ }
+
+ lemma {:autocontracts false} JoinMaintainsReaches0(r0: Element, r1: Element, C: CMap, C': CMap)
+ requires GoodCMap(C)
+ requires r0 in C && r1 in C && C[r0].Root? && C[r1].Root? && C[r0].depth < C[r1].depth
+ requires C' == C[r0 := Link(r1)]
+ requires GoodCMap(C')
+ ensures forall d: nat, e, r :: e in C && Reaches(d, e, r, C) && r != r0 ==> Reaches(d, e, r, C')
+ ensures forall e :: e in C && Reaches(C[r0].depth, e, r0, C) ==> Reaches(C[r1].depth, e, r1, C')
+ {
+ forall d: nat, e, r | e in C && Reaches(d, e, r, C) && r != r0
+ ensures Reaches(d, e, r, C')
+ {
+ ReachUnaffectedByChangeFromRoot(d, e, r, C, C[r0].depth, r0, r1, C');
+ }
+ forall e | e in C && Reaches(C[r0].depth, e, r0, C)
+ ensures Reaches(C[r1].depth, e, r1, C')
+ {
+ ExtendedReach(e, C, C[r0].depth, C[r1].depth, r0, r1, C');
+ }
+ }
+
+ lemma {:autocontracts false} ReachUnaffectedByChangeFromRoot(d: nat, e: Element, r: Element, C: CMap, td: nat, tt: Element, tm: Element, C': CMap)
+ requires GoodCMap(C)
+ requires e in C && Reaches(d, e, r, C)
+ requires tt in C && Reaches(td, tt, tt, C) && tt != r
+ requires C[tt].Root? && C' == C[tt := Link(tm)]
+ requires GoodCMap(C')
+ ensures Reaches(d, e, r, C')
+ {
+ }
+
+ lemma {:autocontracts false} ExtendedReach(e: Element, C: CMap, d0: nat, d1: nat, r0: Element, r1: Element, C': CMap)
+ requires GoodCMap(C) && GoodCMap(C')
+ requires r0 in C && r1 in C && r0 != r1
+ requires C' == C[r0 := Link(r1)]
+ requires C[r0].Root? && d0 <= C[r0].depth && C[r1].Root? && d1 <= C[r1].depth && d0 < d1
+ requires e in C && Reaches(d0, e, r0, C)
+ ensures Reaches(d1, e, r1, C')
+ {
+ match C[e]
+ case Root(_) =>
+ case Link(next) =>
+ ExtendedReach(next, C, d0-1, d1-1, r0, r1, C');
+ }
+ }
+}
diff --git a/Test/dafny4/UnionFind.dfy.expect b/Test/dafny4/UnionFind.dfy.expect
new file mode 100644
index 00000000..8c2a9667
--- /dev/null
+++ b/Test/dafny4/UnionFind.dfy.expect
@@ -0,0 +1,3 @@
+
+Dafny program verifier finished with 89 verified, 0 errors
+Compiled assembly into UnionFind.dll
diff --git a/Test/dafny4/set-compr.dfy b/Test/dafny4/set-compr.dfy
index 71a07f3d..d093a924 100644
--- a/Test/dafny4/set-compr.dfy
+++ b/Test/dafny4/set-compr.dfy
@@ -22,7 +22,7 @@ method O() returns (ghost p: set<object>)
method P() returns (p: set<object>)
{
- p := set o: object | true; // not allowed -- not in a ghost context
+ p := set o: object | true; // error: not (easily) compilable
}
ghost method Q() returns (p: set<object>)
@@ -30,26 +30,54 @@ ghost method Q() returns (p: set<object>)
p := set o: object | true; // allowed, since the whole method is ghost
}
-function F(): int
+function F(p: object): int
+ requires p in set o: object | true // error: function is not allowed to depend on allocation state
+ ensures p in set o: object | true // error: ditto (although one could argue that this would be okay)
+ reads set o: object | true // error: same as for 'requires'
+ decreases set o: object | true // error: same as for 'ensures'
+{
+ if p in set o: object | true then // error: function is not allowed to depend on allocation state
+ F(p)
+ else
+ 0
+}
+
+function method G(p: object): int
+ requires p in set o: object | true // error (see F)
+ ensures p in set o: object | true // error (see F)
+ reads set o: object | true // error (see F)
+ decreases set o: object | true // error (see F)
+{
+ if p in set o: object | true then // error (see F)
+ G(p)
+ else
+ 0
+}
+
+method M0() returns (ghost r: int, s: int)
requires null in set o: object | true // allowed
ensures null in set o: object | true // allowed
- reads set o: object | true // allowed
+ modifies set o: object | true // allowed
decreases set o: object | true // allowed
{
- if null in set o: object | true then // allowed -- in a ghost context
- F()
- else
- 0
+ if null in set o: object | true { // this makes the "if" a ghost
+ r := G(null);
+ s := G(null); // error: assignment of non-ghost not allowed inside ghost "if"
+ } else {
+ r := 0;
+ }
}
-function method G(): int
+method M1() returns (ghost r: int, s: int)
requires null in set o: object | true // (X) allowed
ensures null in set o: object | true // (X) allowed
- reads set o: object | true // allowed
+ modifies set o: object | true // allowed
decreases set o: object | true // (X) allowed
{
- if null in set o: object | true then // not allowed, since this is not a ghost context
- G()
- else
- 0
+ if null in set o: object | true { // this makes the "if" a ghost
+ r := G(null);
+ s := G(null); // error: assignment of non-ghost not allowed inside ghost "if"
+ } else {
+ r := 0;
+ }
}
diff --git a/Test/dafny4/set-compr.dfy.expect b/Test/dafny4/set-compr.dfy.expect
index b31c6ac0..b0490a11 100644
--- a/Test/dafny4/set-compr.dfy.expect
+++ b/Test/dafny4/set-compr.dfy.expect
@@ -1,3 +1,14 @@
-set-compr.dfy(25,7): Error: a set comprehension must produce a finite set, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'o'
-set-compr.dfy(51,13): Error: a set comprehension must produce a finite set, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'o'
-2 resolution/type errors detected in set-compr.dfy
+set-compr.dfy(25,7): Error: set comprehensions in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce or compile a bounded set of values for 'o'
+set-compr.dfy(34,16): Error: a set comprehension involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'o'
+set-compr.dfy(35,15): Error: a set comprehension involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'o'
+set-compr.dfy(36,8): Error: a set comprehension involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'o'
+set-compr.dfy(37,12): Error: a set comprehension involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'o'
+set-compr.dfy(39,10): Error: a set comprehension involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'o'
+set-compr.dfy(46,16): Error: a set comprehension involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'o'
+set-compr.dfy(47,15): Error: a set comprehension involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'o'
+set-compr.dfy(48,8): Error: a set comprehension involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'o'
+set-compr.dfy(49,12): Error: a set comprehension involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'o'
+set-compr.dfy(51,10): Error: a set comprehension involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'o'
+set-compr.dfy(65,6): Error: Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+set-compr.dfy(79,6): Error: Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+13 resolution/type errors detected in set-compr.dfy
diff --git a/Test/hofs/Apply.dfy.expect b/Test/hofs/Apply.dfy.expect
index 77d34c4c..0a923143 100644
--- a/Test/hofs/Apply.dfy.expect
+++ b/Test/hofs/Apply.dfy.expect
@@ -1,4 +1,4 @@
-Apply.dfy(27,16): Error: assertion violation
+Apply.dfy(27,15): Error: assertion violation
Execution trace:
(0,0): anon0
Apply.dfy(26,27): anon15_Else
diff --git a/Test/hofs/Classes.dfy b/Test/hofs/Classes.dfy
index 2b892b35..9d8044db 100644
--- a/Test/hofs/Classes.dfy
+++ b/Test/hofs/Classes.dfy
@@ -30,15 +30,14 @@ function B(t : T) : int -> int
}
function J(t : T) : int
- requires t != null;
- requires t.h.reads(0) == {};
- reads t;
- reads if t != null then t.h.reads(0) else {};
+ requires t != null
+ reads t
+ reads t.h.reads(0)
{
if t.h.requires(0) then
B(t)(0)
else
- B(t)(0) // fail
+ B(t)(0) // error: precondition violation
}
method U(t : T)
@@ -48,3 +47,20 @@ method U(t : T)
t.h := x => x;
assert J(t) == 0; // ok
}
+
+class MyClass {
+ var data: int
+ function method F(): int
+ reads this
+ {
+ data
+ }
+ method M(that: MyClass)
+ requires that != null
+ {
+ var fn := that.F; // "that" is captured into the closure
+ var d := fn();
+ assert d == that.data; // yes
+ assert d == this.data; // error: no reason to believe that this would hold
+ }
+}
diff --git a/Test/hofs/Classes.dfy.expect b/Test/hofs/Classes.dfy.expect
index 3c933bae..a5b33522 100644
--- a/Test/hofs/Classes.dfy.expect
+++ b/Test/hofs/Classes.dfy.expect
@@ -1,10 +1,10 @@
-Classes.dfy(41,6): Error: possible violation of function precondition
+Classes.dfy(64,11): Error: assertion violation
Execution trace:
(0,0): anon0
- (0,0): anon11_Then
- (0,0): anon3
- (0,0): anon12_Then
- (0,0): anon13_Else
- (0,0): anon14_Else
+Classes.dfy(40,5): Error: possible violation of function precondition
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Else
+ (0,0): anon8_Else
-Dafny program verifier finished with 6 verified, 1 error
+Dafny program verifier finished with 8 verified, 2 errors
diff --git a/Test/hofs/Examples.dfy b/Test/hofs/Examples.dfy
index be2672f5..306d278d 100644
--- a/Test/hofs/Examples.dfy
+++ b/Test/hofs/Examples.dfy
@@ -1,14 +1,14 @@
// RUN: %dafny /print:"%t.print" "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
-function Apply(f: A -> B, x: A): B
+function Apply<A,B>(f: A -> B, x: A): B
reads f.reads(x);
requires f.requires(x);
{
f(x)
}
-function Apply'(f: A -> B) : A -> B
+function Apply'<A,B>(f: A -> B) : A -> B
{
x reads f.reads(x)
requires f.requires(x)
@@ -16,7 +16,7 @@ function Apply'(f: A -> B) : A -> B
}
-function Compose(f: B -> C, g:A -> B): A -> C
+function Compose<A,B,C>(f: B -> C, g:A -> B): A -> C
{
x reads g.reads(x)
reads if g.requires(x) then f.reads(g(x)) else {}
@@ -25,21 +25,21 @@ function Compose(f: B -> C, g:A -> B): A -> C
=> f(g(x))
}
-function W(f : (A,A) -> A): A -> A
+function W<A>(f : (A,A) -> A): A -> A
{
x requires f.requires(x,x)
reads f.reads(x,x)
=> f(x,x)
}
-function Curry(f : (A,B) -> C) : A -> B -> C
+function Curry<A,B,C>(f : (A,B) -> C) : A -> B -> C
{
x => y requires f.requires(x,y)
reads f.reads(x,y)
=> f(x,y)
}
-function Uncurry(f : A -> B -> C) : (A,B) -> C
+function Uncurry<A,B,C>(f : A -> B -> C) : (A,B) -> C
{
(x,y) requires f.requires(x)
requires f(x).requires(y)
@@ -48,7 +48,7 @@ function Uncurry(f : A -> B -> C) : (A,B) -> C
=> f(x)(y)
}
-function S(f : (A,B) -> C, g : A -> B): A -> C
+function S<A,B,C>(f : (A,B) -> C, g : A -> B): A -> C
{
x requires g.requires(x)
requires f.requires(x,g(x))
diff --git a/Test/hofs/Field.dfy.expect b/Test/hofs/Field.dfy.expect
index 9f6998f5..0859d83c 100644
--- a/Test/hofs/Field.dfy.expect
+++ b/Test/hofs/Field.dfy.expect
@@ -1,13 +1,13 @@
-Field.dfy(12,12): Error: possible violation of function precondition
+Field.dfy(12,11): Error: possible violation of function precondition
Execution trace:
(0,0): anon0
-Field.dfy(12,15): Error: assertion violation
+Field.dfy(12,14): Error: assertion violation
Execution trace:
(0,0): anon0
-Field.dfy(21,12): Error: possible violation of function precondition
+Field.dfy(21,11): Error: possible violation of function precondition
Execution trace:
(0,0): anon0
-Field.dfy(21,14): Error: assertion violation
+Field.dfy(21,13): Error: assertion violation
Execution trace:
(0,0): anon0
diff --git a/Test/hofs/FnRef.dfy.expect b/Test/hofs/FnRef.dfy.expect
index 0f6f2aa9..e665c830 100644
--- a/Test/hofs/FnRef.dfy.expect
+++ b/Test/hofs/FnRef.dfy.expect
@@ -1,19 +1,19 @@
-FnRef.dfy(17,45): Error: possible violation of function precondition
+FnRef.dfy(17,44): Error: possible violation of function precondition
Execution trace:
(0,0): anon0
FnRef.dfy(15,12): anon5_Else
(0,0): anon6_Then
-FnRef.dfy(32,8): Error: possible violation of function precondition
+FnRef.dfy(32,7): Error: possible violation of function precondition
Execution trace:
(0,0): anon0
FnRef.dfy(26,12): anon9_Else
FnRef.dfy(28,8): anon10_Else
-FnRef.dfy(46,12): Error: assertion violation
+FnRef.dfy(46,11): Error: assertion violation
Execution trace:
(0,0): anon0
FnRef.dfy(43,12): anon7_Else
(0,0): anon9_Then
-FnRef.dfy(65,14): Error: assertion violation
+FnRef.dfy(65,13): Error: assertion violation
Execution trace:
(0,0): anon0
FnRef.dfy(56,12): anon8_Else
diff --git a/Test/hofs/Fold.dfy b/Test/hofs/Fold.dfy
index 6ca2d3b1..9bcd9e02 100644
--- a/Test/hofs/Fold.dfy
+++ b/Test/hofs/Fold.dfy
@@ -13,7 +13,7 @@ function method Eval(e : Expr): int
case Lit(i) => i
}
-function method Fold(xs : List<A>, unit : B, f : (A,B) -> B): B
+function method Fold<A,B>(xs : List<A>, unit : B, f : (A,B) -> B): B
reads f.reads;
requires forall x, y :: x < xs ==> f.requires(x,y);
{
diff --git a/Test/hofs/Frame.dfy.expect b/Test/hofs/Frame.dfy.expect
index 0ee2eadb..9964deb4 100644
--- a/Test/hofs/Frame.dfy.expect
+++ b/Test/hofs/Frame.dfy.expect
@@ -1,35 +1,35 @@
-Frame.dfy(23,16): Error: assertion violation
+Frame.dfy(23,15): Error: assertion violation
Execution trace:
(0,0): anon0
Frame.dfy(19,12): anon5_Else
(0,0): anon6_Then
-Frame.dfy(37,14): Error: assertion violation
+Frame.dfy(37,13): Error: assertion violation
Execution trace:
(0,0): anon0
Frame.dfy(33,12): anon3_Else
-Frame.dfy(63,23): Error: assertion violation
+Frame.dfy(63,22): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon13_Then
Frame.dfy(55,12): anon14_Else
(0,0): anon15_Then
(0,0): anon5
-Frame.dfy(66,19): Error: insufficient reads clause to read array element
+Frame.dfy(66,18): Error: insufficient reads clause to read array element
Execution trace:
(0,0): anon0
(0,0): anon16_Then
(0,0): anon17_Then
-Frame.dfy(68,28): Error: insufficient reads clause to read array element
+Frame.dfy(68,27): Error: insufficient reads clause to read array element
Execution trace:
(0,0): anon0
(0,0): anon16_Else
(0,0): anon18_Then
-Frame.dfy(123,14): Error: possible violation of function precondition
+Frame.dfy(123,13): Error: possible violation of function precondition
Execution trace:
(0,0): anon0
(0,0): anon5_Then
(0,0): anon6_Else
-Frame.dfy(123,19): Error: assertion violation
+Frame.dfy(123,18): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon5_Then
diff --git a/Test/hofs/Lambda.dfy.expect b/Test/hofs/Lambda.dfy.expect
index 4fe8275f..ab57fbe0 100644
--- a/Test/hofs/Lambda.dfy.expect
+++ b/Test/hofs/Lambda.dfy.expect
@@ -1,4 +1,4 @@
-Lambda.dfy(24,12): Error: assertion violation
+Lambda.dfy(24,11): Error: assertion violation
Execution trace:
(0,0): anon0
Lambda.dfy(6,24): anon31_Else
diff --git a/Test/hofs/LambdaParsefail.dfy.expect b/Test/hofs/LambdaParsefail.dfy.expect
index 11deb9b0..a72fc978 100644
--- a/Test/hofs/LambdaParsefail.dfy.expect
+++ b/Test/hofs/LambdaParsefail.dfy.expect
@@ -1,6 +1,6 @@
-LambdaParsefail.dfy(5,19): error: this symbol not expected in VarDeclStatement
-LambdaParsefail.dfy(6,19): error: this symbol not expected in VarDeclStatement
-LambdaParsefail.dfy(7,21): error: this symbol not expected in VarDeclStatement
-LambdaParsefail.dfy(8,15): error: cannot declare identifier beginning with underscore
-LambdaParsefail.dfy(9,17): error: this symbol not expected in VarDeclStatement
+LambdaParsefail.dfy(5,18): Error: this symbol not expected in VarDeclStatement
+LambdaParsefail.dfy(6,18): Error: this symbol not expected in VarDeclStatement
+LambdaParsefail.dfy(7,20): Error: this symbol not expected in VarDeclStatement
+LambdaParsefail.dfy(8,14): Error: cannot declare identifier beginning with underscore
+LambdaParsefail.dfy(9,16): Error: this symbol not expected in VarDeclStatement
5 parse errors detected in LambdaParsefail.dfy
diff --git a/Test/hofs/LambdaParsefail2.dfy.expect b/Test/hofs/LambdaParsefail2.dfy.expect
index 0c9ecb83..1a6a65dc 100644
--- a/Test/hofs/LambdaParsefail2.dfy.expect
+++ b/Test/hofs/LambdaParsefail2.dfy.expect
@@ -1,2 +1,2 @@
-LambdaParsefail2.dfy(6,39): error: invalid LambdaArrow
+LambdaParsefail2.dfy(6,38): Error: invalid LambdaArrow
1 parse errors detected in LambdaParsefail2.dfy
diff --git a/Test/hofs/Monads.dfy b/Test/hofs/Monads.dfy
index 3598d2b3..633dd339 100644
--- a/Test/hofs/Monads.dfy
+++ b/Test/hofs/Monads.dfy
@@ -4,29 +4,29 @@
abstract module Monad {
type M<A>
- function method Return(x: A): M<A>
- function method Bind(m: M<A>, f:A -> M<B>):M<B>
- reads f.reads;
- requires forall a :: f.requires(a);
+ function method Return<A>(x: A): M<A>
+ function method Bind<A,B>(m: M<A>, f:A -> M<B>):M<B>
+ reads f.reads
+ requires forall a :: f.requires(a)
// return x >>= f = f x
- lemma LeftIdentity(x : A, f : A -> M<B>)
- requires forall a :: f.requires(a);
- ensures Bind(Return(x),f) == f(x);
+ lemma LeftIdentity<A,B>(x : A, f : A -> M<B>)
+ requires forall a :: f.requires(a)
+ ensures Bind(Return(x),f) == f(x)
// m >>= return = m
- lemma RightIdentity(m : M<A>)
- ensures Bind(m,Return) == m;
+ lemma RightIdentity<A>(m : M<A>)
+ ensures Bind(m,Return) == m
// (m >>= f) >>= g = m >>= (x => f(x) >>= g)
- lemma Associativity(m : M<A>, f:A -> M<B>, g: B -> M<C>)
- requires forall a :: f.requires(a);
- requires forall b :: g.requires(b);
+ lemma Associativity<A,B,C>(m : M<A>, f:A -> M<B>, g: B -> M<C>)
+ requires forall a :: f.requires(a)
+ requires forall b :: g.requires(b)
ensures Bind(Bind(m,f),g) ==
Bind(m,x reads f.reads(x)
reads g.reads
requires f.requires(x)
- requires forall b :: g.requires(b) => Bind(f(x),g));
+ requires forall b :: g.requires(b) => Bind(f(x),g))
}
module Identity refines Monad {
@@ -101,21 +101,21 @@ module List refines Monad {
function method Return<A>(x: A): M<A>
{ Cons(x,Nil) }
- function method Concat(xs: M<A>, ys: M<A>): M<A>
+ function method Concat<A>(xs: M<A>, ys: M<A>): M<A>
{
match xs
case Nil => ys
case Cons(x,xs) => Cons(x,Concat(xs,ys))
}
- function method Join(xss: M<M<A>>) : M<A>
+ function method Join<A>(xss: M<M<A>>) : M<A>
{
match xss
case Nil => Nil
case Cons(xs,xss) => Concat(xs,Join(xss))
}
- function method Map(xs: M<A>, f: A -> B):M<B>
+ function method Map<A,B>(xs: M<A>, f: A -> B):M<B>
reads f.reads;
requires forall a :: f.requires(a);
{
@@ -170,7 +170,7 @@ module List refines Monad {
ensures Concat(Concat(xs,ys),zs) == Concat(xs,Concat(ys,zs));
{}
- lemma BindMorphism(xs : M<A>, ys: M<A>, f : A -> M<B>)
+ lemma BindMorphism<A,B>(xs : M<A>, ys: M<A>, f : A -> M<B>)
requires forall a :: f.requires(a);
ensures Bind(Concat(xs,ys),f) == Concat(Bind(xs,f),Bind(ys,f));
{
diff --git a/Test/hofs/Naked.dfy b/Test/hofs/Naked.dfy
index fa99377f..d23eb507 100644
--- a/Test/hofs/Naked.dfy
+++ b/Test/hofs/Naked.dfy
@@ -19,17 +19,17 @@ module Functions {
module Requires {
function t(x: nat): nat
- requires !t.requires(x);
+ requires !t.requires(x); // error: use of naked function in its own SCC
{ x }
function g(x: nat): nat
- requires !(g).requires(x);
+ requires !(g).requires(x); // error: use of naked function in its own SCC
{ x }
- function g2(x: int): int { h(x) }
-
+ function D(x: int): int // used so termination errors don't mask other errors
+ function g2(x: int): int decreases D(x) { h(x) } // error: precondition violation
function h(x: int): int
- requires !g2.requires(x);
+ requires !g2.requires(x); // error: use of naked function in its own SCC
{ x }
}
diff --git a/Test/hofs/Naked.dfy.expect b/Test/hofs/Naked.dfy.expect
index 62c035b2..9794478d 100644
--- a/Test/hofs/Naked.dfy.expect
+++ b/Test/hofs/Naked.dfy.expect
@@ -1,50 +1,46 @@
-Naked.dfy(9,16): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+Naked.dfy(9,15): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
Execution trace:
(0,0): anon0
- (0,0): anon7_Else
- (0,0): anon8_Else
- (0,0): anon9_Then
-Naked.dfy(12,8): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
-Execution trace:
- (0,0): anon0
- (0,0): anon7_Else
- (0,0): anon8_Else
(0,0): anon9_Else
-Naked.dfy(17,53): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+ (0,0): anon10_Else
+ (0,0): anon11_Then
+Naked.dfy(12,7): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
- (0,0): anon6_Else
-Naked.dfy(22,13): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+ (0,0): anon9_Else
+ (0,0): anon10_Else
+ (0,0): anon11_Else
+Naked.dfy(17,52): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
Execution trace:
(0,0): anon0
-Naked.dfy(26,14): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+ (0,0): anon7_Else
+ (0,0): anon8_Else
+Naked.dfy(22,12): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
Execution trace:
(0,0): anon0
-Naked.dfy(29,30): Error: cannot prove termination; try supplying a decreases clause
+Naked.dfy(26,13): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-Naked.dfy(29,30): Error: possible violation of function precondition
-Naked.dfy(32,14): Related location
+Naked.dfy(30,44): Error: possible violation of function precondition
+Naked.dfy(32,13): Related location
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-Naked.dfy(32,15): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+ (0,0): anon4_Else
+Naked.dfy(32,14): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
Execution trace:
(0,0): anon0
-Naked.dfy(38,9): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+Naked.dfy(38,8): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
Execution trace:
(0,0): anon0
-Naked.dfy(42,10): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+Naked.dfy(42,9): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
Execution trace:
(0,0): anon0
-Naked.dfy(45,30): Error: cannot prove termination; try supplying a decreases clause
+Naked.dfy(45,29): Error: cannot prove termination; try supplying a decreases clause
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-Naked.dfy(48,11): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+ (0,0): anon4_Else
+Naked.dfy(48,10): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
Execution trace:
(0,0): anon0
-Dafny program verifier finished with 1 verified, 12 errors
+Dafny program verifier finished with 2 verified, 11 errors
diff --git a/Test/hofs/OneShot.dfy b/Test/hofs/OneShot.dfy
index 286be898..e920530a 100644
--- a/Test/hofs/OneShot.dfy
+++ b/Test/hofs/OneShot.dfy
@@ -10,16 +10,15 @@ method OneShot() {
var i : Ref<int>;
i := new Ref;
- g := () -> true;
-
+ g := () reads i -> true; // using a (deprecated) one-shot arrow here means "g" acquires
+ // a precondition that says it can only be applied in this heap
assert g();
i.val := i.val + 1; // heap changes
if * {
- assert g(); // should fail
+ assert g(); // error: precondition violation
} else {
- assert !g(); // should fail
+ assert !g(); // error: precondition violation
}
}
-
diff --git a/Test/hofs/OneShot.dfy.expect b/Test/hofs/OneShot.dfy.expect
index 91b931b8..0b4a2bb8 100644
--- a/Test/hofs/OneShot.dfy.expect
+++ b/Test/hofs/OneShot.dfy.expect
@@ -1,16 +1,16 @@
-OneShot.dfy(20,12): Error: possible violation of function precondition
+OneShot.dfy(20,11): Error: possible violation of function precondition
Execution trace:
(0,0): anon0
(0,0): anon5_Then
OneShot.dfy(13,8): anon5_Else
(0,0): anon6_Then
-OneShot.dfy(22,12): Error: assertion violation
+OneShot.dfy(22,11): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon5_Then
OneShot.dfy(13,8): anon5_Else
(0,0): anon6_Else
-OneShot.dfy(22,13): Error: possible violation of function precondition
+OneShot.dfy(22,12): Error: possible violation of function precondition
Execution trace:
(0,0): anon0
(0,0): anon5_Then
diff --git a/Test/hofs/ReadsReads.dfy b/Test/hofs/ReadsReads.dfy
index e11473bd..60ac35f5 100644
--- a/Test/hofs/ReadsReads.dfy
+++ b/Test/hofs/ReadsReads.dfy
@@ -2,58 +2,58 @@
// RUN: %diff "%s.expect" "%t"
module ReadsRequiresReads {
- function MyReadsOk(f : A -> B, a : A) : set<object>
- reads f.reads(a);
+ function MyReadsOk<A,B>(f : A -> B, a : A) : set<object>
+ reads f.reads(a)
{
f.reads(a)
}
- function MyReadsOk2(f : A -> B, a : A) : set<object>
- reads f.reads(a);
+ function MyReadsOk2<A,B>(f : A -> B, a : A) : set<object>
+ reads f.reads(a)
{
(f.reads)(a)
}
- function MyReadsOk3(f : A -> B, a : A) : set<object>
- reads (f.reads)(a);
+ function MyReadsOk3<A,B>(f : A -> B, a : A) : set<object>
+ reads (f.reads)(a)
{
f.reads(a)
}
- function MyReadsOk4(f : A -> B, a : A) : set<object>
- reads (f.reads)(a);
+ function MyReadsOk4<A,B>(f : A -> B, a : A) : set<object>
+ reads (f.reads)(a)
{
(f.reads)(a)
}
- function MyReadsBad(f : A -> B, a : A) : set<object>
+ function MyReadsBad<A,B>(f : A -> B, a : A) : set<object>
{
f.reads(a) // error: MyReadsBad does not have permission to read what f.reads(a) reads
}
- function MyReadsBad2(f : A -> B, a : A) : set<object>
+ function MyReadsBad2<A,B>(f : A -> B, a : A) : set<object>
{
(f.reads)(a) // error: MyReadsBad2 does not have permission to read what f.reads(a) reads
}
- function MyReadsOk'(f : A -> B, a : A, o : object) : bool
- reads f.reads(a);
+ function MyReadsOk'<A,B>(f : A -> B, a : A, o : object) : bool
+ reads f.reads(a)
{
o in f.reads(a)
}
- function MyReadsBad'(f : A -> B, a : A, o : object) : bool
+ function MyReadsBad'<A,B>(f : A -> B, a : A, o : object) : bool
{
o in f.reads(a) // error: MyReadsBad' does not have permission to read what f.reads(a) reads
}
- function MyRequiresOk(f : A -> B, a : A) : bool
- reads f.reads(a);
+ function MyRequiresOk<A,B>(f : A -> B, a : A) : bool
+ reads f.reads(a)
{
f.requires(a)
}
- function MyRequiresBad(f : A -> B, a : A) : bool
+ function MyRequiresBad<A,B>(f : A -> B, a : A) : bool
{
f.requires(a) // error: MyRequiresBad does not have permission to read what f.requires(a) reads
}
@@ -72,11 +72,11 @@ module WhatWeKnowAboutReads {
}
class S {
- var s : S;
+ var s : S
}
function ReadsSomething(s : S):()
- reads s;
+ reads s
{()}
method MaybeSomething() {
@@ -105,29 +105,29 @@ module WhatWeKnowAboutReads {
module ReadsAll {
function A(f: int -> int) : int
- reads set o,x | o in f.reads(x) :: o;
- requires forall x :: f.requires(x);
+ reads set x,o | o in f.reads(x) :: o // note, with "set o,x ..." instead, Dafny complains (this is perhaps less than ideal)
+ requires forall x :: f.requires(x)
{
f(0) + f(1) + f(2)
}
function method B(f: int -> int) : int
- reads set o,x | o in f.reads(x) :: o;
- requires forall x :: f.requires(x);
+ reads set x,o | o in f.reads(x) :: o // note, with "set o,x ..." instead, Dafny complains (this is perhaps less than ideal)
+ requires forall x :: f.requires(x)
{
f(0) + f(1) + f(2)
}
function C(f: int -> int) : int
- reads f.reads;
- requires forall x :: f.requires(x);
+ reads f.reads
+ requires forall x :: f.requires(x)
{
f(0) + f(1) + f(2)
}
function method D(f: int -> int) : int
- reads f.reads;
- requires forall x :: f.requires(x);
+ reads f.reads
+ requires forall x :: f.requires(x)
{
f(0) + f(1) + f(2)
}
diff --git a/Test/hofs/ReadsReads.dfy.expect b/Test/hofs/ReadsReads.dfy.expect
index 73002b73..0a374c44 100644
--- a/Test/hofs/ReadsReads.dfy.expect
+++ b/Test/hofs/ReadsReads.dfy.expect
@@ -1,33 +1,33 @@
-ReadsReads.dfy(31,7): Error: insufficient reads clause to invoke function
+ReadsReads.dfy(31,6): Error: insufficient reads clause to invoke function
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-ReadsReads.dfy(36,5): Error: insufficient reads clause to invoke function
+ (0,0): anon4_Else
+ReadsReads.dfy(36,4): Error: insufficient reads clause to invoke function
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-ReadsReads.dfy(47,12): Error: insufficient reads clause to invoke function
+ (0,0): anon4_Else
+ReadsReads.dfy(47,11): Error: insufficient reads clause to invoke function
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-ReadsReads.dfy(58,7): Error: insufficient reads clause to invoke function
+ (0,0): anon4_Else
+ReadsReads.dfy(58,6): Error: insufficient reads clause to invoke function
Execution trace:
(0,0): anon0
- (0,0): anon3_Else
-ReadsReads.dfy(87,50): Error: assertion violation
+ (0,0): anon4_Else
+ReadsReads.dfy(87,49): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon16_Then
-ReadsReads.dfy(89,29): Error: assertion violation
+ReadsReads.dfy(89,28): Error: assertion violation
Execution trace:
(0,0): anon0
(0,0): anon18_Then
-ReadsReads.dfy(99,37): Error: assertion violation
+ReadsReads.dfy(99,36): Error: assertion violation
Execution trace:
(0,0): anon0
ReadsReads.dfy(96,14): anon15_Else
(0,0): anon19_Then
-ReadsReads.dfy(101,29): Error: assertion violation
+ReadsReads.dfy(101,28): Error: assertion violation
Execution trace:
(0,0): anon0
ReadsReads.dfy(96,14): anon15_Else
diff --git a/Test/hofs/Requires.dfy b/Test/hofs/Requires.dfy
new file mode 100644
index 00000000..68677b3e
--- /dev/null
+++ b/Test/hofs/Requires.dfy
@@ -0,0 +1,82 @@
+// RUN: %dafny /compile:3 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method Main()
+{
+ test0(10);
+ test5(11);
+ test6(12);
+ test1();
+ test2();
+}
+
+predicate valid(x:int)
+{
+ x > 0
+}
+
+function ref1(y:int) : int
+ requires valid(y);
+{
+ y - 1
+}
+
+lemma assumption1()
+ ensures forall a, b :: valid(a) && valid(b) && ref1(a) == ref1(b) ==> a == b;
+{
+}
+
+method test0(a: int)
+{
+ if ref1.requires(a) {
+ // the precondition should suffice to let us call the method
+ ghost var b := ref1(a);
+ }
+}
+method test5(a: int)
+{
+ if valid(a) {
+ // valid(a) is the precondition of ref1
+ assert ref1.requires(a);
+ }
+}
+method test6(a: int)
+{
+ if ref1.requires(a) {
+ // the precondition of ref1 is valid(a)
+ assert valid(a);
+ }
+}
+
+method test1()
+{
+ if * {
+ assert forall a, b :: valid(a) && valid(b) && ref1(a) == ref1(b) ==> a == b;
+ } else {
+ assert forall a, b :: ref1.requires(a) && ref1.requires(b) && ref1(a) == ref1(b)
+ ==> a == b;
+ }
+}
+
+function {:opaque} ref2(y:int) : int // Now with an opaque attribute
+ requires valid(y);
+{
+ y - 1
+}
+
+lemma assumption2()
+ ensures forall a, b :: valid(a) && valid(b) && ref2(a) == ref2(b) ==> a == b;
+{
+ reveal_ref2();
+}
+
+method test2()
+{
+ assumption2();
+ if * {
+ assert forall a, b :: valid(a) && valid(b) && ref2(a) == ref2(b) ==> a == b;
+ } else {
+ assert forall a, b :: ref2.requires(a) && ref2.requires(b) && ref2(a) == ref2(b)
+ ==> a == b;
+ }
+}
diff --git a/Test/hofs/Requires.dfy.expect b/Test/hofs/Requires.dfy.expect
new file mode 100644
index 00000000..b9a40d66
--- /dev/null
+++ b/Test/hofs/Requires.dfy.expect
@@ -0,0 +1,5 @@
+
+Dafny program verifier finished with 20 verified, 0 errors
+Program compiled successfully
+Running...
+
diff --git a/Test/hofs/ResolveError.dfy b/Test/hofs/ResolveError.dfy
index 3c0d7cd9..ae838eb3 100644
--- a/Test/hofs/ResolveError.dfy
+++ b/Test/hofs/ResolveError.dfy
@@ -3,9 +3,9 @@
method ResolutionErrors() {
- var x;
- var g5 := x, y => (y, x); // fail at resolution
- var g6 := x, (y => (y, x)); // fail at resolution
+ var x;
+ var g5 := x, y => (y, x); // fail at resolution
+ var g6 := x, (y => (y, x)); // fail at resolution
}
// cannot assign functions
@@ -23,20 +23,20 @@ method Nope3() {
method RequiresFail(f : int -> int)
// ok
- requires f(0) == 0;
- requires f.requires(0);
- requires f.reads(0) == {};
+ requires f(0) == 0
+ requires f.requires(0)
+ requires f.reads(0) == {}
// fail
- requires f(0) == true;
- requires f(1,2) == 0;
- requires f(true) == 0;
- requires f.requires(true);
- requires f.requires(1) == 0;
- requires f.requires(1,2);
- requires f.reads(true) == {};
- requires f.reads(1) == 0;
- requires f.reads(1,2) == {};
+ requires f(0) == true
+ requires f(1,2) == 0
+ requires f(true) == 0
+ requires f.requires(true)
+ requires f.requires(1) == 0
+ requires f.requires(1,2)
+ requires f.reads(true) == {}
+ requires f.reads(1) == 0
+ requires f.reads(1,2) == {}
{
}
@@ -56,7 +56,7 @@ method Bla() {
assert Bool;
}
-method Pli(f : A -> B) requires f != null;
+method Pli<A,B>(f : A -> B) requires f != null
{
var o : object;
assert f != o;
@@ -102,7 +102,7 @@ module AritySituations {
w := V; // error
}
- method P(r: T -> U, x: T) returns (u: U)
+ method P<T,U>(r: T -> U, x: T) returns (u: U)
requires r.requires(x);
{
u := r(x);
diff --git a/Test/hofs/ResolveError.dfy.expect b/Test/hofs/ResolveError.dfy.expect
index c3e0c242..11471ffd 100644
--- a/Test/hofs/ResolveError.dfy.expect
+++ b/Test/hofs/ResolveError.dfy.expect
@@ -2,8 +2,8 @@ ResolveError.dfy(86,6): Error: RHS (of type ((int,bool)) -> real) not assignable
ResolveError.dfy(91,15): Error: incorrect type of method in-parameter 0 (expected ? -> ?, got (int,bool) -> real)
ResolveError.dfy(101,6): Error: RHS (of type (()) -> real) not assignable to LHS (of type () -> real)
ResolveError.dfy(102,6): Error: RHS (of type () -> real) not assignable to LHS (of type (()) -> real)
-ResolveError.dfy(7,11): Error: the number of left-hand sides (1) and right-hand sides (2) must match for a multi-assignment
-ResolveError.dfy(8,11): Error: the number of left-hand sides (1) and right-hand sides (2) must match for a multi-assignment
+ResolveError.dfy(7,9): Error: the number of left-hand sides (1) and right-hand sides (2) must match for a multi-assignment
+ResolveError.dfy(8,9): Error: the number of left-hand sides (1) and right-hand sides (2) must match for a multi-assignment
ResolveError.dfy(21,6): Error: LHS of assignment must denote a mutable field
ResolveError.dfy(31,16): Error: arguments must have the same type (got int and bool)
ResolveError.dfy(32,12): Error: wrong number of arguments to function application (function type 'int -> int' expects 1, got 2)
@@ -17,7 +17,7 @@ ResolveError.dfy(39,18): Error: wrong number of arguments to function applicatio
ResolveError.dfy(46,15): Error: a reads-clause expression must denote an object or a collection of objects (instead got int)
ResolveError.dfy(47,7): Error: Precondition must be boolean (got int)
ResolveError.dfy(56,9): Error: condition is expected to be of type bool, but is () -> bool
-ResolveError.dfy(59,34): Error: arguments must have the same type (got A -> B and ?)
+ResolveError.dfy(59,39): Error: arguments must have the same type (got A -> B and ?)
ResolveError.dfy(62,11): Error: arguments must have the same type (got A -> B and object)
ResolveError.dfy(68,24): Error: unresolved identifier: _
22 resolution/type errors detected in ResolveError.dfy
diff --git a/Test/hofs/Simple.dfy b/Test/hofs/Simple.dfy
index c27fa82c..6d98531e 100644
--- a/Test/hofs/Simple.dfy
+++ b/Test/hofs/Simple.dfy
@@ -50,7 +50,7 @@ method Main() {
}
function method succ(x : int) : int
- requires x > 0;
+ requires x > 0
{
x + 1
}
@@ -74,24 +74,24 @@ method Main3() {
}
-function P(f: A -> B, x : A): B
- reads (f.reads)(x);
- requires (f.requires)(x);
+function P<A,B>(f: A -> B, x : A): B
+ reads (f.reads)(x)
+ requires (f.requires)(x)
{
f(x)
}
-function Q(f: U -> V, x : U): V
- reads P.reads(f,x);
- requires f.requires(x); // would be nice to be able to write P.requires(f,x)
+function Q<U,V>(f: U -> V, x : U): V
+ reads P.reads(f,x)
+ requires f.requires(x) // would be nice to be able to write P.requires(f,x)
{
P(f,x)
}
-function QQ(f: U -> V, x : U): V
- reads ((() => ((()=>f)()).reads)())((()=>x)());
- requires ((() => ((()=>f)()).requires)())((()=>x)());
+function QQ<U,V>(f: U -> V, x : U): V
+ reads ((() => ((()=>f)()).reads)())((()=>x)())
+ requires ((() => ((()=>f)()).requires)())((()=>x)())
{
((() => P)())((()=>f)(),(()=>x)())
}
diff --git a/Test/hofs/Simple.dfy.expect b/Test/hofs/Simple.dfy.expect
index b3c126d5..c0123c80 100644
--- a/Test/hofs/Simple.dfy.expect
+++ b/Test/hofs/Simple.dfy.expect
@@ -1,32 +1,29 @@
-Simple.dfy(14,10): Error: possible division by zero
+Simple.dfy(14,9): Error: possible division by zero
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
- (0,0): anon6_Then
-Simple.dfy(27,10): Error: possible division by zero
+ (0,0): anon6_Else
+ (0,0): anon7_Then
+Simple.dfy(27,9): Error: possible division by zero
Execution trace:
(0,0): anon0
- (0,0): anon5_Else
- (0,0): anon6_Then
-Simple.dfy(37,9): Error: possible violation of function precondition
+ (0,0): anon6_Else
+ (0,0): anon7_Then
+Simple.dfy(37,8): Error: possible violation of function precondition
Execution trace:
(0,0): anon0
Simple.dfy(35,13): anon5_Else
-Simple.dfy(49,9): Error: possible violation of function precondition
+Simple.dfy(49,8): Error: possible violation of function precondition
Execution trace:
(0,0): anon0
(0,0): anon3_Then
(0,0): anon2
-Simple.dfy(61,10): Error: possible violation of function precondition
+Simple.dfy(61,9): Error: possible violation of function precondition
Execution trace:
(0,0): anon0
-Simple.dfy(61,18): Error: assertion violation
-Execution trace:
- (0,0): anon0
-Simple.dfy(73,10): Error: assertion violation
+Simple.dfy(73,9): Error: assertion violation
Execution trace:
(0,0): anon0
Simple.dfy(72,38): anon5_Else
Simple.dfy(73,38): anon6_Else
-Dafny program verifier finished with 14 verified, 7 errors
+Dafny program verifier finished with 14 verified, 6 errors
diff --git a/Test/hofs/TreeMapSimple.dfy b/Test/hofs/TreeMapSimple.dfy
index a853b82c..6b8f1377 100644
--- a/Test/hofs/TreeMapSimple.dfy
+++ b/Test/hofs/TreeMapSimple.dfy
@@ -6,7 +6,7 @@ datatype List<A> = Nil | Cons(head: A,tail: List<A>)
datatype Tree<A> = Branch(val: A,trees: List<Tree<A>>)
function ListData(xs : List) : set
- ensures forall x :: x in ListData(xs) ==> x < xs;
+ ensures forall x :: x in ListData(xs) ==> x < xs
{
match xs
case Nil => {}
@@ -14,32 +14,32 @@ function ListData(xs : List) : set
}
function TreeData(t0 : Tree) : set
- ensures forall t :: t in TreeData(t0) ==> t < t0;
+ ensures forall t :: t in TreeData(t0) ==> t < t0
{
var Branch(x,ts) := t0;
{x} + set t, y | t in ListData(ts) && y in TreeData(t) :: y
}
-function Pre(f : A -> B, s : set<A>) : bool
- reads (set x, y | x in s && y in f.reads(x) :: y);
+function Pre<A,B>(f : A -> B, s : set<A>) : bool
+ reads (set x, y | x in s && y in f.reads(x) :: y)
{
forall x :: x in s ==> f.reads(x) == {} && f.requires(x)
}
-function method Map(xs : List<A>, f : A -> B): List<B>
- reads Pre.reads(f, ListData(xs));
- requires Pre(f, ListData(xs));
- decreases xs;
+function method Map<A,B>(xs : List<A>, f : A -> B): List<B>
+ reads Pre.reads(f, ListData(xs))
+ requires Pre(f, ListData(xs))
+ decreases xs
{
match xs
case Nil => Nil
case Cons(x,xs) => Cons(f(x),Map(xs,f))
}
-function method TMap(t0 : Tree<A>, f : A -> B) : Tree<B>
- reads Pre.reads(f, TreeData(t0));
- requires Pre(f, TreeData(t0));
- decreases t0;
+function method TMap<A,B>(t0 : Tree<A>, f : A -> B) : Tree<B>
+ reads Pre.reads(f, TreeData(t0))
+ requires Pre(f, TreeData(t0))
+ decreases t0
{
var Branch(x,ts) := t0;
Branch(f(x),Map(ts, t requires t in ListData(ts)
diff --git a/Test/hofs/Twice.dfy b/Test/hofs/Twice.dfy
index add7e83c..5d948a58 100644
--- a/Test/hofs/Twice.dfy
+++ b/Test/hofs/Twice.dfy
@@ -1,7 +1,7 @@
// RUN: %dafny /print:"%t.print" "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
-function method Twice(f : A -> A): A -> A
+function method Twice<A>(f : A -> A): A -> A
{
x requires f.requires(x) && f.requires(f(x))
reads f.reads(x) reads if f.requires(x) then f.reads(f(x)) else {}
@@ -29,7 +29,7 @@ method WithReads() {
}
-function method Twice_bad(f : A -> A): A -> A
+function method Twice_bad<A>(f : A -> A): A -> A
{
x requires f.requires(x) && f.requires(f(x))
reads f.reads(x) + f.reads(f(x))
diff --git a/Test/hofs/Twice.dfy.expect b/Test/hofs/Twice.dfy.expect
index 5ba4b47b..0ce2450c 100644
--- a/Test/hofs/Twice.dfy.expect
+++ b/Test/hofs/Twice.dfy.expect
@@ -1,11 +1,11 @@
-Twice.dfy(27,22): Error: assertion violation
+Twice.dfy(27,21): Error: assertion violation
Execution trace:
(0,0): anon0
Twice.dfy(23,12): anon3_Else
-Twice.dfy(35,32): Error: possible violation of function precondition
+Twice.dfy(35,31): Error: possible violation of function precondition
Execution trace:
(0,0): anon0
- (0,0): anon9_Else
- (0,0): anon10_Then
+ (0,0): anon10_Else
+ (0,0): anon11_Then
Dafny program verifier finished with 4 verified, 2 errors
diff --git a/Test/hofs/VectorUpdate.dfy b/Test/hofs/VectorUpdate.dfy
index 96edbe77..6fb25a87 100644
--- a/Test/hofs/VectorUpdate.dfy
+++ b/Test/hofs/VectorUpdate.dfy
@@ -1,28 +1,59 @@
-// RUN: %dafny /compile:3 "%s" > "%t"
+// RUN: %dafny /compile:3 /autoTriggers:1 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
-method VectorUpdate(N: int, a : array<A>, f : (int,A) -> A)
- requires a != null;
- requires N == a.Length;
- requires forall j :: 0 <= j < N ==> f.requires(j,a[j]);
- requires forall j :: 0 <= j < N ==> a !in f.reads(j,a[j]);
- modifies a;
- ensures forall j :: 0 <= j < N ==> a[j] == f(j,old(a[j]));
+// this is a rather verbose version of the VectorUpdate method
+method VectorUpdate<A>(N: int, a : array<A>, f : (int,A) -> A)
+ requires a != null
+ requires N == a.Length
+ requires forall j :: 0 <= j < N ==> f.requires(j,a[j])
+ requires forall j :: 0 <= j < N ==> a !in f.reads(j,a[j])
+ modifies a
+ ensures forall j :: 0 <= j < N ==> a[j] == f(j,old(a[j]))
{
var i := 0;
- while (i < N)
- invariant 0 <= i <= N;
- invariant forall j :: i <= j < N ==> f.requires(j,a[j]);
- invariant forall j :: 0 <= j < N ==> f.requires(j,old(a[j]));
- invariant forall j :: i <= j < N ==> a !in f.reads(j,a[j]);
- invariant forall j :: i <= j < N ==> a[j] == old(a[j]);
- invariant forall j :: 0 <= j < i ==> a[j] == f(j,old(a[j]));
+ while i < N
+ invariant 0 <= i <= N
+ invariant forall j :: i <= j < N ==> f.requires(j,a[j])
+ invariant forall j :: 0 <= j < N ==> f.requires(j,old(a[j]))
+ invariant forall j :: i <= j < N ==> a !in f.reads(j,a[j])
+ invariant forall j :: i <= j < N ==> a[j] == old(a[j])
+ invariant forall j :: 0 <= j < i ==> a[j] == f(j,old(a[j]))
{
a[i] := f(i,a[i]);
i := i + 1;
}
}
+// here's a shorter version of the method above
+method VectorUpdate'<A>(a : array<A>, f : (int,A) -> A)
+ requires a != null
+ requires forall j :: 0 <= j < a.Length ==> a !in f.reads(j,a[j]) && f.requires(j,a[j])
+ modifies a
+ ensures forall j :: 0 <= j < a.Length ==> a[j] == f(j,old(a[j]))
+{
+ var i := 0;
+ while i < a.Length
+ invariant 0 <= i <= a.Length
+ invariant forall j :: i <= j < a.Length ==> a[j] == old(a[j])
+ invariant forall j :: 0 <= j < i ==> a[j] == f(j,old(a[j]))
+ {
+ a[i] := f(i,a[i]);
+ i := i + 1;
+ }
+}
+
+// here's yet another version
+method VectorUpdate''<A>(a : array<A>, f : (int,A) -> A)
+ requires a != null
+ requires forall j :: 0 <= j < a.Length ==> a !in f.reads(j,a[j]) && f.requires(j,a[j])
+ modifies a
+ ensures forall j :: 0 <= j < a.Length ==> a[j] == f(j,old(a[j]))
+{
+ forall i | 0 <= i < a.Length {
+ a[i] := f(i,a[i]);
+ }
+}
+
method Main()
{
var v := new int[10];
@@ -46,11 +77,11 @@ method Main()
}
method PrintArray(a : array<int>)
- requires a != null;
+ requires a != null
{
var i := 0;
- while (i < a.Length) {
- if (i != 0) {
+ while i < a.Length {
+ if i != 0 {
print ", ";
}
print a[i];
diff --git a/Test/hofs/VectorUpdate.dfy.expect b/Test/hofs/VectorUpdate.dfy.expect
index b01ace00..18a7b110 100644
--- a/Test/hofs/VectorUpdate.dfy.expect
+++ b/Test/hofs/VectorUpdate.dfy.expect
@@ -1,5 +1,5 @@
-Dafny program verifier finished with 6 verified, 0 errors
+Dafny program verifier finished with 10 verified, 0 errors
Program compiled successfully
Running...
diff --git a/Test/hofs/WhileLoop.dfy b/Test/hofs/WhileLoop.dfy
index f79562e9..2c91a8cc 100644
--- a/Test/hofs/WhileLoop.dfy
+++ b/Test/hofs/WhileLoop.dfy
@@ -34,14 +34,14 @@ method OneShot(n: int) {
method HeapQuant(n: int) {
var f : int -> int := x => x;
- var i := new Ref<int>;
+ var i := new Ref;
ghost var r := 0;
i.val := 0;
- while (i.val < n)
- invariant forall u {:heapQuantifier} :: f.requires(u);
- invariant forall u {:heapQuantifier} :: f.reads(u) == {};
+ while i.val < n
+ invariant forall u :: f.requires(u);
+ invariant forall u :: f.reads(u) == {};
invariant r == i.val;
- invariant forall u {:heapQuantifier} :: f(u) == u + r;
+ invariant forall u :: f(u) == u + r;
{
i.val, r := i.val + 1, r + 1;
f := x => f(x) + 1;
diff --git a/Test/irondafny0/FIFO.dfy b/Test/irondafny0/FIFO.dfy
new file mode 100644
index 00000000..ded8f567
--- /dev/null
+++ b/Test/irondafny0/FIFO.dfy
@@ -0,0 +1,43 @@
+// RUN: %dafny /ironDafny /compile:3 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+include "Queue.dfyi"
+
+module FIFO exclusively refines Queue {
+ type Item = int
+
+ method Init() returns (q: Queue) {
+ q := [];
+ }
+
+ method Push(item: Item, q: Queue) returns (q': Queue) {
+ return q + [item];
+ }
+
+ method Pop(q: Queue) returns (item: Item, q': Queue)
+ ensures item == q[0]
+ {
+ item := q[0];
+ q' := q[1..];
+ }
+}
+
+module MainImpl refines MainSpec {
+ import Q = FIFO
+
+ method Main()
+ {
+ var q := Q.Init();
+ q := Q.Push(0, q);
+ q := Q.Push(1, q);
+ q := Q.Push(2, q);
+
+ var n: int;
+ n, q := Q.Pop(q);
+ print n, "\n";
+ n, q := Q.Pop(q);
+ print n, "\n";
+ n, q := Q.Pop(q);
+ print n, "\n";
+ }
+}
diff --git a/Test/irondafny0/FIFO.dfy.expect b/Test/irondafny0/FIFO.dfy.expect
new file mode 100644
index 00000000..25021947
--- /dev/null
+++ b/Test/irondafny0/FIFO.dfy.expect
@@ -0,0 +1,8 @@
+
+Dafny program verifier finished with 8 verified, 0 errors
+Program compiled successfully
+Running...
+
+0
+1
+2
diff --git a/Test/irondafny0/LIFO.dfy b/Test/irondafny0/LIFO.dfy
new file mode 100644
index 00000000..8c0a08e8
--- /dev/null
+++ b/Test/irondafny0/LIFO.dfy
@@ -0,0 +1,43 @@
+// RUN: %dafny /ironDafny /compile:3 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+include "Queue.dfyi"
+
+module LIFO exclusively refines Queue {
+ type Item = int
+
+ method Init() returns (q: Queue) {
+ q := [];
+ }
+
+ method Push(item: Item, q: Queue) returns (q': Queue) {
+ return [item] + q;
+ }
+
+ method Pop(q: Queue) returns (item: Item, q': Queue)
+ ensures item == q[0]
+ {
+ item := q[0];
+ q' := q[1..];
+ }
+}
+
+module MainImpl refines MainSpec {
+ import Q = LIFO
+
+ method Main()
+ {
+ var q := Q.Init();
+ q := Q.Push(0, q);
+ q := Q.Push(1, q);
+ q := Q.Push(2, q);
+
+ var n: int;
+ n, q := Q.Pop(q);
+ print n, "\n";
+ n, q := Q.Pop(q);
+ print n, "\n";
+ n, q := Q.Pop(q);
+ print n, "\n";
+ }
+}
diff --git a/Test/irondafny0/LIFO.dfy.expect b/Test/irondafny0/LIFO.dfy.expect
new file mode 100644
index 00000000..83f90a5b
--- /dev/null
+++ b/Test/irondafny0/LIFO.dfy.expect
@@ -0,0 +1,8 @@
+
+Dafny program verifier finished with 8 verified, 0 errors
+Program compiled successfully
+Running...
+
+2
+1
+0
diff --git a/Test/irondafny0/Queue.dfyi b/Test/irondafny0/Queue.dfyi
new file mode 100644
index 00000000..06f4b29e
--- /dev/null
+++ b/Test/irondafny0/Queue.dfyi
@@ -0,0 +1,22 @@
+// Queue.dfyi
+
+abstract module Queue {
+ type Item
+ type Queue = seq<Item>
+
+ method Init() returns (q: Queue)
+ ensures |q| == 0;
+
+ method Push(item: Item, q: Queue) returns (q': Queue)
+ ensures |q'| == |q| + 1;
+
+ method Pop(q: Queue) returns (item: Item, q': Queue)
+ requires |q| > 0;
+ ensures item in q;
+ ensures |q'| == |q| - 1;
+}
+
+abstract module MainSpec {
+ import Q : Queue
+}
+
diff --git a/Test/irondafny0/inheritreqs0.dfy b/Test/irondafny0/inheritreqs0.dfy
new file mode 100644
index 00000000..a0117da0
--- /dev/null
+++ b/Test/irondafny0/inheritreqs0.dfy
@@ -0,0 +1,22 @@
+// RUN: %dafny /compile:3 /optimize /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+abstract module Spec {
+ method Greet(b: bool)
+ requires b;
+}
+
+module Impl refines Spec {
+ method Greet(b: bool) {
+ print "o hai!\n";
+ }
+
+ method Xyzzy(b: bool)
+ requires b;
+ {}
+
+ method Main() {
+ Greet(false);
+ Xyzzy(false);
+ }
+}
diff --git a/Test/irondafny0/inheritreqs0.dfy.expect b/Test/irondafny0/inheritreqs0.dfy.expect
new file mode 100644
index 00000000..44e33bc0
--- /dev/null
+++ b/Test/irondafny0/inheritreqs0.dfy.expect
@@ -0,0 +1,6 @@
+inheritreqs0.dfy(19,13): Error BP5002: A precondition for this call might not hold.
+inheritreqs0.dfy[Impl](6,17): Related location: This is the precondition that might not hold.
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 6 verified, 1 error
diff --git a/Test/irondafny0/inheritreqs1.dfy b/Test/irondafny0/inheritreqs1.dfy
new file mode 100644
index 00000000..c83d04ac
--- /dev/null
+++ b/Test/irondafny0/inheritreqs1.dfy
@@ -0,0 +1,22 @@
+// RUN: %dafny /compile:3 /optimize /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+abstract module Spec {
+ method Greet(b: bool)
+ requires b;
+}
+
+module Impl refines Spec {
+ method Greet(b: bool) {
+ print "o hai!\n";
+ }
+
+ method Xyzzy(b: bool)
+ requires b;
+ {}
+
+ method Main() {
+ Greet(true);
+ Xyzzy(false);
+ }
+}
diff --git a/Test/irondafny0/inheritreqs1.dfy.expect b/Test/irondafny0/inheritreqs1.dfy.expect
new file mode 100644
index 00000000..a07d179d
--- /dev/null
+++ b/Test/irondafny0/inheritreqs1.dfy.expect
@@ -0,0 +1,6 @@
+inheritreqs1.dfy(20,13): Error BP5002: A precondition for this call might not hold.
+inheritreqs1.dfy(15,17): Related location: This is the precondition that might not hold.
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 6 verified, 1 error
diff --git a/Test/irondafny0/opened_workaround.dfy b/Test/irondafny0/opened_workaround.dfy
new file mode 100644
index 00000000..6d44ccfd
--- /dev/null
+++ b/Test/irondafny0/opened_workaround.dfy
@@ -0,0 +1,21 @@
+// RUN: %dafny /ironDafny /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+module A {
+
+ predicate P()
+
+ class C
+ {
+ static method{:axiom} M()
+ ensures P();
+ }
+}
+
+abstract module B {
+ import opened A
+}
+
+abstract module C {
+ import Bee : B // Works
+}
diff --git a/Test/irondafny0/opened_workaround.dfy.expect b/Test/irondafny0/opened_workaround.dfy.expect
new file mode 100644
index 00000000..0be94b4c
--- /dev/null
+++ b/Test/irondafny0/opened_workaround.dfy.expect
@@ -0,0 +1,3 @@
+
+Dafny program verifier finished with 3 verified, 0 errors
+Compilation error: Function _0_A_Compile._default.P has no body
diff --git a/Test/irondafny0/optimize0.dfy b/Test/irondafny0/optimize0.dfy
new file mode 100644
index 00000000..865d8707
--- /dev/null
+++ b/Test/irondafny0/optimize0.dfy
@@ -0,0 +1,6 @@
+// RUN: %dafny /compile:3 /optimize /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method Main() {
+ print "o hai!";
+}
diff --git a/Test/irondafny0/optimize0.dfy.expect b/Test/irondafny0/optimize0.dfy.expect
new file mode 100644
index 00000000..6b3e13c5
--- /dev/null
+++ b/Test/irondafny0/optimize0.dfy.expect
@@ -0,0 +1,6 @@
+
+Dafny program verifier finished with 2 verified, 0 errors
+Program compiled successfully
+Running...
+
+o hai! \ No newline at end of file
diff --git a/Test/irondafny0/xrefine0.dfy b/Test/irondafny0/xrefine0.dfy
new file mode 100644
index 00000000..b849111c
--- /dev/null
+++ b/Test/irondafny0/xrefine0.dfy
@@ -0,0 +1,6 @@
+// RUN: %dafny /ironDafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+abstract module Delicious {}
+module Chocolate exclusively refines Delicious {}
+module Strawberry exclusively refines Delicious {}
diff --git a/Test/irondafny0/xrefine0.dfy.expect b/Test/irondafny0/xrefine0.dfy.expect
new file mode 100644
index 00000000..136e06db
--- /dev/null
+++ b/Test/irondafny0/xrefine0.dfy.expect
@@ -0,0 +1,2 @@
+xrefine0.dfy(6,7): Error: no more than one exclusive refinement may exist for a given module.
+1 resolution/type errors detected in xrefine0.dfy
diff --git a/Test/irondafny0/xrefine1.dfy b/Test/irondafny0/xrefine1.dfy
new file mode 100644
index 00000000..1b835649
--- /dev/null
+++ b/Test/irondafny0/xrefine1.dfy
@@ -0,0 +1,77 @@
+// RUN: %dafny /ironDafny /compile:3 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+abstract module ProtocolSpec {
+ type ProtoT
+
+ predicate Init(p:ProtoT)
+}
+
+abstract module HostSpec {
+ type HostT
+ import P : ProtocolSpec
+
+ function method foo(h:HostT) : P.ProtoT
+}
+
+module ProtocolImpl exclusively refines ProtocolSpec {
+ type ProtoT = bool
+
+ predicate Init(p:ProtoT) { !p }
+
+ method orange(i:nat) returns (j:nat)
+ {
+ j := i + 1;
+ }
+}
+
+module HostImpl exclusively refines HostSpec {
+ import P = ProtocolImpl
+
+ type HostT = int
+
+ function method foo(h:HostT) : P.ProtoT
+ {
+ h > 0
+ }
+
+ method apple(i:nat) returns (j:nat)
+ {
+ j := i + 1;
+ }
+}
+
+abstract module MainSpec {
+ import HI : HostSpec
+ import PI : ProtocolSpec
+
+ method Test(h1:HI.HostT, h2:HI.HostT)
+ requires HI.foo(h1) == HI.foo(h2);
+ requires PI.Init(HI.foo(h1))
+}
+
+module MainImpl exclusively refines MainSpec {
+ import HI = HostImpl
+ import PI = ProtocolImpl
+
+ method Test(h1:HI.HostT, h2:HI.HostT)
+ {
+ var a := HI.foo(h1);
+ print "HI.foo(h1) => ", a, "\n";
+ var b := HI.foo(h2);
+ print "HI.foo(h2) => ", b, "\n";
+ var i := PI.orange(1);
+ print "PI.orange(1) => ", i, "\n";
+ var j := HI.apple(2);
+ print "PI.apple(2) => ", j, "\n";
+ }
+
+ method Main()
+ {
+ Test(-1, 1);
+ }
+}
+
+
+
+
diff --git a/Test/irondafny0/xrefine1.dfy.expect b/Test/irondafny0/xrefine1.dfy.expect
new file mode 100644
index 00000000..ec946cda
--- /dev/null
+++ b/Test/irondafny0/xrefine1.dfy.expect
@@ -0,0 +1,6 @@
+xrefine1.dfy(71,12): Error BP5002: A precondition for this call might not hold.
+xrefine1.dfy[MainImpl](49,28): Related location: This is the precondition that might not hold.
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 12 verified, 1 error
diff --git a/Test/irondafny0/xrefine2.dfy b/Test/irondafny0/xrefine2.dfy
new file mode 100644
index 00000000..9c33391b
--- /dev/null
+++ b/Test/irondafny0/xrefine2.dfy
@@ -0,0 +1,77 @@
+// RUN: %dafny /ironDafny /compile:3 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+abstract module ProtocolSpec {
+ type ProtoT
+
+ predicate Init(p:ProtoT)
+}
+
+abstract module HostSpec {
+ type HostT
+ import P : ProtocolSpec
+
+ function method foo(h:HostT) : P.ProtoT
+}
+
+module ProtocolImpl exclusively refines ProtocolSpec {
+ type ProtoT = bool
+
+ predicate Init(p:ProtoT) { p }
+
+ method orange(i:nat) returns (j:nat)
+ {
+ j := i + 1;
+ }
+}
+
+module HostImpl exclusively refines HostSpec {
+ import P = ProtocolImpl
+
+ type HostT = int
+
+ function method foo(h:HostT) : P.ProtoT
+ {
+ h != 0
+ }
+
+ method apple(i:nat) returns (j:nat)
+ {
+ j := i + 1;
+ }
+}
+
+abstract module MainSpec {
+ import HI : HostSpec
+ import PI : ProtocolSpec
+
+ method Test(h1:HI.HostT, h2:HI.HostT)
+ requires HI.foo(h1) == HI.foo(h2);
+ requires PI.Init(HI.foo(h1))
+}
+
+module MainImpl exclusively refines MainSpec {
+ import HI = HostImpl
+ import PI = ProtocolImpl
+
+ method Test(h1:HI.HostT, h2:HI.HostT)
+ {
+ var a := HI.foo(h1);
+ print "HI.foo(h1) => ", a, "\n";
+ var b := HI.foo(h2);
+ print "HI.foo(h2) => ", b, "\n";
+ var i := PI.orange(1);
+ print "PI.orange(1) => ", i, "\n";
+ var j := HI.apple(2);
+ print "PI.apple(2) => ", j, "\n";
+ }
+
+ method Main()
+ {
+ Test(-1, 1);
+ }
+}
+
+
+
+
diff --git a/Test/irondafny0/xrefine2.dfy.expect b/Test/irondafny0/xrefine2.dfy.expect
new file mode 100644
index 00000000..6d3fecd4
--- /dev/null
+++ b/Test/irondafny0/xrefine2.dfy.expect
@@ -0,0 +1,9 @@
+
+Dafny program verifier finished with 13 verified, 0 errors
+Program compiled successfully
+Running...
+
+HI.foo(h1) => True
+HI.foo(h2) => True
+PI.orange(1) => 2
+PI.apple(2) => 3
diff --git a/Test/irondafny0/xrefine3.dfy b/Test/irondafny0/xrefine3.dfy
new file mode 100644
index 00000000..86dbd957
--- /dev/null
+++ b/Test/irondafny0/xrefine3.dfy
@@ -0,0 +1,72 @@
+// RUN: %dafny /ironDafny /compile:3 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+abstract module AlphaSpec {
+ type Alpha
+
+ predicate IsValid(a:Alpha)
+
+ method Init() returns (a:Alpha)
+ ensures IsValid(a);
+}
+
+abstract module BetaSpec {
+ type Beta
+ import A : AlphaSpec
+
+ predicate IsValid(b:Beta)
+
+ method Init(ays:seq<A.Alpha>) returns (b:Beta)
+ requires forall i :: 0 <= i < |ays| ==> A.IsValid(ays[i]);
+ ensures IsValid(b);
+}
+
+module AlphaImpl exclusively refines AlphaSpec {
+ type Alpha = bool
+
+ predicate IsValid(a:Alpha) {
+ a
+ }
+
+ method Init() returns (a:Alpha)
+ ensures IsValid(a);
+ {
+ a := true;
+ }
+}
+
+module BetaImpl exclusively refines BetaSpec {
+ import A = AlphaImpl
+ type Beta = seq<A.Alpha>
+
+ predicate IsValid(b:Beta) {
+ forall i :: 0 <= i < |b| ==> A.IsValid(b[i])
+ }
+
+ method Init(ays:seq<A.Alpha>) returns (b:Beta) {
+ b := ays;
+ }
+}
+
+abstract module MainSpec {
+ import A : AlphaSpec
+ import B : BetaSpec
+
+ method Main()
+ {
+ var a := A.Init();
+ var ays := [a, a];
+ assert forall i :: 0 <= i < |ays| ==> A.IsValid(ays[i]);
+ var b := B.Init(ays);
+ print "o hai!\n";
+ }
+}
+
+module MainImpl exclusively refines MainSpec {
+ import B = BetaImpl
+ import A = AlphaImpl
+}
+
+
+
+
diff --git a/Test/irondafny0/xrefine3.dfy.expect b/Test/irondafny0/xrefine3.dfy.expect
new file mode 100644
index 00000000..1e5a5b4e
--- /dev/null
+++ b/Test/irondafny0/xrefine3.dfy.expect
@@ -0,0 +1,6 @@
+
+Dafny program verifier finished with 14 verified, 0 errors
+Program compiled successfully
+Running...
+
+o hai!
diff --git a/Test/lit.site.cfg b/Test/lit.site.cfg
index d0b3a85b..2d57d389 100644
--- a/Test/lit.site.cfg
+++ b/Test/lit.site.cfg
@@ -22,7 +22,7 @@ config.suffixes = ['.dfy']
# excludes: A list of directories to exclude from the testsuite. The 'Inputs'
# subdirectories contain auxiliary inputs for various tests in their parent
# directories.
-config.excludes = []
+config.excludes = ['Inputs', 'sandbox']
# test_source_root: The root path where tests are located.
config.test_source_root = os.path.dirname(os.path.abspath(__file__))
@@ -79,19 +79,26 @@ lit_config.note('Repository root is {}'.format(repositoryRoot))
binaryDir = os.path.join( repositoryRoot, 'Binaries')
dafnyExecutable = os.path.join( binaryDir, 'Dafny.exe')
+serverExecutable = os.path.join( binaryDir, 'DafnyServer.exe')
if not os.path.exists(dafnyExecutable):
lit_config.fatal('Could not find Dafny.exe at {}'.format(dafnyExecutable))
+if not os.path.exists(serverExecutable):
+ lit_config.warning('Could not find DafnyServer.exe at {}'.format(serverExecutable))
+else:
+ config.suffixes.append('.transcript')
+
dafnyExecutable = quotePath(dafnyExecutable)
if os.name == 'posix':
dafnyExecutable = 'mono ' + dafnyExecutable
+ serverExecutable = 'mono ' + serverExecutable
if lit.util.which('mono') == None:
lit_config.fatal('Cannot find mono. Make sure it is your PATH')
# Expected output does not contain logo
-dafnyExecutable += ' -nologo'
+dafnyExecutable += ' -nologo -countVerificationErrors:0'
# We do not want absolute or relative paths in error messages, just the basename of the file
dafnyExecutable += ' -useBaseNameForFileName'
@@ -105,6 +112,7 @@ if len(dafnyParams) > 0:
lit_config.note('Using Dafny: {}\n'.format(dafnyExecutable))
config.substitutions.append( ('%dafny', dafnyExecutable) )
+config.substitutions.append( ('%server', serverExecutable) )
# Sanity check: Check solver executable is available
# FIXME: Should this check be removed entirely?
diff --git a/Test/pydiff.py b/Test/pydiff.py
index 407fe251..94267960 100644
--- a/Test/pydiff.py
+++ b/Test/pydiff.py
@@ -75,7 +75,8 @@ def preProcess(openFile, stripTrailingCR=False, ignoreAllSpace=False):
# newline characters because this will create a mess when outputting the
# diff. Is this the right behaviour?
deleteChars=' \t'
- translationTable = str.maketrans('','', deleteChars)
+ if sys.version_info.major >= 3:
+ translationTable = str.maketrans('','', deleteChars)
copy = [ ]
for line in original:
diff --git a/Test/runTests.bat b/Test/runTests.bat
new file mode 100644
index 00000000..4856faf8
--- /dev/null
+++ b/Test/runTests.bat
@@ -0,0 +1,2 @@
+@REM runTests.bat -f "/dprelude PRELUDE_FILE" -r REPORT_NAME INPUT_FILES
+C:/Python34/python.exe runTests.py --difftool "C:/Program Files (x86)/Meld/Meld.exe" %*
diff --git a/Test/runTests.py b/Test/runTests.py
new file mode 100644
index 00000000..8caa65d1
--- /dev/null
+++ b/Test/runTests.py
@@ -0,0 +1,567 @@
+import os
+import re
+import sys
+import csv
+import shutil
+import argparse
+import operator
+import platform
+from math import floor, ceil
+from enum import Enum
+from time import time, strftime
+from collections import defaultdict
+from multiprocessing import Pool, Manager
+from subprocess import Popen, call, PIPE, TimeoutExpired
+
+# C:/Python34/python.exe runTests.py --compiler "c:/MSR/dafny/Binaries/Dafny.exe" --flags "/useBaseNameForFileName /compile:1 /nologo" --difftool "C:\Program Files (x86)\Meld\Meld.exe" -j4 --flags "/dprelude preludes\AlmostAllTriggers.bpl" dafny0\SeqFromArray.dfy
+
+# c:/Python34/python.exe runTests.py --compare ../TestStable/results/SequenceAxioms/2015-06-06-00-54-52--PrettyPrinted.report.csv ../TestStable/results/SequenceAxioms/*.csv
+
+VERBOSITY = None
+KILLED = False
+ANSI = False
+
+try:
+ import colorama
+ no_native_ansi = os.name == 'nt' and os.environ.get("TERM") in [None, "cygwin"]
+ tty = all(hasattr(stream, 'isatty') and stream.isatty() for stream in (sys.stdout, sys.stderr))
+ colorama.init(strip=no_native_ansi, convert=no_native_ansi and tty)
+ ANSI = True
+except ImportError:
+ try:
+ import tendo.ansiterm
+ ANSI = True
+ except ImportError:
+ pass
+
+class Defaults:
+ EXCLUDED_FILES = ["^flycheck_"]
+ EXCLUDED_FOLDERS = ["Inputs", "Output", "sandbox", "desktop"]
+ DAFNY_BIN = os.path.realpath(os.path.join(os.path.dirname(__file__), "../Binaries/Dafny.exe"))
+ COMPILER = [DAFNY_BIN]
+ FLAGS = ["/useBaseNameForFileName", "/compile:1", "/nologo", "/timeLimit:300"]
+ EXTENSIONS = [".dfy", ".transcript"]
+
+class Colors:
+ RED = '\033[91m'
+ GREEN = '\033[92m'
+ YELLOW = '\033[93m'
+ BRIGHT = '\033[1m'
+ DIM = '\033[2m'
+ RESET = '\033[0m'
+
+class Debug(Enum):
+ ERROR = (-1, Colors.RED)
+ WARNING = (-1, Colors.YELLOW)
+ REPORT = (0, Colors.RESET, True)
+ INFO = (1, Colors.RESET, True)
+ DEBUG = (2, Colors.RESET)
+ TRACE = (3, Colors.RESET)
+
+ def __init__(self, index, color, elide=False):
+ self.index = index
+ self.color = color
+ self.elide = elide
+
+def wrap_color(string, color, silent=False):
+ if silent:
+ return " " * len(string)
+ elif ANSI:
+ return color + string + Colors.RESET
+ else:
+ return string
+
+def debug(level, *args, **kwargs):
+ kwargs["file"] = sys.stderr
+ kwargs["flush"] = True
+
+ headers = kwargs.pop("headers", [])
+ if isinstance(headers, Enum):
+ headers = [headers]
+
+ silentheaders = kwargs.pop("silentheaders", False)
+
+ if level and level.index <= VERBOSITY:
+ if level:
+ headers = [level] + headers
+
+ headers = tuple(wrap_color("{: <8}".format("[" + h.name + "]"), h.color, silent = silentheaders)
+ for h in headers if not h.elide)
+ print(*(headers + args), **kwargs)
+
+class TestStatus(Enum):
+ PENDING = (0, Colors.RESET)
+ PASSED = (1, Colors.GREEN)
+ FAILED = (2, Colors.RED)
+ UNKNOWN = (3, Colors.RED)
+ TIMEOUT = (4, Colors.RED)
+
+ def __init__(self, index, color):
+ self.index = index
+ self.color = color
+ self.elide = False
+
+class Test:
+ COLUMNS = ["name", "status", "start", "end", "duration", "returncodes", "suite_time", "njobs", "proc_info", "source_path", "temp_directory", "cmds", "expected", "output"]
+
+ def __init__(self, name, source_path, cmds, timeout, compiler_id = 0):
+ self.name = name
+ self.source_path = Test.uncygdrive(source_path)
+ self.expect_path = Test.source_to_expect_path(self.source_path)
+ self.source_directory, self.fname = os.path.split(self.source_path)
+ self.temp_directory = os.path.join(self.source_directory, "Output")
+ self.temp_output_path = os.path.join(self.temp_directory, self.fname + ".tmp")
+
+ self.output = None
+ self.expected = Test.read_normalize(self.expect_path)
+
+ self.cmds = cmds
+ self.timeout = timeout
+ self.compiler_id = compiler_id
+ self.cmds = [cmd.replace("%s", self.source_path) for cmd in self.cmds]
+ self.cmds = [cmd.replace("%S", self.source_directory) for cmd in self.cmds]
+ self.cmds = [cmd.replace("%t", self.temp_output_path) for cmd in self.cmds]
+ self.cmds = [cmd.replace("%T", self.temp_directory) for cmd in self.cmds]
+
+ self.status = TestStatus.PENDING
+ self.proc_info = platform.processor()
+
+ self.time, self.suite_time = None, None
+ self.njobs, self.returncodes = None, []
+ self.start, self.end, self.duration = None, None, None
+
+ @staticmethod
+ def source_to_expect_path(source):
+ return source + ".expect"
+
+ @staticmethod
+ def uncygdrive(path):
+ return re.sub("^/cygdrive/([a-zA-Z])/", r"\1:/", path)
+
+ @staticmethod
+ def read_normalize(path):
+ try:
+ with open(path, mode="rb") as reader:
+ return reader.read().replace(b'\r\n', b'\n').replace(b'\r', b'\n')
+ except FileNotFoundError:
+ debug(Debug.WARNING, "{} not found".format(path))
+ return ""
+
+ @staticmethod
+ def build_report(tests, name):
+ now = strftime("%Y-%m-%d-%H-%M-%S")
+ if name:
+ directory, fname = os.path.split(name)
+ name = os.path.join(directory, now + "--" + fname)
+ else:
+ name = now
+
+ with open(name + ".csv", mode='w', newline='') as writer:
+ csv_writer = csv.DictWriter(writer, Test.COLUMNS, dialect='excel')
+ csv_writer.writeheader()
+ for test in tests:
+ test.serialize(csv_writer)
+
+ @staticmethod
+ def load_report(path):
+ results = []
+ with open(path) as csvfile:
+ for row in csv.DictReader(csvfile): #, fieldnames=Test.COLUMNS):
+ results.append(Test.deserialize(row))
+ return results
+
+ @staticmethod
+ def mean_duration(results, margin):
+ durations = sorted(result.duration for result in results
+ if result.status in (TestStatus.PASSED, TestStatus.FAILED))
+ if len(durations) >= 15:
+ lq = durations[floor(0.25 * len(durations))]
+ hq = durations[ceil(0.85 * len(durations))]
+ iqr = hq - lq
+ filtered = [d for d in durations if (lq - margin * iqr) <= d <= (hq + margin * iqr)]
+ if filtered:
+ avg = sum(durations) / len(durations)
+ trimmed_avg = sum(filtered) / len(filtered)
+ outliers_count = len(durations) - len(filtered)
+ msg = "mean completion time: {:.2f}s".format(avg)
+ if outliers_count > 0:
+ msg += "; ignoring {} outliers: {:.2f}s".format(outliers_count, trimmed_avg)
+ return " ({})".format(msg)
+ return ""
+
+ @staticmethod
+ def summarize(results):
+ debug(Debug.INFO, "\nTesting complete ({} test(s))".format(len(results)))
+
+ if results:
+ grouped = defaultdict(list)
+ for test in results:
+ grouped[test.status].append(test)
+
+ for status, tests in sorted(grouped.items(), key=lambda x: x[0].index):
+ if tests:
+ debug(Debug.REPORT, "{} of {}".format(len(tests), len(results)), headers=status)
+ if status != TestStatus.PASSED:
+ for test in tests:
+ debug(Debug.REPORT, "* " + test.name, headers=status, silentheaders=True)
+
+ debug(Debug.REPORT)
+
+ failing = [t for t in results if t.status != TestStatus.PASSED]
+ if failing:
+ with open("failing.lst", mode='w') as writer:
+ for t in failing:
+ writer.write("{}\n".format(t.name))
+ debug(Debug.REPORT, "Some tests failed: use [runTests.py failing.lst] to rerun the failing tests")
+
+ debug(Debug.REPORT, "Testing took {:.2f}s on {} thread(s){}".format(
+ results[0].suite_time, results[0].njobs, Test.mean_duration(results, 1.5)))
+
+
+ def run(self):
+ debug(Debug.DEBUG, "Starting {}".format(self.name))
+ os.makedirs(self.temp_directory, exist_ok=True)
+ # os.chdir(self.source_directory)
+
+ stdout, stderr = b'', b''
+ self.start = time()
+
+ try:
+ for cmd in self.cmds:
+ debug(Debug.DEBUG, "> {}".format(cmd))
+ try:
+ proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True)
+ _stdout, _stderr = proc.communicate(timeout=self.timeout)
+ stdout, stderr = stdout + _stdout, stderr + _stderr
+ self.returncodes.append(proc.returncode)
+ except FileNotFoundError:
+ debug(Debug.ERROR, "Program '{}' not found".format(cmd))
+ self.status = TestStatus.UNKNOWN
+ return
+ except TimeoutExpired:
+ self.status = TestStatus.TIMEOUT
+ self.end = self.start + self.timeout
+ self.duration = self.timeout
+ return
+
+ self.end = time()
+ self.duration = self.end - self.start
+
+ stdout, stderr = stdout.strip(), stderr.strip()
+ if stdout != b"":
+ debug(Debug.TRACE, "Writing the output of {} to {}".format(self.name, self.temp_output_path))
+ with open(self.temp_output_path, mode='ab') as writer:
+ writer.write(stdout)
+ if stderr != b"":
+ debug(Debug.INFO, stderr.decode("utf-8"))
+
+ self.update_status()
+ except TimeoutExpired:
+ self.status = TestStatus.TIMEOUT
+ except KeyboardInterrupt:
+ raise
+
+ def update_status(self):
+ self.output = Test.read_normalize(self.temp_output_path)
+ self.status = TestStatus.PASSED if self.expected == self.output else TestStatus.FAILED
+
+ def report(self, tid, running, alltests):
+ running = [alltests[rid].fname for rid in running]
+ running = "; oldest: {}".format(running[0]) if running else ""
+
+ fstring = "[{:5.2f}s] {} ({}{})"
+ progress = "{}/{}".format(tid, len(alltests))
+ message = fstring.format(self.duration, wrap_color(self.name, Colors.BRIGHT),
+ wrap_color(progress, Colors.BRIGHT), running)
+
+ debug(Debug.INFO, message, headers=self.status)
+
+ @staticmethod
+ def write_bytes(base_directory, relative_path, extension, contents):
+ with open(os.path.join(base_directory, relative_path + extension), mode='wb') as writer:
+ writer.write(contents)
+
+ def serialize(self, csv_writer):
+ csv_writer.writerow({col: getattr(self, col) for col in Test.COLUMNS})
+
+ @classmethod
+ def deserialize(cls, row):
+ test = cls.__new__(cls)
+ for col, val in row.items():
+ setattr(test, col, val)
+ test.duration = float(test.duration)
+ test.status = next(x for x in TestStatus if str(x) == test.status)
+ return test
+
+def setup_parser():
+ parser = argparse.ArgumentParser(description='Run the Dafny test suite.')
+
+ parser.add_argument('path', type=str, action='store', nargs='+',
+ help='Input files or folders. Folders are searched for test files. Lists of files can also be specified by passing a .lst file (for an example of such a file, look at failing.lst after running failing tests.')
+
+ parser.add_argument('--compiler', type=str, action='append', default=None,
+ help='Dafny executable. Default: {}'.format(Defaults.DAFNY_BIN))
+
+ parser.add_argument('--base-flags', type=str, action='append', default=None,
+ help='Arguments to pass to dafny. Multiple --flags are concatenated. Default: {}'.format(Defaults.FLAGS))
+
+ parser.add_argument('--flags', '-f', type=str, action='append', default=[],
+ help='Additional arguments to pass to dafny. Useful to override some of the defaults found in --base-flags.')
+
+ parser.add_argument('--njobs', '-j', action='store', type=int, default=None,
+ help='Number of test workers.')
+
+ parser.add_argument('--exclude', action='append', type=str, default=[],
+ help='Excluded directories. {} are automatically added.'.format(Defaults.EXCLUDED_FOLDERS))
+
+ parser.add_argument('--verbosity', action='store', type=int, default=1,
+ help='Set verbosity level. 0: Minimal; 1: Some info; 2: More info; 3: Trace.')
+
+ parser.add_argument('-v', action='store_const', default=1, dest="verbosity", const=2,
+ help='Short for --verbosity 2.')
+
+ parser.add_argument('-vv', action='store_const', default=1, dest="verbosity", const=3,
+ help='Short for --verbosity 3.')
+
+ parser.add_argument('--report', '-r', action='store', type=str, default=None,
+ help='Give an explicit name to the report file. Defaults to the current date and time.')
+
+ parser.add_argument('--timeout', action='store', type=float, default=15*60.0,
+ help='Prover timeout')
+
+ parser.add_argument('--compare', action='store_true',
+ help="Compare two previously generated reports.")
+
+ parser.add_argument('--time-all', action='store_true',
+ help="When comparing, include all timings.")
+
+ parser.add_argument('--diff', '-d', action='store_true',
+ help="Don't run tests; show differences between outputs and .expect files, optionally overwritting .expect files.")
+
+ parser.add_argument('--accept', '-a', action='store_true',
+ help="Don't run tests; copy outputs to .expect files.")
+
+ parser.add_argument('--open', '-o', action='store_true',
+ help="Don't run tests; open one file.")
+
+ parser.add_argument('--difftool', action='store', type=str, default="diff",
+ help='Diff program. Default: diff.')
+
+ return parser
+
+def run_one_internal(test, test_id, args, running):
+ global KILLED
+ global VERBOSITY
+ VERBOSITY = args.verbosity
+
+ if not KILLED:
+ try:
+ running.append(test_id)
+ test.run()
+ except KeyboardInterrupt:
+ # There's no reliable way to handle this cleanly on Windows: if one
+ # of the worker dies, it gets respawned. The reliable solution is to
+ # ignore further work once you receive a kill signal
+ KILLED = True
+ except Exception as e:
+ debug(Debug.ERROR, "[{}] {}".format(test.name, e))
+ test.status = TestStatus.UNKNOWN
+ finally:
+ running.remove(test_id)
+
+ return test
+
+def run_one(args):
+ return run_one_internal(*args)
+
+def get_server_path(compiler):
+ REGEXP = r"\bDafny.exe\b.*"
+ if re.search(REGEXP, compiler):
+ return re.sub(REGEXP, "DafnyServer.exe", compiler)
+ else:
+ return None
+
+def substitute_binaries(cmd, compiler):
+ cmd = cmd.replace("%dafny", compiler)
+ cmd = cmd.replace("%server", get_server_path(compiler))
+ return cmd
+
+def read_one_test(fname, compiler_cmds, timeout):
+ for cid, compiler_cmd in enumerate(compiler_cmds):
+ source_path = os.path.realpath(fname)
+ with open(source_path, mode='r') as reader:
+ cmds = []
+ for line in reader:
+ line = line.strip()
+ match = re.match("^[/# ]*RUN: *(?!%diff)([^ ].*)$", line)
+ if match:
+ debug(Debug.TRACE, "Found RUN spec: {}".format(line))
+ cmds.append(substitute_binaries(match.groups()[0], compiler_cmd))
+ else:
+ break
+ if cmds:
+ yield Test(fname, source_path, cmds, timeout, cid)
+ else:
+ debug(Debug.WARNING, "Test file {} has no RUN specification".format(fname))
+
+
+def find_one(fname, compiler_cmds, timeout):
+ _, name = os.path.split(fname)
+ _, ext = os.path.splitext(name)
+ if ext in Defaults.EXTENSIONS and not any(re.search(pattern, name, re.IGNORECASE) for pattern in Defaults.EXCLUDED_FILES):
+ if os.path.exists(fname):
+ debug(Debug.TRACE, "Found test file: {}".format(fname))
+ yield from read_one_test(fname, compiler_cmds, timeout)
+ else:
+ debug(Debug.ERROR, "Test file {} not found".format(fname))
+ else:
+ debug(Debug.TRACE, "Ignoring {}".format(fname))
+
+
+def expand_lsts(paths):
+ for path in paths:
+ _, ext = os.path.splitext(path)
+ if ext == ".lst": #lst files are only read if explicitly listed on the CLI
+ debug(Debug.INFO, "Loading tests from {}".format(path))
+ with open(path) as reader:
+ for line in reader:
+ _path = line.strip()
+ yield _path
+ else:
+ yield path
+
+def find_tests(paths, compiler_cmds, excluded, timeout):
+ for path in expand_lsts(paths):
+ if os.path.isdir(path):
+ debug(Debug.TRACE, "Searching for tests in {}".format(path))
+ for base, dirnames, fnames in os.walk(path):
+ dirnames[:] = [d for d in dirnames if d not in excluded]
+ for fname in fnames:
+ yield from find_one(os.path.join(base, fname), compiler_cmds, timeout)
+ else:
+ yield from find_one(path, compiler_cmds, timeout)
+
+def run_tests(args):
+ if args.compiler is None:
+ args.compiler = Defaults.COMPILER
+ if args.base_flags is None:
+ args.base_flags = Defaults.FLAGS
+
+ for compiler in args.compiler:
+ server = get_server_path(compiler)
+ if not os.path.exists(compiler):
+ debug(Debug.ERROR, "Compiler not found: {}".format(compiler))
+ return
+ if not os.path.exists(server):
+ debug(Debug.WARNING, "Server not found")
+
+ tests = list(find_tests(args.path, [compiler + ' ' + " ".join(args.base_flags + args.flags)
+ for compiler in args.compiler],
+ args.exclude + Defaults.EXCLUDED_FOLDERS, args.timeout))
+ tests.sort(key=operator.attrgetter("name"))
+
+ args.njobs = max(1, min(args.njobs or os.cpu_count() or 1, len(tests)))
+ debug(Debug.INFO, "\nRunning {} test(s) on {} testing thread(s), timeout is {:.2f}s, started at {}".format(len(tests), args.njobs, args.timeout, strftime("%H:%M:%S")))
+
+ try:
+ pool = Pool(args.njobs)
+
+ results = []
+ start = time()
+ with Manager() as manager:
+ running = manager.list()
+ payloads = [(t, tid, args, running) for (tid, t) in enumerate(tests)]
+ for tid, test in enumerate(pool.imap_unordered(run_one, payloads, 1)):
+ test.report(tid + 1, running, tests)
+ results.append(test)
+ pool.close()
+ pool.join()
+ suite_time = time() - start
+
+ for t in results:
+ t.njobs = args.njobs
+ t.suite_time = suite_time
+
+ Test.summarize(results)
+ Test.build_report(results, args.report)
+ except KeyboardInterrupt:
+ try:
+ pool.terminate()
+ pool.join()
+ except (FileNotFoundError, EOFError, ConnectionAbortedError):
+ pass
+ debug(Debug.ERROR, "Testing interrupted")
+
+
+def diff(paths, force_accept, difftool):
+ for path in expand_lsts(paths):
+ if not os.path.exists(path):
+ debug(Debug.ERROR, "Not found: {}".format(path))
+ else:
+ test = Test(None, path, [], None)
+ accept = force_accept
+
+ if not accept:
+ call([difftool, test.expect_path, test.temp_output_path])
+ accept = input("Accept this change? (y/N) ") == "y"
+
+ if accept:
+ debug(Debug.INFO, path, "accepted.")
+ shutil.copy(test.temp_output_path, test.expect_path)
+ else:
+ debug(Debug.INFO, path, "not accepted.")
+
+def compare_results(globs, time_all):
+ from glob import glob
+ paths = [path for g in globs for path in glob(g)]
+ reports = {path: Test.load_report(path) for path in paths}
+ resultsets = {path: {test.name: (test.status, test.duration) for test in report}
+ for path, report in reports.items()}
+
+ all_tests = set(name for resultset in resultsets.values() for name in resultset.keys())
+
+ reference = resultsets[paths[0]]
+ for path, resultset in resultsets.items():
+ resultset["$$TOTAL$$"] = None, sum(v[1] for v in resultset.values() if v[1] and v[0] != TestStatus.TIMEOUT)
+
+ with open("compare.csv", mode='w', newline='') as writer:
+ csv_writer = csv.writer(writer, dialect='excel')
+ csv_writer.writerow(["Name"] + [os.path.split(path)[1].lstrip("0123456789-") for path in paths])
+
+ for name in sorted(all_tests) + ["$$TOTAL$$"]:
+ ref_status, ref_duration = reference[name]
+
+ row = []
+ row.append(name)
+ row.append(ref_duration)
+ for path in paths[1:]:
+ res = resultsets[path].get(name)
+ test_status, test_duration = res if res else (TestStatus.UNKNOWN, None)
+ if res is not None and (test_status == ref_status or time_all):
+ result = "{:.2%}".format((test_duration - ref_duration) / ref_duration)
+ else:
+ result = test_status.name + "?!"
+ row.append(result)
+
+ csv_writer.writerow(row)
+
+def main():
+ global VERBOSITY
+ parser = setup_parser()
+ args = parser.parse_args()
+ VERBOSITY = args.verbosity
+
+ if os.name != 'nt' and os.environ.get("TERM") == "cygwin":
+ debug(Debug.WARNING, "If you run into issues, try using Windows' Python instead of Cygwin's")
+
+ if args.diff or args.accept:
+ diff(args.path, args.accept, args.difftool)
+ elif args.open:
+ os.startfile(args.path[0])
+ elif args.compare:
+ compare_results(args.path, args.time_all)
+ else:
+ run_tests(args)
+
+if __name__ == '__main__':
+ main()
diff --git a/Test/server/minimal.transcript b/Test/server/minimal.transcript
new file mode 100644
index 00000000..394fd921
--- /dev/null
+++ b/Test/server/minimal.transcript
@@ -0,0 +1,8 @@
+# RUN: "%server" "%s" > "%t"
+# RUN: %diff "%s.expect" "%t"
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xuICBhc3NlcnQgZmFsc2U7XG59XG4iLCJz
+b3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
diff --git a/Test/server/minimal.transcript.expect b/Test/server/minimal.transcript.expect
new file mode 100644
index 00000000..bf3f9dfb
--- /dev/null
+++ b/Test/server/minimal.transcript.expect
@@ -0,0 +1,14 @@
+# Reading from minimal.transcript
+
+Verifying CheckWellformed$$_module.__default.A ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+ [2 proof obligations] error
+transcript(3,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
diff --git a/Test/server/simple-session.transcript b/Test/server/simple-session.transcript
new file mode 100644
index 00000000..d095f6dd
--- /dev/null
+++ b/Test/server/simple-session.transcript
@@ -0,0 +1,637 @@
+# RUN: "%server" "%s" > "%t"
+# RUN: %diff "%s.expect" "%t"
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xuICBhc3NlcnQgZmFsc2U7XG59XG4iLCJz
+b3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xuICBhc3NlcnQgZmFsc2U7XG4gfVxuIiwi
+c291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xuICBhc3NlcnQgZmFsc2U7XG59XG4iLCJz
+b3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xuICBhc3NlcnQgZmFsc2U7XG59XG4iLCJz
+b3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG4iLCJzb3VyY2VJc0ZpbGUiOmZh
+bHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5tZXRob2QgTScoKSB7Iiwic291
+cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5tZXRob2QgTScoKSB7XG4gICIs
+InNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5tZXRob2QgTScoKSB7XG59Iiwi
+c291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5tZXRob2QgTScoKSB7XG5cbn0i
+LCJzb3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5tZXRob2QgTScoKSB7XG4gIFxu
+fSIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5tZXRob2QgTScoKSB7XG4gIHhc
+bn0iLCJzb3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5tZXRob2QgTScoKSB7XG4gIFxu
+fSIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5tZXRob2QgTScoKSB7XG4gIHZh
+clxufSIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5tZXRob2QgTScoKSB7XG4gIHZh
+ciB4IDo9IDE7XG59Iiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5tZXRob2QgTScoKSB7XG4gIHZh
+ciB4IDo9IDE7XG4gIFxufSIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5tZXRob2QgTScoKSB7XG4gIHZh
+ciB4IDo9IDE7XG4gIHZhciB5LCB6IDo9IDI7XG59Iiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5tZXRob2QgTScoKSB7XG4gIHZh
+ciB4IDo9IDE7XG4gIHZhciB5LCB6IDo9IDI7XG4gIFxufSIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5tZXRob2QgTScoKSB7XG4gIHZh
+ciB4IDo9IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIFxufSIsInNvdXJjZUlzRmlsZSI6ZmFs
+c2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKCkg
+e1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAyLCAzO1xuICBcbn0iLCJzb3VyY2VJc0Zp
+bGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKCkg
+e1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAyLCAzO1xuICBcbn0iLCJzb3VyY2VJc0Zp
+bGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcblxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAyLCAzO1xuICBcbn0iLCJz
+b3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcblxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAyLCAzO1xuICBcbn0iLCJz
+b3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgXG57XG4gIHZhciB4IDo9IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIFxufSIs
+InNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxXG57XG4gIHZhciB4IDo9IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIFxu
+fSIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxXG57XG4gIHZhciB4IDo9IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIFxu
+fSIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgXG59Iiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzXG59Iiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvclxufSIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JyA6OiBcbn0iLCJzb3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JyA6OiBpbnQsIHgnICogeCcgPiAwO1xufSIsInNvdXJj
+ZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JyA6OiBpbnQsIHgnICogeCcgPiAwO1xufSIsInNvdXJj
+ZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4J2ludCwgeCcgKiB4JyA+IDA7XG59Iiwic291cmNlSXNG
+aWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50LCB4JyAqIHgnID4gMDtcbn0iLCJzb3VyY2VJ
+c0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6ICwgeCcgKiB4JyA+IDA7XG59Iiwic291
+cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPiAwO1xufSIsInNvdXJj
+ZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbn0iLCJzb3Vy
+Y2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgXG59Iiwi
+c291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzXG59
+Iiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn0iLCJzb3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuIiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn0iLCJz
+b3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn0iLCJz
+b3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cbiIs
+InNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNJyh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59Iiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNJyh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59Iiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNJyh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG4iLCJzb3VyY2VJc0ZpbGUiOmZhbHNl
+fQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNJyh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTScodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiB4JyA+PSAwO1xuICBhc3NlcnQg
+eCAqIHggPiAwO1xufSIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0odDogbmF0KVxuICByZXF1aXJlcyB0
+ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAyLCAzO1xuICBhc3NlcnQgZm9y
+YWxsIHgnOiBpbnQgOjogeCcgKiB4JyA+PSAwO1xuICBhc3NlcnQgeCAqIHggPiAwO1xufVxuXG5z
+dGF0aWMgbWV0aG9kIE0odDogbmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAx
+O1xuICB2YXIgeSwgeiA6PSAyLCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiB4
+JyA+PSAwO1xuICBhc3NlcnQgeCAqIHggPiAwO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0odDogbmF0
+KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAyLCAz
+O1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiB4JyA+PSAwO1xuICBhc3NlcnQgeCAq
+IHggPiAwO1xufSIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiB4JyA+PSAwO1xuICBhc3NlcnQg
+eCAqIHggPiAwO1xufSIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiB4JyA+PSAwO1xuICBhc3NlcnQg
+eCAqIHggPiAwO1xufVxuIiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiAtIHgnID49IDA7XG4gIGFzc2Vy
+dCB4ICogeCA+IDA7XG59XG4iLCJzb3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiAtIHgnICAwO1xuICBhc3NlcnQg
+eCAqIHggPiAwO1xufVxuIiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiAtIHgnIDwgMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cbiIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiAtIHgnIDw9IDA7XG4gIGFzc2Vy
+dCB4ICogeCA+IDA7XG59XG4iLCJzb3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiAtIHgnIDw9IDA7XG4gIFxuICBh
+c3NlcnQgeCAqIHggPiAwO1xufVxuIiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiAtIHgnIDw9IDA7XG4gIGFzc1xu
+ICBhc3NlcnQgeCAqIHggPiAwO1xufVxuIiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiAtIHgnIDw9IDA7XG4gIGFzc2Vy
+XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG4iLCJzb3VyY2VJc0ZpbGUiOmZhbHNlfQ==
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiAtIHgnIDw9IDA7XG4gIGFzc1xu
+ICBhc3NlcnQgeCAqIHggPiAwO1xufVxuIiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiAtIHgnIDw9IDA7XG4gIGFzc3Vt
+ZSB5IDwgMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cbiIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiAtIHgnIDw9IDA7XG4gIGFzc3Vt
+ZSB5IDwgMDtcbiAgYXNzZXJ0IDtcbn1cbiIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiAtIHgnIDw9IDA7XG4gIGFzc3Vt
+ZSB5IDwgMDtcbiAgYXNzZXJ0IDtcbn1cbiIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiAtIHgnIDw9IDA7XG4gIGFzc3Vt
+ZSB5IDwgMDtcbiAgYXNzZXJ0IGZhbDtcbn1cbiIsInNvdXJjZUlzRmlsZSI6ZmFsc2V9
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiAtIHgnIDw9IDA7XG4gIGFzc3Vt
+ZSB5IDwgMDtcbiAgYXNzZXJ0IGZhbHNlO1xufVxuIiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
+verify
+eyJhcmdzIjpbIi9jb21waWxlOjAiLCIvbm9sb2dvIiwiL3ByaW50VG9vbHRpcHMiLCIvdGltZUxp
+bWl0OjIwIl0sImZpbGVuYW1lIjoidHJhbnNjcmlwdCIsInNvdXJjZSI6Im1ldGhvZCBBKGE6aW50
+KSByZXR1cm5zIChiOiBpbnQpIHtcbiAgYiA6PSBhO1xufVxuXG5zdGF0aWMgbWV0aG9kIE0nKHQ6
+IG5hdClcbiAgcmVxdWlyZXMgdCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0g
+MiwgMztcbiAgYXNzZXJ0IGZvcmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0
+IHggKiB4ID4gMDtcbn1cblxuXG5zdGF0aWMgbWV0aG9kIE0wKHQ6IG5hdClcbiAgcmVxdWlyZXMg
+dCA+IDBcbntcbiAgdmFyIHggOj0gMTtcbiAgdmFyIHksIHogOj0gMiwgMztcbiAgYXNzZXJ0IGZv
+cmFsbCB4JzogaW50IDo6IHgnICogeCcgPj0gMDtcbiAgYXNzZXJ0IHggKiB4ID4gMDtcbn1cblxu
+c3RhdGljIG1ldGhvZCBNMSh0OiBuYXQpXG4gIHJlcXVpcmVzIHQgPiAwXG57XG4gIHZhciB4IDo9
+IDE7XG4gIHZhciB5LCB6IDo9IDIsIDM7XG4gIGFzc2VydCBmb3JhbGwgeCc6IGludCA6OiB4JyAq
+IHgnID49IDA7XG4gIGFzc2VydCB4ICogeCA+IDA7XG59XG5cbnN0YXRpYyBtZXRob2QgTTIodDog
+bmF0KVxuICByZXF1aXJlcyB0ID4gMFxue1xuICB2YXIgeCA6PSAxO1xuICB2YXIgeSwgeiA6PSAy
+LCAzO1xuICBhc3NlcnQgZm9yYWxsIHgnOiBpbnQgOjogeCcgKiAtIHgnIDw9IDA7XG4gIGFzc3Vt
+ZSB5IDwgMDtcbiAgYXNzZXJ0IGZhbHNlO1xufVxuIiwic291cmNlSXNGaWxlIjpmYWxzZX0=
+[[DAFNY-CLIENT: EOM]]
diff --git a/Test/server/simple-session.transcript.expect b/Test/server/simple-session.transcript.expect
new file mode 100644
index 00000000..a5f841bc
--- /dev/null
+++ b/Test/server/simple-session.transcript.expect
@@ -0,0 +1,992 @@
+# Reading from simple-session.transcript
+
+Verifying CheckWellformed$$_module.__default.A ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+ [2 proof obligations] error
+transcript(3,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [2 proof obligations] error
+transcript(3,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [2 proof obligations] error
+transcript(3,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [2 proof obligations] error
+transcript(3,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+
+Verifying CheckWellformed$$_module.__default.A ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+ [0 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,13): Error: rbrace expected
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(6,2): Error: rbrace expected
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+ [0 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [0 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [0 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(7,0): Error: invalid UpdateStmt
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [0 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(7,0): Error: invalid VarDeclStatement
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+ [1 proof obligation] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [1 proof obligation] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(7,11): Error: the number of left-hand sides (2) and right-hand sides (1) must match for a multi-assignment
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(7,11): Error: the number of left-hand sides (2) and right-hand sides (1) must match for a multi-assignment
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+ [2 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [2 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [2 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+ [3 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [3 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [3 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(6,2): Error: EOF expected
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(6,2): Error: EOF expected
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+ [3 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(11,0): Error: invalid UpdateStmt
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(11,0): Error: semi expected
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(11,0): Error: invalid UnaryExpression
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,25): Error: openparen expected
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,25): Error: openparen expected
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,26): Error: invalid QSep
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,28): Error: invalid QSep
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,27): Error: invalid UnaryExpression
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,9): Warning: /!\ No terms found to trigger on.
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+ [1 proof obligation] error
+transcript(10,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,9): Warning: /!\ No terms found to trigger on.
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+ [1 proof obligation] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,9): Warning: /!\ No terms found to trigger on.
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [1 proof obligation] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(12,0): Error: invalid UpdateStmt
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,9): Warning: /!\ No terms found to trigger on.
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+ [1 proof obligation] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,9): Warning: /!\ No terms found to trigger on.
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [1 proof obligation] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,14): Error: Duplicate member name: M'
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,14): Error: Duplicate member name: M'
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,14): Error: Duplicate member name: M'
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,14): Error: Duplicate member name: M'
+transcript(24,14): Error: Duplicate member name: M'
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,14): Error: Duplicate member name: M'
+transcript(24,14): Error: Duplicate member name: M'
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,14): Error: Duplicate member name: M'
+transcript(24,14): Error: Duplicate member name: M'
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,14): Error: Duplicate member name: M'
+transcript(24,14): Error: Duplicate member name: M'
+transcript(33,14): Error: Duplicate member name: M'
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,14): Error: Duplicate member name: M
+transcript(33,14): Error: Duplicate member name: M
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,9): Warning: /!\ No terms found to trigger on.
+transcript(20,9): Warning: /!\ No terms found to trigger on.
+transcript(29,9): Warning: /!\ No terms found to trigger on.
+transcript(38,9): Warning: /!\ No terms found to trigger on.
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [1 proof obligation] verified
+
+Verifying CheckWellformed$$_module.__default.M0 ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M0 ...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M1 ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M1 ...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M2 ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M2 ...
+ [5 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,9): Warning: /!\ No terms found to trigger on.
+transcript(20,9): Warning: /!\ No terms found to trigger on.
+transcript(29,9): Warning: /!\ No terms found to trigger on.
+transcript(38,9): Warning: /!\ No terms found to trigger on.
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [1 proof obligation] verified
+
+Verifying CheckWellformed$$_module.__default.M0 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M0...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M0 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M0...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M1 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M1...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M1 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M1...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M2 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M2...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M2 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M2...
+ [5 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,9): Warning: /!\ No terms found to trigger on.
+transcript(20,9): Warning: /!\ No terms found to trigger on.
+transcript(29,9): Warning: /!\ No terms found to trigger on.
+transcript(38,9): Warning: /!\ No terms found to trigger on.
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [1 proof obligation] verified
+
+Verifying CheckWellformed$$_module.__default.M0 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M0...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M0 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M0...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M1 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M1...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M1 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M1...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M2 ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M2 ...
+ [2 proof obligations] error
+transcript(38,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(38,38): Error: semi expected
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,9): Warning: /!\ No terms found to trigger on.
+transcript(20,9): Warning: /!\ No terms found to trigger on.
+transcript(29,9): Warning: /!\ No terms found to trigger on.
+transcript(38,9): Warning: /!\ No terms found to trigger on.
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [1 proof obligation] verified
+
+Verifying CheckWellformed$$_module.__default.M0 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M0...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M0 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M0...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M1 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M1...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M1 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M1...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M2 ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M2 ...
+ [2 proof obligations] error
+transcript(38,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,9): Warning: /!\ No terms found to trigger on.
+transcript(20,9): Warning: /!\ No terms found to trigger on.
+transcript(29,9): Warning: /!\ No terms found to trigger on.
+transcript(38,9): Warning: /!\ No terms found to trigger on.
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [1 proof obligation] verified
+
+Verifying CheckWellformed$$_module.__default.M0 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M0...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M0 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M0...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M1 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M1...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M1 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M1...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M2 ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M2 ...
+ [2 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,9): Warning: /!\ No terms found to trigger on.
+transcript(20,9): Warning: /!\ No terms found to trigger on.
+transcript(29,9): Warning: /!\ No terms found to trigger on.
+transcript(38,9): Warning: /!\ No terms found to trigger on.
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [1 proof obligation] verified
+
+Verifying CheckWellformed$$_module.__default.M0 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M0...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M0 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M0...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M1 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M1...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M1 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M1...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M2 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M2...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M2 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M2...
+ [2 proof obligations] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(40,2): Error: invalid UpdateStmt
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(40,2): Error: invalid UpdateStmt
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(40,2): Error: invalid UpdateStmt
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,9): Warning: /!\ No terms found to trigger on.
+transcript(20,9): Warning: /!\ No terms found to trigger on.
+transcript(29,9): Warning: /!\ No terms found to trigger on.
+transcript(38,9): Warning: /!\ No terms found to trigger on.
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [1 proof obligation] verified
+
+Verifying CheckWellformed$$_module.__default.M0 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M0...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M0 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M0...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M1 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M1...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M1 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M1...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M2 ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M2 ...
+ [1 proof obligation] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(40,9): Error: invalid AssertStmt
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(40,9): Error: invalid AssertStmt
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(40,9): Error: unresolved identifier: fal
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,9): Warning: /!\ No terms found to trigger on.
+transcript(20,9): Warning: /!\ No terms found to trigger on.
+transcript(29,9): Warning: /!\ No terms found to trigger on.
+transcript(38,9): Warning: /!\ No terms found to trigger on.
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [1 proof obligation] verified
+
+Verifying CheckWellformed$$_module.__default.M0 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M0...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M0 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M0...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M1 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M1...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M1 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M1...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M2 ...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M2 ...
+ [1 proof obligation] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+transcript(5,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(15,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(24,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(33,0): Warning: module-level methods are always non-instance, so the 'static' keyword is not allowed here
+transcript(10,9): Warning: /!\ No terms found to trigger on.
+transcript(20,9): Warning: /!\ No terms found to trigger on.
+transcript(29,9): Warning: /!\ No terms found to trigger on.
+transcript(38,9): Warning: /!\ No terms found to trigger on.
+
+Verifying CheckWellformed$$_module.__default.A ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.A ...
+Retrieving cached verification result for implementation Impl$$_module.__default.A...
+ [0 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M_k ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M_k...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M_k ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M_k...
+ [1 proof obligation] verified
+
+Verifying CheckWellformed$$_module.__default.M0 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M0...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M0 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M0...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M1 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M1...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M1 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M1...
+ [5 proof obligations] verified
+
+Verifying CheckWellformed$$_module.__default.M2 ...
+Retrieving cached verification result for implementation CheckWellformed$$_module.__default.M2...
+ [0 proof obligations] verified
+
+Verifying Impl$$_module.__default.M2 ...
+Retrieving cached verification result for implementation Impl$$_module.__default.M2...
+ [1 proof obligation] verified
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
+Verification completed successfully!
+[SUCCESS] [[DAFNY-SERVER: EOM]]
diff --git a/Test/triggers/auto-triggers-fix-an-issue-listed-in-the-ironclad-notebook.dfy b/Test/triggers/auto-triggers-fix-an-issue-listed-in-the-ironclad-notebook.dfy
new file mode 100644
index 00000000..09032453
--- /dev/null
+++ b/Test/triggers/auto-triggers-fix-an-issue-listed-in-the-ironclad-notebook.dfy
@@ -0,0 +1,23 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This example was listed in IronClad's notebook as one place were z3 picked
+// much too liberal triggers. THe Boogie code for this is shown below:
+//
+// forall k#2: Seq Box :: $Is(k#2, TSeq(TInt)) && $IsAlloc(k#2, TSeq(TInt), $Heap)
+// ==> Seq#Equal(_module.__default.HashtableLookup($Heap, h1#0, k#2),
+// _module.__default.HashtableLookup($Heap, h2#0, k#2))
+//
+// and z3 would pick $Is(k#2, TSeq(TInt)) or $IsAlloc(k#2, TSeq(TInt), $Heap) as
+// triggers.
+
+type Key = seq<int>
+type Value = seq<int>
+
+type Hashtable = map<Key, Value>
+function HashtableLookup(h: Hashtable, k: Key): Value
+
+lemma HashtableAgreement(h1:Hashtable, h2:Hashtable, k:Key)
+ requires forall k :: HashtableLookup(h1,k) == HashtableLookup(h2,k) {
+ assert true || (k in h1) == (k in h2);
+}
diff --git a/Test/triggers/auto-triggers-fix-an-issue-listed-in-the-ironclad-notebook.dfy.expect b/Test/triggers/auto-triggers-fix-an-issue-listed-in-the-ironclad-notebook.dfy.expect
new file mode 100644
index 00000000..46ec143e
--- /dev/null
+++ b/Test/triggers/auto-triggers-fix-an-issue-listed-in-the-ironclad-notebook.dfy.expect
@@ -0,0 +1,4 @@
+auto-triggers-fix-an-issue-listed-in-the-ironclad-notebook.dfy(21,11): Info: Selected triggers:
+ {HashtableLookup(h2, k)}, {HashtableLookup(h1, k)}
+
+Dafny program verifier finished with 3 verified, 0 errors
diff --git a/Test/triggers/constructors-cause-matching-loops.dfy b/Test/triggers/constructors-cause-matching-loops.dfy
new file mode 100644
index 00000000..61e6a66b
--- /dev/null
+++ b/Test/triggers/constructors-cause-matching-loops.dfy
@@ -0,0 +1,11 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file is just a small test to check that constructors do cause loops
+
+datatype Nat = Zero | Succ(x: Nat)
+function f(n: Nat): Nat
+
+method M() {
+ assert forall s :: true || f(Succ(s)) == f(s);
+}
diff --git a/Test/triggers/constructors-cause-matching-loops.dfy.expect b/Test/triggers/constructors-cause-matching-loops.dfy.expect
new file mode 100644
index 00000000..e7a671ab
--- /dev/null
+++ b/Test/triggers/constructors-cause-matching-loops.dfy.expect
@@ -0,0 +1,6 @@
+constructors-cause-matching-loops.dfy(10,9): Info: Selected triggers: {Succ(s)}
+ Rejected triggers:
+ {f(s)} (may loop with "f(Succ(s))")
+ {f(Succ(s))} (more specific than {Succ(s)})
+
+Dafny program verifier finished with 3 verified, 0 errors
diff --git a/Test/triggers/function-applications-are-triggers.dfy b/Test/triggers/function-applications-are-triggers.dfy
new file mode 100644
index 00000000..0aad9018
--- /dev/null
+++ b/Test/triggers/function-applications-are-triggers.dfy
@@ -0,0 +1,15 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file checks that function applications yield trigger candidates
+
+method M(P: (int -> int) -> bool, g: int -> int)
+ requires P.requires(g)
+ requires P(g) {
+ assume forall f: int -> int :: P.requires(f);
+ assume forall f: int -> int :: P(f) ==> f.requires(10) && f(10) == 0;
+ assert forall f: int -> int ::
+ (forall x :: f.requires(x) && g.requires(x) ==> f(x) == g(x)) ==>
+ f.requires(10) ==>
+ f(10) == 0;
+}
diff --git a/Test/triggers/function-applications-are-triggers.dfy.expect b/Test/triggers/function-applications-are-triggers.dfy.expect
new file mode 100644
index 00000000..1214536d
--- /dev/null
+++ b/Test/triggers/function-applications-are-triggers.dfy.expect
@@ -0,0 +1,13 @@
+function-applications-are-triggers.dfy(9,9): Info: Selected triggers: {P.requires(f)}
+function-applications-are-triggers.dfy(10,9): Info: For expression "P(f) ==> f.requires(10)":
+ Selected triggers:
+ {f(10)}, {f.requires(10)}, {P(f)}
+function-applications-are-triggers.dfy(10,9): Info: For expression "P(f) ==> f(10) == 0":
+ Selected triggers:
+ {f(10)}, {f.requires(10)}, {P(f)}
+function-applications-are-triggers.dfy(11,9): Info: Selected triggers:
+ {f(10)}, {f.requires(10)}
+function-applications-are-triggers.dfy(12,5): Info: Selected triggers:
+ {g(x)}, {f(x)}, {g.requires(x)}, {f.requires(x)}
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/triggers/large-quantifiers-dont-break-dafny.dfy b/Test/triggers/large-quantifiers-dont-break-dafny.dfy
new file mode 100644
index 00000000..58eb56e1
--- /dev/null
+++ b/Test/triggers/large-quantifiers-dont-break-dafny.dfy
@@ -0,0 +1,61 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This test ensures that the trigger collector (the routine that picks trigger
+// candidates) does not actually consider all subsets of terms; if it did, the
+// following would take horribly long
+
+predicate P0(x: bool)
+predicate P1(x: bool)
+predicate P2(x: bool)
+predicate P3(x: bool)
+predicate P4(x: bool)
+predicate P5(x: bool)
+predicate P6(x: bool)
+predicate P7(x: bool)
+predicate P8(x: bool)
+predicate P9(x: bool)
+predicate P10(x: bool)
+predicate P11(x: bool)
+predicate P12(x: bool)
+predicate P13(x: bool)
+predicate P14(x: bool)
+predicate P15(x: bool)
+predicate P16(x: bool)
+predicate P17(x: bool)
+predicate P18(x: bool)
+predicate P19(x: bool)
+predicate P20(x: bool)
+predicate P21(x: bool)
+predicate P22(x: bool)
+predicate P23(x: bool)
+predicate P24(x: bool)
+predicate P25(x: bool)
+predicate P26(x: bool)
+predicate P27(x: bool)
+predicate P28(x: bool)
+predicate P29(x: bool)
+predicate P30(x: bool)
+predicate P31(x: bool)
+predicate P32(x: bool)
+predicate P33(x: bool)
+predicate P34(x: bool)
+predicate P35(x: bool)
+predicate P36(x: bool)
+predicate P37(x: bool)
+predicate P38(x: bool)
+predicate P39(x: bool)
+predicate P40(x: bool)
+predicate P41(x: bool)
+predicate P42(x: bool)
+predicate P43(x: bool)
+predicate P44(x: bool)
+predicate P45(x: bool)
+predicate P46(x: bool)
+predicate P47(x: bool)
+predicate P48(x: bool)
+predicate P49(x: bool)
+
+method M() {
+ assert forall x :: true || P0(x) || P1(x) || P2(x) || P3(x) || P4(x) || P5(x) || P6(x) || P7(x) || P8(x) || P9(x) || P10(x) || P11(x) || P12(x) || P13(x) || P14(x) || P15(x) || P16(x) || P17(x) || P18(x) || P19(x) || P20(x) || P21(x) || P22(x) || P23(x) || P24(x) || P25(x) || P26(x) || P27(x) || P28(x) || P29(x) || P30(x) || P31(x) || P32(x) || P33(x) || P34(x) || P35(x) || P36(x) || P37(x) || P38(x) || P39(x) || P40(x) || P41(x) || P42(x) || P43(x) || P44(x) || P45(x) || P46(x) || P47(x) || P48(x) || P49(x);
+}
diff --git a/Test/triggers/large-quantifiers-dont-break-dafny.dfy.expect b/Test/triggers/large-quantifiers-dont-break-dafny.dfy.expect
new file mode 100644
index 00000000..5e7c14b9
--- /dev/null
+++ b/Test/triggers/large-quantifiers-dont-break-dafny.dfy.expect
@@ -0,0 +1,4 @@
+large-quantifiers-dont-break-dafny.dfy(60,9): Info: Selected triggers:
+ {P49(x)}, {P48(x)}, {P47(x)}, {P46(x)}, {P45(x)}, {P44(x)}, {P43(x)}, {P42(x)}, {P41(x)}, {P40(x)}, {P39(x)}, {P38(x)}, {P37(x)}, {P36(x)}, {P35(x)}, {P34(x)}, {P33(x)}, {P32(x)}, {P31(x)}, {P30(x)}, {P29(x)}, {P28(x)}, {P27(x)}, {P26(x)}, {P25(x)}, {P24(x)}, {P23(x)}, {P22(x)}, {P21(x)}, {P20(x)}, {P19(x)}, {P18(x)}, {P17(x)}, {P16(x)}, {P15(x)}, {P14(x)}, {P13(x)}, {P12(x)}, {P11(x)}, {P10(x)}, {P9(x)}, {P8(x)}, {P7(x)}, {P6(x)}, {P5(x)}, {P4(x)}, {P3(x)}, {P2(x)}, {P1(x)}, {P0(x)}
+
+Dafny program verifier finished with 52 verified, 0 errors
diff --git a/Test/triggers/loop-detection-is-not-too-strict.dfy b/Test/triggers/loop-detection-is-not-too-strict.dfy
new file mode 100644
index 00000000..81f764ad
--- /dev/null
+++ b/Test/triggers/loop-detection-is-not-too-strict.dfy
@@ -0,0 +1,40 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This test shows that the loop detection engine makes compromises when looking
+// for subexpressions matching a trigger; in particular, it allows a
+// subexpression to match a trigger without reporting a loop and without being
+// equal to that trigger, as long as the only differences are variable
+
+predicate P(x: int, y: int)
+predicate Q(x: int)
+
+method Test(z: int) {
+ // P(x, y) and P(y, x) might look like they would cause a loop. Since they
+ // only differ by their variables, though, they won't raise flags.
+ assume forall x: int, y: int :: P(x, y) == P(y, x);
+
+ // This works independent of extra parentheses:
+ assume forall x: int, y: int :: P(x, y) == (P(y, x));
+
+ // Contrast with the following:
+ assume forall x: int, y: int :: P(x, y) == P(x, y+1);
+
+ // The following examples were made legal after an exchange where Chris
+ // pointed examples in the IronClad sources where things like this were
+ // incorrectly flagged.
+ assert forall x :: true || Q(x) || Q(0);
+ assert forall x :: true || Q(x) || Q(z);
+ assert forall x :: true || P(x, 1) || P(x, z);
+
+ // Support for the following was added following a discussion with Rustan; in
+ // the second one the expression `if z > 1 then z else 3 * z + 1` is not
+ // directly a constant expression, but it does not involve x, so it's ok:
+ assert forall x :: true || Q(x) || Q(0+1);
+ assert forall x :: true || Q(x) || Q(if z > 1 then z else 3 * z + 1);
+ // Sanity check:
+ assert forall x :: true || Q(x) || Q(if z > 1 then x else 3 * z + 1);
+
+ // WISH: It might also be good to zeta-reduce before loop detection.
+ assert forall x :: true || Q(x) || (var xx := x+1; Q(xx));
+}
diff --git a/Test/triggers/loop-detection-is-not-too-strict.dfy.expect b/Test/triggers/loop-detection-is-not-too-strict.dfy.expect
new file mode 100644
index 00000000..65ea0d79
--- /dev/null
+++ b/Test/triggers/loop-detection-is-not-too-strict.dfy.expect
@@ -0,0 +1,17 @@
+loop-detection-is-not-too-strict.dfy(15,9): Info: Selected triggers:
+ {P(y, x)}, {P(x, y)}
+loop-detection-is-not-too-strict.dfy(18,9): Info: Selected triggers:
+ {P(y, x)}, {P(x, y)}
+loop-detection-is-not-too-strict.dfy(21,9): Warning: Selected triggers: {P(x, y)} (may loop with "P(x, y + 1)")
+ /!\ Suppressing loops would leave this expression without triggers.
+loop-detection-is-not-too-strict.dfy(26,9): Info: Selected triggers: {Q(x)}
+loop-detection-is-not-too-strict.dfy(27,9): Info: Selected triggers: {Q(x)}
+loop-detection-is-not-too-strict.dfy(28,9): Info: Selected triggers:
+ {P(x, z)}, {P(x, 1)}
+loop-detection-is-not-too-strict.dfy(33,9): Info: Selected triggers: {Q(x)}
+loop-detection-is-not-too-strict.dfy(34,9): Info: Selected triggers: {Q(x)}
+loop-detection-is-not-too-strict.dfy(36,9): Warning: Selected triggers: {Q(x)} (may loop with "Q(if z > 1 then x else 3 * z + 1)")
+ /!\ Suppressing loops would leave this expression without triggers.
+loop-detection-is-not-too-strict.dfy(39,9): Info: Selected triggers: {Q(x)}
+
+Dafny program verifier finished with 4 verified, 0 errors
diff --git a/Test/triggers/loop-detection-looks-at-ranges-too.dfy b/Test/triggers/loop-detection-looks-at-ranges-too.dfy
new file mode 100644
index 00000000..7a99ea2d
--- /dev/null
+++ b/Test/triggers/loop-detection-looks-at-ranges-too.dfy
@@ -0,0 +1,14 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file checks that loops between the range and the term of a quantifier
+// are properly detected.
+
+predicate P(x: int)
+
+method M(x: int) {
+ // This will be flagged as a loop even without looking at the range
+ assert true || forall x: int | P(x) :: P(x+1);
+ // This requires checking the range for looping terms
+ assert true || forall x: int | P(x+1) :: P(x);
+}
diff --git a/Test/triggers/loop-detection-looks-at-ranges-too.dfy.expect b/Test/triggers/loop-detection-looks-at-ranges-too.dfy.expect
new file mode 100644
index 00000000..a32e4a60
--- /dev/null
+++ b/Test/triggers/loop-detection-looks-at-ranges-too.dfy.expect
@@ -0,0 +1,6 @@
+loop-detection-looks-at-ranges-too.dfy(11,17): Warning: Selected triggers: {P(x)} (may loop with "P(x + 1)")
+ /!\ Suppressing loops would leave this expression without triggers.
+loop-detection-looks-at-ranges-too.dfy(13,17): Warning: Selected triggers: {P(x)} (may loop with "P(x + 1)")
+ /!\ Suppressing loops would leave this expression without triggers.
+
+Dafny program verifier finished with 3 verified, 0 errors
diff --git a/Test/triggers/loop-detection-messages--unit-tests.dfy b/Test/triggers/loop-detection-messages--unit-tests.dfy
new file mode 100644
index 00000000..c1560317
--- /dev/null
+++ b/Test/triggers/loop-detection-messages--unit-tests.dfy
@@ -0,0 +1,29 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file is a series of basic tests for loop detection, focusing on the
+// warnings and information messages
+
+function f(i: int): int
+function g(i: int): int
+
+method M() {
+ assert forall i :: false ==> f(i) == f(f(i));
+ assert forall i :: false ==> f(i) == f(i+1);
+ assert forall i {:matchingloop} :: false ==> f(i) == f(i+1);
+
+ assert forall i :: false ==> f(i) == f(i+1) && f(i) == g(i);
+ assert forall i :: false ==> f(i) == f(i+1) && f(i) == f(i);
+ assert forall i {:matchingloop} :: false ==> f(i) == f(i+1) && f(i) == f(i);
+
+ assert forall i :: false ==> f(i) == 0;
+ assert forall i :: false ==> f(i+1) == 0;
+ assert forall i {:autotriggers false} :: false ==> f(i+1) == 0;
+
+ assert forall i, j: int :: false ==> f(i) == f(j);
+ assert forall i, j: int :: false ==> f(i) == f(i);
+ assert forall i, j: int :: false ==> f(i) == f(i) && g(j) == 0;
+ assert forall i, j: int :: false ==> f(i) == f(i) && g(j+1) == 0;
+ assert forall i, j: int {:autotriggers false} :: false ==> f(i) == f(i);
+ assert forall i, j: int {:trigger f(i), g(j)} :: false ==> f(i) == f(i);
+}
diff --git a/Test/triggers/loop-detection-messages--unit-tests.dfy.expect b/Test/triggers/loop-detection-messages--unit-tests.dfy.expect
new file mode 100644
index 00000000..eba8c179
--- /dev/null
+++ b/Test/triggers/loop-detection-messages--unit-tests.dfy.expect
@@ -0,0 +1,37 @@
+loop-detection-messages--unit-tests.dfy(11,9): Info: Selected triggers: {f(f(i))}
+ Rejected triggers: {f(i)} (may loop with "f(f(i))")
+loop-detection-messages--unit-tests.dfy(12,9): Warning: Selected triggers: {f(i)} (may loop with "f(i + 1)")
+ /!\ Suppressing loops would leave this expression without triggers.
+loop-detection-messages--unit-tests.dfy(13,9): Info: Selected triggers: {f(i)} (may loop with "f(i + 1)")
+loop-detection-messages--unit-tests.dfy(15,9): Info: For expression "false ==> f(i) == f(i + 1)":
+ Selected triggers: {g(i)}
+ Rejected triggers: {f(i)} (may loop with "f(i + 1)")
+loop-detection-messages--unit-tests.dfy(15,9): Info: For expression "false ==> f(i) == g(i)":
+ Selected triggers:
+ {g(i)}, {f(i)}
+loop-detection-messages--unit-tests.dfy(16,9): Warning: For expression "false ==> f(i) == f(i + 1)":
+ Selected triggers: {f(i)} (may loop with "f(i + 1)")
+ /!\ Suppressing loops would leave this expression without triggers.
+loop-detection-messages--unit-tests.dfy(16,9): Info: For expression "false ==> f(i) == f(i)":
+ Selected triggers: {f(i)}
+loop-detection-messages--unit-tests.dfy(17,9): Info: For expression "false ==> f(i) == f(i + 1)":
+ Selected triggers: {f(i)} (may loop with "f(i + 1)")
+loop-detection-messages--unit-tests.dfy(17,9): Info: For expression "false ==> f(i) == f(i)":
+ Selected triggers: {f(i)}
+loop-detection-messages--unit-tests.dfy(19,9): Info: Selected triggers: {f(i)}
+loop-detection-messages--unit-tests.dfy(20,9): Warning: /!\ No terms found to trigger on.
+loop-detection-messages--unit-tests.dfy(21,9): Info: Not generating triggers for "false ==> f(i + 1) == 0". Note that {:autotriggers false} can cause instabilities. Consider using {:nowarn}, {:matchingloop} (not great either), or a manual trigger instead.
+loop-detection-messages--unit-tests.dfy(23,9): Info: Selected triggers: {f(j), f(i)}
+loop-detection-messages--unit-tests.dfy(24,9): Warning: /!\ No trigger covering all quantified variables found.
+loop-detection-messages--unit-tests.dfy(25,9): Info: For expression "false ==> f(i) == f(i)":
+ Selected triggers: {g(j), f(i)}
+loop-detection-messages--unit-tests.dfy(25,9): Info: For expression "false ==> g(j) == 0":
+ Selected triggers: {g(j), f(i)}
+loop-detection-messages--unit-tests.dfy(26,9): Warning: For expression "false ==> f(i) == f(i)":
+ /!\ No trigger covering all quantified variables found.
+loop-detection-messages--unit-tests.dfy(26,9): Warning: For expression "false ==> g(j + 1) == 0":
+ /!\ No trigger covering all quantified variables found.
+loop-detection-messages--unit-tests.dfy(27,9): Info: Not generating triggers for "false ==> f(i) == f(i)". Note that {:autotriggers false} can cause instabilities. Consider using {:nowarn}, {:matchingloop} (not great either), or a manual trigger instead.
+loop-detection-messages--unit-tests.dfy(28,9): Info: Not generating triggers for "false ==> f(i) == f(i)".
+
+Dafny program verifier finished with 4 verified, 0 errors
diff --git a/Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy b/Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy
new file mode 100644
index 00000000..c54089f2
--- /dev/null
+++ b/Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy
@@ -0,0 +1,32 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file shows cases where loops could hide behind equalities. In all three
+// cases we behave the same; that is, we don't warn for loops that would only
+// exist in the presence of an equality. The easiest way to understand the
+// issue, I (CPC) feel, is to look at the old case: f(x) could very well loop
+// with old(f(f(x))) if f(f(x)) did not change the heap at all.
+
+// This equality issue is generally undecidable. It could make sense to special
+// case `old`, but KRML and CPC decided against it on 2015-08-21. Future
+// experiences could cause a change of mind.
+
+class C { }
+function f(c: C): C
+function g(c: C): C
+function h(c: C, i: int): C
+
+// With explicit arguments
+method M0(i: int, j: int, sc: set<C>) {
+ assert forall c | c in sc :: true || h(c, i) == h(h(c, j), j);
+}
+
+// With implicit arguments (f and g respectively, to Apply)
+method M1(f: int -> int, g: int -> int) {
+ assert forall x :: true || f(x) == g(f(x));
+}
+
+// With implicit arguments (the heap, to old)
+method M2(sc: set<C>) {
+ assert forall c | c in sc :: true || f(c) == old(f(f(c)));
+}
diff --git a/Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy.expect b/Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy.expect
new file mode 100644
index 00000000..e900c1f9
--- /dev/null
+++ b/Test/triggers/looping-is-hard-to-decide-modulo-equality.dfy.expect
@@ -0,0 +1,10 @@
+looping-is-hard-to-decide-modulo-equality.dfy(21,9): Info: Selected triggers:
+ {h(h(c, j), j)}, {h(c, i)}, {c in sc}
+ Rejected triggers: {h(c, j)} (may loop with "h(h(c, j), j)")
+looping-is-hard-to-decide-modulo-equality.dfy(26,9): Info: Selected triggers: {f(x)}
+ Rejected triggers: {g(f(x))} (more specific than {f(x)})
+looping-is-hard-to-decide-modulo-equality.dfy(31,9): Info: Selected triggers:
+ {old(f(f(c)))}, {f(c)}, {c in sc}
+ Rejected triggers: {old(f(c))} (may loop with "old(f(f(c)))")
+
+Dafny program verifier finished with 9 verified, 0 errors
diff --git a/Test/triggers/matrix-accesses-are-triggers.dfy b/Test/triggers/matrix-accesses-are-triggers.dfy
new file mode 100644
index 00000000..630fab9d
--- /dev/null
+++ b/Test/triggers/matrix-accesses-are-triggers.dfy
@@ -0,0 +1,9 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file checks that multi-dimensional array accesses yield trigger candidates
+
+method M(m: array2<int>)
+ requires m != null
+ requires forall i, j | 0 <= i < m.Length0 && 0 <= j < m.Length1 :: m[i, j] == m[j, i+1] {
+}
diff --git a/Test/triggers/matrix-accesses-are-triggers.dfy.expect b/Test/triggers/matrix-accesses-are-triggers.dfy.expect
new file mode 100644
index 00000000..572fc41f
--- /dev/null
+++ b/Test/triggers/matrix-accesses-are-triggers.dfy.expect
@@ -0,0 +1,12 @@
+matrix-accesses-are-triggers.dfy(8,11): Warning: Selected triggers: {m[i, j]} (may loop with "m[j, i + 1]")
+ /!\ Suppressing loops would leave this expression without triggers.
+matrix-accesses-are-triggers.dfy(8,81): Error: index 0 out of range
+Execution trace:
+ (0,0): anon0
+ (0,0): anon4_Then
+matrix-accesses-are-triggers.dfy(8,86): Error: index 1 out of range
+Execution trace:
+ (0,0): anon0
+ (0,0): anon4_Then
+
+Dafny program verifier finished with 1 verified, 2 errors
diff --git a/Test/triggers/nested-quantifiers-all-get-triggers.dfy b/Test/triggers/nested-quantifiers-all-get-triggers.dfy
new file mode 100644
index 00000000..a55019db
--- /dev/null
+++ b/Test/triggers/nested-quantifiers-all-get-triggers.dfy
@@ -0,0 +1,9 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This checks that nested quantifiers do get triggers, and that the parent
+// quantifier does not get annotated twice
+
+method M() {
+ ghost var x := forall s: set<int>, x: int :: (x in s ==> forall y :: y == x ==> y in s);
+}
diff --git a/Test/triggers/nested-quantifiers-all-get-triggers.dfy.expect b/Test/triggers/nested-quantifiers-all-get-triggers.dfy.expect
new file mode 100644
index 00000000..172f5607
--- /dev/null
+++ b/Test/triggers/nested-quantifiers-all-get-triggers.dfy.expect
@@ -0,0 +1,4 @@
+nested-quantifiers-all-get-triggers.dfy(8,17): Info: Selected triggers: {x in s}
+nested-quantifiers-all-get-triggers.dfy(8,59): Info: Selected triggers: {y in s}
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/triggers/old-is-a-special-case-for-triggers.dfy b/Test/triggers/old-is-a-special-case-for-triggers.dfy
new file mode 100644
index 00000000..4424e8d3
--- /dev/null
+++ b/Test/triggers/old-is-a-special-case-for-triggers.dfy
@@ -0,0 +1,32 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file ensures that `old()` receives the special treatment that it
+// requires; that is, `old(f(x))` is not less liberal than `f(x)`, and
+// old(f(f(x))) does not loop with f(x) (doesn't it?)
+
+class C { }
+function f(c: C): C
+function g(c: C): C
+function h(c: C, i: int): C
+
+method M(sc: set<C>)
+ // Ensure that old(c) does not get picked as a trigger
+ ensures forall c | c in sc :: true || c == old(f(c))
+
+ // This checks whether loop detection handles `old` expressions properly.
+ // In the first one f(c)/old(f(f(c))) is not reported as a loop. See
+ // looping-is-hard-to-decide-modulo-equalities.dfy for an explanation.
+ ensures forall c | c in sc :: true || f(c) == old(f(f(c)))
+ ensures forall c | c in sc :: true || old(f(f(c))) == old(g(f(c))) || old(f(g(c))) == g(f(c)) || f(g(c)) == g(f(c))
+
+ // These check that the final trigger filtering step doesn't get confused
+ // between old expressions and regular expressions.
+ ensures forall c | c in sc :: true || f(c) == old(g(f(c)))
+ ensures forall c | c in sc :: true || f(c) == old(f(c)) || old(g(f(c))) == g(f(c))
+
+ // WISH: A Dafny rewriter could cleanup expressions so that adding the
+ // expression forall c :: c == old(c) in a quantifier would cause a warning,
+ // instead of a trigger generation error as it does now.
+{
+}
diff --git a/Test/triggers/old-is-a-special-case-for-triggers.dfy.expect b/Test/triggers/old-is-a-special-case-for-triggers.dfy.expect
new file mode 100644
index 00000000..7388a911
--- /dev/null
+++ b/Test/triggers/old-is-a-special-case-for-triggers.dfy.expect
@@ -0,0 +1,22 @@
+old-is-a-special-case-for-triggers.dfy(15,10): Info: Selected triggers:
+ {old(f(c))}, {c in sc}
+old-is-a-special-case-for-triggers.dfy(20,10): Info: Selected triggers:
+ {old(f(f(c)))}, {f(c)}, {c in sc}
+ Rejected triggers: {old(f(c))} (may loop with "old(f(f(c)))")
+old-is-a-special-case-for-triggers.dfy(21,10): Info: Selected triggers:
+ {f(g(c))}, {g(f(c))}, {old(f(g(c)))}, {old(g(f(c)))}, {old(f(f(c)))}, {c in sc}
+ Rejected triggers:
+ {g(c)} (may loop with "g(f(c))")
+ {f(c)} (may loop with "f(g(c))")
+ {old(g(c))} (may loop with "old(g(f(c)))")
+ {old(f(c))} (may loop with "old(f(f(c)))", "old(f(g(c)))")
+old-is-a-special-case-for-triggers.dfy(25,10): Info: Selected triggers:
+ {old(f(c))}, {f(c)}, {c in sc}
+ Rejected triggers: {old(g(f(c)))} (more specific than {old(f(c))})
+old-is-a-special-case-for-triggers.dfy(26,10): Info: Selected triggers:
+ {old(f(c))}, {f(c)}, {c in sc}
+ Rejected triggers:
+ {g(f(c))} (more specific than {f(c)})
+ {old(g(f(c)))} (more specific than {old(f(c))})
+
+Dafny program verifier finished with 5 verified, 0 errors
diff --git a/Test/triggers/redundancy-detection-is-bidirectional.dfy b/Test/triggers/redundancy-detection-is-bidirectional.dfy
new file mode 100644
index 00000000..06541b70
--- /dev/null
+++ b/Test/triggers/redundancy-detection-is-bidirectional.dfy
@@ -0,0 +1,29 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This test checks for tricky cases of redundancy suppression when building
+// triggers.
+
+predicate P(x: int, y: int)
+predicate Q(x: int)
+predicate R(x: int)
+
+method M() {
+ // For this term, it is enough to order the terms by number of variables
+ assert forall x, y :: true || P(x, y) || Q(y) || R(x);
+ assert forall x, y :: true || Q(y) || P(x, y) || R(x);
+ assert forall x, y :: true || Q(y) || R(x) || P(x, y);
+}
+
+predicate PP(x: int, y: int, z: int)
+predicate QQ(x: int, y: int)
+predicate RR(x: int, y: int)
+predicate SS(x: int, y: int)
+
+method MM() {
+ // Not for this one, though
+ assert forall x, y, z, u, v, w :: true || PP(x, y, z) || QQ(x, u) || RR(y, v) || SS(z, w);
+ assert forall x, y, z, u, v, w :: true || QQ(x, u) || PP(x, y, z) || RR(y, v) || SS(z, w);
+ assert forall x, y, z, u, v, w :: true || QQ(x, u) || RR(y, v) || PP(x, y, z) || SS(z, w);
+ assert forall x, y, z, u, v, w :: true || QQ(x, u) || RR(y, v) || SS(z, w) || PP(x, y, z);
+}
diff --git a/Test/triggers/redundancy-detection-is-bidirectional.dfy.expect b/Test/triggers/redundancy-detection-is-bidirectional.dfy.expect
new file mode 100644
index 00000000..78c9e7ca
--- /dev/null
+++ b/Test/triggers/redundancy-detection-is-bidirectional.dfy.expect
@@ -0,0 +1,12 @@
+redundancy-detection-is-bidirectional.dfy(13,9): Info: Selected triggers:
+ {R(x), Q(y)}, {P(x, y)}
+redundancy-detection-is-bidirectional.dfy(14,9): Info: Selected triggers:
+ {R(x), Q(y)}, {P(x, y)}
+redundancy-detection-is-bidirectional.dfy(15,9): Info: Selected triggers:
+ {P(x, y)}, {R(x), Q(y)}
+redundancy-detection-is-bidirectional.dfy(25,9): Info: Selected triggers: {SS(z, w), RR(y, v), QQ(x, u)}
+redundancy-detection-is-bidirectional.dfy(26,9): Info: Selected triggers: {SS(z, w), RR(y, v), QQ(x, u)}
+redundancy-detection-is-bidirectional.dfy(27,9): Info: Selected triggers: {SS(z, w), RR(y, v), QQ(x, u)}
+redundancy-detection-is-bidirectional.dfy(28,9): Info: Selected triggers: {SS(z, w), RR(y, v), QQ(x, u)}
+
+Dafny program verifier finished with 11 verified, 0 errors
diff --git a/Test/triggers/regression-tests.dfy b/Test/triggers/regression-tests.dfy
new file mode 100644
index 00000000..263e424a
--- /dev/null
+++ b/Test/triggers/regression-tests.dfy
@@ -0,0 +1,20 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This tests checks that quantifier splitting is resilient to the fact that
+// certain statements (like calc) can return duplicate subexpressions. This was
+// once a problem, because a quantifier that got returned twice would get split
+// on the first pass over it, and would have its nely created children re-split
+// on the second pass. This created a split quantifier whose children were split
+// quantifiers, which violated an invariant of spliit quantifiers.
+
+abstract module Base { }
+
+module Blah refines Base {
+ lemma A() {
+ calc {
+ forall b :: b;
+ }
+ }
+}
+
diff --git a/Test/triggers/regression-tests.dfy.expect b/Test/triggers/regression-tests.dfy.expect
new file mode 100644
index 00000000..e780e966
--- /dev/null
+++ b/Test/triggers/regression-tests.dfy.expect
@@ -0,0 +1,3 @@
+regression-tests.dfy(16,5): Warning: /!\ No terms found to trigger on.
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/triggers/set-construction-is-a-good-trigger.dfy b/Test/triggers/set-construction-is-a-good-trigger.dfy
new file mode 100644
index 00000000..b3dee172
--- /dev/null
+++ b/Test/triggers/set-construction-is-a-good-trigger.dfy
@@ -0,0 +1,12 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file ensures that display expressions can be picked as triggers. This is
+// useful for code that checks if a set, sequence, or multiset is a singleton.
+
+method M(s: seq<int>, st: set<int>, mst: multiset<int>)
+ requires exists y :: s == [y] // Seq#Build(Seq#Empty(): Seq Box, $Box(y#3))
+ requires exists y :: st == {y} // Set#UnionOne(Set#Empty(): Set Box, $Box(y#4))
+ requires exists y :: mst == multiset{y} // MultiSet#UnionOne(MultiSet#Empty(): MultiSet Box, $Box(y#5))
+{
+}
diff --git a/Test/triggers/set-construction-is-a-good-trigger.dfy.expect b/Test/triggers/set-construction-is-a-good-trigger.dfy.expect
new file mode 100644
index 00000000..822b8498
--- /dev/null
+++ b/Test/triggers/set-construction-is-a-good-trigger.dfy.expect
@@ -0,0 +1,5 @@
+set-construction-is-a-good-trigger.dfy(8,11): Info: Selected triggers: {[y]}
+set-construction-is-a-good-trigger.dfy(9,11): Info: Selected triggers: {{y}}
+set-construction-is-a-good-trigger.dfy(10,11): Info: Selected triggers: {multiset{y}}
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/triggers/some-proofs-only-work-without-autoTriggers.dfy b/Test/triggers/some-proofs-only-work-without-autoTriggers.dfy
new file mode 100644
index 00000000..bc2e0934
--- /dev/null
+++ b/Test/triggers/some-proofs-only-work-without-autoTriggers.dfy
@@ -0,0 +1,48 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// The examples below work nicely with /autoTriggers:0, but break when we use
+// /autoTriggers.
+
+// The issue is that the axioms for sequences are missing a number of facts,
+// which was not a problem before /autoTriggers and /stricterTriggers, but has
+// become one. Here are examples of things that Dafny won’t prove with
+// /autoTriggers (I would expect it wouldn’t with stricterTriggers either,
+// though the second example is trickier than the first):
+
+method M(a: seq<int>) {
+ if * {
+ // This fails; it needs the following axiom:
+ // axiom (forall<T> s: Seq T ::
+ // { Seq#Take(s, Seq#Length(s)) }
+ // Seq#Take(s, Seq#Length(s)) == s);
+ assume forall x :: x in a ==> x > 0;
+ assert forall x :: x in a[..|a|] ==> x > 0;
+ } else if * {
+ // This fails; it needs the following axiom:
+ // axiom (forall<T> s: Seq T, i: int ::
+ // { Seq#Index(s, i) }
+ // 0 <= i && i < Seq#Length(s) ==>
+ // Seq#Contains(s, Seq#Index(s, i)));
+ assume forall x :: x in a ==> x > 0;
+ assert forall i | 0 <= i < |a| :: a[i] > 0;
+ } else if * {
+ assume |a| > 3;
+ assume forall x | x in a[..3] :: x > 1;
+ // This fails, but here it's a lot harder to know what a good axiom would be.
+ assert forall x | x in a[..2] :: x > 1;
+ }
+}
+
+
+// In the first case, the Boogie version is
+//
+// Seq#Contains(Seq#Take(a#0, Seq#Length(a#0)), $Box(x#0_1)) ⟹ x#0_1 > 0
+//
+// And of course Z3 picks $Box(x#0_1). The third case is similar.
+//
+// The problem is of course that knowing that x ∈ a[..2] doesn’t magically give
+// you a term that matches x ∈ a[..3]. One could imagine introducing an extra
+// symbol in the translation to put x and a together for triggering purposes,
+// but that would have the same sort of issues as adding symbols for arithmetic
+// operators.
diff --git a/Test/triggers/some-proofs-only-work-without-autoTriggers.dfy.expect b/Test/triggers/some-proofs-only-work-without-autoTriggers.dfy.expect
new file mode 100644
index 00000000..d48840b8
--- /dev/null
+++ b/Test/triggers/some-proofs-only-work-without-autoTriggers.dfy.expect
@@ -0,0 +1,31 @@
+some-proofs-only-work-without-autoTriggers.dfy(19,11): Info: Selected triggers: {x in a}
+some-proofs-only-work-without-autoTriggers.dfy(20,11): Info: Selected triggers: {x in a[..|a|]}
+some-proofs-only-work-without-autoTriggers.dfy(27,11): Info: Selected triggers: {x in a}
+some-proofs-only-work-without-autoTriggers.dfy(28,11): Info: Selected triggers: {a[i]}
+some-proofs-only-work-without-autoTriggers.dfy(31,11): Info: Selected triggers: {x in a[..3]}
+some-proofs-only-work-without-autoTriggers.dfy(33,11): Info: Selected triggers: {x in a[..2]}
+some-proofs-only-work-without-autoTriggers.dfy(20,11): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon22_Then
+ (0,0): anon3
+ (0,0): anon23_Then
+ (0,0): anon5
+some-proofs-only-work-without-autoTriggers.dfy(28,11): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon25_Then
+ (0,0): anon9
+ (0,0): anon26_Then
+ (0,0): anon27_Then
+ (0,0): anon13
+some-proofs-only-work-without-autoTriggers.dfy(33,11): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon28_Then
+ (0,0): anon29_Then
+ (0,0): anon17
+ (0,0): anon30_Then
+ (0,0): anon19
+
+Dafny program verifier finished with 1 verified, 3 errors
diff --git a/Test/triggers/some-terms-do-not-look-like-the-triggers-they-match.dfy b/Test/triggers/some-terms-do-not-look-like-the-triggers-they-match.dfy
new file mode 100644
index 00000000..d7636ea2
--- /dev/null
+++ b/Test/triggers/some-terms-do-not-look-like-the-triggers-they-match.dfy
@@ -0,0 +1,16 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file shows how Dafny detects loops even for terms that are not literal
+// AST matches. This file also checks that triggers are reported exactly as
+// picked (that is, `x in s` yields `s[x]` for a multiset s), but matches as
+// they appear in the buffer text (that is, `x+1 in s` is not translated to
+// s[x+1] when highlited as a cause for a potential matching loop.
+
+method M() {
+ // This is an obvious loop
+ ghost var b := forall s: multiset<int>, x: int :: s[x] > 0 ==> s[x+1] > 0;
+
+ // x in s loops with s[x+1] due to the way [x in s] is translated
+ ghost var a := forall s: multiset<int>, x: int :: x in s ==> s[x+1] > 0 && x+2 !in s;
+}
diff --git a/Test/triggers/some-terms-do-not-look-like-the-triggers-they-match.dfy.expect b/Test/triggers/some-terms-do-not-look-like-the-triggers-they-match.dfy.expect
new file mode 100644
index 00000000..1a143edb
--- /dev/null
+++ b/Test/triggers/some-terms-do-not-look-like-the-triggers-they-match.dfy.expect
@@ -0,0 +1,10 @@
+some-terms-do-not-look-like-the-triggers-they-match.dfy(12,17): Warning: Selected triggers: {s[x]} (may loop with "s[x + 1]")
+ /!\ Suppressing loops would leave this expression without triggers.
+some-terms-do-not-look-like-the-triggers-they-match.dfy(15,17): Warning: For expression "x in s ==> s[x + 1] > 0":
+ Selected triggers: {s[x]} (may loop with "s[x + 1]")
+ /!\ Suppressing loops would leave this expression without triggers.
+some-terms-do-not-look-like-the-triggers-they-match.dfy(15,17): Warning: For expression "x in s ==> x + 2 !in s":
+ Selected triggers: {s[x]} (may loop with "x + 2 !in s")
+ /!\ Suppressing loops would leave this expression without triggers.
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/triggers/splitting-picks-the-right-tokens.dfy b/Test/triggers/splitting-picks-the-right-tokens.dfy
new file mode 100644
index 00000000..76065eca
--- /dev/null
+++ b/Test/triggers/splitting-picks-the-right-tokens.dfy
@@ -0,0 +1,24 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file ensures that trigger splitting picks the right tokens
+
+function Id(i: int): int { i }
+
+method MSuchThat()
+ requires forall x | x > 0 :: Id(x) > 1 && x > 2 && x > -1 { }
+
+method MImplies()
+ // The bodies of the two terms that are produced here are both
+ // BinaryExpressions(==>); the token they use, however, is that of the RHS
+ // terms of these implications; otherwise, error messages would get stacked on
+ // the ==> sign
+ requires forall x :: x > 0 ==> Id(x) > 1 && x > 2 && x > -1 { }
+
+method M() {
+ if * {
+ MImplies();
+ } else {
+ MSuchThat();
+ }
+}
diff --git a/Test/triggers/splitting-picks-the-right-tokens.dfy.expect b/Test/triggers/splitting-picks-the-right-tokens.dfy.expect
new file mode 100644
index 00000000..f01ed1a0
--- /dev/null
+++ b/Test/triggers/splitting-picks-the-right-tokens.dfy.expect
@@ -0,0 +1,38 @@
+splitting-picks-the-right-tokens.dfy(9,11): Info: For expression "Id(x) > 1":
+ Selected triggers: {Id(x)}
+splitting-picks-the-right-tokens.dfy(9,11): Info: For expression "x > 2":
+ Selected triggers: {Id(x)}
+splitting-picks-the-right-tokens.dfy(9,11): Info: For expression "x > -1":
+ Selected triggers: {Id(x)}
+splitting-picks-the-right-tokens.dfy(16,11): Info: For expression "x > 0 ==> Id(x) > 1":
+ Selected triggers: {Id(x)}
+splitting-picks-the-right-tokens.dfy(16,11): Info: For expression "x > 0 ==> x > 2":
+ Selected triggers: {Id(x)}
+splitting-picks-the-right-tokens.dfy(16,11): Info: For expression "x > 0 ==> x > -1":
+ Selected triggers: {Id(x)}
+splitting-picks-the-right-tokens.dfy(20,12): Error BP5002: A precondition for this call might not hold.
+splitting-picks-the-right-tokens.dfy(16,11): Related location: This is the precondition that might not hold.
+splitting-picks-the-right-tokens.dfy(16,48): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Then
+splitting-picks-the-right-tokens.dfy(20,12): Error BP5002: A precondition for this call might not hold.
+splitting-picks-the-right-tokens.dfy(16,11): Related location: This is the precondition that might not hold.
+splitting-picks-the-right-tokens.dfy(16,39): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Then
+splitting-picks-the-right-tokens.dfy(22,13): Error BP5002: A precondition for this call might not hold.
+splitting-picks-the-right-tokens.dfy(9,11): Related location: This is the precondition that might not hold.
+splitting-picks-the-right-tokens.dfy(9,46): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Else
+splitting-picks-the-right-tokens.dfy(22,13): Error BP5002: A precondition for this call might not hold.
+splitting-picks-the-right-tokens.dfy(9,11): Related location: This is the precondition that might not hold.
+splitting-picks-the-right-tokens.dfy(9,37): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Else
+
+Dafny program verifier finished with 6 verified, 4 errors
diff --git a/Test/triggers/splitting-triggers-recovers-expressivity.dfy b/Test/triggers/splitting-triggers-recovers-expressivity.dfy
new file mode 100644
index 00000000..dd1bd81d
--- /dev/null
+++ b/Test/triggers/splitting-triggers-recovers-expressivity.dfy
@@ -0,0 +1,61 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+predicate P(i: int)
+predicate Q(i: int)
+
+/* This file demonstrates a case where automatic trigger splitting is useful to
+ prevent loop detection from reducing expressivity too much. */
+
+lemma exists_0()
+ requires P(0)
+ ensures exists i {:split false} :: P(i) || (Q(i) ==> P(i+1)) {
+ // Fails: P(i) is not a trigger
+}
+
+lemma forall_0(i: int)
+ requires forall j {:split false} :: j >= 0 ==> (P(j) && (Q(j) ==> P(j+1)))
+ requires i >= 0
+ ensures P(i) {
+ // Fails: P(i) is not a trigger
+}
+
+
+lemma exists_1()
+ requires P(0)
+ ensures exists i {:split false} :: P(i) || (Q(i) ==> P(i+1)) {
+ assert Q(0) || !Q(0);
+ // Works: the dummy assertion introduces a term that causes the quantifier
+ // to trigger, producing a witness.
+ }
+
+lemma forall_1(i: int)
+ requires forall j {:split false} :: j >= 0 ==> (P(j) && (Q(j) ==> P(j+1)))
+ requires i >= 0
+ ensures P(i) {
+ assert Q(i) || !Q(i);
+ // Works: the dummy assertion introduces a term that causes the quantifier
+ // to trigger, producing a witness.
+}
+
+
+lemma exists_2()
+ requires P(0)
+ ensures exists i :: P(i) || (Q(i) ==> P(i+1)) {
+ // Works: automatic trigger splitting allows P(i) to get its own triggers
+}
+
+lemma forall_2(i: int)
+ requires forall j :: j >= 0 ==> (P(j) && (Q(j) ==> P(j+1)))
+ requires i >= 0
+ ensures P(i) {
+ // Works: automatic trigger splitting allows P(i) to get its own triggers
+}
+
+
+lemma loop()
+ requires P(0)
+ requires forall i {:matchingloop} :: i >= 0 ==> Q(i) && (P(i) ==> P(i+1))
+ ensures P(100) {
+ // Works: the matching loop is explicitly allowed
+}
diff --git a/Test/triggers/splitting-triggers-recovers-expressivity.dfy.expect b/Test/triggers/splitting-triggers-recovers-expressivity.dfy.expect
new file mode 100644
index 00000000..a8bb2345
--- /dev/null
+++ b/Test/triggers/splitting-triggers-recovers-expressivity.dfy.expect
@@ -0,0 +1,39 @@
+splitting-triggers-recovers-expressivity.dfy(12,10): Info: Selected triggers: {Q(i)}
+ Rejected triggers: {P(i)} (may loop with "P(i + 1)")
+splitting-triggers-recovers-expressivity.dfy(17,11): Info: Selected triggers: {Q(j)}
+ Rejected triggers: {P(j)} (may loop with "P(j + 1)")
+splitting-triggers-recovers-expressivity.dfy(26,10): Info: Selected triggers: {Q(i)}
+ Rejected triggers: {P(i)} (may loop with "P(i + 1)")
+splitting-triggers-recovers-expressivity.dfy(33,11): Info: Selected triggers: {Q(j)}
+ Rejected triggers: {P(j)} (may loop with "P(j + 1)")
+splitting-triggers-recovers-expressivity.dfy(44,10): Info: For expression "P(i)":
+ Selected triggers:
+ {Q(i)}, {P(i)}
+splitting-triggers-recovers-expressivity.dfy(44,10): Info: For expression "!Q(i)":
+ Selected triggers:
+ {Q(i)}, {P(i)}
+splitting-triggers-recovers-expressivity.dfy(44,10): Info: For expression "P(i + 1)":
+ Selected triggers: {Q(i)}
+ Rejected triggers: {P(i)} (may loop with "P(i + 1)")
+splitting-triggers-recovers-expressivity.dfy(49,11): Info: For expression "j >= 0 ==> P(j)":
+ Selected triggers:
+ {Q(j)}, {P(j)}
+splitting-triggers-recovers-expressivity.dfy(49,11): Info: For expression "j >= 0 ==> Q(j) ==> P(j + 1)":
+ Selected triggers: {Q(j)}
+ Rejected triggers: {P(j)} (may loop with "P(j + 1)")
+splitting-triggers-recovers-expressivity.dfy(58,11): Info: For expression "i >= 0 ==> Q(i)":
+ Selected triggers:
+ {P(i)}, {Q(i)}
+splitting-triggers-recovers-expressivity.dfy(58,11): Info: For expression "i >= 0 ==> P(i) ==> P(i + 1)":
+ Selected triggers:
+ {P(i)} (may loop with "P(i + 1)"), {Q(i)}
+splitting-triggers-recovers-expressivity.dfy(12,63): Error BP5003: A postcondition might not hold on this return path.
+splitting-triggers-recovers-expressivity.dfy(12,10): Related location: This is the postcondition that might not hold.
+Execution trace:
+ (0,0): anon0
+splitting-triggers-recovers-expressivity.dfy(19,15): Error BP5003: A postcondition might not hold on this return path.
+splitting-triggers-recovers-expressivity.dfy(19,10): Related location: This is the postcondition that might not hold.
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 14 verified, 2 errors
diff --git a/Test/triggers/splitting-triggers-yields-better-precondition-related-errors.dfy b/Test/triggers/splitting-triggers-yields-better-precondition-related-errors.dfy
new file mode 100644
index 00000000..20e90843
--- /dev/null
+++ b/Test/triggers/splitting-triggers-yields-better-precondition-related-errors.dfy
@@ -0,0 +1,21 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This tests shows that, since quantifiers are split, it becomes possible to know more precisely what part of a precondition did not hold at the call site.
+
+method f()
+ requires forall y :: y > 0 && y < 0 {
+}
+
+method g(x: int) {
+ f();
+}
+
+function gf(): int
+ requires forall y :: y > 0 && y < 0 {
+ 1
+}
+
+function gg(x: int): int {
+ gf()
+}
diff --git a/Test/triggers/splitting-triggers-yields-better-precondition-related-errors.dfy.expect b/Test/triggers/splitting-triggers-yields-better-precondition-related-errors.dfy.expect
new file mode 100644
index 00000000..27548ac9
--- /dev/null
+++ b/Test/triggers/splitting-triggers-yields-better-precondition-related-errors.dfy.expect
@@ -0,0 +1,32 @@
+splitting-triggers-yields-better-precondition-related-errors.dfy(7,11): Warning: For expression "y > 0":
+ /!\ No terms found to trigger on.
+splitting-triggers-yields-better-precondition-related-errors.dfy(7,11): Warning: For expression "y < 0":
+ /!\ No terms found to trigger on.
+splitting-triggers-yields-better-precondition-related-errors.dfy(15,11): Warning: For expression "y > 0":
+ /!\ No terms found to trigger on.
+splitting-triggers-yields-better-precondition-related-errors.dfy(15,11): Warning: For expression "y < 0":
+ /!\ No terms found to trigger on.
+splitting-triggers-yields-better-precondition-related-errors.dfy(11,3): Error BP5002: A precondition for this call might not hold.
+splitting-triggers-yields-better-precondition-related-errors.dfy(7,11): Related location: This is the precondition that might not hold.
+splitting-triggers-yields-better-precondition-related-errors.dfy(7,34): Related location
+Execution trace:
+ (0,0): anon0
+splitting-triggers-yields-better-precondition-related-errors.dfy(11,3): Error BP5002: A precondition for this call might not hold.
+splitting-triggers-yields-better-precondition-related-errors.dfy(7,11): Related location: This is the precondition that might not hold.
+splitting-triggers-yields-better-precondition-related-errors.dfy(7,25): Related location
+Execution trace:
+ (0,0): anon0
+splitting-triggers-yields-better-precondition-related-errors.dfy(20,2): Error: possible violation of function precondition
+splitting-triggers-yields-better-precondition-related-errors.dfy(15,11): Related location
+splitting-triggers-yields-better-precondition-related-errors.dfy(15,34): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon4_Else
+splitting-triggers-yields-better-precondition-related-errors.dfy(20,2): Error: possible violation of function precondition
+splitting-triggers-yields-better-precondition-related-errors.dfy(15,11): Related location
+splitting-triggers-yields-better-precondition-related-errors.dfy(15,25): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon4_Else
+
+Dafny program verifier finished with 4 verified, 4 errors
diff --git a/Test/triggers/suppressing-warnings-behaves-properly.dfy b/Test/triggers/suppressing-warnings-behaves-properly.dfy
new file mode 100644
index 00000000..237269e5
--- /dev/null
+++ b/Test/triggers/suppressing-warnings-behaves-properly.dfy
@@ -0,0 +1,21 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file checks that suppressing warnings works properly
+
+predicate f(x: int)
+predicate g(x: int)
+
+method M() {
+ assert forall n :: n >= 0 || n < 0;
+ assert forall n {:nowarn} :: n >= 0 || n < 0;
+ assert forall n {:autotriggers false} :: n >= 0 || n < 0;
+
+ assert forall n: nat :: (n != 0) == f(n) || true;
+ assert forall n: nat {:nowarn} :: (n != 0) == f(n) || true;
+ assert forall n: nat {:autotriggers false} :: (n != 0) == f(n) || true;
+
+ assert forall n: nat :: f(n) == f(n+1) || g(n) || true;
+ assert forall n: nat {:nowarn} :: (n != 0) == f(n) || true;
+ assert forall n: nat {:autotriggers false} :: (n != 0) == f(n) || true;
+}
diff --git a/Test/triggers/suppressing-warnings-behaves-properly.dfy.expect b/Test/triggers/suppressing-warnings-behaves-properly.dfy.expect
new file mode 100644
index 00000000..124984b1
--- /dev/null
+++ b/Test/triggers/suppressing-warnings-behaves-properly.dfy.expect
@@ -0,0 +1,14 @@
+suppressing-warnings-behaves-properly.dfy(10,9): Warning: /!\ No terms found to trigger on.
+suppressing-warnings-behaves-properly.dfy(11,9): Info: (Suppressed warning) No terms found to trigger on.
+suppressing-warnings-behaves-properly.dfy(12,9): Info: Not generating triggers for "n >= 0 || n < 0". Note that {:autotriggers false} can cause instabilities. Consider using {:nowarn}, {:matchingloop} (not great either), or a manual trigger instead.
+suppressing-warnings-behaves-properly.dfy(14,9): Info: Selected triggers: {f(n)}
+suppressing-warnings-behaves-properly.dfy(15,9): Warning: Selected triggers: {f(n)}
+ /!\ There is no warning here to suppress.
+suppressing-warnings-behaves-properly.dfy(16,9): Info: Not generating triggers for "(n != 0) == f(n) || true". Note that {:autotriggers false} can cause instabilities. Consider using {:nowarn}, {:matchingloop} (not great either), or a manual trigger instead.
+suppressing-warnings-behaves-properly.dfy(18,9): Info: Selected triggers: {g(n)}
+ Rejected triggers: {f(n)} (may loop with "f(n + 1)")
+suppressing-warnings-behaves-properly.dfy(19,9): Warning: Selected triggers: {f(n)}
+ /!\ There is no warning here to suppress.
+suppressing-warnings-behaves-properly.dfy(20,9): Info: Not generating triggers for "(n != 0) == f(n) || true". Note that {:autotriggers false} can cause instabilities. Consider using {:nowarn}, {:matchingloop} (not great either), or a manual trigger instead.
+
+Dafny program verifier finished with 4 verified, 0 errors
diff --git a/Test/triggers/triggers-prevent-some-inlining.dfy b/Test/triggers/triggers-prevent-some-inlining.dfy
new file mode 100644
index 00000000..90af62a3
--- /dev/null
+++ b/Test/triggers/triggers-prevent-some-inlining.dfy
@@ -0,0 +1,26 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file looks at the interactions between inlining and triggers. The
+// sum_is_sum predicate gets a {sum(a, b)} trigger, which explicitly depends on
+// one of the variables being passed in. Since triggers are generated prior to
+// inlining (inlining happens during translation), inlining the last two
+// instances of that call below would cause b+1 (a trigger killer) to pop up in
+// a trigger. This would create an invalid trigger, so Dafny doesn't let it
+// happen.
+
+function sum(a: int, b: int): int {
+ a + b
+}
+
+predicate sum_is_sum(b: int, c: int) {
+ forall a: int :: sum(a, b) + c == a + b + c
+}
+
+method can_we_inline(b: int, c: int)
+ ensures sum_is_sum(0, 0) // OK to inline
+ ensures sum_is_sum(b, c) // OK to inline
+ ensures sum_is_sum(b, c+1) // OK to inline
+ ensures sum_is_sum(b+1, c) // NOK to inline
+ ensures sum_is_sum(b+1, c+1) // NOK to inline
+{ }
diff --git a/Test/triggers/triggers-prevent-some-inlining.dfy.expect b/Test/triggers/triggers-prevent-some-inlining.dfy.expect
new file mode 100644
index 00000000..0b6f3e30
--- /dev/null
+++ b/Test/triggers/triggers-prevent-some-inlining.dfy.expect
@@ -0,0 +1,9 @@
+triggers-prevent-some-inlining.dfy(17,2): Info: Selected triggers: {sum(a, b)}
+triggers-prevent-some-inlining.dfy(24,10): Info: Some instances of this call cannot safely be inlined.
+triggers-prevent-some-inlining.dfy(25,10): Info: Some instances of this call cannot safely be inlined.
+triggers-prevent-some-inlining.dfy(24,10): Info: Some instances of this call cannot safely be inlined.
+triggers-prevent-some-inlining.dfy(25,10): Info: Some instances of this call cannot safely be inlined.
+triggers-prevent-some-inlining.dfy(24,10): Info: Some instances of this call cannot safely be inlined.
+triggers-prevent-some-inlining.dfy(25,10): Info: Some instances of this call cannot safely be inlined.
+
+Dafny program verifier finished with 4 verified, 0 errors
diff --git a/Test/triggers/useless-triggers-are-removed.dfy b/Test/triggers/useless-triggers-are-removed.dfy
new file mode 100644
index 00000000..658890f2
--- /dev/null
+++ b/Test/triggers/useless-triggers-are-removed.dfy
@@ -0,0 +1,25 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file ensures that Dafny does get rid of redundant triggers before
+// annotating a quantifier, and that ths process does not interfere with cycle
+// detection.
+
+function f(x: int): int
+function g(x: int): int
+function h(x: int): int
+
+method M()
+ // In the following, only f(x) is kept. Note that the subset enumeration was
+ // already smart enough to not build any trigger with multiple terms (it only
+ // built 5 candidates)
+ requires forall x: int :: f(x) + g(f(x)) + h(f(x)) + g(h(f(x))) + h(g(f(x))) == 0
+
+ // Loop detection still works fine: in the following example, the trigger is
+ // f(f(x))
+ requires forall x: int :: f(x) == f(f(x))
+
+ // This works for multi-triggers, too:
+ requires forall x, y :: f(x) + g(f(y)) + g(y) + g(f(x)) == 0
+{
+}
diff --git a/Test/triggers/useless-triggers-are-removed.dfy.expect b/Test/triggers/useless-triggers-are-removed.dfy.expect
new file mode 100644
index 00000000..d6b49a9e
--- /dev/null
+++ b/Test/triggers/useless-triggers-are-removed.dfy.expect
@@ -0,0 +1,17 @@
+useless-triggers-are-removed.dfy(16,11): Info: Selected triggers: {f(x)}
+ Rejected triggers:
+ {h(g(f(x)))} (more specific than {g(f(x))}, {f(x)})
+ {g(h(f(x)))} (more specific than {h(f(x))}, {f(x)})
+ {h(f(x))} (more specific than {f(x)})
+ {g(f(x))} (more specific than {f(x)})
+useless-triggers-are-removed.dfy(20,11): Info: Selected triggers: {f(f(x))}
+ Rejected triggers: {f(x)} (may loop with "f(f(x))")
+useless-triggers-are-removed.dfy(23,11): Info: Selected triggers:
+ {g(f(x)), g(y)}, {f(y), f(x)}
+ Rejected triggers:
+ {g(y), f(x)} (may loop with "g(f(y))", "g(f(x))")
+ {g(f(x)), g(f(y))} (more specific than {g(f(x)), f(y)}, {g(f(y)), f(x)}, {f(y), f(x)})
+ {g(f(x)), f(y)} (more specific than {f(y), f(x)})
+ {g(f(y)), f(x)} (more specific than {f(y), f(x)})
+
+Dafny program verifier finished with 5 verified, 0 errors
diff --git a/Test/triggers/wf-checks-use-the-original-quantifier.dfy b/Test/triggers/wf-checks-use-the-original-quantifier.dfy
new file mode 100644
index 00000000..a1a2bd90
--- /dev/null
+++ b/Test/triggers/wf-checks-use-the-original-quantifier.dfy
@@ -0,0 +1,28 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This test checks that typical expressions requiring WF checks do not suddenly
+// loose expressivity due to quantifier splitting. Without special care, the
+// expression (forall x :: x != null && x.a == 0) could fail to verify.
+
+// The logic about split quantifiers is that Boogie (and z3) should never realize
+// that there was an unsplit quantifier. The WF check code does not produce a
+// quantifier, at least in it's checking part; thus, it should use original
+// quantifier. This fixes a problem in VerifyThis2015/Problem2.dfy with a null
+// check, and a problem spotted by Chris, made into a test case saved in
+// triggers/wf-checks-use-the-original-quantifier.dfy.
+
+// Of course, the assumption that WF checks produce for a quantifier is a
+// quantifier, so the assumption part that comes after the WF check does use the
+// split expression.
+
+// This test case is inspired by the example that Chris gave.
+
+predicate P(b: nat)
+function f(a: int): int
+class C { var x: int; }
+
+method M(s: set<C>)
+ requires forall n: nat :: 0 <= f(n) && P(f(n))
+ requires forall c, c' | c in s && c' in s :: c != null && c'!= null && c.x == c'.x {
+}
diff --git a/Test/triggers/wf-checks-use-the-original-quantifier.dfy.expect b/Test/triggers/wf-checks-use-the-original-quantifier.dfy.expect
new file mode 100644
index 00000000..6c3e4853
--- /dev/null
+++ b/Test/triggers/wf-checks-use-the-original-quantifier.dfy.expect
@@ -0,0 +1,17 @@
+wf-checks-use-the-original-quantifier.dfy(26,11): Info: For expression "0 <= f(n)":
+ Selected triggers: {f(n)}
+ Rejected triggers: {P(f(n))} (more specific than {f(n)})
+wf-checks-use-the-original-quantifier.dfy(26,11): Info: For expression "P(f(n))":
+ Selected triggers: {f(n)}
+ Rejected triggers: {P(f(n))} (more specific than {f(n)})
+wf-checks-use-the-original-quantifier.dfy(27,11): Info: For expression "c != null":
+ Selected triggers:
+ {c'.x, c.x}, {c'.x, c in s}, {c.x, c' in s}, {c' in s, c in s}
+wf-checks-use-the-original-quantifier.dfy(27,11): Info: For expression "c' != null":
+ Selected triggers:
+ {c'.x, c.x}, {c'.x, c in s}, {c.x, c' in s}, {c' in s, c in s}
+wf-checks-use-the-original-quantifier.dfy(27,11): Info: For expression "c.x == c'.x":
+ Selected triggers:
+ {c'.x, c.x}, {c'.x, c in s}, {c.x, c' in s}, {c' in s, c in s}
+
+Dafny program verifier finished with 4 verified, 0 errors
diff --git a/Test/tutorial/maximum.dfy b/Test/tutorial/maximum.dfy
new file mode 100644
index 00000000..81faa219
--- /dev/null
+++ b/Test/tutorial/maximum.dfy
@@ -0,0 +1,32 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// This file shows how to specify and implement a function to compute the
+// largest element of a list. The function is fully specified by two
+// preconditions, as proved by the MaximumIsUnique lemma below.
+
+method Maximum(values: seq<int>) returns (max: int)
+ requires values != []
+ ensures max in values
+ ensures forall i | 0 <= i < |values| :: values[i] <= max
+{
+ max := values[0];
+ var idx := 0;
+ while (idx < |values|)
+ invariant max in values
+ invariant idx <= |values|
+ invariant forall j | 0 <= j < idx :: values[j] <= max
+ {
+ if (values[idx] > max) {
+ max := values[idx];
+ }
+ idx := idx + 1;
+ }
+}
+
+lemma MaximumIsUnique(values: seq<int>, m1: int, m2: int)
+ requires m1 in values && forall i | 0 <= i < |values| :: values[i] <= m1
+ requires m2 in values && forall i | 0 <= i < |values| :: values[i] <= m2
+ ensures m1 == m2 {
+ // This lemma does not need a body: Dafny is able to prove it correct entirely automatically.
+}
diff --git a/Test/tutorial/maximum.dfy.expect b/Test/tutorial/maximum.dfy.expect
new file mode 100644
index 00000000..16a67088
--- /dev/null
+++ b/Test/tutorial/maximum.dfy.expect
@@ -0,0 +1,7 @@
+maximum.dfy(11,10): Info: Selected triggers: {values[i]}
+maximum.dfy(18,14): Info: Selected triggers: {values[j]}
+maximum.dfy(28,27): Info: Selected triggers: {values[i]}
+maximum.dfy(29,27): Info: Selected triggers: {values[i]}
+maximum.dfy(15,2): Info: decreases |values| - idx
+
+Dafny program verifier finished with 4 verified, 0 errors
diff --git a/Test/vacid0/Composite.dfy b/Test/vacid0/Composite.dfy
index d5551d82..bc3b5baf 100644
--- a/Test/vacid0/Composite.dfy
+++ b/Test/vacid0/Composite.dfy
@@ -68,7 +68,7 @@ class Composite {
// sets child.parent to this:
ensures child.parent == this;
// leaves everything in S+U valid:
- ensures (forall c :: c in S+U ==> c.Valid(S+U));
+ ensures (forall c {:autotriggers false} :: c in S+U ==> c.Valid(S+U)); // We can't generate a trigger for this at the moment; if we did, we would still need to prevent TrSplitExpr from translating c in S+U to S[c] || U[c].
{
if (left == null) {
left := child;
diff --git a/Test/vstte2012/BreadthFirstSearch.dfy b/Test/vstte2012/BreadthFirstSearch.dfy
index b111a438..375f4a09 100644
--- a/Test/vstte2012/BreadthFirstSearch.dfy
+++ b/Test/vstte2012/BreadthFirstSearch.dfy
@@ -1,4 +1,4 @@
-// RUN: %dafny /compile:0 /dprint:"%t.dprint" /vcsMaxKeepGoingSplits:10 "%s" > "%t"
+// RUN: %dafny /compile:0 /dprint:"%t.dprint" /vcsMaxKeepGoingSplits:10 /autoTriggers:0 "%s" > "%t"
// RUN: %diff "%s.expect" "%t"
class BreadthFirstSearch<Vertex(==)>
diff --git a/Test/vstte2012/Combinators.dfy b/Test/vstte2012/Combinators.dfy
index be7bc25f..ba4a4141 100644
--- a/Test/vstte2012/Combinators.dfy
+++ b/Test/vstte2012/Combinators.dfy
@@ -170,7 +170,7 @@ function IsTerminal(t: Term): bool
// The following theorem states the correctness of the FindAndStep function:
-ghost method Theorem_FindAndStep(t: Term)
+lemma Theorem_FindAndStep(t: Term)
// If FindAndStep returns the term it started from, then there is no
// way to take a step. More precisely, there is no C[u] == t for which the
// Step applies to "u".
@@ -194,7 +194,7 @@ ghost method Theorem_FindAndStep(t: Term)
// computes the value of FindAndStep(t) as it goes along and it returns
// that value.
-ghost method Lemma_FindAndStep(t: Term) returns (r: Term, C: Context, u: Term)
+lemma Lemma_FindAndStep(t: Term) returns (r: Term, C: Context, u: Term)
ensures r == FindAndStep(t);
ensures r == t ==> IsTerminal(t);
ensures r != t ==>
@@ -255,7 +255,7 @@ ghost method Lemma_FindAndStep(t: Term) returns (r: Term, C: Context, u: Term)
// The proof of the lemma above used one more lemma, namely one that enumerates
// lays out the options for how to represent a term as a C[u] pair.
-ghost method Lemma_ContextPossibilities(t: Term)
+lemma Lemma_ContextPossibilities(t: Term)
ensures forall C,u :: IsContext(C) && t == EvalExpr(C, u) ==>
(C == Hole && t == u) ||
(t.Apply? && exists D :: C == C_term(D, t.cdr) && t.car == EvalExpr(D, u)) ||
@@ -442,7 +442,7 @@ function method ks(n: nat): Term
// VerificationTask2) it computes the same thing as method VerificationTask2
// does.
-ghost method VerificationTask3()
+lemma VerificationTask3()
ensures forall n: nat ::
TerminatingReduction(ks(n)) == if n % 2 == 0 then K else Apply(K, K);
{
@@ -451,13 +451,13 @@ ghost method VerificationTask3()
}
}
-ghost method VT3(n: nat)
+lemma VT3(n: nat)
ensures TerminatingReduction(ks(n)) == if n % 2 == 0 then K else Apply(K, K);
{
// Dafny's (way cool) induction tactic kicks in and proves the following
// assertion automatically:
assert forall p :: 2 <= p ==> FindAndStep(ks(p)) == ks(p-2);
- // And then Dafny's (cool beyond words) induction tactic for ghost methods kicks
+ // And then Dafny's (cool beyond words) induction tactic for lemmas kicks
// in to prove the postcondition. (If this got you curious, scope out Leino's
// VMCAI 2012 paper "Automating Induction with an SMT Solver".)
}
diff --git a/Test/vstte2012/Tree.dfy b/Test/vstte2012/Tree.dfy
index 4a45d011..662024e4 100644
--- a/Test/vstte2012/Tree.dfy
+++ b/Test/vstte2012/Tree.dfy
@@ -22,9 +22,9 @@ datatype Result = Fail | Res(t: Tree, sOut: seq<int>)
// The postconditions state properties that are needed
// in the completeness proof.
function toList(d: int, t: Tree): seq<int>
- ensures toList(d, t) != [] && toList(d, t)[0] >= d;
- ensures (toList(d, t)[0] == d) == (t == Leaf);
- decreases t;
+ ensures toList(d, t) != [] && toList(d, t)[0] >= d
+ ensures (toList(d, t)[0] == d) == (t == Leaf)
+ decreases t
{
match t
case Leaf => [d]
@@ -43,10 +43,10 @@ function toList(d: int, t: Tree): seq<int>
function method build_rec(d: int, s: seq<int>): Result
ensures build_rec(d, s).Res? ==>
|build_rec(d, s).sOut| < |s| &&
- build_rec(d, s).sOut == s[|s|-|build_rec(d, s).sOut|..];
+ build_rec(d, s).sOut == s[|s|-|build_rec(d, s).sOut|..]
ensures build_rec(d, s).Res? ==>
- toList(d,build_rec(d, s).t) == s[..|s|-|build_rec(d, s).sOut|];
- decreases |s|, (if s==[] then 0 else s[0]-d);
+ toList(d,build_rec(d, s).t) == s[..|s|-|build_rec(d, s).sOut|]
+ decreases |s|, (if s==[] then 0 else s[0]-d)
{
if s==[] || s[0] < d then
Fail
@@ -68,14 +68,14 @@ function method build_rec(d: int, s: seq<int>): Result
// sequence yields exactly the input sequence.
// Completeness is proved as a lemma, see below.
function method build(s: seq<int>): Result
- ensures build(s).Res? ==> toList(0,build(s).t) == s;
+ ensures build(s).Res? ==> toList(0,build(s).t) == s
{
var r := build_rec(0, s);
if r.Res? && r.sOut == [] then r else Fail
}
-// This ghost methods encodes the main lemma for the
+// This is the main lemma for the
// completeness theorem. If a sequence s starts with a
// valid encoding of a tree t then build_rec yields a
// result (i.e., does not fail) and the rest of the sequence.
@@ -83,41 +83,39 @@ function method build(s: seq<int>): Result
// induction on t. Dafny proves termination (using the
// height of the term t as termination measure), which
// ensures that the induction hypothesis is applied
-// correctly (encoded by calls to this ghost method).
-ghost method lemma0(t: Tree, d: int, s: seq<int>)
+// correctly (encoded by calls to this lemma).
+lemma lemma0(t: Tree, d: int, s: seq<int>)
ensures build_rec(d, toList(d, t) + s).Res? &&
- build_rec(d, toList(d, t) + s).sOut == s;
+ build_rec(d, toList(d, t) + s).sOut == s
{
match(t) {
case Leaf =>
assert toList(d, t) == [d];
case Node(l, r) =>
assert toList(d, t) + s == toList(d+1, l) + (toList(d+1, r) + s);
-
- lemma0(l, d+1, toList(d+1, r) + s); // apply the induction hypothesis
- lemma0(r, d+1, s); // apply the induction hypothesis
+ // the rest follows from (two invocations of) the (automatically applied) induction hypothesis
}
}
-// This ghost method encodes a lemma that states the
+// This lemma states the
// completeness property. It is proved by applying the
// main lemma (lemma0). In this lemma, the bound variables
// of the completeness theorem are passed as arguments;
-// the following two ghost methods replace these arguments
+// the following two lemmas replace these arguments
// by quantified variables.
-ghost method lemma1(t: Tree, s:seq<int>)
- requires s == toList(0, t) + [];
- ensures build(s).Res?;
+lemma lemma1(t: Tree, s:seq<int>)
+ requires s == toList(0, t) + []
+ ensures build(s).Res?
{
lemma0(t, 0, []);
}
-// This ghost method encodes a lemma that introduces the
-// existential quantifier in the completeness property.
-ghost method lemma2(s: seq<int>)
- ensures (exists t: Tree :: toList(0,t) == s) ==> build(s).Res?;
+// This lemma introduces the existential quantifier in the completeness
+// property.
+lemma lemma2(s: seq<int>)
+ ensures (exists t: Tree :: toList(0,t) == s) ==> build(s).Res?
{
forall t | toList(0,t) == s {
lemma1(t, s);
@@ -125,13 +123,13 @@ ghost method lemma2(s: seq<int>)
}
-// This ghost method encodes the completeness theorem.
+// This lemma encodes the completeness theorem.
// For each sequence for which there is a corresponding
// tree, function build yields a result different from Fail.
// The body of the method converts the argument of lemma2
// into a universally quantified variable.
-ghost method completeness()
- ensures forall s: seq<int> :: ((exists t: Tree :: toList(0,t) == s) ==> build(s).Res?);
+lemma completeness()
+ ensures forall s: seq<int> :: ((exists t: Tree :: toList(0,t) == s) ==> build(s).Res?)
{
forall s {
lemma2(s);
@@ -145,21 +143,8 @@ ghost method completeness()
// unfold the necessary definitions.
method harness0()
ensures build([1,3,3,2]).Res? &&
- build([1,3,3,2]).t == Node(Leaf, Node(Node(Leaf, Leaf), Leaf));
+ build([1,3,3,2]).t == Node(Leaf, Node(Node(Leaf, Leaf), Leaf))
{
- assert build_rec(2, [2]) ==
- Res(Leaf, []);
- assert build_rec(2, [3,3,2]) ==
- Res(Node(Leaf, Leaf), [2]);
- assert build_rec(1, [3,3,2]) ==
- Res(Node(Node(Leaf, Leaf), Leaf), []);
- assert build_rec(1, [1,3,3,2]) ==
- Res(Leaf, [3,3,2]);
- assert build_rec(0, [1,3,3,2]) ==
- Res(
- Node(build_rec(1, [1,3,3,2]).t,
- build_rec(1, [3,3,2]).t),
- []);
}
@@ -168,10 +153,6 @@ method harness0()
// assertions are required by the verifier to
// unfold the necessary definitions.
method harness1()
- ensures build([1,3,2,2]).Fail?;
+ ensures build([1,3,2,2]).Fail?
{
- assert build_rec(1,[1,3,2,2]) == Res(Leaf, [3,2,2]);
- assert build_rec(3,[2,2]).Fail?;
- assert build_rec(2,[3,2,2]).Fail?;
- assert build_rec(1,[3,2,2]).Fail?;
}
diff --git a/Test/wishlist/calc.dfy b/Test/wishlist/calc.dfy
new file mode 100644
index 00000000..308fbb9a
--- /dev/null
+++ b/Test/wishlist/calc.dfy
@@ -0,0 +1,17 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// There is a bug in Dafny that causes the error from `L` to be reported at
+// position 0 in this file, instead of on a curly brace.
+
+lemma L()
+ ensures false {
+ calc { true; }
+}
+
+// Empty calc statements work fine, though:
+
+lemma L'()
+ ensures false {
+ calc { }
+}
diff --git a/Test/wishlist/calc.dfy.expect b/Test/wishlist/calc.dfy.expect
new file mode 100644
index 00000000..9e4e7b44
--- /dev/null
+++ b/Test/wishlist/calc.dfy.expect
@@ -0,0 +1,11 @@
+calc.dfy(8,16): Error BP5003: A postcondition might not hold on this return path.
+calc.dfy(8,10): Related location: This is the postcondition that might not hold.
+Execution trace:
+ (0,0): anon0
+ calc.dfy(9,5): anon2_Else
+calc.dfy(15,16): Error BP5003: A postcondition might not hold on this return path.
+calc.dfy(15,10): Related location: This is the postcondition that might not hold.
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 2 verified, 2 errors
diff --git a/Test/wishlist/exists-b-exists-not-b.dfy b/Test/wishlist/exists-b-exists-not-b.dfy
new file mode 100644
index 00000000..2573b2f2
--- /dev/null
+++ b/Test/wishlist/exists-b-exists-not-b.dfy
@@ -0,0 +1,10 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// It would be great if Dafny was able to verify the following statements;
+// otherwise, trigger splitting prevents `exists b :: b || not b` from verifying
+
+method M() {
+ assert exists b : bool {:nowarn} :: b; // WISH
+ assert exists b : bool {:nowarn} :: !b; // WISH
+}
diff --git a/Test/wishlist/exists-b-exists-not-b.dfy.expect b/Test/wishlist/exists-b-exists-not-b.dfy.expect
new file mode 100644
index 00000000..c785ee97
--- /dev/null
+++ b/Test/wishlist/exists-b-exists-not-b.dfy.expect
@@ -0,0 +1,8 @@
+exists-b-exists-not-b.dfy(8,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+exists-b-exists-not-b.dfy(9,9): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 1 verified, 2 errors
diff --git a/Test/wishlist/granted/useless-casts-in-decreases-clauses.dfy b/Test/wishlist/granted/useless-casts-in-decreases-clauses.dfy
new file mode 100644
index 00000000..9b002d47
--- /dev/null
+++ b/Test/wishlist/granted/useless-casts-in-decreases-clauses.dfy
@@ -0,0 +1,9 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method M() {
+ var pos := 10;
+ while (pos > 0) { // This shouldn't print int(pos) - int(0); pos - 0 would be better
+ pos := pos - 1;
+ }
+}
diff --git a/Test/wishlist/granted/useless-casts-in-decreases-clauses.dfy.expect b/Test/wishlist/granted/useless-casts-in-decreases-clauses.dfy.expect
new file mode 100644
index 00000000..36d7e6b8
--- /dev/null
+++ b/Test/wishlist/granted/useless-casts-in-decreases-clauses.dfy.expect
@@ -0,0 +1,3 @@
+useless-casts-in-decreases-clauses.dfy(6,2): Info: decreases pos - 0
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/wishlist/naked-function-in-recursive-setting.dfy b/Test/wishlist/naked-function-in-recursive-setting.dfy
new file mode 100644
index 00000000..650fc4c3
--- /dev/null
+++ b/Test/wishlist/naked-function-in-recursive-setting.dfy
@@ -0,0 +1,13 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+function fact(n: int): int
+ requires n >= 0
+{
+ if n == 0 then
+ 1
+ else (
+ assert fact.requires(n-1); //WISH
+ n * fact(n-1)
+ )
+}
diff --git a/Test/wishlist/naked-function-in-recursive-setting.dfy.expect b/Test/wishlist/naked-function-in-recursive-setting.dfy.expect
new file mode 100644
index 00000000..4b1691b4
--- /dev/null
+++ b/Test/wishlist/naked-function-in-recursive-setting.dfy.expect
@@ -0,0 +1,8 @@
+naked-function-in-recursive-setting.dfy(4,9): Info: decreases n
+naked-function-in-recursive-setting.dfy(10,11): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Else
+ (0,0): anon8_Else
+
+Dafny program verifier finished with 0 verified, 1 error
diff --git a/Test/wishlist/sequences-literals.dfy b/Test/wishlist/sequences-literals.dfy
new file mode 100644
index 00000000..382349a4
--- /dev/null
+++ b/Test/wishlist/sequences-literals.dfy
@@ -0,0 +1,58 @@
+// RUN: %dafny /compile:0 /autoTriggers:1 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// Note: in the tests below, it could be useful to experiment with the
+// following triggers for some of the library axioms:
+//
+// axiom (forall<T> s0: Seq T, s1: Seq T, x: T ::
+// { Seq#Contains(s0, x), Seq#Append(s0, s1) }
+// { Seq#Contains(s1, x), Seq#Append(s0, s1) }
+// Seq#Contains(Seq#Append(s0, s1), x)
+// <==> Seq#Contains(s0, x) || Seq#Contains(s1, x));
+//
+// axiom (forall<T> s: Seq T, v: T, x: T ::
+// { Seq#Contains(s, x), Seq#Build(s, v) }
+// Seq#Contains(Seq#Build(s, v), x) <==> v == x || Seq#Contains(s, x));
+//
+// Another, not necessarily incompatible approach would be to explicitly add
+// `assume k in s` for each element k of constant lists.
+
+method SmallList() {
+ var s := [0, 1, 5, 6];
+ if * {
+ // This fails: Dafny needs a hint here, because the triggers on the library axioms are pretty strict:
+ assert exists n :: n in s; // WISH
+ } else if * {
+ // This works
+ assert 0 in s;
+ assert exists n :: n in s;
+ } else if * {
+ // This also works, thanks to the magic of triggering on `$Box`.
+ assert exists n {:autotriggers false} :: n in s;
+ }
+}
+
+method LargeList() {
+ var s := [0, 1, 2, 3, 4, 5, 6, 7, 8, /* 9, 10, 11, */ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, /* 119, 120, 121, */ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136];
+ if * {
+ // The hint fails here. Maybe because z3 gets into a loop trying to unwrap
+ // this large list? This is also very slow.
+ assert 0 in s; // WISH
+ assert exists n :: n in s;
+ } else if * {
+ // Strangely, the hint works here. Why?
+ assert 122 in s;
+ assert exists n :: n in s;
+ } else if * {
+ // This also fails; since z3 only goes to a depth of 100, this probably
+ // wouldn't work with relaxed triggers eithers
+ assert exists n :: n in s && n >= 120;
+ } else if * {
+ // This works: this is certainly more `triggering-on-$Box` magic, but I'm
+ // not sure exactly how it works
+ assert exists n {:autotriggers false} :: n in s && n >= 120;
+ } else if * {
+ // `$Box` only offers limited solace, though
+ assert exists n {:autotriggers false} :: n in s && n < 3;
+ }
+}
diff --git a/Test/wishlist/sequences-literals.dfy.expect b/Test/wishlist/sequences-literals.dfy.expect
new file mode 100644
index 00000000..18e3f98a
--- /dev/null
+++ b/Test/wishlist/sequences-literals.dfy.expect
@@ -0,0 +1,20 @@
+sequences-literals.dfy(24,11): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Then
+sequences-literals.dfy(40,13): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon17_Then
+sequences-literals.dfy(49,11): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon20_Then
+ (0,0): anon7
+sequences-literals.dfy(56,11): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon24_Then
+ (0,0): anon15
+
+Dafny program verifier finished with 2 verified, 4 errors
diff --git a/Test/wishlist/sequences-s0-in-s.dfy b/Test/wishlist/sequences-s0-in-s.dfy
new file mode 100644
index 00000000..c221dbb2
--- /dev/null
+++ b/Test/wishlist/sequences-s0-in-s.dfy
@@ -0,0 +1,25 @@
+// RUN: %dafny /compile:0 /autoTriggers:1 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// The following is also due to a weakness in the axiomatization: namely, it is
+// not easy to learn, using Dafny's axioms, that s[0] in s. One can of course
+// prove it, but it doesn't come for free.
+
+method InSeqTriggers(s: seq<int>, i: nat)
+ requires forall x :: x in s ==> x > 0;
+ requires |s| > 0 {
+ if * {
+ // Fails
+ assert s[0] > 0; // WISH
+ } else if * {
+ // Works
+ assert s[0] in s;
+ assert s[0] > 0;
+ }
+}
+
+method InSeqNoAutoTriggers(s: seq<int>, i: nat)
+ requires forall x {:autotriggers false} :: x in s ==> x > 0;
+ requires |s| > 0 {
+ assert s[0] > 0; // Works (Z3 matches on $Box above)
+}
diff --git a/Test/wishlist/sequences-s0-in-s.dfy.expect b/Test/wishlist/sequences-s0-in-s.dfy.expect
new file mode 100644
index 00000000..4633e5f6
--- /dev/null
+++ b/Test/wishlist/sequences-s0-in-s.dfy.expect
@@ -0,0 +1,6 @@
+sequences-s0-in-s.dfy(13,18): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon5_Then
+
+Dafny program verifier finished with 3 verified, 1 error
diff --git a/Test/wishlist/strings.dfy b/Test/wishlist/strings.dfy
new file mode 100644
index 00000000..372711b0
--- /dev/null
+++ b/Test/wishlist/strings.dfy
@@ -0,0 +1,6 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method EqualityOfStrings() {
+ assert "a" != "b"; // WISH
+}
diff --git a/Test/wishlist/strings.dfy.expect b/Test/wishlist/strings.dfy.expect
new file mode 100644
index 00000000..2817a66e
--- /dev/null
+++ b/Test/wishlist/strings.dfy.expect
@@ -0,0 +1,5 @@
+strings.dfy(5,13): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 1 verified, 1 error
diff --git a/Test/wishlist/we-should-always-print-tooltips.dfy b/Test/wishlist/we-should-always-print-tooltips.dfy
new file mode 100644
index 00000000..d7a55845
--- /dev/null
+++ b/Test/wishlist/we-should-always-print-tooltips.dfy
@@ -0,0 +1,4 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" /autoTriggers:1 /printTooltips "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// WISH it would be great to add /printTooltips to all tests
diff --git a/Test/wishlist/we-should-always-print-tooltips.dfy.expect b/Test/wishlist/we-should-always-print-tooltips.dfy.expect
new file mode 100644
index 00000000..a1c1f7b9
--- /dev/null
+++ b/Test/wishlist/we-should-always-print-tooltips.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 0 verified, 0 errors